diff options
Diffstat (limited to 'Swiften')
1896 files changed, 87583 insertions, 64539 deletions
diff --git a/Swiften/AdHoc/OutgoingAdHocCommandSession.cpp b/Swiften/AdHoc/OutgoingAdHocCommandSession.cpp index cd6b4a3..22c478d 100644 --- a/Swiften/AdHoc/OutgoingAdHocCommandSession.cpp +++ b/Swiften/AdHoc/OutgoingAdHocCommandSession.cpp @@ -1,16 +1,17 @@ /* - * Copyright (c) 2010-2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/AdHoc/OutgoingAdHocCommandSession.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Queries/GenericRequest.h> #include <Swiften/Base/Algorithm.h> +#include <Swiften/Queries/GenericRequest.h> namespace Swift { OutgoingAdHocCommandSession::OutgoingAdHocCommandSession(const JID& to, const std::string& commandNode, IQRouter* iqRouter) : to_(to), commandNode_(commandNode), iqRouter_(iqRouter), isMultiStage_(false) { @@ -18,83 +19,83 @@ OutgoingAdHocCommandSession::OutgoingAdHocCommandSession(const JID& to, const st } OutgoingAdHocCommandSession::~OutgoingAdHocCommandSession() { - connection_.disconnect(); + connection_.disconnect(); } -void OutgoingAdHocCommandSession::handleResponse(boost::shared_ptr<Command> payload, ErrorPayload::ref error) { - if (error) { - onError(error); - } else { - const std::vector<Command::Action>& actions = payload->getAvailableActions(); - actionStates_.clear(); - if (payload->getStatus() == Command::Executing ) { - actionStates_[Command::Cancel] = EnabledAndPresent; - actionStates_[Command::Complete] = Present; - if (std::find(actions.begin(), actions.end(), Command::Complete) != actions.end()) { - actionStates_[Command::Complete] = EnabledAndPresent; - } - - if (getIsMultiStage()) { - actionStates_[Command::Next] = Present; - actionStates_[Command::Prev] = Present; - } - - if (std::find(actions.begin(), actions.end(), Command::Next) != actions.end()) { - actionStates_[Command::Next] = EnabledAndPresent; - } - if (std::find(actions.begin(), actions.end(), Command::Prev) != actions.end()) { - actionStates_[Command::Prev] = EnabledAndPresent; - } - } - - sessionID_ = payload->getSessionID(); - if (std::find(actions.begin(), actions.end(), Command::Next) != actions.end() - || std::find(actions.begin(), actions.end(), Command::Prev) != actions.end()) { - isMultiStage_ = true; - } - onNextStageReceived(payload); - } +void OutgoingAdHocCommandSession::handleResponse(std::shared_ptr<Command> payload, ErrorPayload::ref error) { + if (error) { + onError(error); + } else { + const std::vector<Command::Action>& actions = payload->getAvailableActions(); + actionStates_.clear(); + if (payload->getStatus() == Command::Executing ) { + actionStates_[Command::Cancel] = EnabledAndPresent; + actionStates_[Command::Complete] = Present; + if (std::find(actions.begin(), actions.end(), Command::Complete) != actions.end()) { + actionStates_[Command::Complete] = EnabledAndPresent; + } + + if (getIsMultiStage()) { + actionStates_[Command::Next] = Present; + actionStates_[Command::Prev] = Present; + } + + if (std::find(actions.begin(), actions.end(), Command::Next) != actions.end()) { + actionStates_[Command::Next] = EnabledAndPresent; + } + if (std::find(actions.begin(), actions.end(), Command::Prev) != actions.end()) { + actionStates_[Command::Prev] = EnabledAndPresent; + } + } + + sessionID_ = payload->getSessionID(); + if (std::find(actions.begin(), actions.end(), Command::Next) != actions.end() + || std::find(actions.begin(), actions.end(), Command::Prev) != actions.end()) { + isMultiStage_ = true; + } + onNextStageReceived(payload); + } } bool OutgoingAdHocCommandSession::getIsMultiStage() const { - return isMultiStage_; + return isMultiStage_; } void OutgoingAdHocCommandSession::start() { - boost::shared_ptr<GenericRequest<Command> > commandRequest = boost::make_shared< GenericRequest<Command> >(IQ::Set, to_, boost::make_shared<Command>(commandNode_), iqRouter_); - connection_ = commandRequest->onResponse.connect(boost::bind(&OutgoingAdHocCommandSession::handleResponse, this, _1, _2)); - commandRequest->send(); + std::shared_ptr<GenericRequest<Command> > commandRequest = std::make_shared< GenericRequest<Command> >(IQ::Set, to_, std::make_shared<Command>(commandNode_), iqRouter_); + connection_ = commandRequest->onResponse.connect(boost::bind(&OutgoingAdHocCommandSession::handleResponse, this, _1, _2)); + commandRequest->send(); } void OutgoingAdHocCommandSession::cancel() { - if (!sessionID_.empty()) { - submitForm(Form::ref(), Command::Cancel); - } + if (!sessionID_.empty()) { + submitForm(Form::ref(), Command::Cancel); + } } void OutgoingAdHocCommandSession::goBack() { - submitForm(Form::ref(), Command::Prev); + submitForm(Form::ref(), Command::Prev); } void OutgoingAdHocCommandSession::complete(Form::ref form) { - submitForm(form, Command::Complete); + submitForm(form, Command::Complete); } void OutgoingAdHocCommandSession::goNext(Form::ref form) { - submitForm(form, Command::Next); + submitForm(form, Command::Next); } void OutgoingAdHocCommandSession::submitForm(Form::ref form, Command::Action action) { - boost::shared_ptr<Command> command(boost::make_shared<Command>(commandNode_, sessionID_, action)); - command->setForm(form); - boost::shared_ptr<GenericRequest<Command> > commandRequest = boost::make_shared< GenericRequest<Command> >(IQ::Set, to_, command, iqRouter_); - connection_.disconnect(); - connection_ = commandRequest->onResponse.connect(boost::bind(&OutgoingAdHocCommandSession::handleResponse, this, _1, _2)); - commandRequest->send(); + std::shared_ptr<Command> command(std::make_shared<Command>(commandNode_, sessionID_, action)); + command->setForm(form); + std::shared_ptr<GenericRequest<Command> > commandRequest = std::make_shared< GenericRequest<Command> >(IQ::Set, to_, command, iqRouter_); + connection_.disconnect(); + connection_ = commandRequest->onResponse.connect(boost::bind(&OutgoingAdHocCommandSession::handleResponse, this, _1, _2)); + commandRequest->send(); } OutgoingAdHocCommandSession::ActionState OutgoingAdHocCommandSession::getActionState(Command::Action action) const { - return get(actionStates_, action, Absent); + return get(actionStates_, action, Absent); } } diff --git a/Swiften/AdHoc/OutgoingAdHocCommandSession.h b/Swiften/AdHoc/OutgoingAdHocCommandSession.h index 74d6c59..da4acf5 100644 --- a/Swiften/AdHoc/OutgoingAdHocCommandSession.h +++ b/Swiften/AdHoc/OutgoingAdHocCommandSession.h @@ -1,99 +1,97 @@ /* - * Copyright (c) 2010-2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <string> #include <map> +#include <memory> +#include <string> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Elements/Command.h> #include <Swiften/Elements/ErrorPayload.h> -#include <boost/signals/connection.hpp> +#include <Swiften/JID/JID.h> namespace Swift { - class IQRouter; - class MainWindow; - class UIEventStream; + class IQRouter; - class SWIFTEN_API OutgoingAdHocCommandSession { - public: + class SWIFTEN_API OutgoingAdHocCommandSession { + public: - /** - * Availability of action. - */ - enum ActionState { - Absent /** Action isn't applicable to this command. */ = 0, - Present /** Action is applicable to this command */= 1, - Enabled /** Action is applicable and currently available */ = 2, - EnabledAndPresent = 3}; + /** + * Availability of action. + */ + enum ActionState { + Absent /** Action isn't applicable to this command. */ = 0, + Present /** Action is applicable to this command */= 1, + Enabled /** Action is applicable and currently available */ = 2, + EnabledAndPresent = 3}; - OutgoingAdHocCommandSession(const JID& to, const std::string& commandNode, IQRouter* iqRouter); - ~OutgoingAdHocCommandSession(); - /** - * Send initial request to the target. - */ - void start(); - /** - * Cancel command session with the target. - */ - void cancel(); - /** - * Return to the previous stage. - */ - void goBack(); - /** - * Send the form to complete the command. - * \param form Form for submission - if missing the command will be submitted with no form. - */ - void complete(Form::ref form); - /** - * Send the form to advance to the next stage of the command. - * \param form Form for submission - if missing the command will be submitted with no form. - */ - void goNext(Form::ref form); + OutgoingAdHocCommandSession(const JID& to, const std::string& commandNode, IQRouter* iqRouter); + ~OutgoingAdHocCommandSession(); + /** + * Send initial request to the target. + */ + void start(); + /** + * Cancel command session with the target. + */ + void cancel(); + /** + * Return to the previous stage. + */ + void goBack(); + /** + * Send the form to complete the command. + * \param form Form for submission - if missing the command will be submitted with no form. + */ + void complete(Form::ref form); + /** + * Send the form to advance to the next stage of the command. + * \param form Form for submission - if missing the command will be submitted with no form. + */ + void goNext(Form::ref form); - /** - * Is the form multi-stage? - */ - bool getIsMultiStage() const; + /** + * Is the form multi-stage? + */ + bool getIsMultiStage() const; - /** - * Emitted when the form for the next stage is available. - */ - boost::signal<void (Command::ref)> onNextStageReceived; + /** + * Emitted when the form for the next stage is available. + */ + boost::signals2::signal<void (Command::ref)> onNextStageReceived; - /** - * Emitted on error. - */ - boost::signal<void (ErrorPayload::ref)> onError; + /** + * Emitted on error. + */ + boost::signals2::signal<void (ErrorPayload::ref)> onError; - /** - * Get the state of a given action. - * This is useful for a UI to determine which buttons should be visible, - * and which enabled. - * Use for Next, Prev, Cancel and Complete only. - * If no actions are available, the command has completed. - */ - ActionState getActionState(Command::Action action) const; + /** + * Get the state of a given action. + * This is useful for a UI to determine which buttons should be visible, + * and which enabled. + * Use for Next, Prev, Cancel and Complete only. + * If no actions are available, the command has completed. + */ + ActionState getActionState(Command::Action action) const; - private: - void handleResponse(boost::shared_ptr<Command> payload, ErrorPayload::ref error); - void submitForm(Form::ref, Command::Action action); + private: + void handleResponse(std::shared_ptr<Command> payload, ErrorPayload::ref error); + void submitForm(Form::ref, Command::Action action); - private: - JID to_; - std::string commandNode_; - IQRouter* iqRouter_; - bool isMultiStage_; - std::string sessionID_; - std::map<Command::Action, ActionState> actionStates_; - boost::bsignals::connection connection_; - }; + private: + JID to_; + std::string commandNode_; + IQRouter* iqRouter_; + bool isMultiStage_; + std::string sessionID_; + std::map<Command::Action, ActionState> actionStates_; + boost::signals2::connection connection_; + }; } diff --git a/Swiften/AdHoc/SConscript b/Swiften/AdHoc/SConscript index 69c9083..6d3f176 100644 --- a/Swiften/AdHoc/SConscript +++ b/Swiften/AdHoc/SConscript @@ -1,6 +1,6 @@ Import("swiften_env") objects = swiften_env.SwiftenObject([ - "OutgoingAdHocCommandSession.cpp", - ]) + "OutgoingAdHocCommandSession.cpp", + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Avatars/AvatarManager.cpp b/Swiften/Avatars/AvatarManager.cpp index ce7d372..bf19b6a 100644 --- a/Swiften/Avatars/AvatarManager.cpp +++ b/Swiften/Avatars/AvatarManager.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Avatars/AvatarManager.h> diff --git a/Swiften/Avatars/AvatarManager.h b/Swiften/Avatars/AvatarManager.h index 1e92328..a71d323 100644 --- a/Swiften/Avatars/AvatarManager.h +++ b/Swiften/Avatars/AvatarManager.h @@ -1,27 +1,27 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/filesystem/path.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Base/ByteArray.h> namespace Swift { - class JID; + class JID; - class SWIFTEN_API AvatarManager { - public: - virtual ~AvatarManager(); + class SWIFTEN_API AvatarManager { + public: + virtual ~AvatarManager(); - virtual ByteArray getAvatar(const JID&) const = 0; - virtual boost::filesystem::path getAvatarPath(const JID&) const = 0; + virtual ByteArray getAvatar(const JID&) const = 0; + virtual boost::filesystem::path getAvatarPath(const JID&) const = 0; - boost::signal<void (const JID&)> onAvatarChanged; - }; + boost::signals2::signal<void (const JID&)> onAvatarChanged; + }; } diff --git a/Swiften/Avatars/AvatarManagerImpl.cpp b/Swiften/Avatars/AvatarManagerImpl.cpp index 7c3baa7..6e98b1b 100644 --- a/Swiften/Avatars/AvatarManagerImpl.cpp +++ b/Swiften/Avatars/AvatarManagerImpl.cpp @@ -1,64 +1,66 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Avatars/AvatarManagerImpl.h> #include <boost/bind.hpp> -#include <Swiften/Avatars/VCardUpdateAvatarManager.h> -#include <Swiften/Avatars/VCardAvatarManager.h> #include <Swiften/Avatars/AvatarStorage.h> #include <Swiften/Avatars/OfflineAvatarManager.h> +#include <Swiften/Avatars/VCardAvatarManager.h> +#include <Swiften/Avatars/VCardUpdateAvatarManager.h> #include <Swiften/Base/ByteArray.h> namespace Swift { AvatarManagerImpl::AvatarManagerImpl(VCardManager* vcardManager, StanzaChannel* stanzaChannel, AvatarStorage* avatarStorage, CryptoProvider* crypto, MUCRegistry* mucRegistry) : avatarStorage(avatarStorage) { - vcardUpdateAvatarManager = new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto, mucRegistry); - combinedAvatarProvider.addProvider(vcardUpdateAvatarManager); + vcardUpdateAvatarManager = new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto, mucRegistry); + combinedAvatarProvider.addProvider(vcardUpdateAvatarManager); - vcardAvatarManager = new VCardAvatarManager(vcardManager, avatarStorage, crypto, mucRegistry); - combinedAvatarProvider.addProvider(vcardAvatarManager); + vcardAvatarManager = new VCardAvatarManager(vcardManager, avatarStorage, crypto, mucRegistry); + combinedAvatarProvider.addProvider(vcardAvatarManager); - offlineAvatarManager = new OfflineAvatarManager(avatarStorage); - combinedAvatarProvider.addProvider(offlineAvatarManager); + offlineAvatarManager = new OfflineAvatarManager(avatarStorage); + combinedAvatarProvider.addProvider(offlineAvatarManager); - combinedAvatarProvider.onAvatarChanged.connect(boost::bind(&AvatarManagerImpl::handleCombinedAvatarChanged, this, _1)); + combinedAvatarProvider.onAvatarChanged.connect(boost::bind(&AvatarManagerImpl::handleCombinedAvatarChanged, this, _1)); } AvatarManagerImpl::~AvatarManagerImpl() { - combinedAvatarProvider.onAvatarChanged.disconnect(boost::bind(&AvatarManagerImpl::handleCombinedAvatarChanged, this, _1)); + combinedAvatarProvider.onAvatarChanged.disconnect(boost::bind(&AvatarManagerImpl::handleCombinedAvatarChanged, this, _1)); - combinedAvatarProvider.removeProvider(offlineAvatarManager); - delete offlineAvatarManager; - combinedAvatarProvider.removeProvider(vcardAvatarManager); - delete vcardAvatarManager; - combinedAvatarProvider.removeProvider(vcardUpdateAvatarManager); - delete vcardUpdateAvatarManager; + combinedAvatarProvider.removeProvider(offlineAvatarManager); + delete offlineAvatarManager; + combinedAvatarProvider.removeProvider(vcardAvatarManager); + delete vcardAvatarManager; + combinedAvatarProvider.removeProvider(vcardUpdateAvatarManager); + delete vcardUpdateAvatarManager; } boost::filesystem::path AvatarManagerImpl::getAvatarPath(const JID& jid) const { - std::string hash = combinedAvatarProvider.getAvatarHash(jid); - if (!hash.empty()) { - return avatarStorage->getAvatarPath(hash); - } - return boost::filesystem::path(); + boost::optional<std::string> hash = combinedAvatarProvider.getAvatarHash(jid); + if (hash && !hash->empty()) { + return avatarStorage->getAvatarPath(*hash); + } + return boost::filesystem::path(); } ByteArray AvatarManagerImpl::getAvatar(const JID& jid) const { - std::string hash = combinedAvatarProvider.getAvatarHash(jid); - if (!hash.empty()) { - return avatarStorage->getAvatar(hash); - } - return ByteArray(); + boost::optional<std::string> hash = combinedAvatarProvider.getAvatarHash(jid); + if (hash && !hash->empty()) { + return avatarStorage->getAvatar(*hash); + } + return ByteArray(); } void AvatarManagerImpl::handleCombinedAvatarChanged(const JID& jid) { - offlineAvatarManager->setAvatar(jid, combinedAvatarProvider.getAvatarHash(jid)); - onAvatarChanged(jid); + boost::optional<std::string> hash = combinedAvatarProvider.getAvatarHash(jid); + assert(hash); + offlineAvatarManager->setAvatar(jid, *hash); + onAvatarChanged(jid); } } diff --git a/Swiften/Avatars/AvatarManagerImpl.h b/Swiften/Avatars/AvatarManagerImpl.h index 4f59fe5..d58e09f 100644 --- a/Swiften/Avatars/AvatarManagerImpl.h +++ b/Swiften/Avatars/AvatarManagerImpl.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,32 +10,32 @@ #include <Swiften/Avatars/CombinedAvatarProvider.h> namespace Swift { - class MUCRegistry; - class AvatarStorage; - class StanzaChannel; - class VCardManager; - class VCardUpdateAvatarManager; - class VCardAvatarManager; - class OfflineAvatarManager; - class CryptoProvider; - - class AvatarManagerImpl : public AvatarManager { - public: - AvatarManagerImpl(VCardManager*, StanzaChannel*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL); - virtual ~AvatarManagerImpl(); - - virtual boost::filesystem::path getAvatarPath(const JID&) const; - virtual ByteArray getAvatar(const JID&) const; - - private: - void handleCombinedAvatarChanged(const JID& jid); - - - private: - CombinedAvatarProvider combinedAvatarProvider; - AvatarStorage* avatarStorage; - VCardUpdateAvatarManager* vcardUpdateAvatarManager; - VCardAvatarManager* vcardAvatarManager; - OfflineAvatarManager* offlineAvatarManager; - }; + class MUCRegistry; + class AvatarStorage; + class StanzaChannel; + class VCardManager; + class VCardUpdateAvatarManager; + class VCardAvatarManager; + class OfflineAvatarManager; + class CryptoProvider; + + class AvatarManagerImpl : public AvatarManager { + public: + AvatarManagerImpl(VCardManager*, StanzaChannel*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = nullptr); + virtual ~AvatarManagerImpl(); + + virtual boost::filesystem::path getAvatarPath(const JID&) const; + virtual ByteArray getAvatar(const JID&) const; + + private: + void handleCombinedAvatarChanged(const JID& jid); + + + private: + CombinedAvatarProvider combinedAvatarProvider; + AvatarStorage* avatarStorage; + VCardUpdateAvatarManager* vcardUpdateAvatarManager; + VCardAvatarManager* vcardAvatarManager; + OfflineAvatarManager* offlineAvatarManager; + }; } diff --git a/Swiften/Avatars/AvatarMemoryStorage.h b/Swiften/Avatars/AvatarMemoryStorage.h index 095b144..bc40a26 100644 --- a/Swiften/Avatars/AvatarMemoryStorage.h +++ b/Swiften/Avatars/AvatarMemoryStorage.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,35 +9,36 @@ #include <map> #include <string> -#include <Swiften/Base/ByteArray.h> #include <Swiften/Avatars/AvatarStorage.h> +#include <Swiften/Base/API.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/JID/JID.h> namespace Swift { - class AvatarMemoryStorage : public AvatarStorage { - public: - virtual bool hasAvatar(const std::string& hash) const { return avatars.find(hash) != avatars.end(); } - virtual void addAvatar(const std::string& hash, const ByteArray& avatar) { avatars[hash] = avatar; } - virtual ByteArray getAvatar(const std::string& hash) const { - std::map<std::string, ByteArray>::const_iterator i = avatars.find(hash); - return i == avatars.end() ? ByteArray() : i->second; - } - - virtual boost::filesystem::path getAvatarPath(const std::string& hash) const { - return boost::filesystem::path("/avatars") / hash; - } - - virtual void setAvatarForJID(const JID& jid, const std::string& hash) { - jidAvatars[jid] = hash; - } - - virtual std::string getAvatarForJID(const JID& jid) const { - std::map<JID, std::string>::const_iterator i = jidAvatars.find(jid); - return i == jidAvatars.end() ? "" : i->second; - } - - private: - std::map<std::string, ByteArray> avatars; - std::map<JID, std::string> jidAvatars; - }; + class SWIFTEN_API AvatarMemoryStorage : public AvatarStorage { + public: + virtual bool hasAvatar(const std::string& hash) const { return avatars.find(hash) != avatars.end(); } + virtual void addAvatar(const std::string& hash, const ByteArray& avatar) { avatars[hash] = avatar; } + virtual ByteArray getAvatar(const std::string& hash) const { + std::map<std::string, ByteArray>::const_iterator i = avatars.find(hash); + return i == avatars.end() ? ByteArray() : i->second; + } + + virtual boost::filesystem::path getAvatarPath(const std::string& hash) const { + return boost::filesystem::path("/avatars") / hash; + } + + virtual void setAvatarForJID(const JID& jid, const std::string& hash) { + jidAvatars[jid] = hash; + } + + virtual std::string getAvatarForJID(const JID& jid) const { + std::map<JID, std::string>::const_iterator i = jidAvatars.find(jid); + return i == jidAvatars.end() ? "" : i->second; + } + + private: + std::map<std::string, ByteArray> avatars; + std::map<JID, std::string> jidAvatars; + }; } diff --git a/Swiften/Avatars/AvatarProvider.cpp b/Swiften/Avatars/AvatarProvider.cpp index 44c89d5..da4666a 100644 --- a/Swiften/Avatars/AvatarProvider.cpp +++ b/Swiften/Avatars/AvatarProvider.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Avatars/AvatarProvider.h> diff --git a/Swiften/Avatars/AvatarProvider.h b/Swiften/Avatars/AvatarProvider.h index 5c9460d..a92418f 100644 --- a/Swiften/Avatars/AvatarProvider.h +++ b/Swiften/Avatars/AvatarProvider.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class JID; + class JID; - class SWIFTEN_API AvatarProvider { - public: - virtual ~AvatarProvider(); + class SWIFTEN_API AvatarProvider { + public: + virtual ~AvatarProvider(); - virtual std::string getAvatarHash(const JID&) const = 0; + virtual boost::optional<std::string> getAvatarHash(const JID&) const = 0; - boost::signal<void (const JID&)> onAvatarChanged; - }; + boost::signals2::signal<void (const JID&)> onAvatarChanged; + }; } diff --git a/Swiften/Avatars/AvatarStorage.cpp b/Swiften/Avatars/AvatarStorage.cpp index 8bb1126..89325bf 100644 --- a/Swiften/Avatars/AvatarStorage.cpp +++ b/Swiften/Avatars/AvatarStorage.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Avatars/AvatarStorage.h> diff --git a/Swiften/Avatars/AvatarStorage.h b/Swiften/Avatars/AvatarStorage.h index 7f61ca2..dc3eb34 100644 --- a/Swiften/Avatars/AvatarStorage.h +++ b/Swiften/Avatars/AvatarStorage.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/filesystem/path.hpp> #include <string> +#include <boost/filesystem/path.hpp> + #include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> namespace Swift { - class JID; + class JID; - class SWIFTEN_API AvatarStorage { - public: - virtual ~AvatarStorage(); + class SWIFTEN_API AvatarStorage { + public: + virtual ~AvatarStorage(); - virtual bool hasAvatar(const std::string& hash) const = 0; - virtual void addAvatar(const std::string& hash, const ByteArray& avatar) = 0; - virtual ByteArray getAvatar(const std::string& hash) const = 0; - virtual boost::filesystem::path getAvatarPath(const std::string& hash) const = 0; + virtual bool hasAvatar(const std::string& hash) const = 0; + virtual void addAvatar(const std::string& hash, const ByteArray& avatar) = 0; + virtual ByteArray getAvatar(const std::string& hash) const = 0; + virtual boost::filesystem::path getAvatarPath(const std::string& hash) const = 0; - virtual void setAvatarForJID(const JID& jid, const std::string& hash) = 0; - virtual std::string getAvatarForJID(const JID& jid) const = 0; - }; + virtual void setAvatarForJID(const JID& jid, const std::string& hash) = 0; + virtual std::string getAvatarForJID(const JID& jid) const = 0; + }; } diff --git a/Swiften/Avatars/CombinedAvatarProvider.cpp b/Swiften/Avatars/CombinedAvatarProvider.cpp index d283664..ba6e6be 100644 --- a/Swiften/Avatars/CombinedAvatarProvider.cpp +++ b/Swiften/Avatars/CombinedAvatarProvider.cpp @@ -1,57 +1,62 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Avatars/CombinedAvatarProvider.h> #include <algorithm> + #include <boost/bind.hpp> #include <Swiften/Base/Log.h> namespace Swift { -std::string CombinedAvatarProvider::getAvatarHash(const JID& jid) const { - return getCombinedAvatarAndCache(jid); +boost::optional<std::string> CombinedAvatarProvider::getAvatarHash(const JID& jid) const { + return getCombinedAvatarAndCache(jid); } void CombinedAvatarProvider::addProvider(AvatarProvider* provider) { - provider->onAvatarChanged.connect(boost::bind(&CombinedAvatarProvider::handleAvatarChanged, this, _1)); - providers.push_back(provider); + provider->onAvatarChanged.connect(boost::bind(&CombinedAvatarProvider::handleAvatarChanged, this, _1)); + providers.push_back(provider); } void CombinedAvatarProvider::removeProvider(AvatarProvider* provider) { - std::vector<AvatarProvider*>::iterator i = std::remove(providers.begin(), providers.end(), provider); - for(std::vector<AvatarProvider*>::iterator j = i; j < providers.end(); ++j) { - provider->onAvatarChanged.disconnect(boost::bind(&CombinedAvatarProvider::handleAvatarChanged, this, _1)); - } - providers.erase(i, providers.end()); + std::vector<AvatarProvider*>::iterator i = std::remove(providers.begin(), providers.end(), provider); + for(std::vector<AvatarProvider*>::iterator j = i; j < providers.end(); ++j) { + provider->onAvatarChanged.disconnect(boost::bind(&CombinedAvatarProvider::handleAvatarChanged, this, _1)); + } + providers.erase(i, providers.end()); } void CombinedAvatarProvider::handleAvatarChanged(const JID& jid) { - std::string oldHash; - std::map<JID, std::string>::const_iterator i = avatars.find(jid); - if (i != avatars.end()) { - oldHash = i->second; - } - std::string newHash = getCombinedAvatarAndCache(jid); - if (newHash != oldHash) { - SWIFT_LOG(debug) << "Avatar changed: " << jid << ": " << oldHash << " -> " << newHash << std::endl; - onAvatarChanged(jid); - } + std::string oldHash; + std::map<JID, std::string>::const_iterator i = avatars.find(jid); + if (i != avatars.end()) { + oldHash = i->second; + } + boost::optional<std::string> newHash = getCombinedAvatarAndCache(jid); + if (newHash != oldHash) { + SWIFT_LOG(debug) << "Avatar changed: " << jid << ": " << oldHash << " -> " << (newHash ? newHash.get() : "NULL"); + onAvatarChanged(jid); + } } -std::string CombinedAvatarProvider::getCombinedAvatarAndCache(const JID& jid) const { - SWIFT_LOG(debug) << "JID: " << jid << std::endl; - std::string hash; - for (size_t i = 0; i < providers.size() && hash.empty(); ++i) { - hash = providers[i]->getAvatarHash(jid); - SWIFT_LOG(debug) << "Provider " << providers[i] << ": " << hash << std::endl; - } - avatars[jid] = hash; - return hash; +boost::optional<std::string> CombinedAvatarProvider::getCombinedAvatarAndCache(const JID& jid) const { + SWIFT_LOG(debug) << "JID: " << jid; + boost::optional<std::string> hash; + for (size_t i = 0; i < providers.size() && !hash; ++i) { + hash = providers[i]->getAvatarHash(jid); + SWIFT_LOG(debug) << "Provider " << providers[i] << ": " << (hash ? hash.get() : "NULL"); + } + if (hash) { + avatars[jid] = *hash; + } else { + avatars[jid] = ""; + } + return hash; } } diff --git a/Swiften/Avatars/CombinedAvatarProvider.h b/Swiften/Avatars/CombinedAvatarProvider.h index 96989b2..f667ad2 100644 --- a/Swiften/Avatars/CombinedAvatarProvider.h +++ b/Swiften/Avatars/CombinedAvatarProvider.h @@ -1,32 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <map> +#include <vector> -#include <Swiften/Base/API.h> #include <Swiften/Avatars/AvatarProvider.h> +#include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API CombinedAvatarProvider : public AvatarProvider { - public: - virtual std::string getAvatarHash(const JID&) const; + class SWIFTEN_API CombinedAvatarProvider : public AvatarProvider { + public: + virtual boost::optional<std::string> getAvatarHash(const JID&) const; - void addProvider(AvatarProvider*); - void removeProvider(AvatarProvider*); + void addProvider(AvatarProvider*); + void removeProvider(AvatarProvider*); - private: - void handleAvatarChanged(const JID&); - std::string getCombinedAvatarAndCache(const JID&) const; + private: + void handleAvatarChanged(const JID&); + boost::optional<std::string> getCombinedAvatarAndCache(const JID&) const; - private: - std::vector<AvatarProvider*> providers; - mutable std::map<JID, std::string> avatars; - }; + private: + std::vector<AvatarProvider*> providers; + mutable std::map<JID, std::string> avatars; + }; } diff --git a/Swiften/Avatars/DummyAvatarManager.h b/Swiften/Avatars/DummyAvatarManager.h index e73c61e..f079be1 100644 --- a/Swiften/Avatars/DummyAvatarManager.h +++ b/Swiften/Avatars/DummyAvatarManager.h @@ -1,33 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <map> -#include <Swiften/JID/JID.h> #include <Swiften/Avatars/AvatarManager.h> +#include <Swiften/JID/JID.h> namespace Swift { - class DummyAvatarManager : public AvatarManager { - public: - virtual boost::filesystem::path getAvatarPath(const JID& j) const { - return boost::filesystem::path("/avatars") / j.toString(); - } + class DummyAvatarManager : public AvatarManager { + public: + virtual boost::filesystem::path getAvatarPath(const JID& j) const { + return boost::filesystem::path("/avatars") / j.toString(); + } - virtual ByteArray getAvatar(const JID& jid) const { - std::map<JID, ByteArray>::const_iterator i = avatars.find(jid); - if (i != avatars.end()) { - return i->second; - } - else { - return ByteArray(); - } - } + virtual ByteArray getAvatar(const JID& jid) const { + std::map<JID, ByteArray>::const_iterator i = avatars.find(jid); + if (i != avatars.end()) { + return i->second; + } + else { + return ByteArray(); + } + } - std::map<JID, ByteArray> avatars; - }; + std::map<JID, ByteArray> avatars; + }; } diff --git a/Swiften/Avatars/NullAvatarManager.h b/Swiften/Avatars/NullAvatarManager.h index 3f5b9f5..adc1acc 100644 --- a/Swiften/Avatars/NullAvatarManager.h +++ b/Swiften/Avatars/NullAvatarManager.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,14 +9,14 @@ #include <Swiften/Avatars/AvatarManager.h> namespace Swift { - class NullAvatarManager : public AvatarManager { - public: - virtual boost::filesystem::path getAvatarPath(const JID&) const { - return boost::filesystem::path(); - } + class NullAvatarManager : public AvatarManager { + public: + virtual boost::filesystem::path getAvatarPath(const JID&) const { + return boost::filesystem::path(); + } - virtual ByteArray getAvatar(const JID&) const { - return ByteArray(); - } - }; + virtual ByteArray getAvatar(const JID&) const { + return ByteArray(); + } + }; } diff --git a/Swiften/Avatars/OfflineAvatarManager.cpp b/Swiften/Avatars/OfflineAvatarManager.cpp index 02c6a35..e2468e6 100644 --- a/Swiften/Avatars/OfflineAvatarManager.cpp +++ b/Swiften/Avatars/OfflineAvatarManager.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Avatars/OfflineAvatarManager.h> @@ -18,15 +18,15 @@ OfflineAvatarManager::OfflineAvatarManager(AvatarStorage* avatarStorage) : avata OfflineAvatarManager::~OfflineAvatarManager() { } -std::string OfflineAvatarManager::getAvatarHash(const JID& jid) const { - return avatarStorage->getAvatarForJID(jid); +boost::optional<std::string> OfflineAvatarManager::getAvatarHash(const JID& jid) const { + return avatarStorage->getAvatarForJID(jid); } void OfflineAvatarManager::setAvatar(const JID& jid, const std::string& hash) { - if (getAvatarHash(jid) != hash) { - avatarStorage->setAvatarForJID(jid, hash); - onAvatarChanged(jid); - } + if (getAvatarHash(jid) != hash) { + avatarStorage->setAvatarForJID(jid, hash); + onAvatarChanged(jid); + } } } diff --git a/Swiften/Avatars/OfflineAvatarManager.h b/Swiften/Avatars/OfflineAvatarManager.h index 2098990..11b1d5f 100644 --- a/Swiften/Avatars/OfflineAvatarManager.h +++ b/Swiften/Avatars/OfflineAvatarManager.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Avatars/AvatarProvider.h> +#include <Swiften/Base/API.h> namespace Swift { - class AvatarStorage; + class AvatarStorage; - class OfflineAvatarManager : public AvatarProvider { - public: - OfflineAvatarManager(AvatarStorage*); - ~OfflineAvatarManager(); + class SWIFTEN_API OfflineAvatarManager : public AvatarProvider { + public: + OfflineAvatarManager(AvatarStorage*); + ~OfflineAvatarManager(); - virtual std::string getAvatarHash(const JID&) const; - void setAvatar(const JID&, const std::string& hash); + virtual boost::optional<std::string> getAvatarHash(const JID&) const; + void setAvatar(const JID&, const std::string& hash); - private: - AvatarStorage* avatarStorage; - }; + private: + AvatarStorage* avatarStorage; + }; } diff --git a/Swiften/Avatars/SConscript b/Swiften/Avatars/SConscript index 9c219a4..0cd419d 100644 --- a/Swiften/Avatars/SConscript +++ b/Swiften/Avatars/SConscript @@ -1,13 +1,13 @@ Import("swiften_env") objects = swiften_env.SwiftenObject([ - "VCardUpdateAvatarManager.cpp", - "VCardAvatarManager.cpp", - "OfflineAvatarManager.cpp", - "AvatarManager.cpp", - "AvatarManagerImpl.cpp", - "AvatarStorage.cpp", - "AvatarProvider.cpp", - "CombinedAvatarProvider.cpp", - ]) + "VCardUpdateAvatarManager.cpp", + "VCardAvatarManager.cpp", + "OfflineAvatarManager.cpp", + "AvatarManager.cpp", + "AvatarManagerImpl.cpp", + "AvatarStorage.cpp", + "AvatarProvider.cpp", + "CombinedAvatarProvider.cpp", + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp b/Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp new file mode 100644 index 0000000..5a35410 --- /dev/null +++ b/Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <string> + +#include <boost/bind.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Avatars/AvatarManagerImpl.h> +#include <Swiften/Avatars/AvatarMemoryStorage.h> +#include <Swiften/Avatars/CombinedAvatarProvider.h> +#include <Swiften/Avatars/OfflineAvatarManager.h> +#include <Swiften/Avatars/VCardAvatarManager.h> +#include <Swiften/Avatars/VCardUpdateAvatarManager.h> +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Elements/VCardUpdate.h> +#include <Swiften/JID/JID.h> +#include <Swiften/MUC/MUCRegistry.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/VCards/VCardManager.h> +#include <Swiften/VCards/VCardMemoryStorage.h> + +using namespace Swift; + +class AvatarManagerImplTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(AvatarManagerImplTest); + CPPUNIT_TEST(testGetSetAvatar); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + ownerJID = JID("owner@domain.com/theowner"); + stanzaChannel = std::make_shared<DummyStanzaChannel>(); + iqRouter = std::make_shared<IQRouter>(stanzaChannel.get()); + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + vcardStorage = std::make_shared<VCardMemoryStorage>(crypto.get()); + vcardManager = std::make_shared<VCardManager>(ownerJID, iqRouter.get(), vcardStorage.get()); + avatarStorage = std::make_shared<AvatarMemoryStorage>(); + mucRegistry = std::make_shared<DummyMUCRegistry>(); + avatarManager = std::make_shared<AvatarManagerImpl>(vcardManager.get(), stanzaChannel.get(), avatarStorage.get(), crypto.get(), mucRegistry.get()); + } + + void testGetSetAvatar() { + /* initially we have no knowledge of the user or their avatar */ + JID personJID("person@domain.com/theperson"); + ByteArray avatar = avatarManager->getAvatar(personJID.toBare()); + CPPUNIT_ASSERT(!avatar.size()); + + /* notify the 'owner' JID that our avatar has changed */ + + ByteArray fullAvatar = createByteArray("abcdefg"); + std::shared_ptr<VCardUpdate> vcardUpdate = std::make_shared<VCardUpdate>(); + vcardUpdate->setPhotoHash(Hexify::hexify(crypto->getSHA1Hash(fullAvatar))); + std::shared_ptr<Presence> presence = std::make_shared<Presence>(); + presence->setTo(ownerJID); + presence->setFrom(personJID); + presence->setType(Presence::Available); + presence->addPayload(vcardUpdate); + stanzaChannel->onPresenceReceived(presence); + + /* reply to the avatar request with our new avatar */ + + CPPUNIT_ASSERT_EQUAL(size_t(1), stanzaChannel->sentStanzas.size()); + std::shared_ptr<IQ> request = std::dynamic_pointer_cast<IQ>(stanzaChannel->sentStanzas[0]); + stanzaChannel->sentStanzas.pop_back(); + CPPUNIT_ASSERT(!!request); + std::shared_ptr<VCard> vcard = request->getPayload<VCard>(); + CPPUNIT_ASSERT(!!vcard); + + std::shared_ptr<IQ> reply = std::make_shared<IQ>(IQ::Result); + reply->setTo(request->getFrom()); + reply->setFrom(request->getTo()); + reply->setID(request->getID()); + vcard->setPhoto(fullAvatar); + reply->addPayload(vcard); + stanzaChannel->onIQReceived(reply); + + /* check hash through avatarManager that it received the correct photo */ + + ByteArray reportedAvatar = avatarManager->getAvatar(personJID.toBare()); + CPPUNIT_ASSERT_EQUAL(byteArrayToString(fullAvatar), byteArrayToString(reportedAvatar)); + + /* send new presence to notify of blank avatar */ + + vcardUpdate = std::make_shared<VCardUpdate>(); + vcardUpdate->setPhotoHash("da39a3ee5e6b4b0d3255bfef95601890afd80709"); + presence = std::make_shared<Presence>(); + presence->setTo(ownerJID); + presence->setFrom(personJID); + presence->setType(Presence::Available); + presence->addPayload(vcardUpdate); + stanzaChannel->onPresenceReceived(presence); + + /* reply to the avatar request with our EMPTY avatar */ + + CPPUNIT_ASSERT_EQUAL(size_t(1), stanzaChannel->sentStanzas.size()); + request = std::dynamic_pointer_cast<IQ>(stanzaChannel->sentStanzas[0]); + stanzaChannel->sentStanzas.pop_back(); + CPPUNIT_ASSERT(!!request); + vcard = request->getPayload<VCard>(); + CPPUNIT_ASSERT(!!vcard); + + ByteArray blankAvatar = createByteArray(""); + reply = std::make_shared<IQ>(IQ::Result); + reply->setTo(request->getFrom()); + reply->setFrom(request->getTo()); + reply->setID(request->getID()); + vcard->setPhoto(blankAvatar); + reply->addPayload(vcard); + stanzaChannel->onIQReceived(reply); + + /* check hash through avatarManager that it received the correct photo */ + + reportedAvatar = avatarManager->getAvatar(personJID.toBare()); + CPPUNIT_ASSERT_EQUAL(byteArrayToString(blankAvatar), byteArrayToString(reportedAvatar)); + } + + struct DummyMUCRegistry : public MUCRegistry { + bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); } + std::vector<JID> mucs_; + }; + + private: + + JID ownerJID; + std::shared_ptr<DummyStanzaChannel> stanzaChannel; + std::shared_ptr<IQRouter> iqRouter; + std::shared_ptr<CryptoProvider> crypto; + std::shared_ptr<VCardMemoryStorage> vcardStorage; + std::shared_ptr<VCardManager> vcardManager; + std::shared_ptr<AvatarMemoryStorage> avatarStorage; + std::shared_ptr<DummyMUCRegistry> mucRegistry; + std::shared_ptr<AvatarManagerImpl> avatarManager; + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(AvatarManagerImplTest); diff --git a/Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp b/Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp index 50b0adb..3e5e9e6 100644 --- a/Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp +++ b/Swiften/Avatars/UnitTest/CombinedAvatarProviderTest.cpp @@ -1,226 +1,375 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> +#include <string> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> -#include <Swiften/JID/JID.h> -#include <string> +#include <Swiften/Avatars/AvatarMemoryStorage.h> #include <Swiften/Avatars/CombinedAvatarProvider.h> +#include <Swiften/Avatars/OfflineAvatarManager.h> +#include <Swiften/Avatars/VCardAvatarManager.h> +#include <Swiften/Avatars/VCardUpdateAvatarManager.h> +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/JID/JID.h> +#include <Swiften/MUC/MUCRegistry.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/VCards/VCardManager.h> +#include <Swiften/VCards/VCardMemoryStorage.h> using namespace Swift; class CombinedAvatarProviderTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(CombinedAvatarProviderTest); - CPPUNIT_TEST(testGetAvatarWithNoAvatarProviderReturnsEmpty); - CPPUNIT_TEST(testGetAvatarWithSingleAvatarProvider); - CPPUNIT_TEST(testGetAvatarWithMultipleAvatarProviderReturnsFirstAvatar); - CPPUNIT_TEST(testGetAvatarWithMultipleAvatarProviderAndFailingFirstProviderReturnsSecondAvatar); - CPPUNIT_TEST(testProviderUpdateTriggersChange); - CPPUNIT_TEST(testProviderUpdateWithoutChangeDoesNotTriggerChange); - CPPUNIT_TEST(testProviderSecondUpdateTriggersChange); - CPPUNIT_TEST(testProviderUpdateWithAvatarDisappearingTriggersChange); - CPPUNIT_TEST(testProviderUpdateAfterAvatarDisappearedTriggersChange); - CPPUNIT_TEST(testProviderUpdateAfterGetDoesNotTriggerChange); - CPPUNIT_TEST(testProviderUpdateBareJIDAfterGetFullJID); - CPPUNIT_TEST(testRemoveProviderDisconnectsUpdates); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - avatarProvider1 = new DummyAvatarProvider(); - avatarProvider2 = new DummyAvatarProvider(); - user1 = JID("user1@bar.com/bla"); - user2 = JID("user2@foo.com/baz"); - avatarHash1 = "ABCDEFG"; - avatarHash2 = "XYZU"; - avatarHash3 = "IDGH"; - } - - void tearDown() { - delete avatarProvider1; - delete avatarProvider2; - } - - void testGetAvatarWithNoAvatarProviderReturnsEmpty() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - - CPPUNIT_ASSERT(testling->getAvatarHash(user1).empty()); - } - - void testGetAvatarWithSingleAvatarProvider() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - avatarProvider1->avatars[user1] = avatarHash1; - testling->addProvider(avatarProvider1); - - CPPUNIT_ASSERT_EQUAL(avatarHash1, testling->getAvatarHash(user1)); - } - - void testGetAvatarWithMultipleAvatarProviderReturnsFirstAvatar() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - avatarProvider1->avatars[user1] = avatarHash1; - avatarProvider2->avatars[user1] = avatarHash2; - testling->addProvider(avatarProvider1); - testling->addProvider(avatarProvider2); - - CPPUNIT_ASSERT_EQUAL(avatarHash1, testling->getAvatarHash(user1)); - } - - void testGetAvatarWithMultipleAvatarProviderAndFailingFirstProviderReturnsSecondAvatar() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - avatarProvider2->avatars[user1] = avatarHash2; - testling->addProvider(avatarProvider1); - testling->addProvider(avatarProvider2); - - CPPUNIT_ASSERT_EQUAL(avatarHash2, testling->getAvatarHash(user1)); - } - - void testProviderUpdateTriggersChange() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - testling->addProvider(avatarProvider1); - avatarProvider1->avatars[user1] = avatarHash1; - avatarProvider1->onAvatarChanged(user1); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - } - - void testProviderUpdateWithoutChangeDoesNotTriggerChange() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - testling->addProvider(avatarProvider1); - testling->addProvider(avatarProvider2); - avatarProvider1->avatars[user1] = avatarHash1; - avatarProvider1->onAvatarChanged(user1); - changes.clear(); - - avatarProvider2->avatars[user1] = avatarHash2; - avatarProvider2->onAvatarChanged(user1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); - } - - void testProviderSecondUpdateTriggersChange() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - testling->addProvider(avatarProvider1); - avatarProvider1->avatars[user1] = avatarHash1; - avatarProvider1->onAvatarChanged(user1); - changes.clear(); - avatarProvider1->avatars[user1] = avatarHash2; - avatarProvider1->onAvatarChanged(user1); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - } - - - void testProviderUpdateWithAvatarDisappearingTriggersChange() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - testling->addProvider(avatarProvider1); - avatarProvider1->avatars[user1] = avatarHash1; - avatarProvider1->onAvatarChanged(user1); - changes.clear(); - avatarProvider1->avatars.clear(); - avatarProvider1->onAvatarChanged(user1); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - } - - void testProviderUpdateAfterAvatarDisappearedTriggersChange() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - testling->addProvider(avatarProvider1); - avatarProvider1->avatars[user1] = avatarHash1; - avatarProvider1->onAvatarChanged(user1); - avatarProvider1->avatars.clear(); - avatarProvider1->onAvatarChanged(user1); - changes.clear(); - avatarProvider1->avatars[user1] = avatarHash1; - avatarProvider1->onAvatarChanged(user1); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - } - - - void testProviderUpdateAfterGetDoesNotTriggerChange() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - testling->addProvider(avatarProvider1); - avatarProvider1->avatars[user1] = avatarHash1; - - testling->getAvatarHash(user1); - avatarProvider1->onAvatarChanged(user1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); - } - - void testRemoveProviderDisconnectsUpdates() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - testling->addProvider(avatarProvider1); - testling->addProvider(avatarProvider2); - testling->removeProvider(avatarProvider1); - avatarProvider1->avatars[user1] = avatarHash1; - avatarProvider2->avatars[user1] = avatarHash2; - avatarProvider1->onAvatarChanged(user1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); - } - - void testProviderUpdateBareJIDAfterGetFullJID() { - boost::shared_ptr<CombinedAvatarProvider> testling(createProvider()); - avatarProvider1->useBare = true; - testling->addProvider(avatarProvider1); - - avatarProvider1->avatars[user1.toBare()] = avatarHash1; - testling->getAvatarHash(user1); - avatarProvider1->avatars[user1.toBare()] = avatarHash2; - avatarProvider1->onAvatarChanged(user1.toBare()); - - CPPUNIT_ASSERT_EQUAL(avatarHash2, testling->getAvatarHash(user1)); - } - - private: - boost::shared_ptr<CombinedAvatarProvider> createProvider() { - boost::shared_ptr<CombinedAvatarProvider> result(new CombinedAvatarProvider()); - result->onAvatarChanged.connect(boost::bind(&CombinedAvatarProviderTest::handleAvatarChanged, this, _1)); - return result; - } - - void handleAvatarChanged(const JID& jid) { - changes.push_back(jid); - } - - private: - struct DummyAvatarProvider : public AvatarProvider { - DummyAvatarProvider() : useBare(false) { - } - - std::string getAvatarHash(const JID& jid) const { - JID actualJID = useBare ? jid.toBare() : jid; - std::map<JID, std::string>::const_iterator i = avatars.find(actualJID); - if (i != avatars.end()) { - return i->second; - } - else { - return std::string(); - } - } - - bool useBare; - std::map<JID, std::string> avatars; - }; - - DummyAvatarProvider* avatarProvider1; - DummyAvatarProvider* avatarProvider2; - JID user1; - JID user2; - std::string avatarHash1; - std::string avatarHash2; - std::string avatarHash3; - std::vector<JID> changes; + CPPUNIT_TEST_SUITE(CombinedAvatarProviderTest); + CPPUNIT_TEST(testGetAvatarWithNoAvatarProviderReturnsEmpty); + CPPUNIT_TEST(testGetAvatarWithSingleAvatarProvider); + CPPUNIT_TEST(testGetAvatarWithMultipleAvatarProviderReturnsFirstAvatar); + CPPUNIT_TEST(testGetAvatarWithMultipleAvatarProviderAndFailingFirstProviderReturnsSecondAvatar); + CPPUNIT_TEST(testProviderUpdateTriggersChange); + CPPUNIT_TEST(testProviderUpdateWithoutChangeDoesNotTriggerChange); + CPPUNIT_TEST(testProviderSecondUpdateTriggersChange); + CPPUNIT_TEST(testProviderUpdateWithAvatarDisappearingTriggersChange); + CPPUNIT_TEST(testProviderUpdateAfterAvatarDisappearedTriggersChange); + CPPUNIT_TEST(testProviderUpdateAfterGetDoesNotTriggerChange); + CPPUNIT_TEST(testProviderUpdateBareJIDAfterGetFullJID); + CPPUNIT_TEST(testRemoveProviderDisconnectsUpdates); + CPPUNIT_TEST(testAddRemoveFallthrough); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + avatarProvider1 = std::make_unique<DummyAvatarProvider>(); + avatarProvider2 = std::make_unique<DummyAvatarProvider>(); + user1 = JID("user1@bar.com/bla"); + user2 = JID("user2@foo.com/baz"); + avatarHash1 = "ABCDEFG"; + avatarHash2 = "XYZU"; + avatarHash3 = "IDGH"; + } + + void testGetAvatarWithNoAvatarProviderReturnsEmpty() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + + boost::optional<std::string> hash = testling->getAvatarHash(user1); + CPPUNIT_ASSERT(!hash); + } + + void testGetAvatarWithSingleAvatarProvider() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + avatarProvider1->avatars[user1] = avatarHash1; + testling->addProvider(avatarProvider1.get()); + + boost::optional<std::string> hash = testling->getAvatarHash(user1); + CPPUNIT_ASSERT(hash); + CPPUNIT_ASSERT_EQUAL(avatarHash1, *hash); + } + + void testGetAvatarWithMultipleAvatarProviderReturnsFirstAvatar() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + avatarProvider1->avatars[user1] = avatarHash1; + avatarProvider2->avatars[user1] = avatarHash2; + testling->addProvider(avatarProvider1.get()); + testling->addProvider(avatarProvider2.get()); + + boost::optional<std::string> hash = testling->getAvatarHash(user1); + CPPUNIT_ASSERT(hash); + CPPUNIT_ASSERT_EQUAL(avatarHash1, *hash); + } + + void testGetAvatarWithMultipleAvatarProviderAndFailingFirstProviderReturnsSecondAvatar() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + avatarProvider2->avatars[user1] = avatarHash2; + testling->addProvider(avatarProvider1.get()); + testling->addProvider(avatarProvider2.get()); + + boost::optional<std::string> hash = testling->getAvatarHash(user1); + CPPUNIT_ASSERT(hash); + CPPUNIT_ASSERT_EQUAL(avatarHash2, *hash); + } + + void testProviderUpdateTriggersChange() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + testling->addProvider(avatarProvider1.get()); + avatarProvider1->avatars[user1] = avatarHash1; + avatarProvider1->onAvatarChanged(user1); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + } + + void testProviderUpdateWithoutChangeDoesNotTriggerChange() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + testling->addProvider(avatarProvider1.get()); + testling->addProvider(avatarProvider2.get()); + avatarProvider1->avatars[user1] = avatarHash1; + avatarProvider1->onAvatarChanged(user1); + changes.clear(); + + avatarProvider2->avatars[user1] = avatarHash2; + avatarProvider2->onAvatarChanged(user1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testProviderSecondUpdateTriggersChange() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + testling->addProvider(avatarProvider1.get()); + avatarProvider1->avatars[user1] = avatarHash1; + avatarProvider1->onAvatarChanged(user1); + changes.clear(); + avatarProvider1->avatars[user1] = avatarHash2; + avatarProvider1->onAvatarChanged(user1); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + } + + + void testProviderUpdateWithAvatarDisappearingTriggersChange() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + testling->addProvider(avatarProvider1.get()); + avatarProvider1->avatars[user1] = avatarHash1; + avatarProvider1->onAvatarChanged(user1); + changes.clear(); + avatarProvider1->avatars.clear(); + avatarProvider1->onAvatarChanged(user1); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + } + + void testProviderUpdateAfterAvatarDisappearedTriggersChange() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + testling->addProvider(avatarProvider1.get()); + avatarProvider1->avatars[user1] = avatarHash1; + avatarProvider1->onAvatarChanged(user1); + avatarProvider1->avatars.clear(); + avatarProvider1->onAvatarChanged(user1); + changes.clear(); + avatarProvider1->avatars[user1] = avatarHash1; + avatarProvider1->onAvatarChanged(user1); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + } + + + void testProviderUpdateAfterGetDoesNotTriggerChange() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + testling->addProvider(avatarProvider1.get()); + avatarProvider1->avatars[user1] = avatarHash1; + + testling->getAvatarHash(user1); + avatarProvider1->onAvatarChanged(user1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testRemoveProviderDisconnectsUpdates() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + testling->addProvider(avatarProvider1.get()); + testling->addProvider(avatarProvider2.get()); + testling->removeProvider(avatarProvider1.get()); + avatarProvider1->avatars[user1] = avatarHash1; + avatarProvider2->avatars[user1] = avatarHash2; + avatarProvider1->onAvatarChanged(user1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testProviderUpdateBareJIDAfterGetFullJID() { + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + avatarProvider1->useBare = true; + testling->addProvider(avatarProvider1.get()); + + avatarProvider1->avatars[user1.toBare()] = avatarHash1; + testling->getAvatarHash(user1); + avatarProvider1->avatars[user1.toBare()] = avatarHash2; + avatarProvider1->onAvatarChanged(user1.toBare()); + + boost::optional<std::string> hash = testling->getAvatarHash(user1); + CPPUNIT_ASSERT(hash); + CPPUNIT_ASSERT_EQUAL(avatarHash2, *hash); + } + + void testAddRemoveFallthrough() { + JID ownJID = JID("user0@own.com/res"); + JID user1 = JID("user1@bar.com/bla"); + + std::shared_ptr<CryptoProvider> crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + DummyStanzaChannel* stanzaChannel = new DummyStanzaChannel(); + stanzaChannel->setAvailable(true); + IQRouter* iqRouter = new IQRouter(stanzaChannel); + DummyMUCRegistry* mucRegistry = new DummyMUCRegistry(); + AvatarMemoryStorage* avatarStorage = new AvatarMemoryStorage(); + VCardMemoryStorage* vcardStorage = new VCardMemoryStorage(crypto.get()); + VCardManager* vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage); + + std::shared_ptr<VCardUpdateAvatarManager> updateManager(new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto.get(), mucRegistry)); + updateManager->onAvatarChanged.connect(boost::bind(&CombinedAvatarProviderTest::handleAvatarChanged, this, _1)); + + std::shared_ptr<VCardAvatarManager> manager(new VCardAvatarManager(vcardManager, avatarStorage, crypto.get(), mucRegistry)); + manager->onAvatarChanged.connect(boost::bind(&CombinedAvatarProviderTest::handleAvatarChanged, this, _1)); + + std::shared_ptr<OfflineAvatarManager> offlineManager(new OfflineAvatarManager(avatarStorage)); + offlineManager->onAvatarChanged.connect(boost::bind(&CombinedAvatarProviderTest::handleAvatarChanged, this, _1)); + + std::shared_ptr<CombinedAvatarProvider> testling(createProvider()); + avatarProvider1->useBare = true; + testling->addProvider(updateManager.get()); + testling->addProvider(manager.get()); + testling->addProvider(offlineManager.get()); + + /* place an avatar in the cache, check that it reads back OK */ + + CPPUNIT_ASSERT_EQUAL(size_t(0), changes.size()); + + ByteArray avatar1 = createByteArray("abcdefg"); + std::string avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1)); + VCard::ref vcard1(new VCard()); + vcard1->setPhoto(avatar1); + + vcardStorage->setVCard(user1.toBare(), vcard1); + boost::optional<std::string> testHash = testling->getAvatarHash(user1.toBare()); + CPPUNIT_ASSERT(testHash); + CPPUNIT_ASSERT_EQUAL(avatar1Hash, *testHash); + + VCard::ref storedVCard = vcardStorage->getVCard(user1.toBare()); + CPPUNIT_ASSERT(!!storedVCard); + testHash = Hexify::hexify(crypto->getSHA1Hash(storedVCard->getPhoto())); + CPPUNIT_ASSERT_EQUAL(avatar1Hash, *testHash); + + /* change the avatar by sending an VCard IQ */ + + vcardManager->requestVCard(user1.toBare()); + CPPUNIT_ASSERT_EQUAL(size_t(1), stanzaChannel->sentStanzas.size()); + IQ::ref request = std::dynamic_pointer_cast<IQ>(stanzaChannel->sentStanzas.back()); + VCard::ref payload = request->getPayload<VCard>(); + CPPUNIT_ASSERT(!!payload); + stanzaChannel->sentStanzas.pop_back(); + + ByteArray avatar2 = createByteArray("1234567"); + std::string avatar2Hash = Hexify::hexify(crypto->getSHA1Hash(avatar2)); + VCard::ref vcard2(new VCard()); + vcard2->setPhoto(avatar2); + + IQ::ref reply = std::make_shared<IQ>(); + reply->setTo(request->getFrom()); + reply->setFrom(request->getTo()); + reply->setID(request->getID()); + reply->addPayload(vcard2); + reply->setType(IQ::Result); + + stanzaChannel->onIQReceived(reply); + + /* check that we changed the avatar successfully and that we were notified about the changes */ + + testHash = testling->getAvatarHash(user1.toBare()); + CPPUNIT_ASSERT(testHash); + CPPUNIT_ASSERT_EQUAL(avatar2Hash, *testHash); + CPPUNIT_ASSERT_EQUAL(size_t(3), changes.size()); + CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[0]); + CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[1]); + CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[2]); + changes.clear(); + storedVCard = vcardStorage->getVCard(user1.toBare()); + CPPUNIT_ASSERT(!!storedVCard); + testHash = Hexify::hexify(crypto->getSHA1Hash(storedVCard->getPhoto())); + CPPUNIT_ASSERT_EQUAL(avatar2Hash, *testHash); + + /* change the avatar to the empty avatar */ + + vcardManager->requestVCard(user1.toBare()); + CPPUNIT_ASSERT_EQUAL(size_t(1), stanzaChannel->sentStanzas.size()); + request = std::dynamic_pointer_cast<IQ>(stanzaChannel->sentStanzas.back()); + payload = request->getPayload<VCard>(); + CPPUNIT_ASSERT(!!payload); + stanzaChannel->sentStanzas.pop_back(); + + VCard::ref vcard3(new VCard()); + reply = std::make_shared<IQ>(); + reply->setTo(request->getFrom()); + reply->setFrom(request->getTo()); + reply->setID(request->getID()); + reply->addPayload(vcard3); + reply->setType(IQ::Result); + stanzaChannel->onIQReceived(reply); + + /* check that we changed the avatar successfully */ + + testHash = testling->getAvatarHash(user1.toBare()); + CPPUNIT_ASSERT(testHash); + CPPUNIT_ASSERT_EQUAL(std::string(""), *testHash); + CPPUNIT_ASSERT_EQUAL(size_t(3), changes.size()); + CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[0]); + CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[1]); + CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[2]); + changes.clear(); + storedVCard = vcardStorage->getVCard(user1.toBare()); + CPPUNIT_ASSERT(!!storedVCard); + CPPUNIT_ASSERT(!storedVCard->getPhoto().size()); + + delete vcardManager; + delete vcardStorage; + delete mucRegistry; + delete iqRouter; + delete stanzaChannel; + } + + private: + std::shared_ptr<CombinedAvatarProvider> createProvider() { + std::shared_ptr<CombinedAvatarProvider> result(new CombinedAvatarProvider()); + result->onAvatarChanged.connect(boost::bind(&CombinedAvatarProviderTest::handleAvatarChanged, this, _1)); + return result; + } + + void handleAvatarChanged(const JID& jid) { + changes.push_back(jid); + } + + private: + struct DummyAvatarProvider : public AvatarProvider { + DummyAvatarProvider() : useBare(false) { + } + + boost::optional<std::string> getAvatarHash(const JID& jid) const { + JID actualJID = useBare ? jid.toBare() : jid; + std::map<JID, std::string>::const_iterator i = avatars.find(actualJID); + if (i != avatars.end()) { + return i->second; + } + else { + return boost::optional<std::string>(); + } + } + + bool useBare; + std::map<JID, std::string> avatars; + }; + + struct DummyMUCRegistry : public MUCRegistry { + bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); } + std::vector<JID> mucs_; + }; + + std::unique_ptr<DummyAvatarProvider> avatarProvider1; + std::unique_ptr<DummyAvatarProvider> avatarProvider2; + JID user1; + JID user2; + std::string avatarHash1; + std::string avatarHash2; + std::string avatarHash3; + std::vector<JID> changes; }; CPPUNIT_TEST_SUITE_REGISTRATION(CombinedAvatarProviderTest); diff --git a/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp b/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp index 97edc73..2ca9c1a 100644 --- a/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp +++ b/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp @@ -1,170 +1,176 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> +#include <boost/bind.hpp> + #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> -#include <Swiften/Elements/VCard.h> -#include <Swiften/Avatars/VCardAvatarManager.h> -#include <Swiften/VCards/VCardMemoryStorage.h> #include <Swiften/Avatars/AvatarMemoryStorage.h> -#include <Swiften/VCards/VCardManager.h> -#include <Swiften/MUC/MUCRegistry.h> -#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Avatars/VCardAvatarManager.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Elements/VCard.h> +#include <Swiften/MUC/MUCRegistry.h> +#include <Swiften/Queries/IQRouter.h> #include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/VCards/VCardManager.h> +#include <Swiften/VCards/VCardMemoryStorage.h> using namespace Swift; class VCardAvatarManagerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(VCardAvatarManagerTest); - CPPUNIT_TEST(testGetAvatarHashKnownAvatar); - CPPUNIT_TEST(testGetAvatarHashEmptyAvatar); - CPPUNIT_TEST(testGetAvatarHashUnknownAvatarKnownVCardStoresAvatar); - CPPUNIT_TEST(testGetAvatarHashUnknownAvatarUnknownVCard); - CPPUNIT_TEST(testVCardUpdateTriggersUpdate); - CPPUNIT_TEST(testGetAvatarHashKnownAvatarUnknownVCard); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - ownJID = JID("foo@fum.com/bum"); - stanzaChannel = new DummyStanzaChannel(); - stanzaChannel->setAvailable(true); - iqRouter = new IQRouter(stanzaChannel); - mucRegistry = new DummyMUCRegistry(); - avatarStorage = new AvatarMemoryStorage(); - vcardStorage = new VCardMemoryStorage(crypto.get()); - vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage); - avatar1 = createByteArray("abcdefg"); - avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1)); - user1 = JID("user1@bar.com/bla"); - user2 = JID("user2@foo.com/baz"); - } - - void tearDown() { - delete vcardManager; - delete vcardStorage; - delete avatarStorage; - delete mucRegistry; - delete iqRouter; - delete stanzaChannel; - } - - void testGetAvatarHashKnownAvatar() { - boost::shared_ptr<VCardAvatarManager> testling = createManager(); - storeVCardWithPhoto(user1.toBare(), avatar1); - avatarStorage->addAvatar(avatar1Hash, avatar1); - - std::string result = testling->getAvatarHash(user1); - - CPPUNIT_ASSERT_EQUAL(avatar1Hash, result); - } - - void testGetAvatarHashEmptyAvatar() { - boost::shared_ptr<VCardAvatarManager> testling = createManager(); - storeEmptyVCard(user1.toBare()); - - std::string result = testling->getAvatarHash(user1); - - CPPUNIT_ASSERT_EQUAL(std::string(), result); - } - - void testGetAvatarHashUnknownAvatarKnownVCardStoresAvatar() { - boost::shared_ptr<VCardAvatarManager> testling = createManager(); - storeVCardWithPhoto(user1.toBare(), avatar1); - - std::string result = testling->getAvatarHash(user1); - - CPPUNIT_ASSERT_EQUAL(avatar1Hash, result); - CPPUNIT_ASSERT(avatarStorage->hasAvatar(avatar1Hash)); - CPPUNIT_ASSERT_EQUAL(avatar1, avatarStorage->getAvatar(avatar1Hash)); - } - - void testGetAvatarHashUnknownAvatarUnknownVCard() { - boost::shared_ptr<VCardAvatarManager> testling = createManager(); - - std::string result = testling->getAvatarHash(user1); - - CPPUNIT_ASSERT_EQUAL(std::string(), result); - } - - void testGetAvatarHashKnownAvatarUnknownVCard() { - boost::shared_ptr<VCardAvatarManager> testling = createManager(); - - avatarStorage->setAvatarForJID(user1, avatar1Hash); - - std::string result = testling->getAvatarHash(user1); - - CPPUNIT_ASSERT_EQUAL(std::string(), result); - } - - - void testVCardUpdateTriggersUpdate() { - boost::shared_ptr<VCardAvatarManager> testling = createManager(); - vcardManager->requestVCard(user1); - sendVCardResult(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - } - - private: - boost::shared_ptr<VCardAvatarManager> createManager() { - boost::shared_ptr<VCardAvatarManager> result(new VCardAvatarManager(vcardManager, avatarStorage, crypto.get(), mucRegistry)); - result->onAvatarChanged.connect(boost::bind(&VCardAvatarManagerTest::handleAvatarChanged, this, _1)); - return result; - } - - void storeVCardWithPhoto(const JID& jid, const ByteArray& avatar) { - VCard::ref vcard(new VCard()); - vcard->setPhoto(avatar); - vcardStorage->setVCard(jid, vcard); - } - - void storeEmptyVCard(const JID& jid) { - VCard::ref vcard(new VCard()); - vcardStorage->setVCard(jid, vcard); - } - - void handleAvatarChanged(const JID& jid) { - changes.push_back(jid); - } - - void sendVCardResult() { - VCard::ref vcard(new VCard()); - vcard->setFullName("Foo Bar"); - stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard)); - } - - private: - struct DummyMUCRegistry : public MUCRegistry { - bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); } - std::vector<JID> mucs_; - }; - - JID ownJID; - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - DummyMUCRegistry* mucRegistry; - AvatarMemoryStorage* avatarStorage; - VCardManager* vcardManager; - VCardMemoryStorage* vcardStorage; - ByteArray avatar1; - std::string avatar1Hash; - std::vector<JID> changes; - JID user1; - JID user2; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(VCardAvatarManagerTest); + CPPUNIT_TEST(testGetAvatarHashKnownAvatar); + CPPUNIT_TEST(testGetAvatarHashEmptyAvatar); + CPPUNIT_TEST(testGetAvatarHashUnknownAvatarKnownVCardStoresAvatar); + CPPUNIT_TEST(testGetAvatarHashUnknownAvatarUnknownVCard); + CPPUNIT_TEST(testVCardUpdateTriggersUpdate); + CPPUNIT_TEST(testGetAvatarHashKnownAvatarUnknownVCard); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + ownJID = JID("foo@fum.com/bum"); + stanzaChannel = new DummyStanzaChannel(); + stanzaChannel->setAvailable(true); + iqRouter = new IQRouter(stanzaChannel); + mucRegistry = new DummyMUCRegistry(); + avatarStorage = new AvatarMemoryStorage(); + vcardStorage = new VCardMemoryStorage(crypto.get()); + vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage); + avatar1 = createByteArray("abcdefg"); + avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1)); + user1 = JID("user1@bar.com/bla"); + user2 = JID("user2@foo.com/baz"); + } + + void tearDown() { + delete vcardManager; + delete vcardStorage; + delete avatarStorage; + delete mucRegistry; + delete iqRouter; + delete stanzaChannel; + } + + void testGetAvatarHashKnownAvatar() { + std::shared_ptr<VCardAvatarManager> testling = createManager(); + storeVCardWithPhoto(user1.toBare(), avatar1); + avatarStorage->addAvatar(avatar1Hash, avatar1); + + boost::optional<std::string> result = testling->getAvatarHash(user1); + + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(avatar1Hash, *result); + } + + void testGetAvatarHashEmptyAvatar() { + std::shared_ptr<VCardAvatarManager> testling = createManager(); + storeEmptyVCard(user1.toBare()); + + boost::optional<std::string> result = testling->getAvatarHash(user1); + + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(std::string(), *result); + } + + void testGetAvatarHashUnknownAvatarKnownVCardStoresAvatar() { + std::shared_ptr<VCardAvatarManager> testling = createManager(); + storeVCardWithPhoto(user1.toBare(), avatar1); + + boost::optional<std::string> result = testling->getAvatarHash(user1); + + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(avatar1Hash, *result); + CPPUNIT_ASSERT(avatarStorage->hasAvatar(avatar1Hash)); + CPPUNIT_ASSERT_EQUAL(avatar1, avatarStorage->getAvatar(avatar1Hash)); + } + + void testGetAvatarHashUnknownAvatarUnknownVCard() { + std::shared_ptr<VCardAvatarManager> testling = createManager(); + + boost::optional<std::string> result = testling->getAvatarHash(user1); + + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(std::string(), *result); + } + + void testGetAvatarHashKnownAvatarUnknownVCard() { + std::shared_ptr<VCardAvatarManager> testling = createManager(); + + avatarStorage->setAvatarForJID(user1, avatar1Hash); + + boost::optional<std::string> result = testling->getAvatarHash(user1); + + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(std::string(), *result); + } + + + void testVCardUpdateTriggersUpdate() { + std::shared_ptr<VCardAvatarManager> testling = createManager(); + vcardManager->requestVCard(user1); + sendVCardResult(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + } + + private: + std::shared_ptr<VCardAvatarManager> createManager() { + std::shared_ptr<VCardAvatarManager> result(new VCardAvatarManager(vcardManager, avatarStorage, crypto.get(), mucRegistry)); + result->onAvatarChanged.connect(boost::bind(&VCardAvatarManagerTest::handleAvatarChanged, this, _1)); + return result; + } + + void storeVCardWithPhoto(const JID& jid, const ByteArray& avatar) { + VCard::ref vcard(new VCard()); + vcard->setPhoto(avatar); + vcardStorage->setVCard(jid, vcard); + } + + void storeEmptyVCard(const JID& jid) { + VCard::ref vcard(new VCard()); + vcardStorage->setVCard(jid, vcard); + } + + void handleAvatarChanged(const JID& jid) { + changes.push_back(jid); + } + + void sendVCardResult() { + VCard::ref vcard(new VCard()); + vcard->setFullName("Foo Bar"); + stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard)); + } + + private: + struct DummyMUCRegistry : public MUCRegistry { + bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); } + std::vector<JID> mucs_; + }; + + JID ownJID; + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + DummyMUCRegistry* mucRegistry; + AvatarMemoryStorage* avatarStorage; + VCardManager* vcardManager; + VCardMemoryStorage* vcardStorage; + ByteArray avatar1; + std::string avatar1Hash; + std::vector<JID> changes; + JID user1; + JID user2; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardAvatarManagerTest); diff --git a/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp b/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp index 01b10a2..bfa13cd 100644 --- a/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp +++ b/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp @@ -1,201 +1,212 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> +#include <boost/bind.hpp> + #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> -#include <Swiften/Elements/VCardUpdate.h> -#include <Swiften/Avatars/VCardUpdateAvatarManager.h> #include <Swiften/Avatars/AvatarMemoryStorage.h> -#include <Swiften/VCards/VCardMemoryStorage.h> -#include <Swiften/VCards/VCardManager.h> -#include <Swiften/MUC/MUCRegistry.h> -#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Avatars/VCardUpdateAvatarManager.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Client/DummyStanzaChannel.h> -#include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Elements/VCardUpdate.h> +#include <Swiften/MUC/MUCRegistry.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/VCards/VCardManager.h> +#include <Swiften/VCards/VCardMemoryStorage.h> using namespace Swift; class VCardUpdateAvatarManagerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(VCardUpdateAvatarManagerTest); - CPPUNIT_TEST(testUpdate_NewHashNewVCardRequestsVCard); - CPPUNIT_TEST(testUpdate_NewHashStoresAvatarAndEmitsNotificationOnVCardReceive); - CPPUNIT_TEST(testUpdate_KnownHash); - CPPUNIT_TEST(testUpdate_KnownHashFromDifferentUserDoesNotRequestVCardButTriggersNotification); - CPPUNIT_TEST(testVCardWithEmptyPhoto); - CPPUNIT_TEST(testStanzaChannelReset_ClearsHash); - CPPUNIT_TEST(testStanzaChannelReset_ReceiveHashAfterResetUpdatesHash); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - ownJID = JID("foo@fum.com/bum"); - stanzaChannel = new DummyStanzaChannel(); - stanzaChannel->setAvailable(true); - iqRouter = new IQRouter(stanzaChannel); - mucRegistry = new DummyMUCRegistry(); - avatarStorage = new AvatarMemoryStorage(); - vcardStorage = new VCardMemoryStorage(crypto.get()); - vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage); - avatar1 = createByteArray("abcdefg"); - avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1)); - user1 = JID("user1@bar.com/bla"); - user2 = JID("user2@foo.com/baz"); - } - - - void tearDown() { - delete vcardManager; - delete vcardStorage; - delete avatarStorage; - delete mucRegistry; - delete iqRouter; - delete stanzaChannel; - } - - void testUpdate_NewHashNewVCardRequestsVCard() { - boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); - stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, user1.toBare(), IQ::Get)); - } - - void testUpdate_NewHashStoresAvatarAndEmitsNotificationOnVCardReceive() { - boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); - stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); - stanzaChannel->onIQReceived(createVCardResult(avatar1)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[0]); - CPPUNIT_ASSERT_EQUAL(avatar1Hash, testling->getAvatarHash(user1.toBare())); - CPPUNIT_ASSERT(avatarStorage->hasAvatar(avatar1Hash)); - CPPUNIT_ASSERT_EQUAL(avatar1, avatarStorage->getAvatar(avatar1Hash)); - } - - void testUpdate_KnownHash() { - boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); - stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); - stanzaChannel->onIQReceived(createVCardResult(avatar1)); - changes.clear(); - stanzaChannel->sentStanzas.clear(); - - stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); - } - - void testUpdate_KnownHashFromDifferentUserDoesNotRequestVCardButTriggersNotification() { - boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); - stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); - stanzaChannel->onIQReceived(createVCardResult(avatar1)); - changes.clear(); - stanzaChannel->sentStanzas.clear(); - - stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user2, avatar1Hash)); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user2.toBare(), changes[0]); - CPPUNIT_ASSERT_EQUAL(avatar1Hash, testling->getAvatarHash(user2.toBare())); - } - - void testVCardWithEmptyPhoto() { - boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); - vcardManager->requestVCard(JID("foo@bar.com")); - stanzaChannel->onIQReceived(createVCardResult(ByteArray())); - - CPPUNIT_ASSERT(!avatarStorage->hasAvatar(Hexify::hexify(crypto->getSHA1Hash(ByteArray())))); - CPPUNIT_ASSERT_EQUAL(std::string(), testling->getAvatarHash(JID("foo@bar.com"))); - } - - void testStanzaChannelReset_ClearsHash() { - boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); - stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); - stanzaChannel->onIQReceived(createVCardResult(avatar1)); - changes.clear(); - stanzaChannel->sentStanzas.clear(); - - stanzaChannel->setAvailable(false); - stanzaChannel->setAvailable(true); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[0]); - CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getAvatarHash(user1.toBare())); - } - - void testStanzaChannelReset_ReceiveHashAfterResetUpdatesHash() { - boost::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); - stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); - stanzaChannel->onIQReceived(createVCardResult(avatar1)); - changes.clear(); - stanzaChannel->sentStanzas.clear(); - - stanzaChannel->setAvailable(false); - stanzaChannel->setAvailable(true); - stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[1]); - CPPUNIT_ASSERT_EQUAL(avatar1Hash, testling->getAvatarHash(user1.toBare())); - } - - private: - boost::shared_ptr<VCardUpdateAvatarManager> createManager() { - boost::shared_ptr<VCardUpdateAvatarManager> result(new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto.get(), mucRegistry)); - result->onAvatarChanged.connect(boost::bind(&VCardUpdateAvatarManagerTest::handleAvatarChanged, this, _1)); - return result; - } - - boost::shared_ptr<Presence> createPresenceWithPhotoHash(const JID& jid, const std::string& hash) { - boost::shared_ptr<Presence> presence(new Presence()); - presence->setFrom(jid); - presence->addPayload(boost::make_shared<VCardUpdate>(hash)); - return presence; - } - - IQ::ref createVCardResult(const ByteArray& avatar) { - VCard::ref vcard(new VCard()); - if (!avatar.empty()) { - vcard->setPhoto(avatar); - } - return IQ::createResult(JID("baz@fum.com"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard); - } - - void handleAvatarChanged(const JID& jid) { - changes.push_back(jid); - } - - private: - struct DummyMUCRegistry : public MUCRegistry { - bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); } - std::vector<JID> mucs_; - }; - - JID ownJID; - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - DummyMUCRegistry* mucRegistry; - AvatarMemoryStorage* avatarStorage; - VCardManager* vcardManager; - VCardMemoryStorage* vcardStorage; - ByteArray avatar1; - std::string avatar1Hash; - std::vector<JID> changes; - JID user1; - JID user2; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(VCardUpdateAvatarManagerTest); + CPPUNIT_TEST(testUpdate_NewHashNewVCardRequestsVCard); + CPPUNIT_TEST(testUpdate_NewHashStoresAvatarAndEmitsNotificationOnVCardReceive); + CPPUNIT_TEST(testUpdate_KnownHash); + CPPUNIT_TEST(testUpdate_KnownHashFromDifferentUserDoesNotRequestVCardButTriggersNotification); + CPPUNIT_TEST(testVCardWithEmptyPhoto); + CPPUNIT_TEST(testStanzaChannelReset_ClearsHash); + CPPUNIT_TEST(testStanzaChannelReset_ReceiveHashAfterResetUpdatesHash); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + ownJID = JID("foo@fum.com/bum"); + stanzaChannel = new DummyStanzaChannel(); + stanzaChannel->setAvailable(true); + iqRouter = new IQRouter(stanzaChannel); + mucRegistry = new DummyMUCRegistry(); + avatarStorage = new AvatarMemoryStorage(); + vcardStorage = new VCardMemoryStorage(crypto.get()); + vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage); + avatar1 = createByteArray("abcdefg"); + avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1)); + user1 = JID("user1@bar.com/bla"); + user2 = JID("user2@foo.com/baz"); + } + + + void tearDown() { + delete vcardManager; + delete vcardStorage; + delete avatarStorage; + delete mucRegistry; + delete iqRouter; + delete stanzaChannel; + } + + void testUpdate_NewHashNewVCardRequestsVCard() { + std::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); + stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, user1.toBare(), IQ::Get)); + } + + void testUpdate_NewHashStoresAvatarAndEmitsNotificationOnVCardReceive() { + std::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); + stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); + stanzaChannel->onIQReceived(createVCardResult(avatar1)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[0]); + boost::optional<std::string> hash = testling->getAvatarHash(user1.toBare()); + CPPUNIT_ASSERT(hash); + CPPUNIT_ASSERT_EQUAL(avatar1Hash, *hash); + CPPUNIT_ASSERT(avatarStorage->hasAvatar(avatar1Hash)); + CPPUNIT_ASSERT_EQUAL(avatar1, avatarStorage->getAvatar(avatar1Hash)); + } + + void testUpdate_KnownHash() { + std::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); + stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); + stanzaChannel->onIQReceived(createVCardResult(avatar1)); + changes.clear(); + stanzaChannel->sentStanzas.clear(); + + stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testUpdate_KnownHashFromDifferentUserDoesNotRequestVCardButTriggersNotification() { + std::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); + stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); + stanzaChannel->onIQReceived(createVCardResult(avatar1)); + changes.clear(); + stanzaChannel->sentStanzas.clear(); + + stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user2, avatar1Hash)); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user2.toBare(), changes[0]); + boost::optional<std::string> hash = testling->getAvatarHash(user2.toBare()); + CPPUNIT_ASSERT(hash); + CPPUNIT_ASSERT_EQUAL(avatar1Hash, *hash); + } + + void testVCardWithEmptyPhoto() { + std::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); + vcardManager->requestVCard(JID("foo@bar.com")); + stanzaChannel->onIQReceived(createVCardResult(ByteArray())); + + CPPUNIT_ASSERT(!avatarStorage->hasAvatar(Hexify::hexify(crypto->getSHA1Hash(ByteArray())))); + boost::optional<std::string> hash = testling->getAvatarHash(JID("foo@bar.com")); + CPPUNIT_ASSERT(hash); + CPPUNIT_ASSERT_EQUAL(std::string(), *hash); + } + + void testStanzaChannelReset_ClearsHash() { + std::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); + stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); + stanzaChannel->onIQReceived(createVCardResult(avatar1)); + changes.clear(); + stanzaChannel->sentStanzas.clear(); + + stanzaChannel->setAvailable(false); + stanzaChannel->setAvailable(true); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[0]); + boost::optional<std::string> hash = testling->getAvatarHash(user1.toBare()); + CPPUNIT_ASSERT(!hash); + //CPPUNIT_ASSERT_EQUAL(std::string(""), *hash); + } + + void testStanzaChannelReset_ReceiveHashAfterResetUpdatesHash() { + std::shared_ptr<VCardUpdateAvatarManager> testling = createManager(); + stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); + stanzaChannel->onIQReceived(createVCardResult(avatar1)); + changes.clear(); + stanzaChannel->sentStanzas.clear(); + + stanzaChannel->setAvailable(false); + stanzaChannel->setAvailable(true); + stanzaChannel->onPresenceReceived(createPresenceWithPhotoHash(user1, avatar1Hash)); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1.toBare(), changes[1]); + boost::optional<std::string> hash = testling->getAvatarHash(user1.toBare()); + CPPUNIT_ASSERT(hash); + CPPUNIT_ASSERT_EQUAL(avatar1Hash, *hash); + } + + private: + std::shared_ptr<VCardUpdateAvatarManager> createManager() { + std::shared_ptr<VCardUpdateAvatarManager> result(new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto.get(), mucRegistry)); + result->onAvatarChanged.connect(boost::bind(&VCardUpdateAvatarManagerTest::handleAvatarChanged, this, _1)); + return result; + } + + std::shared_ptr<Presence> createPresenceWithPhotoHash(const JID& jid, const std::string& hash) { + std::shared_ptr<Presence> presence(new Presence()); + presence->setFrom(jid); + presence->addPayload(std::make_shared<VCardUpdate>(hash)); + return presence; + } + + IQ::ref createVCardResult(const ByteArray& avatar) { + VCard::ref vcard(new VCard()); + if (!avatar.empty()) { + vcard->setPhoto(avatar); + } + return IQ::createResult(JID("baz@fum.com"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard); + } + + void handleAvatarChanged(const JID& jid) { + changes.push_back(jid); + } + + private: + struct DummyMUCRegistry : public MUCRegistry { + bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); } + std::vector<JID> mucs_; + }; + + JID ownJID; + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + DummyMUCRegistry* mucRegistry; + AvatarMemoryStorage* avatarStorage; + VCardManager* vcardManager; + VCardMemoryStorage* vcardStorage; + ByteArray avatar1; + std::string avatar1Hash; + std::vector<JID> changes; + JID user1; + JID user2; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardUpdateAvatarManagerTest); diff --git a/Swiften/Avatars/VCardAvatarManager.cpp b/Swiften/Avatars/VCardAvatarManager.cpp index 8212a6e..919d833 100644 --- a/Swiften/Avatars/VCardAvatarManager.cpp +++ b/Swiften/Avatars/VCardAvatarManager.cpp @@ -1,62 +1,62 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Avatars/VCardAvatarManager.h> #include <boost/bind.hpp> -#include <Swiften/Elements/VCard.h> -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Avatars/AvatarStorage.h> +#include <Swiften/Base/Log.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Elements/VCard.h> #include <Swiften/MUC/MUCRegistry.h> +#include <Swiften/StringCodecs/Hexify.h> #include <Swiften/VCards/VCardManager.h> -#include <Swiften/Base/Log.h> namespace Swift { VCardAvatarManager::VCardAvatarManager(VCardManager* vcardManager, AvatarStorage* avatarStorage, CryptoProvider* crypto, MUCRegistry* mucRegistry) : vcardManager_(vcardManager), avatarStorage_(avatarStorage), crypto_(crypto), mucRegistry_(mucRegistry) { - vcardManager_->onVCardChanged.connect(boost::bind(&VCardAvatarManager::handleVCardChanged, this, _1)); + vcardManager_->onVCardChanged.connect(boost::bind(&VCardAvatarManager::handleVCardChanged, this, _1)); } void VCardAvatarManager::handleVCardChanged(const JID& from) { - // We don't check whether the avatar actually changed. Direct use of this - // manager could cause unnecessary updates, but in practice, this will be - // caught by the wrapping CombinedAvatarManager anyway. - onAvatarChanged(from); + // We don't check whether the avatar actually changed. Direct use of this + // manager could cause unnecessary updates, but in practice, this will be + // caught by the wrapping CombinedAvatarManager anyway. + onAvatarChanged(from); } -std::string VCardAvatarManager::getAvatarHash(const JID& jid) const { - JID avatarJID = getAvatarJID(jid); - std::string hash = vcardManager_->getPhotoHash(avatarJID); - if (!hash.empty()) { - if (!avatarStorage_->hasAvatar(hash)) { - VCard::ref vCard = vcardManager_->getVCard(avatarJID); - if (vCard) { - std::string newHash = Hexify::hexify(crypto_->getSHA1Hash(vCard->getPhoto())); - if (newHash != hash) { - // Shouldn't happen, but sometimes seem to. Might be fixed if we - // move to a safer backend. - SWIFT_LOG(warning) << "Inconsistent vCard photo hash cache"; - hash = newHash; - } - avatarStorage_->addAvatar(hash, vCard->getPhoto()); - } - else { - // Can happen if the cache is inconsistent. - hash = ""; - } - } - } - return hash; +boost::optional<std::string> VCardAvatarManager::getAvatarHash(const JID& jid) const { + JID avatarJID = getAvatarJID(jid); + std::string hash = vcardManager_->getPhotoHash(avatarJID); + if (!hash.empty()) { + if (!avatarStorage_->hasAvatar(hash)) { + VCard::ref vCard = vcardManager_->getVCard(avatarJID); + if (vCard) { + std::string newHash = Hexify::hexify(crypto_->getSHA1Hash(vCard->getPhoto())); + if (newHash != hash) { + // Shouldn't happen, but sometimes seem to. Might be fixed if we + // move to a safer backend. + SWIFT_LOG(warning) << "Inconsistent vCard photo hash cache"; + hash = newHash; + } + avatarStorage_->addAvatar(hash, vCard->getPhoto()); + } + else { + // Can happen if the cache is inconsistent. + hash = ""; + } + } + } + return hash; } JID VCardAvatarManager::getAvatarJID(const JID& jid) const { - JID bareFrom = jid.toBare(); - return (mucRegistry_ && mucRegistry_->isMUC(bareFrom)) ? jid : bareFrom; + JID bareFrom = jid.toBare(); + return (mucRegistry_ && mucRegistry_->isMUC(bareFrom)) ? jid : bareFrom; } } diff --git a/Swiften/Avatars/VCardAvatarManager.h b/Swiften/Avatars/VCardAvatarManager.h index 9c6943e..70df6a8 100644 --- a/Swiften/Avatars/VCardAvatarManager.h +++ b/Swiften/Avatars/VCardAvatarManager.h @@ -1,35 +1,35 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> #include <Swiften/Avatars/AvatarProvider.h> +#include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> namespace Swift { - class MUCRegistry; - class AvatarStorage; - class VCardManager; - class CryptoProvider; + class MUCRegistry; + class AvatarStorage; + class VCardManager; + class CryptoProvider; - class SWIFTEN_API VCardAvatarManager : public AvatarProvider { - public: - VCardAvatarManager(VCardManager*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL); + class SWIFTEN_API VCardAvatarManager : public AvatarProvider { + public: + VCardAvatarManager(VCardManager*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = nullptr); - std::string getAvatarHash(const JID&) const; + boost::optional<std::string> getAvatarHash(const JID&) const; - private: - void handleVCardChanged(const JID& from); - JID getAvatarJID(const JID& o) const; + private: + void handleVCardChanged(const JID& from); + JID getAvatarJID(const JID& o) const; - private: - VCardManager* vcardManager_; - AvatarStorage* avatarStorage_; - CryptoProvider* crypto_; - MUCRegistry* mucRegistry_; - }; + private: + VCardManager* vcardManager_; + AvatarStorage* avatarStorage_; + CryptoProvider* crypto_; + MUCRegistry* mucRegistry_; + }; } diff --git a/Swiften/Avatars/VCardUpdateAvatarManager.cpp b/Swiften/Avatars/VCardUpdateAvatarManager.cpp index adbefd5..d04c13c 100644 --- a/Swiften/Avatars/VCardUpdateAvatarManager.cpp +++ b/Swiften/Avatars/VCardUpdateAvatarManager.cpp @@ -1,104 +1,108 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Avatars/VCardUpdateAvatarManager.h> #include <boost/bind.hpp> +#include <Swiften/Avatars/AvatarStorage.h> +#include <Swiften/Base/Log.h> #include <Swiften/Client/StanzaChannel.h> -#include <Swiften/Elements/VCardUpdate.h> -#include <Swiften/VCards/GetVCardRequest.h> #include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/Avatars/AvatarStorage.h> +#include <Swiften/Elements/VCardUpdate.h> #include <Swiften/MUC/MUCRegistry.h> +#include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/VCards/GetVCardRequest.h> #include <Swiften/VCards/VCardManager.h> -#include <Swiften/Base/Log.h> namespace Swift { VCardUpdateAvatarManager::VCardUpdateAvatarManager(VCardManager* vcardManager, StanzaChannel* stanzaChannel, AvatarStorage* avatarStorage, CryptoProvider* crypto, MUCRegistry* mucRegistry) : vcardManager_(vcardManager), avatarStorage_(avatarStorage), crypto_(crypto), mucRegistry_(mucRegistry) { - stanzaChannel->onPresenceReceived.connect(boost::bind(&VCardUpdateAvatarManager::handlePresenceReceived, this, _1)); - stanzaChannel->onAvailableChanged.connect(boost::bind(&VCardUpdateAvatarManager::handleStanzaChannelAvailableChanged, this, _1)); - vcardManager_->onVCardChanged.connect(boost::bind(&VCardUpdateAvatarManager::handleVCardChanged, this, _1, _2)); + stanzaChannel->onPresenceReceived.connect(boost::bind(&VCardUpdateAvatarManager::handlePresenceReceived, this, _1)); + stanzaChannel->onAvailableChanged.connect(boost::bind(&VCardUpdateAvatarManager::handleStanzaChannelAvailableChanged, this, _1)); + vcardManager_->onVCardChanged.connect(boost::bind(&VCardUpdateAvatarManager::handleVCardChanged, this, _1, _2)); } -void VCardUpdateAvatarManager::handlePresenceReceived(boost::shared_ptr<Presence> presence) { - boost::shared_ptr<VCardUpdate> update = presence->getPayload<VCardUpdate>(); - if (!update || presence->getPayload<ErrorPayload>()) { - return; - } - JID from = getAvatarJID(presence->getFrom()); - if (getAvatarHash(from) == update->getPhotoHash()) { - return; - } - SWIFT_LOG(debug) << "Updated hash: " << from << " -> " << update->getPhotoHash() << std::endl; - if (avatarStorage_->hasAvatar(update->getPhotoHash())) { - setAvatarHash(from, update->getPhotoHash()); - } - else { - vcardManager_->requestVCard(from); - } +void VCardUpdateAvatarManager::handlePresenceReceived(std::shared_ptr<Presence> presence) { + std::shared_ptr<VCardUpdate> update = presence->getPayload<VCardUpdate>(); + if (!update || presence->getPayload<ErrorPayload>()) { + return; + } + JID from = getAvatarJID(presence->getFrom()); + if (update->getPhotoHash().size() != 40) { + SWIFT_LOG(debug) << "Invalid vCard avatar photo hash length. Must be hex-encoded SHA-1, i.e. 40 characters."; + return; + } + if (getAvatarHash(from) == update->getPhotoHash()) { + return; + } + SWIFT_LOG(debug) << "Updated hash: " << from << " -> " << update->getPhotoHash(); + if (avatarStorage_->hasAvatar(update->getPhotoHash())) { + setAvatarHash(from, update->getPhotoHash()); + } + else { + vcardManager_->requestVCard(from); + } } void VCardUpdateAvatarManager::handleVCardChanged(const JID& from, VCard::ref vCard) { - if (!vCard) { - std::cerr << "Warning: " << from << ": null vcard payload" << std::endl; - return; - } + if (!vCard) { + SWIFT_LOG(debug) << "Missing element: " << from << ": null vcard payload"; + return; + } - if (vCard->getPhoto().empty()) { - setAvatarHash(from, ""); - } - else { - std::string hash = Hexify::hexify(crypto_->getSHA1Hash(vCard->getPhoto())); - if (!avatarStorage_->hasAvatar(hash)) { - avatarStorage_->addAvatar(hash, vCard->getPhoto()); - } - setAvatarHash(from, hash); - } + if (vCard->getPhoto().empty()) { + setAvatarHash(from, ""); + } + else { + std::string hash = Hexify::hexify(crypto_->getSHA1Hash(vCard->getPhoto())); + if (!avatarStorage_->hasAvatar(hash)) { + avatarStorage_->addAvatar(hash, vCard->getPhoto()); + } + setAvatarHash(from, hash); + } } void VCardUpdateAvatarManager::setAvatarHash(const JID& from, const std::string& hash) { - SWIFT_LOG(debug) << "Updating hash: " << from << " -> " << hash << std::endl; - avatarHashes_[from] = hash; - onAvatarChanged(from); + SWIFT_LOG(debug) << "Updating hash: " << from << " -> " << hash; + avatarHashes_[from] = hash; + onAvatarChanged(from); } /* void VCardUpdateAvatarManager::setAvatar(const JID& jid, const ByteArray& avatar) { - std::string hash = Hexify::hexify(SHA1::getHash(avatar)); - avatarStorage_->addAvatar(hash, avatar); - setAvatarHash(getAvatarJID(jid), hash); + std::string hash = Hexify::hexify(SHA1::getHash(avatar)); + avatarStorage_->addAvatar(hash, avatar); + setAvatarHash(getAvatarJID(jid), hash); } */ -std::string VCardUpdateAvatarManager::getAvatarHash(const JID& jid) const { - std::map<JID, std::string>::const_iterator i = avatarHashes_.find(getAvatarJID(jid)); - if (i != avatarHashes_.end()) { - return i->second; - } - else { - return ""; - } +boost::optional<std::string> VCardUpdateAvatarManager::getAvatarHash(const JID& jid) const { + std::map<JID, std::string>::const_iterator i = avatarHashes_.find(getAvatarJID(jid)); + if (i != avatarHashes_.end()) { + return i->second; + } + else { + return boost::optional<std::string>(); + } } JID VCardUpdateAvatarManager::getAvatarJID(const JID& jid) const { - JID bareFrom = jid.toBare(); - return (mucRegistry_ && mucRegistry_->isMUC(bareFrom)) ? jid : bareFrom; + JID bareFrom = jid.toBare(); + return (mucRegistry_ && mucRegistry_->isMUC(bareFrom)) ? jid : bareFrom; } void VCardUpdateAvatarManager::handleStanzaChannelAvailableChanged(bool available) { - if (available) { - std::map<JID, std::string> oldAvatarHashes; - avatarHashes_.swap(oldAvatarHashes); - for(std::map<JID, std::string>::const_iterator i = oldAvatarHashes.begin(); i != oldAvatarHashes.end(); ++i) { - onAvatarChanged(i->first); - } - } + if (available) { + std::map<JID, std::string> oldAvatarHashes; + avatarHashes_.swap(oldAvatarHashes); + for(std::map<JID, std::string>::const_iterator i = oldAvatarHashes.begin(); i != oldAvatarHashes.end(); ++i) { + onAvatarChanged(i->first); + } + } } diff --git a/Swiften/Avatars/VCardUpdateAvatarManager.h b/Swiften/Avatars/VCardUpdateAvatarManager.h index 3409f99..19ed672 100644 --- a/Swiften/Avatars/VCardUpdateAvatarManager.h +++ b/Swiften/Avatars/VCardUpdateAvatarManager.h @@ -1,46 +1,46 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> #include <map> +#include <memory> -#include <Swiften/Base/API.h> #include <Swiften/Avatars/AvatarProvider.h> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ErrorPayload.h> #include <Swiften/Elements/Presence.h> #include <Swiften/Elements/VCard.h> -#include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class MUCRegistry; - class AvatarStorage; - class StanzaChannel; - class VCardManager; - class CryptoProvider; - - class SWIFTEN_API VCardUpdateAvatarManager : public AvatarProvider, public boost::bsignals::trackable { - public: - VCardUpdateAvatarManager(VCardManager*, StanzaChannel*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL); - - std::string getAvatarHash(const JID&) const; - - private: - void handlePresenceReceived(boost::shared_ptr<Presence>); - void handleStanzaChannelAvailableChanged(bool); - void handleVCardChanged(const JID& from, VCard::ref); - void setAvatarHash(const JID& from, const std::string& hash); - JID getAvatarJID(const JID& o) const; - - private: - VCardManager* vcardManager_; - AvatarStorage* avatarStorage_; - CryptoProvider* crypto_; - MUCRegistry* mucRegistry_; - std::map<JID, std::string> avatarHashes_; - }; + class MUCRegistry; + class AvatarStorage; + class StanzaChannel; + class VCardManager; + class CryptoProvider; + + class SWIFTEN_API VCardUpdateAvatarManager : public AvatarProvider, public boost::signals2::trackable { + public: + VCardUpdateAvatarManager(VCardManager*, StanzaChannel*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = nullptr); + + boost::optional<std::string> getAvatarHash(const JID&) const; + + private: + void handlePresenceReceived(std::shared_ptr<Presence>); + void handleStanzaChannelAvailableChanged(bool); + void handleVCardChanged(const JID& from, VCard::ref); + void setAvatarHash(const JID& from, const std::string& hash); + JID getAvatarJID(const JID& o) const; + + private: + VCardManager* vcardManager_; + AvatarStorage* avatarStorage_; + CryptoProvider* crypto_; + MUCRegistry* mucRegistry_; + std::map<JID, std::string> avatarHashes_; + }; } diff --git a/Swiften/Base/API.h b/Swiften/Base/API.h index 388ad0a..06359ba 100644 --- a/Swiften/Base/API.h +++ b/Swiften/Base/API.h @@ -1,15 +1,16 @@ /* - * Copyright (c) 2012-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/Platform.h> +#include <boost/config.hpp> #ifdef SWIFTEN_STATIC -# define SWIFTEN_API +# define SWIFTEN_API #else # ifdef SWIFTEN_PLATFORM_WINDOWS # ifdef SWIFTEN_BUILDING @@ -20,6 +21,22 @@ # elif __GNUC__ >= 4 # define SWIFTEN_API __attribute__((visibility("default"))) # else -# define SWIFTEN_API +# define SWIFTEN_API # endif #endif + +#ifdef BOOST_NO_DEFAULTED_FUNCTIONS +# define SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(cls) +# define SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(cls) +#else +# define SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(cls) \ + cls(const cls&) = default; +# define SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(cls) \ + cls& operator=(const cls&) = default; +#endif + +#ifdef BOOST_NO_NOEXCEPT +#define SWIFTEN_NOEXCEPT throw() +#else +#define SWIFTEN_NOEXCEPT noexcept +#endif diff --git a/Swiften/Base/Algorithm.h b/Swiften/Base/Algorithm.h index d5edab1..ee761b7 100644 --- a/Swiften/Base/Algorithm.h +++ b/Swiften/Base/Algorithm.h @@ -1,154 +1,187 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> +#include <algorithm> #include <list> #include <map> -#include <algorithm> +#include <string> +#include <vector> namespace Swift { - /* - * Generic erase() - */ - namespace Detail { - struct VectorCategory {}; - struct ListCategory {}; - struct MapCategory {}; - - template<typename T> - struct ContainerTraits; - - template<typename A, typename B> - struct ContainerTraits< std::vector<A, B> > { - typedef VectorCategory Category; - }; - - template<> - struct ContainerTraits< std::string > { - typedef VectorCategory Category; - }; - - template<typename A, typename B> - struct ContainerTraits< std::list<A, B> > { - typedef ListCategory Category; - }; - - template<typename A, typename B, typename C, typename D> - struct ContainerTraits< std::map<A, B, C, D> > { - typedef MapCategory Category; - }; - - template<typename C, typename V> - void eraseImpl(C& c, const V& v, VectorCategory) { - c.erase(std::remove(c.begin(), c.end(), v), c.end()); - } - - template<typename C, typename V> - void eraseImpl(C& c, const V& v, ListCategory) { - c.remove(v); - } - - template<typename C, typename V> - void eraseImpl(C& c, const V& v, MapCategory) { - for (typename C::iterator it = c.begin(); it != c.end(); ) { - if (it->second == v) { - c.erase(it++); - } - else { - ++it; - } - } - } - - template<typename C, typename P> - void eraseIfImpl(C& c, const P& p, MapCategory) { - for (typename C::iterator it = c.begin(); it != c.end(); ) { - if (p(*it)) { - c.erase(it++); - } - else { - ++it; - } - } - } - - template<typename C, typename P> - void eraseIfImpl(C& c, const P& p, VectorCategory) { - c.erase(std::remove_if(c.begin(), c.end(), p), c.end()); - } - } - - template<typename C, typename V> - void erase(C& container, const V& value) { - Detail::eraseImpl(container, value, typename Detail::ContainerTraits<C>::Category()); - } - - template<typename C, typename P> - void eraseIf(C& container, const P& predicate) { - Detail::eraseIfImpl(container, predicate, typename Detail::ContainerTraits<C>::Category()); - } - - template<typename Source, typename Target> - void append(Target& target, const Source& source) { - target.insert(target.end(), source.begin(), source.end()); - } - - template<typename Source, typename Target> - void assign(Target& target, const Source& source) { - target.assign(source.begin(), source.end()); - } - - template<typename A, typename B, typename C, typename D> - B get(const std::map<A, B, C, D>& map, const A& key, const B& defaultValue) { - typename std::map<A, B, C, D>::const_iterator i = map.find(key); - if (i != map.end()) { - return i->second; - } - else { - return defaultValue; - } - } - - template<typename Container> - void safeClear(Container& c) { - std::fill(c.begin(), c.end(), 0); - c.clear(); - } - - /* - * Functors - */ - template<typename K, typename V> - class PairFirstEquals { - public: - PairFirstEquals(const K& value) : value(value) { - } - - bool operator()(const std::pair<K,V>& pair) const { - return pair.first == value; - } - - private: - K value; - }; - - template<typename K, typename V> - class PairSecondEquals { - public: - PairSecondEquals(const V& value) : value(value) { - } - - bool operator()(const std::pair<K,V>& pair) const { - return pair.second == value; - } - - private: - V value; - }; + /* + * Generic erase() + */ + namespace Detail { + struct VectorCategory {}; + struct ListCategory {}; + struct MapCategory {}; + + template<typename T> + struct ContainerTraits; + + template<typename A, typename B> + struct ContainerTraits< std::vector<A, B> > { + typedef VectorCategory Category; + }; + + template<> + struct ContainerTraits< std::string > { + typedef VectorCategory Category; + }; + + template<typename A, typename B> + struct ContainerTraits< std::list<A, B> > { + typedef ListCategory Category; + }; + + template<typename A, typename B, typename C, typename D> + struct ContainerTraits< std::map<A, B, C, D> > { + typedef MapCategory Category; + }; + + template<typename C, typename V> + void eraseImpl(C& c, const V& v, VectorCategory) { + c.erase(std::remove(c.begin(), c.end(), v), c.end()); + } + + template<typename C, typename V> + void eraseImpl(C& c, const V& v, ListCategory) { + c.remove(v); + } + + template<typename C, typename V> + void eraseImpl(C& c, const V& v, MapCategory) { + for (typename C::iterator it = c.begin(); it != c.end(); ) { + if (it->second == v) { + c.erase(it++); + } + else { + ++it; + } + } + } + + template<typename C, typename P> + void eraseIfImpl(C& c, const P& p, MapCategory) { + for (typename C::iterator it = c.begin(); it != c.end(); ) { + if (p(*it)) { + c.erase(it++); + } + else { + ++it; + } + } + } + + template<typename C, typename P> + void eraseIfImpl(C& c, const P& p, VectorCategory) { + c.erase(std::remove_if(c.begin(), c.end(), p), c.end()); + } + } + + template<typename C, typename V> + void erase(C& container, const V& value) { + Detail::eraseImpl(container, value, typename Detail::ContainerTraits<C>::Category()); + } + + template<typename C, typename P> + void eraseIf(C& container, const P& predicate) { + Detail::eraseIfImpl(container, predicate, typename Detail::ContainerTraits<C>::Category()); + } + + template<typename Source, typename Target> + void append(Target& target, const Source& source) { + target.insert(target.end(), source.begin(), source.end()); + } + + template<typename Source, typename Target> + void assign(Target& target, const Source& source) { + target.assign(source.begin(), source.end()); + } + + template<typename A, typename B, typename C, typename D> + B get(const std::map<A, B, C, D>& map, const A& key, const B& defaultValue) { + typename std::map<A, B, C, D>::const_iterator i = map.find(key); + if (i != map.end()) { + return i->second; + } + else { + return defaultValue; + } + } + + template<typename Container> + void safeClear(Container& c) { + std::fill(c.begin(), c.end(), 0); + c.clear(); + } + + /* + * Functors + */ + template<typename K, typename V> + class PairFirstEquals { + public: + PairFirstEquals(const K& value) : value(value) { + } + + bool operator()(const std::pair<K,V>& pair) const { + return pair.first == value; + } + + private: + K value; + }; + + template<typename K, typename V> + class PairSecondEquals { + public: + PairSecondEquals(const V& value) : value(value) { + } + + bool operator()(const std::pair<K,V>& pair) const { + return pair.second == value; + } + + private: + V value; + }; + + template <typename Map> + bool key_compare(Map const& lhs, Map const& rhs) { + + auto pred = [](decltype(*lhs.begin()) a, decltype(a) b) { return a.first == b.first; }; + + return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin(), pred); + } + + /** + * Ranges + */ + template <typename T> + class range_t { + public: + range_t(T b, T e) : b_(b), e_(e) {} + + T begin() { + return b_; + } + T end() { + return e_; + } + private: + T b_; + T e_; + }; + + template <typename T> + range_t<T> range(T b, T e) { + return range_t<T>(b, e); + } } diff --git a/Swiften/Base/Atomic.h b/Swiften/Base/Atomic.h new file mode 100644 index 0000000..ae065d4 --- /dev/null +++ b/Swiften/Base/Atomic.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <mutex> + +namespace Swift { + +/** + * This class template provides a read/write access synchronized wrapper for other types. + */ +template <typename ValueType> +class Atomic { + public: + Atomic(const ValueType& v) : value_(v) { + } + + /** + * Synchronized write access. + */ + Atomic<ValueType>& operator=(const ValueType& newValue) { + std::lock_guard<std::mutex> lock(valueMutex_); + value_ = newValue; + return *this; + } + + /** + * Synchronized read access. + */ + operator ValueType() { + std::lock_guard<std::mutex> lock(valueMutex_); + return value_; + } + + private: + std::mutex valueMutex_; + ValueType value_; +}; + +} diff --git a/Swiften/Base/BoostFilesystemVersion.h b/Swiften/Base/BoostFilesystemVersion.h index 1b1676c..fff6ce9 100644 --- a/Swiften/Base/BoostFilesystemVersion.h +++ b/Swiften/Base/BoostFilesystemVersion.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once diff --git a/Swiften/Base/BoostRandomGenerator.cpp b/Swiften/Base/BoostRandomGenerator.cpp deleted file mode 100644 index a661639..0000000 --- a/Swiften/Base/BoostRandomGenerator.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/Base/BoostRandomGenerator.h> - -#include <numeric> -#include <boost/random/uniform_int.hpp> -#include <boost/random/variate_generator.hpp> -#include <ctime> - -namespace Swift { - -BoostRandomGenerator::BoostRandomGenerator() { - // FIXME: Not a good seed - generator.seed(static_cast<unsigned int>(std::time(0))); -} - -int BoostRandomGenerator::generateRandomInteger(int maximum) { - boost::uniform_int<> distribution(0, maximum); - return distribution(generator); -} - -} diff --git a/Swiften/Base/BoostRandomGenerator.h b/Swiften/Base/BoostRandomGenerator.h deleted file mode 100644 index 6065ff3..0000000 --- a/Swiften/Base/BoostRandomGenerator.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include <Swiften/Base/RandomGenerator.h> -#include <Swiften/Base/Override.h> - -#include <boost/random/mersenne_twister.hpp> - -namespace Swift { - class BoostRandomGenerator : public RandomGenerator{ - public: - BoostRandomGenerator(); - - int generateRandomInteger(int max) SWIFTEN_OVERRIDE; - - private: - boost::mt19937 generator; - }; -} diff --git a/Swiften/Base/ByteArray.cpp b/Swiften/Base/ByteArray.cpp index 466db5f..882421d 100644 --- a/Swiften/Base/ByteArray.cpp +++ b/Swiften/Base/ByteArray.cpp @@ -1,50 +1,50 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/ByteArray.h> -#include <boost/numeric/conversion/cast.hpp> #include <boost/filesystem/fstream.hpp> +#include <boost/numeric/conversion/cast.hpp> namespace Swift { static const int BUFFER_SIZE = 4096; void readByteArrayFromFile(ByteArray& data, const boost::filesystem::path& file) { - boost::filesystem::ifstream input(file, std::ios_base::in|std::ios_base::binary); - while (input.good()) { - size_t oldSize = data.size(); - data.resize(oldSize + BUFFER_SIZE); - input.read(reinterpret_cast<char*>(&data[oldSize]), BUFFER_SIZE); - data.resize(oldSize + boost::numeric_cast<size_t>(input.gcount())); - } - input.close(); + boost::filesystem::ifstream input(file, std::ios_base::in|std::ios_base::binary); + while (input.good()) { + size_t oldSize = data.size(); + data.resize(oldSize + BUFFER_SIZE); + input.read(reinterpret_cast<char*>(&data[oldSize]), BUFFER_SIZE); + data.resize(oldSize + boost::numeric_cast<size_t>(input.gcount())); + } + input.close(); } std::vector<unsigned char> createByteArray(const std::string& s) { - return std::vector<unsigned char>(s.begin(), s.end()); + return std::vector<unsigned char>(s.begin(), s.end()); } std::vector<unsigned char> createByteArray(const char* c) { - std::vector<unsigned char> data; - while (*c) { - data.push_back(static_cast<unsigned char>(*c)); - ++c; - } - return data; + std::vector<unsigned char> data; + while (*c) { + data.push_back(static_cast<unsigned char>(*c)); + ++c; + } + return data; } std::string byteArrayToString(const ByteArray& b) { - size_t i; - for (i = b.size(); i > 0; --i) { - if (b[i - 1] != 0) { - break; - } - } - return i > 0 ? std::string(reinterpret_cast<const char*>(vecptr(b)), i) : ""; + size_t i; + for (i = b.size(); i > 0; --i) { + if (b[i - 1] != 0) { + break; + } + } + return i > 0 ? std::string(reinterpret_cast<const char*>(vecptr(b)), i) : ""; } } diff --git a/Swiften/Base/ByteArray.h b/Swiften/Base/ByteArray.h index 133b75f..b567b5a 100644 --- a/Swiften/Base/ByteArray.h +++ b/Swiften/Base/ByteArray.h @@ -1,47 +1,48 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <string> +#include <vector> -#include <Swiften/Base/API.h> #include <boost/filesystem/path.hpp> +#include <Swiften/Base/API.h> + namespace Swift { - typedef std::vector<unsigned char> ByteArray; + typedef std::vector<unsigned char> ByteArray; + + SWIFTEN_API ByteArray createByteArray(const std::string& s); + SWIFTEN_API ByteArray createByteArray(const char* c); - SWIFTEN_API ByteArray createByteArray(const std::string& s); - SWIFTEN_API ByteArray createByteArray(const char* c); + inline ByteArray createByteArray(const unsigned char* c, size_t n) { + return ByteArray(c, c + n); + } - inline ByteArray createByteArray(const unsigned char* c, size_t n) { - return ByteArray(c, c + n); - } + inline ByteArray createByteArray(const char* c, size_t n) { + return ByteArray(c, c + n); + } - inline ByteArray createByteArray(const char* c, size_t n) { - return ByteArray(c, c + n); - } + inline ByteArray createByteArray(char c) { + return std::vector<unsigned char>(1, static_cast<unsigned char>(c)); + } - inline ByteArray createByteArray(char c) { - return std::vector<unsigned char>(1, static_cast<unsigned char>(c)); - } + template<typename T, typename A> + static const T* vecptr(const std::vector<T, A>& v) { + return v.empty() ? nullptr : &v[0]; + } - template<typename T, typename A> - static const T* vecptr(const std::vector<T, A>& v) { - return v.empty() ? NULL : &v[0]; - } + template<typename T, typename A> + static T* vecptr(std::vector<T, A>& v) { + return v.empty() ? nullptr : &v[0]; + } - template<typename T, typename A> - static T* vecptr(std::vector<T, A>& v) { - return v.empty() ? NULL : &v[0]; - } - - SWIFTEN_API std::string byteArrayToString(const ByteArray& b); + SWIFTEN_API std::string byteArrayToString(const ByteArray& b); - SWIFTEN_API void readByteArrayFromFile(ByteArray&, const boost::filesystem::path& file); + SWIFTEN_API void readByteArrayFromFile(ByteArray&, const boost::filesystem::path& file); } diff --git a/Swiften/Base/Concat.h b/Swiften/Base/Concat.h index 83a43b6..8923a8f 100644 --- a/Swiften/Base/Concat.h +++ b/Swiften/Base/Concat.h @@ -1,73 +1,41 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -namespace Swift { - template<typename C> - C concat(const C& c1, const C& c2) { - C result; - result.resize(c1.size() + c2.size()); - std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin())); - return result; - } - - template<typename C> - C concat(const C& c1, const C& c2, const C& c3) { - C result; - result.resize(c1.size() + c2.size() + c3.size()); - std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin()))); - return result; - } - - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size()); - std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin())))); - return result; - } - - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4, const C& c5) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size() + c5.size()); - std::copy(c5.begin(), c5.end(), std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin()))))); - return result; - } +#include <algorithm> +#include <type_traits> - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4, const C& c5, const C& c6) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size() + c5.size() + c6.size()); - std::copy(c6.begin(), c6.end(), std::copy(c5.begin(), c5.end(), std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin())))))); - return result; - } - - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4, const C& c5, const C& c6, const C& c7) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size() + c5.size() + c6.size() + c7.size()); - std::copy(c7.begin(), c7.end(), std::copy(c6.begin(), c6.end(), std::copy(c5.begin(), c5.end(), std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin()))))))); - return result; - } - - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4, const C& c5, const C& c6, const C& c7, const C& c8) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size() + c5.size() + c6.size() + c7.size() + c8.size()); - std::copy(c8.begin(), c8.end(), std::copy(c7.begin(), c7.end(), std::copy(c6.begin(), c6.end(), std::copy(c5.begin(), c5.end(), std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin())))))))); - return result; - } +namespace Swift { + template<typename V1, typename V2, typename... Rest> + std::size_t getReserveAmount(V1 const& v1, V2 const& v2, Rest const&... rest) SWIFTEN_NOEXCEPT + { + // Total size of the concatenated output is equal to sum of sizes of all the containers that were passed in. + // Two first can be accessed directly: + std::size_t sizeSum = v1.size() + v2.size(); + // While the rest needs to be calculated in parameter pack expansion: + // http://stackoverflow.com/a/25683817/61574 + // Pack expansion can occur inside a braced-init-list - dummy array is used for that (with side effect of accumulating the size) + int dummy[] = {0, ((sizeSum += rest.size()), void(), 0)...}; + + (void)dummy; // dummy is unused - suppress compiler warning + return sizeSum; +} - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4, const C& c5, const C& c6, const C& c7, const C& c8, const C& c9) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size() + c5.size() + c6.size() + c7.size() + c8.size() + c9.size()); - std::copy(c9.begin(), c9.end(), std::copy(c8.begin(), c8.end(), std::copy(c7.begin(), c7.end(), std::copy(c6.begin(), c6.end(), std::copy(c5.begin(), c5.end(), std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin()))))))))); - return result; - } + template<typename V1, typename V2, typename... Rest> + typename std::decay<V1>::type concat(V1&& v1, V2&& v2, Rest&&... rest) { + // Create the output container and reserve the required amount of space + typename std::decay<V1>::type v; + v.reserve(getReserveAmount(v1, v2, rest...)); + // Insert the elements from input containers to output. Directly for the first two: + v.insert(v.cend(), v1.cbegin(), v1.cend()); + v.insert(v.cend(), v2.cbegin(), v2.cend()); + // Use pack expansion for the others: + int dummy[] = {0, ((v.insert(v.cend(), rest.cbegin(), rest.cend())), void(), 0 )...}; + (void)dummy; + return v; + } } diff --git a/Swiften/Base/DateTime.cpp b/Swiften/Base/DateTime.cpp index 5d192c4..23b3b84 100644 --- a/Swiften/Base/DateTime.cpp +++ b/Swiften/Base/DateTime.cpp @@ -1,39 +1,48 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/DateTime.h> #include <locale> -#include <boost/date_time/time_facet.hpp> + +#include <boost/date_time/c_local_time_adjustor.hpp> #include <boost/date_time/local_time/local_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp> -#include <boost/date_time/c_local_time_adjustor.hpp> +#include <boost/date_time/time_facet.hpp> +#include <Swiften/Base/Log.h> #include <Swiften/Base/String.h> namespace Swift { boost::posix_time::ptime stringToDateTime(const std::string& string) { - static std::locale locale(std::locale::classic(), new boost::local_time::local_time_input_facet("%Y-%m-%d %H:%M:%S%F%ZP")); - std::istringstream stream(string); - stream.imbue(locale); - boost::local_time::local_date_time result(boost::date_time::not_a_date_time); - stream >> result; - return result.utc_time(); + static std::locale locale(std::locale::classic(), new boost::local_time::local_time_input_facet("%Y-%m-%d %H:%M:%S%F%ZP")); + std::istringstream stream(string); + stream.imbue(locale); + boost::local_time::local_date_time result(boost::date_time::not_a_date_time); + stream >> result; + return result.utc_time(); } std::string dateTimeToString(const boost::posix_time::ptime& time) { - std::string stampString = std::string(boost::posix_time::to_iso_extended_string(time)); - String::replaceAll(stampString, ',', "."); - stampString += "Z"; - return stampString; + std::string stampString = std::string(boost::posix_time::to_iso_extended_string(time)); + String::replaceAll(stampString, ',', "."); + stampString += "Z"; + return stampString; } std::string dateTimeToLocalString(const boost::posix_time::ptime& time) { - return boost::posix_time::to_simple_string(boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local(time)); + std::string localString; + try { + localString = boost::posix_time::to_simple_string(boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local(time)); + } + catch(std::out_of_range& exception) { + SWIFT_LOG(debug) << exception.what(); + } + return localString; } } diff --git a/Swiften/Base/DateTime.h b/Swiften/Base/DateTime.h index 891b170..36cff65 100644 --- a/Swiften/Base/DateTime.h +++ b/Swiften/Base/DateTime.h @@ -1,28 +1,29 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> #include <boost/date_time/posix_time/ptime.hpp> +#include <Swiften/Base/API.h> + namespace Swift { - /** - * Converts a date formatted according to XEP-0082 into a ptime - * object (in UTC). - */ - SWIFTEN_API boost::posix_time::ptime stringToDateTime(const std::string& string); + /** + * Converts a date formatted according to XEP-0082 into a ptime + * object (in UTC). + */ + SWIFTEN_API boost::posix_time::ptime stringToDateTime(const std::string& string); - /** - * Converts a UTC ptime object to a XEP-0082 formatted string. - */ - SWIFTEN_API std::string dateTimeToString(const boost::posix_time::ptime& time); + /** + * Converts a UTC ptime object to a XEP-0082 formatted string. + */ + SWIFTEN_API std::string dateTimeToString(const boost::posix_time::ptime& time); - /** - * Converts a UTC ptime object to a localized human readable string. - */ - SWIFTEN_API std::string dateTimeToLocalString(const boost::posix_time::ptime& time); + /** + * Converts a UTC ptime object to a localized human readable string. + */ + SWIFTEN_API std::string dateTimeToLocalString(const boost::posix_time::ptime& time); } diff --git a/Swiften/Base/Debug.cpp b/Swiften/Base/Debug.cpp new file mode 100644 index 0000000..b4245c3 --- /dev/null +++ b/Swiften/Base/Debug.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Base/Debug.h> + +#include <iostream> +#include <memory> + +#include <Swiften/Client/ClientError.h> +#include <Swiften/Client/ClientSession.h> +#include <Swiften/Serializer/PayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/XMPPSerializer.h> + +std::ostream& operator<<(std::ostream& os, const Swift::ClientError& error) { + os << "ClientError("; + switch(error.getType()) { + case Swift::ClientError::UnknownError: + os << "UnknownError"; + break; + case Swift::ClientError::DomainNameResolveError: + os << "DomainNameResolveError"; + break; + case Swift::ClientError::ConnectionError: + os << "ConnectionError"; + break; + case Swift::ClientError::ConnectionReadError: + os << "ConnectionReadError"; + break; + case Swift::ClientError::ConnectionWriteError: + os << "ConnectionWriteError"; + break; + case Swift::ClientError::XMLError: + os << "XMLError"; + break; + case Swift::ClientError::AuthenticationFailedError: + os << "AuthenticationFailedError"; + break; + case Swift::ClientError::CompressionFailedError: + os << "CompressionFailedError"; + break; + case Swift::ClientError::ServerVerificationFailedError: + os << "ServerVerificationFailedError"; + break; + case Swift::ClientError::NoSupportedAuthMechanismsError: + os << "NoSupportedAuthMechanismsError"; + break; + case Swift::ClientError::UnexpectedElementError: + os << "UnexpectedElementError"; + break; + case Swift::ClientError::ResourceBindError: + os << "ResourceBindError"; + break; + case Swift::ClientError::SessionStartError: + os << "SessionStartError"; + break; + case Swift::ClientError::StreamError: + os << "StreamError"; + break; + case Swift::ClientError::TLSError: + os << "TLSError"; + break; + case Swift::ClientError::ClientCertificateLoadError: + os << "ClientCertificateLoadError"; + break; + case Swift::ClientError::ClientCertificateError: + os << "ClientCertificateError"; + break; + case Swift::ClientError::CertificateCardRemoved: + os << "CertificateCardRemoved"; + break; + case Swift::ClientError::UnknownCertificateError: + os << "UnknownCertificateError"; + break; + case Swift::ClientError::CertificateExpiredError: + os << "CertificateExpiredError"; + break; + case Swift::ClientError::CertificateNotYetValidError: + os << "CertificateNotYetValidError"; + break; + case Swift::ClientError::CertificateSelfSignedError: + os << "CertificateSelfSignedError"; + break; + case Swift::ClientError::CertificateRejectedError: + os << "CertificateRejectedError"; + break; + case Swift::ClientError::CertificateUntrustedError: + os << "CertificateUntrustedError"; + break; + case Swift::ClientError::InvalidCertificatePurposeError: + os << "InvalidCertificatePurposeError"; + break; + case Swift::ClientError::CertificatePathLengthExceededError: + os << "CertificatePathLengthExceededError"; + break; + case Swift::ClientError::InvalidCertificateSignatureError: + os << "InvalidCertificateSignatureError"; + break; + case Swift::ClientError::InvalidCAError: + os << "InvalidCAError"; + break; + case Swift::ClientError::InvalidServerIdentityError: + os << "InvalidServerIdentityError"; + break; + case Swift::ClientError::RevokedError: + os << "RevokedError"; + break; + case Swift::ClientError::RevocationCheckFailedError: + os << "RevocationCheckFailedError"; + break; + } + os << ")"; + return os; +} + +std::ostream& operator<<(std::ostream& os, Swift::Element* ele) { + using namespace Swift; + + std::shared_ptr<Element> element = std::shared_ptr<Element>(ele); + + std::shared_ptr<Payload> payload = std::dynamic_pointer_cast<Payload>(element); + if (payload) { + FullPayloadSerializerCollection payloadSerializerCollection; + PayloadSerializer *serializer = payloadSerializerCollection.getPayloadSerializer(payload); + os << "Payload(" << serializer->serialize(payload) << ")"; + return os; + } + std::shared_ptr<ToplevelElement> topLevelElement = std::dynamic_pointer_cast<ToplevelElement>(element); + if (topLevelElement) { + FullPayloadSerializerCollection payloadSerializerCollection; + XMPPSerializer xmppSerializer(&payloadSerializerCollection, ClientStreamType, false); + SafeByteArray serialized = xmppSerializer.serializeElement(topLevelElement); + os << "TopLevelElement(" << safeByteArrayToString(serialized) << ")"; + return os; + } + os << "Element(Unknown)"; + return os; +} + +std::ostream& operator<<(std::ostream& os, Swift::ClientSession::State state) { + using CS = Swift::ClientSession; + switch (state) { + case CS::State::Initial: + os << "ClientSession::State::Initial"; + break; + case CS::State::WaitingForStreamStart: + os << "ClientSession::State::WaitingForStreamStart"; + break; + case CS::State::Negotiating: + os << "ClientSession::State::Negotiating"; + break; + case CS::State::Compressing: + os << "ClientSession::State::Compressing"; + break; + case CS::State::WaitingForEncrypt: + os << "ClientSession::State::WaitingForEncrypt"; + break; + case CS::State::Encrypting: + os << "ClientSession::State::Encrypting"; + break; + case CS::State::WaitingForCredentials: + os << "ClientSession::State::WaitingForCredentials"; + break; + case CS::State::Authenticating: + os << "ClientSession::State::Authenticating"; + break; + case CS::State::EnablingSessionManagement: + os << "ClientSession::State::EnablingSessionManagement"; + break; + case CS::State::BindingResource: + os << "ClientSession::State::BindingResource"; + break; + case CS::State::StartingSession: + os << "ClientSession::State::StartingSession"; + break; + case CS::State::Initialized: + os << "ClientSession::State::Initialized"; + break; + case CS::State::Finishing: + os << "ClientSession::State::Finishing"; + break; + case CS::State::Finished: + os << "ClientSession::State::Finished"; + break; + } + return os; +} diff --git a/Swiften/Base/Debug.h b/Swiften/Base/Debug.h new file mode 100644 index 0000000..75575de --- /dev/null +++ b/Swiften/Base/Debug.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <iosfwd> + +#include <Swiften/Client/ClientSession.h> + +namespace Swift { + class ClientError; + class Element; +} + +SWIFTEN_API std::ostream& operator<<(std::ostream& os, const Swift::ClientError& error); + +SWIFTEN_API std::ostream& operator<<(std::ostream& os, Swift::Element* ele); + +SWIFTEN_API std::ostream& operator<<(std::ostream& os, Swift::ClientSession::State state); diff --git a/Swiften/Base/Error.cpp b/Swiften/Base/Error.cpp index 60ad7ac..4745f34 100644 --- a/Swiften/Base/Error.cpp +++ b/Swiften/Base/Error.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/Error.h> diff --git a/Swiften/Base/Error.h b/Swiften/Base/Error.h index d9f3b91..af4f27e 100644 --- a/Swiften/Base/Error.h +++ b/Swiften/Base/Error.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,8 +9,11 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API Error { - public: - virtual ~Error(); - }; + class SWIFTEN_API Error { + public: + Error() {} + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(Error) + SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(Error) + virtual ~Error(); + }; } diff --git a/Swiften/Base/FileSize.cpp b/Swiften/Base/FileSize.cpp new file mode 100644 index 0000000..a335337 --- /dev/null +++ b/Swiften/Base/FileSize.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Base/FileSize.h> + +#include <boost/format.hpp> + +namespace Swift { + +std::string formatSize(const boost::uintmax_t bytes) { + static const char *siPrefix[] = {"k", "M", "G", "T", "P", "E", "Z", "Y", nullptr}; + int power = 0; + double engBytes = bytes; + while (engBytes >= 1000) { + ++power; + engBytes = engBytes / 1000.0; + } + return str( boost::format("%.1lf %sB") % engBytes % (power > 0 ? siPrefix[power-1] : "") ); +} + +} diff --git a/Swiften/Base/FileSize.h b/Swiften/Base/FileSize.h new file mode 100644 index 0000000..af303cc --- /dev/null +++ b/Swiften/Base/FileSize.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <boost/cstdint.hpp> + +#include <Swiften/Base/API.h> + +namespace Swift { + +SWIFTEN_API std::string formatSize(const boost::uintmax_t bytes); + +} diff --git a/Swiften/Base/IDGenerator.cpp b/Swiften/Base/IDGenerator.cpp index 5556f7b..b59a39c 100644 --- a/Swiften/Base/IDGenerator.cpp +++ b/Swiften/Base/IDGenerator.cpp @@ -1,24 +1,27 @@ /* - * Copyright (c) 2010-2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/IDGenerator.h> +#include <boost/lexical_cast.hpp> #include <boost/uuid/uuid.hpp> -#include <boost/uuid/uuid_io.hpp> #include <boost/uuid/uuid_generators.hpp> -#include <boost/lexical_cast.hpp> +#include <boost/uuid/uuid_io.hpp> namespace Swift { IDGenerator::IDGenerator() { } +IDGenerator::~IDGenerator() { +} + std::string IDGenerator::generateID() { - static boost::uuids::random_generator generator; - return boost::lexical_cast<std::string>(generator()); + static boost::uuids::random_generator generator; + return boost::lexical_cast<std::string>(generator()); } } diff --git a/Swiften/Base/IDGenerator.h b/Swiften/Base/IDGenerator.h index 14ecfdc..6b53994 100644 --- a/Swiften/Base/IDGenerator.h +++ b/Swiften/Base/IDGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,10 +11,11 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API IDGenerator { - public: - IDGenerator(); + class SWIFTEN_API IDGenerator { + public: + IDGenerator(); + virtual ~IDGenerator(); - std::string generateID(); - }; + virtual std::string generateID(); + }; } diff --git a/Swiften/Base/LRUCache.h b/Swiften/Base/LRUCache.h new file mode 100644 index 0000000..1f92612 --- /dev/null +++ b/Swiften/Base/LRUCache.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <functional> +#include <utility> + +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/hashed_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <boost/optional.hpp> + +namespace Swift { + + +/** + * The \ref LRUCache template class implements a lookup cache which removes + * the least recently used cached item from the cache, if the cache size hits + * the \p MAX_SIZE limit. + * + * An example use is a cache for entity capabilities hash to DiscoInfo. + */ +template <typename KEY_TYPE, typename VALUE_TYPE, size_t MAX_SIZE> +class LRUCache { +public: + using cacheMissFunction = std::function<boost::optional<VALUE_TYPE>(const KEY_TYPE& )>; + +public: + /** + * Inserts the key/value pair in the front of the cache. If the \p key + * already exists in the cache, it is moved to the front instead. If + * afterwards, the cahe size exceeds the \p MAX_SIZE limit, the least + * recently item is removed from the cache. + */ + void insert(const KEY_TYPE& key, VALUE_TYPE value) { + auto pushResult = cache.push_front(entry_t(key, value)); + if (!pushResult.second) { + cache.relocate(cache.begin(), pushResult.first); + } + else if (cache.size() > MAX_SIZE) { + cache.pop_back(); + } + } + + /** + * Looks up a cache entry based on the provided \p key and moves it back + * to the front of the cache. If there is no cache entry for the provided + * \p key, an uninitialized \p boost::optional is returned. + * If the optional \p missFunction is provided, it is called on a cache miss. + * If the \p missFunction returns an initialized \p boost::optional, the + * value is inserted in the cache. + */ + boost::optional<VALUE_TYPE> get(const KEY_TYPE& key, cacheMissFunction missFunction = cacheMissFunction()) { + boost::optional<VALUE_TYPE> cachedValue; + auto cacheItemIterator = boost::multi_index::get<1>(cache).find(key); + if (cacheItemIterator != boost::multi_index::get<1>(cache).end()) { + cachedValue = cacheItemIterator->second; + cache.relocate(cache.begin(), cache.iterator_to(*cacheItemIterator)); + } + else if (missFunction && (cachedValue = missFunction(key))) { + insert(key, cachedValue.get()); + } + return cachedValue; + } + +private: + using entry_t = std::pair<KEY_TYPE, VALUE_TYPE>; + +private: + boost::multi_index_container< entry_t, boost::multi_index::indexed_by< boost::multi_index::sequenced<>, boost::multi_index::hashed_unique< + BOOST_MULTI_INDEX_MEMBER(entry_t, KEY_TYPE, first)> > > cache; +}; + +} diff --git a/Swiften/Base/Listenable.h b/Swiften/Base/Listenable.h index 445dfd7..ae83f4e 100644 --- a/Swiften/Base/Listenable.h +++ b/Swiften/Base/Listenable.h @@ -1,52 +1,55 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2015 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> -#include <boost/bind.hpp> #include <algorithm> +#include <vector> + +#include <boost/bind.hpp> + +#include <Swiften/Base/API.h> namespace Swift { - template<typename T> - class SWIFTEN_API Listenable { - public: - void addListener(T* listener) { - listeners.push_back(listener); - } - - void removeListener(T* listener) { - listeners.erase(std::remove(listeners.begin(), listeners.end(), listener), listeners.end()); - } - - protected: - template<typename F> - void notifyListeners(F event) { - for (typename std::vector<T*>::iterator i = listeners.begin(); i != listeners.end(); ++i) { - event(*i); - } - } - - template<typename F, typename A1> - void notifyListeners(F f, const A1& a1) { - notifyListeners(boost::bind(f, _1, a1)); - } - - template<typename F, typename A1, typename A2> - void notifyListeners(F f, const A1& a1, const A2& a2) { - notifyListeners(boost::bind(f, _1, a1, a2)); - } - - template<typename F, typename A1, typename A2, typename A3> - void notifyListeners(F f, const A1& a1, const A2& a2, const A3& a3) { - notifyListeners(boost::bind(f, _1, a1, a2, a3)); - } - - private: - std::vector<T*> listeners; - }; + template<typename T> + class SWIFTEN_API Listenable { + public: + void addListener(T* listener) { + listeners.push_back(listener); + } + + void removeListener(T* listener) { + listeners.erase(std::remove(listeners.begin(), listeners.end(), listener), listeners.end()); + } + + protected: + template<typename F> + void notifyListeners(F event) { + for (typename std::vector<T*>::iterator i = listeners.begin(); i != listeners.end(); ++i) { + event(*i); + } + } + + template<typename F, typename A1> + void notifyListeners(F f, const A1& a1) { + notifyListeners(boost::bind(f, _1, a1)); + } + + template<typename F, typename A1, typename A2> + void notifyListeners(F f, const A1& a1, const A2& a2) { + notifyListeners(boost::bind(f, _1, a1, a2)); + } + + template<typename F, typename A1, typename A2, typename A3> + void notifyListeners(F f, const A1& a1, const A2& a2, const A3& a3) { + notifyListeners(boost::bind(f, _1, a1, a2, a3)); + } + + private: + std::vector<T*> listeners; + }; } diff --git a/Swiften/Base/Log.cpp b/Swiften/Base/Log.cpp index 317798c..b6f1851 100644 --- a/Swiften/Base/Log.cpp +++ b/Swiften/Base/Log.cpp @@ -1,43 +1,83 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/Log.h> #include <cstdio> +#if defined(SWIFT_ANDROID_LOGGING) && defined(__ANDROID__) +#include <android/log.h> +#endif + namespace Swift { static Log::Severity logLevel = Log::warning; +std::unique_ptr<FILE, Log::LogFileClose> Log::logfile; +Log::Callback Log::logCallback; Log::Log() { } Log::~Log() { - // Using stdio for thread safety (POSIX file i/o calls are guaranteed to be atomic) - fprintf(stderr, "%s", stream.str().c_str()); - fflush(stderr); +#if defined(SWIFT_ANDROID_LOGGING) && defined(__ANDROID__) + __android_log_print(ANDROID_LOG_VERBOSE, "Swift", stream.str().c_str(), 1); +#else + // Using stdio for thread safety (POSIX file i/o calls are guaranteed to be atomic) + if (logCallback) { + logCallback(severity_, std::move(file_), line_, std::move(function_), stream.str()); + } + else { + stream << std::endl; + if (logfile) { + fwrite(stream.str().c_str(), sizeof(char), stream.str().size(), logfile.get()); + fflush(logfile.get()); + } + else { + fwrite(stream.str().c_str(), sizeof(char), stream.str().size(), stderr); + fflush(stderr); + } + } +#endif } std::ostringstream& Log::getStream( - Severity /*severity*/, - const std::string& severityString, - const std::string& file, - int line, - const std::string& function) { - stream << "[" << severityString << "] " << file << ":" << line << " " << function << ": "; - return stream; + Severity severity, + std::string severityString, + std::string file, + int line, + std::string function) { + if (logCallback) { + severity_ = severity; + file_ = std::move(file); + line_ = line; + function_ = std::move(function); + } + else { + stream << "[" << severityString << "] " << file << ":" << line << " " << function << ": "; + } + return stream; } Log::Severity Log::getLogLevel() { - return logLevel; + return logLevel; } void Log::setLogLevel(Severity level) { - logLevel = level; + logLevel = level; +} + +void Log::setLogFile(const std::string& fileName) { + if (!fileName.empty()) { + logfile = std::unique_ptr<FILE, Log::LogFileClose>(fopen(fileName.c_str(), "a")); + } +} + +void Log::setLogCallback(Callback callback) { + Log::logCallback = callback; } } diff --git a/Swiften/Base/Log.h b/Swiften/Base/Log.h index a46860f..255e478 100644 --- a/Swiften/Base/Log.h +++ b/Swiften/Base/Log.h @@ -1,44 +1,63 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <cstdio> +#include <functional> +#include <memory> #include <sstream> #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API Log { - public: - enum Severity { - error, warning, info, debug - }; - - Log(); - ~Log(); - - std::ostringstream& getStream( - Severity severity, - const std::string& severityString, - const std::string& file, - int line, - const std::string& function); - - static Severity getLogLevel(); - static void setLogLevel(Severity level); - - private: - std::ostringstream stream; - }; + class SWIFTEN_API Log { + public: + enum Severity { + error, warning, info, debug + }; + using Callback = std::function<void(Severity severity, std::string file, int line, std::string function, std::string message)>; + + Log(); + ~Log(); + + std::ostringstream& getStream( + Severity severity, + std::string severityString, + std::string file, + int line, + std::string function); + + static Severity getLogLevel(); + static void setLogLevel(Severity level); + static void setLogFile(const std::string& fileName); + static void setLogCallback(Callback callback); + + private: + struct LogFileClose { + void operator()(FILE* p) { + if (p) { + fclose(p); + } + } + }; + std::ostringstream stream; + static std::unique_ptr<FILE, LogFileClose> logfile; + static Callback logCallback; + Severity severity_; + std::string file_; + int line_; + std::string function_; + }; } #define SWIFT_LOG(severity) \ - if (Log::severity > Log::getLogLevel()) ; \ - else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__) + if (Log::severity > Log::getLogLevel()) ; \ + else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__) #define SWIFT_LOG_ASSERT(test, severity) \ - if (Log::severity > Log::getLogLevel() || (test)) ; \ - else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__) << "Assertion failed: " << #test << ". " + if (Log::severity > Log::getLogLevel() || (test)) ; \ + else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__) << "Assertion failed: " << #test << ". " diff --git a/Swiften/Base/LogSerializers.cpp b/Swiften/Base/LogSerializers.cpp new file mode 100644 index 0000000..3f8e9ce --- /dev/null +++ b/Swiften/Base/LogSerializers.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Base/LogSerializers.h> + +#include <Swiften/Elements/Presence.h> +#include <Swiften/Network/BOSHConnection.h> + +namespace Swift { + +std::ostream& operator<<(std::ostream& stream, const Presence& presence) { + std::string typeString; + switch (presence.getType()) { + case Presence::Available: + typeString = "Available"; + break; + case Presence::Error: + typeString = "Error"; + break; + case Presence::Probe: + typeString = "Probe"; + break; + case Presence::Subscribe: + typeString = "Subscribe"; + break; + case Presence::Subscribed: + typeString = "Subscribed"; + break; + case Presence::Unavailable: + typeString = "Unavailable"; + break; + case Presence::Unsubscribe: + typeString = "Unsubscribe"; + break; + case Presence::Unsubscribed: + typeString = "Unsubscribed"; + break; + } + + std::string showTypeString; + switch (presence.getShow()) { + case StatusShow::Online: + showTypeString = "Online"; + break; + case StatusShow::Away: + showTypeString = "Away"; + break; + case StatusShow::FFC: + showTypeString = "FFC"; + break; + case StatusShow::DND: + showTypeString = "DND"; + break; + case StatusShow::XA: + showTypeString = "XA"; + break; + case StatusShow::None: + showTypeString = "None"; + break; + } + + stream << "Presence(" << "from: " << presence.getFrom() << ", to: " << presence.getTo() << ", type: " << typeString << ", status: " << showTypeString << ", priority: " << presence.getPriority() << ", '" << presence.getStatus() << "'" << " )"; + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const BOSHError& boshError) { + std::string errorString; + switch (boshError.getType()) { + case BOSHError::BadRequest: + errorString = "BadRequest"; + break; + case BOSHError::HostGone: + errorString = "HostGone"; + break; + case BOSHError::HostUnknown: + errorString = "HostUnknown"; + break; + case BOSHError::ImproperAddressing: + errorString = "ImproperAddressing"; + break; + case BOSHError::InternalServerError: + errorString = "InternalServerError"; + break; + case BOSHError::ItemNotFound: + errorString = "ItemNotFound"; + break; + case BOSHError::OtherRequest: + errorString = "OtherRequest"; + break; + case BOSHError::PolicyViolation: + errorString = "PolicyViolation"; + break; + case BOSHError::RemoteConnectionFailed: + errorString = "RemoteConnectionFailed"; + break; + case BOSHError::RemoteStreamError: + errorString = "RemoteStreamError"; + break; + case BOSHError::SeeOtherURI: + errorString = "SeeOtherURI"; + break; + case BOSHError::SystemShutdown: + errorString = "SystemShutdown"; + break; + case BOSHError::UndefinedCondition: + errorString = "UndefinedCondition"; + break; + case BOSHError::NoError: + errorString = "NoError"; + break; + } + + stream << "BOSHError( " << errorString << " )"; + return stream; +} + +}; + +::std::ostream& operator<<(::std::ostream& os, const boost::optional<std::string>& optStr) { + if (optStr.is_initialized()) { + return os << "boost::optional<std::string>(\"" << optStr.get() << "\")"; + } + else { + return os << "boost::optional<std::string>()"; + } +} + diff --git a/Swiften/Base/LogSerializers.h b/Swiften/Base/LogSerializers.h new file mode 100644 index 0000000..7f73686 --- /dev/null +++ b/Swiften/Base/LogSerializers.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <map> +#include <memory> +#include <ostream> +#include <string> +#include <utility> +#include <vector> + +#include <boost/optional.hpp> + +namespace Swift { + +class Presence; +class BOSHError; + +template <typename T> +std::ostream& operator<<(std::ostream& stream, const std::shared_ptr<T>& ptr) { + if (ptr) { + stream << *ptr; + } + else { + stream << "nullptr"; + } + return stream; +} + +template <typename T> +std::ostream& operator<<(std::ostream& stream, const std::vector<T>& vec) { + stream << "["; + if (!vec.empty()) { + auto it = std::begin(vec); + stream << *it; + + ++it; + for (auto end = std::end(vec); it != end; ++it) { + stream << ", " << *it; + } + } + stream << "]"; + return stream; +} + +template <typename KEY, typename VALUE> +std::ostream& operator<<(std::ostream& stream, const std::pair<KEY, VALUE>& pair) { + stream << pair.first << ":" << pair.second; + return stream; +} + +template <typename KEY, typename VALUE> +std::ostream& operator<<(std::ostream& stream, const std::map<KEY, VALUE>& map) { + stream << "{"; + if (!map.empty()) { + auto it = std::begin(map); + stream << *it; + + ++it; + for (auto end = std::end(map); it != end; ++it) { + stream << ", " << *it; + } + } + stream << "}"; + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const Presence& presence); + +std::ostream& operator<<(std::ostream& stream, const BOSHError& boshError); + +}; + +::std::ostream& operator<<(::std::ostream& os, const boost::optional<std::string>& optStr); + diff --git a/Swiften/Base/Override.h b/Swiften/Base/Override.h deleted file mode 100644 index 6d9baaa..0000000 --- a/Swiften/Base/Override.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#if defined(__clang__) -# if __has_feature(cxx_override_control) || __has_extension(cxx_override_control) -# define SWIFTEN_OVERRIDE override -# else -# define SWIFTEN_OVERRIDE -# endif - -#elif defined(__GNUC__) -# if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))) && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define SWIFTEN_OVERRIDE override -# else -# define SWIFTEN_OVERRIDE -# endif - -#elif defined(_MSC_VER) -// Actually, 1700 is the first version that supports the C++11 override, but -// older versions apparently support a similar keyword. -# if _MSC_VER >= 1400 -# define SWIFTEN_OVERRIDE override -# else -# define SWIFTEN_OVERRIDE -# endif - -#else -# define SWIFTEN_OVERRIDE -#endif diff --git a/Swiften/Base/Path.cpp b/Swiften/Base/Path.cpp index 2a49676..ffee09b 100644 --- a/Swiften/Base/Path.cpp +++ b/Swiften/Base/Path.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -13,16 +13,16 @@ using namespace Swift; boost::filesystem::path Swift::stringToPath(const std::string& path) { #ifdef SWIFTEN_PLATFORM_WINDOWS - return boost::filesystem::path(convertStringToWString(path)); + return boost::filesystem::path(convertStringToWString(path)); #else - return boost::filesystem::path(path); + return boost::filesystem::path(path); #endif } std::string Swift::pathToString(const boost::filesystem::path& path) { #ifdef SWIFTEN_PLATFORM_WINDOWS - return convertWStringToString(path.native()); + return convertWStringToString(path.native()); #else - return path.native(); + return path.native(); #endif } diff --git a/Swiften/Base/Path.h b/Swiften/Base/Path.h index ea99be9..40141b5 100644 --- a/Swiften/Base/Path.h +++ b/Swiften/Base/Path.h @@ -1,27 +1,29 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> -#include <boost/filesystem/path.hpp> #include <string> +#include <boost/filesystem/path.hpp> + +#include <Swiften/Base/API.h> + namespace Swift { - /** - * Creates a path for the given UTF-8 encoded string. - * This works independently of global locale settings. - */ - SWIFTEN_API boost::filesystem::path stringToPath(const std::string&); - - /** - * Returns the UTF-8 representation of the given path - * This works independently of global locale settings. - */ - SWIFTEN_API std::string pathToString(const boost::filesystem::path&); + /** + * Creates a path for the given UTF-8 encoded string. + * This works independently of global locale settings. + */ + SWIFTEN_API boost::filesystem::path stringToPath(const std::string&); + + /** + * Returns the UTF-8 representation of the given path + * This works independently of global locale settings. + */ + SWIFTEN_API std::string pathToString(const boost::filesystem::path&); } diff --git a/Swiften/Base/Paths.cpp b/Swiften/Base/Paths.cpp index 8ad1159..cbb16f3 100644 --- a/Swiften/Base/Paths.cpp +++ b/Swiften/Base/Paths.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/Paths.h> @@ -21,28 +21,28 @@ namespace Swift { boost::filesystem::path Paths::getExecutablePath() { #if defined(SWIFTEN_PLATFORM_MACOSX) - ByteArray path; - uint32_t size = 4096; - path.resize(size); - if (_NSGetExecutablePath(const_cast<char*>(reinterpret_cast<const char*>(vecptr(path))), &size) == 0) { - return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path(); - } + ByteArray path; + uint32_t size = 4096; + path.resize(size); + if (_NSGetExecutablePath(const_cast<char*>(reinterpret_cast<const char*>(vecptr(path))), &size) == 0) { + return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path(); + } #elif defined(SWIFTEN_PLATFORM_LINUX) - ByteArray path; - path.resize(4096); - size_t size = static_cast<size_t>(readlink("/proc/self/exe", reinterpret_cast<char*>(vecptr(path)), path.size())); - if (size > 0) { - path.resize(size); - return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path(); - } + ByteArray path; + path.resize(4096); + size_t size = static_cast<size_t>(readlink("/proc/self/exe", reinterpret_cast<char*>(vecptr(path)), path.size())); + if (size > 0) { + path.resize(size); + return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path(); + } #elif defined(SWIFTEN_PLATFORM_WINDOWS) - std::vector<wchar_t> data; - data.resize(2048); - GetModuleFileNameW(NULL, vecptr(data), data.size()); - return boost::filesystem::path( - std::wstring(vecptr(data), data.size())).parent_path(); + std::vector<wchar_t> data; + data.resize(2048); + GetModuleFileNameW(NULL, vecptr(data), data.size()); + return boost::filesystem::path( + std::wstring(vecptr(data), data.size())).parent_path(); #endif - return boost::filesystem::path(); + return boost::filesystem::path(); } } diff --git a/Swiften/Base/Paths.h b/Swiften/Base/Paths.h index 94e62d1..71b55fb 100644 --- a/Swiften/Base/Paths.h +++ b/Swiften/Base/Paths.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,8 +11,8 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API Paths { - public: - static boost::filesystem::path getExecutablePath(); - }; + class SWIFTEN_API Paths { + public: + static boost::filesystem::path getExecutablePath(); + }; } diff --git a/Swiften/Base/Platform.h b/Swiften/Base/Platform.h index a22f556..22dff30 100644 --- a/Swiften/Base/Platform.h +++ b/Swiften/Base/Platform.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -43,9 +43,9 @@ #endif // Endianness -#include <boost/detail/endian.hpp> -#if defined(BOOST_LITTLE_ENDIAN) +#include <boost/predef/other/endian.h> +#if defined(BOOST_ENDIAN_LITTLE_BYTE) #define SWIFTEN_LITTLE_ENDIAN -#elif defined(BOOST_BIG_ENDIAN) +#elif defined(BOOST_ENDIAN_BIG_BYTE) #define SWIFTEN_BIG_ENDIAN #endif diff --git a/Swiften/Base/RandomGenerator.cpp b/Swiften/Base/RandomGenerator.cpp index f2dcca3..e43c01a 100644 --- a/Swiften/Base/RandomGenerator.cpp +++ b/Swiften/Base/RandomGenerator.cpp @@ -1,15 +1,13 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/RandomGenerator.h> namespace Swift { -RandomGenerator::~RandomGenerator() { - -} +RandomGenerator::~RandomGenerator() = default; } diff --git a/Swiften/Base/RandomGenerator.h b/Swiften/Base/RandomGenerator.h index eb5b84d..06677ec 100644 --- a/Swiften/Base/RandomGenerator.h +++ b/Swiften/Base/RandomGenerator.h @@ -1,23 +1,24 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> #include <vector> +#include <Swiften/Base/API.h> + namespace Swift { - class SWIFTEN_API RandomGenerator { - public: - virtual ~RandomGenerator(); + class SWIFTEN_API RandomGenerator { + public: + virtual ~RandomGenerator(); - /** - * Generates a random integer between 0 and 'max', - * 'max' inclusive. - */ - virtual int generateRandomInteger(int max) = 0; - }; + /** + * Generates a random integer between 0 and 'max', + * 'max' inclusive. + */ + virtual int generateRandomInteger(int max) = 0; + }; } diff --git a/Swiften/Base/Regex.cpp b/Swiften/Base/Regex.cpp index 5e3d89a..7843833 100644 --- a/Swiften/Base/Regex.cpp +++ b/Swiften/Base/Regex.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ /* @@ -18,20 +18,20 @@ namespace Swift { - namespace Regex { - std::string escape(const std::string& source) { - // escape regex special characters: ^.$| etc - // these need to be escaped: [\^\$\|.........] - // and then C++ requires '\' to be escaped, too.... - static const boost::regex esc("([\\^\\.\\$\\|\\(\\)\\[\\]\\*\\+\\?\\/\\{\\}\\\\])"); - // matched character should be prepended with '\' - // replace matched special character with \\\1 - // and escape once more for C++ rules... - static const std::string rep("\\\\\\1"); - return boost::regex_replace(source, esc, rep); - } - - } + namespace Regex { + std::string escape(const std::string& source) { + // escape regex special characters: ^.$| etc + // these need to be escaped: [\^\$\|.........] + // and then C++ requires '\' to be escaped, too.... + static const boost::regex esc("([\\^\\.\\$\\|\\(\\)\\[\\]\\*\\+\\?\\/\\{\\}\\\\])"); + // matched character should be prepended with '\' + // replace matched special character with \\\1 + // and escape once more for C++ rules... + static const std::string rep("\\\\\\1"); + return boost::regex_replace(source, esc, rep); + } + + } } - + diff --git a/Swiften/Base/Regex.h b/Swiften/Base/Regex.h index 6d12a60..7d352c0 100644 --- a/Swiften/Base/Regex.h +++ b/Swiften/Base/Regex.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -12,8 +12,8 @@ namespace Swift { - namespace Regex { - SWIFTEN_API std::string escape(const std::string& source); - } + namespace Regex { + SWIFTEN_API std::string escape(const std::string& source); + } } diff --git a/Swiften/Base/SConscript b/Swiften/Base/SConscript index 094059a..1f48f19 100644 --- a/Swiften/Base/SConscript +++ b/Swiften/Base/SConscript @@ -1,21 +1,23 @@ Import("swiften_env") objects = swiften_env.SwiftenObject([ - "ByteArray.cpp", - "DateTime.cpp", - "SafeByteArray.cpp", - "SafeAllocator.cpp", - "Error.cpp", - "Log.cpp", - "Path.cpp", - "Paths.cpp", - "String.cpp", - "IDGenerator.cpp", - "SimpleIDGenerator.cpp", - "RandomGenerator.cpp", - "BoostRandomGenerator.cpp", - "sleep.cpp", - "URL.cpp", - "Regex.cpp" - ]) + "ByteArray.cpp", + "DateTime.cpp", + "Error.cpp", + "FileSize.cpp", + "IDGenerator.cpp", + "Log.cpp", + "LogSerializers.cpp", + "Path.cpp", + "Paths.cpp", + "RandomGenerator.cpp", + "Regex.cpp", + "SafeAllocator.cpp", + "SafeByteArray.cpp", + "SimpleIDGenerator.cpp", + "StdRandomGenerator.cpp", + "String.cpp", + "URL.cpp", + "sleep.cpp", + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Base/SafeAllocator.cpp b/Swiften/Base/SafeAllocator.cpp index d61d8b9..df51e20 100644 --- a/Swiften/Base/SafeAllocator.cpp +++ b/Swiften/Base/SafeAllocator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/SafeByteArray.h> @@ -13,14 +13,14 @@ namespace Swift { -void secureZeroMemory(char* memory, size_t numberOfBytes) { +SWIFTEN_API void secureZeroMemory(char* memory, size_t numberOfBytes) { #ifdef SWIFTEN_PLATFORM_WINDOWS - SecureZeroMemory(memory, numberOfBytes); + SecureZeroMemory(memory, numberOfBytes); #else - volatile char* p = memory; - for (size_t i = 0; i < numberOfBytes; ++i) { - *(p++) = 0; - } + volatile char* p = memory; + for (size_t i = 0; i < numberOfBytes; ++i) { + *(p++) = 0; + } #endif } diff --git a/Swiften/Base/SafeAllocator.h b/Swiften/Base/SafeAllocator.h index b01d77d..d47bb02 100644 --- a/Swiften/Base/SafeAllocator.h +++ b/Swiften/Base/SafeAllocator.h @@ -1,34 +1,36 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <algorithm> +#include <vector> + +#include <Swiften/Base/API.h> namespace Swift { - void secureZeroMemory(char* memory, size_t numberOfBytes); - - template<typename T> - class SafeAllocator : public std::allocator<T> { - public: - template <class U> struct rebind { - typedef SafeAllocator<U> other; - }; - - SafeAllocator() throw() {} - SafeAllocator(const SafeAllocator&) throw() : std::allocator<T>() {} - template <class U> SafeAllocator(const SafeAllocator<U>&) throw() {} - ~SafeAllocator() throw() {} - - void deallocate (T* p, size_t num) { - secureZeroMemory(reinterpret_cast<char*>(p), num); - std::allocator<T>::deallocate(p, num); - } - - private: - }; + SWIFTEN_API void secureZeroMemory(char* memory, size_t numberOfBytes); + + template<typename T> + class SWIFTEN_API SafeAllocator : public std::allocator<T> { + public: + template <class U> struct rebind { + typedef SafeAllocator<U> other; + }; + + SafeAllocator() SWIFTEN_NOEXCEPT {} + SafeAllocator(const SafeAllocator&) SWIFTEN_NOEXCEPT : std::allocator<T>() {} + template <class U> SafeAllocator(const SafeAllocator<U>&) SWIFTEN_NOEXCEPT {} + ~SafeAllocator() SWIFTEN_NOEXCEPT {} + + void deallocate (T* p, size_t num) { + secureZeroMemory(reinterpret_cast<char*>(p), num); + std::allocator<T>::deallocate(p, num); + } + + SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(SafeAllocator) + }; } diff --git a/Swiften/Base/SafeByteArray.cpp b/Swiften/Base/SafeByteArray.cpp index 848b6d8..dd3736e 100644 --- a/Swiften/Base/SafeByteArray.cpp +++ b/Swiften/Base/SafeByteArray.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/SafeByteArray.h> @@ -11,12 +11,12 @@ using namespace Swift; namespace Swift { SafeByteArray createSafeByteArray(const char* c) { - SafeByteArray data; - while (*c) { - data.push_back(static_cast<unsigned char>(*c)); - ++c; - } - return data; + SafeByteArray data; + while (*c) { + data.push_back(static_cast<unsigned char>(*c)); + ++c; + } + return data; } } diff --git a/Swiften/Base/SafeByteArray.h b/Swiften/Base/SafeByteArray.h index b85373c..342c185 100644 --- a/Swiften/Base/SafeByteArray.h +++ b/Swiften/Base/SafeByteArray.h @@ -1,59 +1,59 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <vector> #include <Swiften/Base/API.h> -#include <Swiften/Base/SafeAllocator.h> #include <Swiften/Base/ByteArray.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Base/SafeAllocator.h> namespace Swift { - typedef std::vector<unsigned char, SafeAllocator<unsigned char> > SafeByteArray; + typedef std::vector<unsigned char, SafeAllocator<unsigned char> > SafeByteArray; - inline SafeByteArray createSafeByteArray(const ByteArray& a) { - return SafeByteArray(a.begin(), a.end()); - } + inline SafeByteArray createSafeByteArray(const ByteArray& a) { + return SafeByteArray(a.begin(), a.end()); + } - SWIFTEN_API SafeByteArray createSafeByteArray(const char* c); + SWIFTEN_API SafeByteArray createSafeByteArray(const char* c); - inline SafeByteArray createSafeByteArray(const std::string& s) { - return SafeByteArray(s.begin(), s.end()); - } + inline SafeByteArray createSafeByteArray(const std::string& s) { + return SafeByteArray(s.begin(), s.end()); + } - inline boost::shared_ptr<SafeByteArray> createSafeByteArrayRef(const std::string& s) { - return boost::make_shared<SafeByteArray>(s.begin(), s.end()); - } + inline std::shared_ptr<SafeByteArray> createSafeByteArrayRef(const std::string& s) { + return std::make_shared<SafeByteArray>(s.begin(), s.end()); + } - inline SafeByteArray createSafeByteArray(char c) { - return SafeByteArray(1, static_cast<unsigned char>(c)); - } + inline SafeByteArray createSafeByteArray(char c) { + return SafeByteArray(1, static_cast<unsigned char>(c)); + } - inline SafeByteArray createSafeByteArray(const char* c, size_t n) { - return SafeByteArray(c, c + n); - } + inline SafeByteArray createSafeByteArray(const char* c, size_t n) { + return SafeByteArray(c, c + n); + } - inline boost::shared_ptr<SafeByteArray> createSafeByteArrayRef(const char* c, size_t n) { - return boost::make_shared<SafeByteArray>(c, c + n); - } + inline std::shared_ptr<SafeByteArray> createSafeByteArrayRef(const char* c, size_t n) { + return std::make_shared<SafeByteArray>(c, c + n); + } - inline SafeByteArray createSafeByteArray(const unsigned char* c, size_t n) { - return SafeByteArray(c, c + n); - } + inline SafeByteArray createSafeByteArray(const unsigned char* c, size_t n) { + return SafeByteArray(c, c + n); + } - inline boost::shared_ptr<SafeByteArray> createSafeByteArrayRef(const unsigned char* c, size_t n) { - return boost::make_shared<SafeByteArray>(c, c + n); - } + inline std::shared_ptr<SafeByteArray> createSafeByteArrayRef(const unsigned char* c, size_t n) { + return std::make_shared<SafeByteArray>(c, c + n); + } - /* WARNING! This breaks the safety of the data in the safe byte array. - * Do not use in modes that require data safety. */ - inline std::string safeByteArrayToString(const SafeByteArray& b) { - return byteArrayToString(ByteArray(b.begin(), b.end())); - } + /* WARNING! This breaks the safety of the data in the safe byte array. + * Do not use in modes that require data safety. */ + inline std::string safeByteArrayToString(const SafeByteArray& b) { + return byteArrayToString(ByteArray(b.begin(), b.end())); + } } diff --git a/Swiften/Base/SafeString.h b/Swiften/Base/SafeString.h index ef9c7cc..5e54537 100644 --- a/Swiften/Base/SafeString.h +++ b/Swiften/Base/SafeString.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class SafeString { - public: - SafeString(const SafeByteArray& data) : data(data) { - } + class SWIFTEN_API SafeString { + public: + SafeString(const SafeByteArray& data) : data(data) { + } - SafeString(const std::string& s) { - data = createSafeByteArray(s); - } + SafeString(const std::string& s) { + data = createSafeByteArray(s); + } - SafeString(const char* s) { - data = createSafeByteArray(s); - } + SafeString(const char* s) { + data = createSafeByteArray(s); + } - operator SafeByteArray () const { - return data; - } + operator SafeByteArray () const { + return data; + } - private: - SafeByteArray data; - }; + private: + SafeByteArray data; + }; } diff --git a/Swiften/Base/SimpleIDGenerator.cpp b/Swiften/Base/SimpleIDGenerator.cpp index 06cccea..e6d72b3 100644 --- a/Swiften/Base/SimpleIDGenerator.cpp +++ b/Swiften/Base/SimpleIDGenerator.cpp @@ -1,34 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include "Swiften/Base/SimpleIDGenerator.h" +#include <Swiften/Base/SimpleIDGenerator.h> namespace Swift { SimpleIDGenerator::SimpleIDGenerator() { } +SimpleIDGenerator::~SimpleIDGenerator() { +} + std::string SimpleIDGenerator::generateID() { - bool carry = true; - size_t i = 0; - while (carry && i < currentID.size()) { - char c = currentID[i]; - if (c >= 'z') { - currentID[i] = 'a'; - } - else { - currentID[i] = c+1; - carry = false; - } - ++i; - } - if (carry) { - currentID += 'a'; - } - return currentID; + bool carry = true; + size_t i = 0; + while (carry && i < currentID.size()) { + char c = currentID[i]; + if (c >= 'z') { + currentID[i] = 'a'; + } + else { + currentID[i] = c+1; + carry = false; + } + ++i; + } + if (carry) { + currentID += 'a'; + } + return currentID; } } diff --git a/Swiften/Base/SimpleIDGenerator.h b/Swiften/Base/SimpleIDGenerator.h index fee857d..09e01de 100644 --- a/Swiften/Base/SimpleIDGenerator.h +++ b/Swiften/Base/SimpleIDGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,15 +9,23 @@ #include <string> #include <Swiften/Base/API.h> +#include <Swiften/Base/IDGenerator.h> namespace Swift { - class SWIFTEN_API SimpleIDGenerator { - public: - SimpleIDGenerator(); - std::string generateID(); + /** + * @brief The SimpleIDGenerator class implements a IDGenerator generating consecutive ID strings from + * the lower case latin alphabet. + */ - private: - std::string currentID; - }; + class SWIFTEN_API SimpleIDGenerator : public IDGenerator { + public: + SimpleIDGenerator(); + ~SimpleIDGenerator() override; + + std::string generateID() override; + + private: + std::string currentID; + }; } diff --git a/Swiften/Base/StartStopper.h b/Swiften/Base/StartStopper.h index 7ea6049..af1a72d 100644 --- a/Swiften/Base/StartStopper.h +++ b/Swiften/Base/StartStopper.h @@ -1,23 +1,23 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once namespace Swift { - template<typename T> class StartStopper { - public: - StartStopper(T* target) : target(target) { - target->start(); - } + template<typename T> class StartStopper { + public: + StartStopper(T* target) : target(target) { + target->start(); + } - ~StartStopper() { - target->stop(); - } - - private: - T* target; - }; + ~StartStopper() { + target->stop(); + } + + private: + T* target; + }; } diff --git a/Swiften/Base/StdRandomGenerator.cpp b/Swiften/Base/StdRandomGenerator.cpp new file mode 100644 index 0000000..8b1dee0 --- /dev/null +++ b/Swiften/Base/StdRandomGenerator.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Base/StdRandomGenerator.h> + +#include <algorithm> +#include <functional> + +namespace { + template<class T = std::mt19937, std::size_t N = T::state_size> + typename std::enable_if<!!N, T>::type createSeededRandomEngine() { + typename T::result_type random_data[N]; + std::random_device source; + std::generate(std::begin(random_data), std::end(random_data), std::ref(source)); + std::seed_seq seeds(std::begin(random_data), std::end(random_data)); + return T(seeds); + } +} + +namespace Swift { + +StdRandomGenerator::StdRandomGenerator() : generator(createSeededRandomEngine()) { +} + +int StdRandomGenerator::generateRandomInteger(int maximum) { + std::uniform_int_distribution<> distribution(0, maximum); + return distribution(generator); +} + +} diff --git a/Swiften/Base/StdRandomGenerator.h b/Swiften/Base/StdRandomGenerator.h new file mode 100644 index 0000000..159d361 --- /dev/null +++ b/Swiften/Base/StdRandomGenerator.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <random> + +#include <Swiften/Base/API.h> +#include <Swiften/Base/RandomGenerator.h> + +namespace Swift { + class SWIFTEN_API StdRandomGenerator : public RandomGenerator { + public: + StdRandomGenerator(); + + int generateRandomInteger(int max) override; + + private: + std::mt19937 generator; + }; +} diff --git a/Swiften/Base/String.cpp b/Swiften/Base/String.cpp index 40ea2e1..bbc3003 100644 --- a/Swiften/Base/String.cpp +++ b/Swiften/Base/String.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/Platform.h> @@ -17,136 +17,232 @@ #include <Swiften/Base/String.h> #include <Swiften/Base/ByteArray.h> +namespace { +const static std::uint32_t UTF8_ACCEPT = 0; + +const static std::uint8_t UTF8D[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df + 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef + 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff + 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2 + 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4 + 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6 + 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8 +}; + +//http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ +std::uint32_t decode(std::uint32_t & state, std::uint32_t & codepoint, std::uint8_t byte) { + const auto type = UTF8D[byte]; + codepoint = (state != UTF8_ACCEPT) ? (byte & 0x3fu) | (codepoint << 6) : (0xff >> type) & (byte); + state = UTF8D[256 + state * 16 + type]; + return state; +} + +std::uint32_t getNextCodepoint(const char * begin, const char * end, std::size_t & consumed, bool & ok) { + consumed = 0; + ok = true; + + std::uint32_t state = 0; + std::uint32_t codepoint = 0; + + for (auto it = begin; it != end; ++it) { + ++consumed; + if (!decode(state, codepoint, static_cast<std::uint8_t>(*it))) + return codepoint; + } + if (state != UTF8_ACCEPT) { + ok = false; + } + return codepoint; +} + +} + namespace Swift { static inline size_t sequenceLength(char firstByte) { - if ((firstByte & 0x80) == 0) { - return 1; - } - if ((firstByte & 0xE0) == 0xC0) { - return 2; - } - if ((firstByte & 0xF0) == 0xE0) { - return 3; - } - if ((firstByte & 0xF8) == 0xF0) { - return 4; - } - if ((firstByte & 0xFC) == 0xF8) { - return 5; - } - if ((firstByte & 0xFE) == 0xFC) { - return 6; - } - assert(false); - return 1; + if ((firstByte & 0x80) == 0) { + return 1; + } + if ((firstByte & 0xE0) == 0xC0) { + return 2; + } + if ((firstByte & 0xF0) == 0xE0) { + return 3; + } + if ((firstByte & 0xF8) == 0xF0) { + return 4; + } + if ((firstByte & 0xFC) == 0xF8) { + return 5; + } + if ((firstByte & 0xFE) == 0xFC) { + return 6; + } + assert(false); + return 1; } std::vector<unsigned int> String::getUnicodeCodePoints(const std::string& s) { - std::vector<unsigned int> result; - for (size_t i = 0; i < s.size();) { - unsigned int codePoint = 0; - char firstChar = s[i]; - size_t length = sequenceLength(firstChar); - - // First character is special - size_t firstCharBitSize = 7 - length; - if (length == 1) { - firstCharBitSize = 7; - } - codePoint = firstChar & ((1<<(firstCharBitSize+1)) - 1); - - for (size_t j = 1; j < length; ++j) { - codePoint = (codePoint<<6) | (s[i+j] & 0x3F); - } - result.push_back(codePoint); - i += length; - } - return result; + std::vector<unsigned int> result; + for (size_t i = 0; i < s.size();) { + unsigned int codePoint = 0; + char firstChar = s[i]; + size_t length = sequenceLength(firstChar); + + // First character is special + size_t firstCharBitSize = 7 - length; + if (length == 1) { + firstCharBitSize = 7; + } + codePoint = firstChar & ((1<<(firstCharBitSize+1)) - 1); + + for (size_t j = 1; j < length; ++j) { + codePoint = (codePoint<<6) | (s[i+j] & 0x3F); + } + result.push_back(codePoint); + i += length; + } + return result; } std::pair<std::string,std::string> String::getSplittedAtFirst(const std::string& s, char c) { - assert((c & 0x80) == 0); - size_t firstMatch = s.find(c); - if (firstMatch != s.npos) { - return std::make_pair(s.substr(0,firstMatch),s.substr(firstMatch+1,s.npos)); - } - else { - return std::make_pair(s, ""); - } + assert((c & 0x80) == 0); + size_t firstMatch = s.find(c); + if (firstMatch != s.npos) { + return std::make_pair(s.substr(0,firstMatch),s.substr(firstMatch+1,s.npos)); + } + else { + return std::make_pair(s, ""); + } } void String::replaceAll(std::string& src, char c, const std::string& s) { - size_t lastPos = 0; - size_t matchingIndex = 0; - while ((matchingIndex = src.find(c, lastPos)) != src.npos) { - src.replace(matchingIndex, 1, s); - lastPos = matchingIndex + s.size(); - } + size_t lastPos = 0; + size_t matchingIndex = 0; + while ((matchingIndex = src.find(c, lastPos)) != src.npos) { + src.replace(matchingIndex, 1, s); + lastPos = matchingIndex + s.size(); + } +} + +bool String::isValidXMPPCharacter(std::uint32_t codepoint) { + // Special accepted characters: + if (codepoint == '\t' || codepoint == '\r' || codepoint == '\n') + return true; + // Discouraged characters: + if (codepoint >= 0x7Fu && codepoint <= 0x84u) + return false; + if (codepoint >= 0x86u && codepoint <= 0x9Fu) + return false; + if (codepoint >= 0xFDD0u && codepoint <= 0xFDEFu) + return false; + if (((codepoint & 0xFFFEu) == 0xFFEEu) || ((codepoint & 0xFFFFu) == 0xFFFFu)) + return false; + // Other valid characters (after filtering for discouraged ones above) + if (codepoint >= 0x20u && codepoint <= 0xD7FFu) + return true; + if (codepoint >= 0xE000u && codepoint <= 0xFFFDu) + return true; + if (codepoint >= 0x10000u && codepoint <= 0x10FFFFu) + return true; + return false; +} + +std::string String::sanitizeXMPPString(const std::string& input) { + std::string result; + result.reserve(input.length()); + + auto it = input.data(); + const auto end = it + input.length(); + + std::size_t consumed; + bool status = UTF8_ACCEPT; + + while (it < end) { + const auto codepoint = getNextCodepoint(it, end, consumed, status); + if (status) { + if (isValidXMPPCharacter(codepoint)) { + std::copy(it, it + consumed, std::back_inserter(result)); + } + it += consumed; + } + else { + ++it; + } + } + result.shrink_to_fit(); + return result; } std::vector<std::string> String::split(const std::string& s, char c) { - assert((c & 0x80) == 0); - std::vector<std::string> result; - std::string accumulator; - for (size_t i = 0; i < s.size(); ++i) { - if (s[i] == c) { - result.push_back(accumulator); - accumulator = ""; - } - else { - accumulator += s[i]; - } - } - result.push_back(accumulator); - return result; + assert((c & 0x80) == 0); + std::vector<std::string> result; + std::string accumulator; + for (char i : s) { + if (i == c) { + result.push_back(accumulator); + accumulator = ""; + } + else { + accumulator += i; + } + } + result.push_back(accumulator); + return result; } std::string String::convertIntToHexString(int h) { - std::stringstream ss; - ss << std::setbase(16); - ss << h; - return ss.str(); + std::stringstream ss; + ss << std::setbase(16); + ss << h; + return ss.str(); } int String::convertHexStringToInt(const std::string& s) { - std::stringstream ss; - int h; - ss << std::setbase(16); - ss << s; - ss >> h; - return h; + std::stringstream ss; + int h; + ss << std::setbase(16); + ss << s; + ss >> h; + return h; } - #ifdef SWIFTEN_PLATFORM_WINDOWS std::string convertWStringToString(const std::wstring& s) { - int utf8Size = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, NULL, 0, NULL, NULL); - if (utf8Size < 0) { - throw std::runtime_error("Conversion error"); - } - std::vector<char> utf8Data(utf8Size); - int result = WideCharToMultiByte( - CP_UTF8, 0, s.c_str(), -1, vecptr(utf8Data), utf8Data.size(), NULL, NULL); - if (result < 0) { - throw std::runtime_error("Conversion error"); - } - return std::string(vecptr(utf8Data), utf8Size-1 /* trailing 0 character */); + int utf8Size = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, NULL, 0, NULL, NULL); + if (utf8Size < 0) { + throw std::runtime_error("Conversion error"); + } + std::vector<char> utf8Data(utf8Size); + int result = WideCharToMultiByte( + CP_UTF8, 0, s.c_str(), -1, vecptr(utf8Data), utf8Data.size(), NULL, NULL); + if (result < 0) { + throw std::runtime_error("Conversion error"); + } + return std::string(vecptr(utf8Data), utf8Size-1 /* trailing 0 character */); } std::wstring convertStringToWString(const std::string& s) { - int utf16Size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0); - if (utf16Size < 0) { - throw std::runtime_error("Conversion error"); - } - std::vector<wchar_t> utf16Data(utf16Size); - int result = MultiByteToWideChar( - CP_UTF8, 0, s.c_str(), -1, vecptr(utf16Data), utf16Data.size()); - if (result < 0) { - throw std::runtime_error("Conversion error"); - } - return std::wstring(vecptr(utf16Data), utf16Size-1 /* trailing 0 character */); + int utf16Size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0); + if (utf16Size < 0) { + throw std::runtime_error("Conversion error"); + } + std::vector<wchar_t> utf16Data(utf16Size); + int result = MultiByteToWideChar( + CP_UTF8, 0, s.c_str(), -1, vecptr(utf16Data), utf16Data.size()); + if (result < 0) { + throw std::runtime_error("Conversion error"); + } + return std::wstring(vecptr(utf16Data), utf16Size-1 /* trailing 0 character */); } #endif diff --git a/Swiften/Base/String.h b/Swiften/Base/String.h index 5a5642e..3a7ca65 100644 --- a/Swiften/Base/String.h +++ b/Swiften/Base/String.h @@ -1,58 +1,60 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <cstdint> +#include <sstream> #include <string> #include <vector> -#include <sstream> #include <Swiften/Base/API.h> #include <Swiften/Base/Platform.h> - #define SWIFTEN_STRING_TO_CFSTRING(a) \ - CFStringCreateWithBytes(NULL, reinterpret_cast<const UInt8*>(a.c_str()), a.size(), kCFStringEncodingUTF8, false) + CFStringCreateWithBytes(NULL, reinterpret_cast<const UInt8*>(a.c_str()), a.size(), kCFStringEncodingUTF8, false) namespace Swift { - namespace String { - SWIFTEN_API std::vector<unsigned int> getUnicodeCodePoints(const std::string&); - SWIFTEN_API std::pair<std::string, std::string> getSplittedAtFirst(const std::string&, char c); - SWIFTEN_API std::vector<std::string> split(const std::string&, char c); - SWIFTEN_API void replaceAll(std::string&, char c, const std::string& s); + namespace String { + SWIFTEN_API std::vector<unsigned int> getUnicodeCodePoints(const std::string&); + SWIFTEN_API std::pair<std::string, std::string> getSplittedAtFirst(const std::string&, char c); + SWIFTEN_API std::vector<std::string> split(const std::string&, char c); + SWIFTEN_API void replaceAll(std::string&, char c, const std::string& s); + SWIFTEN_API bool isValidXMPPCharacter(std::uint32_t codepoint); + SWIFTEN_API std::string sanitizeXMPPString(const std::string& input); - inline bool beginsWith(const std::string& s, char c) { - return s.size() > 0 && s[0] == c; - } + inline bool beginsWith(const std::string& s, char c) { + return s.size() > 0 && s[0] == c; + } - inline bool endsWith(const std::string& s, char c) { - return s.size() > 0 && s[s.size()-1] == c; - } + inline bool endsWith(const std::string& s, char c) { + return s.size() > 0 && s[s.size()-1] == c; + } - std::string convertIntToHexString(int h); - int convertHexStringToInt(const std::string& s); + std::string convertIntToHexString(int h); + int convertHexStringToInt(const std::string& s); - } + } #ifdef SWIFTEN_PLATFORM_WINDOWS - SWIFTEN_API std::string convertWStringToString(const std::wstring& s); - SWIFTEN_API std::wstring convertStringToWString(const std::string& s); + SWIFTEN_API std::string convertWStringToString(const std::wstring& s); + SWIFTEN_API std::wstring convertStringToWString(const std::string& s); #endif - class SWIFTEN_API makeString { - public: - template <typename T> makeString& operator<<(T const& v) { - stream << v; - return *this; - } + class SWIFTEN_API makeString { + public: + template <typename T> makeString& operator<<(T const& v) { + stream << v; + return *this; + } - operator std::string() const { - return stream.str(); - } + operator std::string() const { + return stream.str(); + } - private: - std::ostringstream stream; - }; + private: + std::ostringstream stream; + }; } diff --git a/Swiften/Base/Tristate.h b/Swiften/Base/Tristate.h new file mode 100644 index 0000000..edb7444 --- /dev/null +++ b/Swiften/Base/Tristate.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +namespace Swift { + +enum Tristate {Yes, No, Maybe}; + +} diff --git a/Swiften/Base/URL.cpp b/Swiften/Base/URL.cpp index 866cd45..5c0f0d7 100644 --- a/Swiften/Base/URL.cpp +++ b/Swiften/Base/URL.cpp @@ -1,114 +1,141 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/URL.h> +#include <algorithm> #include <iostream> namespace Swift { -int URL::getPortOrDefaultPort(const URL& url) { - if (url.getPort()) { - return *url.getPort(); - } - else if (url.getScheme() == "http") { - return 80; - } - else if (url.getScheme() == "https") { - return 443; - } - else { - std::cerr << "Unknown scheme: " + url.getScheme() << std::endl; - return 80; - } +unsigned short URL::getPortOrDefaultPort(const URL& url) { + if (url.getPort()) { + return *url.getPort(); + } + else if (url.getScheme() == "http") { + return 80; + } + else if (url.getScheme() == "https") { + return 443; + } + else { + std::cerr << "Unknown scheme: " + url.getScheme() << std::endl; + return 80; + } } URL URL::fromString(const std::string& urlString) { - size_t colonIndex = urlString.find(':'); - if (colonIndex == std::string::npos) { - return URL(); - } - std::string scheme = urlString.substr(0, colonIndex); + size_t colonIndex = urlString.find(':'); + if (colonIndex == std::string::npos) { + return URL(); + } + std::string scheme = urlString.substr(0, colonIndex); - // Authority - if (urlString.size() > colonIndex + 2 && urlString[colonIndex+1] == '/' && urlString[colonIndex+2] == '/') { - size_t authorityIndex = colonIndex + 3; - size_t slashIndex = urlString.find('/', authorityIndex); - std::string authority; - std::string path; - if (slashIndex == std::string::npos) { - authority = urlString.substr(authorityIndex); - path = ""; - } - else { - authority = urlString.substr(authorityIndex, slashIndex - authorityIndex); - path = unescape(urlString.substr(slashIndex)); - } + // Authority + if (urlString.size() > colonIndex + 2 && urlString[colonIndex+1] == '/' && urlString[colonIndex+2] == '/') { + size_t authorityIndex = colonIndex + 3; + size_t slashIndex = urlString.find('/', authorityIndex); + std::string authority; + std::string path; + if (slashIndex == std::string::npos) { + authority = urlString.substr(authorityIndex); + path = ""; + } + else { + authority = urlString.substr(authorityIndex, slashIndex - authorityIndex); + path = unescape(urlString.substr(slashIndex)); + } - size_t atIndex = authority.find('@'); - std::string userInfo; - std::string hostAndPort; - if (atIndex != std::string::npos) { - userInfo = authority.substr(0, atIndex); - hostAndPort = authority.substr(atIndex + 1); - } - else { - userInfo = ""; - hostAndPort = authority; - } + size_t atIndex = authority.find('@'); + std::string userInfo; + std::string hostAndPort; + if (atIndex != std::string::npos) { + userInfo = authority.substr(0, atIndex); + hostAndPort = authority.substr(atIndex + 1); + } + else { + userInfo = ""; + hostAndPort = authority; + } - std::string host; - boost::optional<int> port; - colonIndex = hostAndPort.find(':'); - if (colonIndex != std::string::npos) { - host = unescape(hostAndPort.substr(0, colonIndex)); - try { - port = boost::lexical_cast<int>(hostAndPort.substr(colonIndex + 1)); - } - catch (const boost::bad_lexical_cast&) { - return URL(); - } - } - else { - host = unescape(hostAndPort); - } + std::string host; + boost::optional<unsigned short> port; + if (hostAndPort[0] == '[') { + // handle IPv6 address literals + size_t addressEndIndex = hostAndPort.find(']'); + if (addressEndIndex != std::string::npos) { + host = hostAndPort.substr(1, addressEndIndex - 1); + colonIndex = hostAndPort.find(':', addressEndIndex); + if (colonIndex != std::string::npos) { + try { + port = boost::numeric_cast<unsigned short>(boost::lexical_cast<int>(hostAndPort.substr(colonIndex + 1))); + } + catch (...) { + return URL(); + } + } + } + else { + return URL(); + } + } + else { + colonIndex = hostAndPort.find(':'); + if (colonIndex != std::string::npos) { + host = unescape(hostAndPort.substr(0, colonIndex)); + try { + port = boost::numeric_cast<unsigned short>(boost::lexical_cast<int>(hostAndPort.substr(colonIndex + 1))); + } + catch (const boost::bad_lexical_cast&) { + return URL(); + } + } + else { + host = unescape(hostAndPort); + } + } - if (port) { - return URL(scheme, host, *port, path); - } - else { - return URL(scheme, host, path); - } - } - else { - // We don't support URLs without authorities yet - return URL(); - } + if (port) { + return URL(scheme, host, *port, path); + } + else { + return URL(scheme, host, path); + } + } + else { + // We don't support URLs without authorities yet + return URL(); + } } // FIXME: Escape non-ascii characters std::string URL::toString() const { - if (empty) { - return ""; - } - std::string result = scheme + "://"; - if (!user.empty()) { - result += user; - if (!password.empty()) { - result += ":" + password; - } - result += "@"; - } - result += host; - if (port) { - result += ":"; - result += boost::lexical_cast<std::string>(*port); - } - result += path; - return result; + if (empty) { + return ""; + } + std::string result = scheme + "://"; + if (!user.empty()) { + result += user; + if (!password.empty()) { + result += ":" + password; + } + result += "@"; + } + if (host.find(':') != std::string::npos) { + result += "[" + host + "]"; + } + else { + result += host; + } + if (port) { + result += ":"; + result += std::to_string(*port); + } + result += path; + return result; } // Disabling this code for now, since GCC4.5+boost1.42 (on ubuntu) seems to @@ -118,72 +145,72 @@ std::string URL::toString() const { struct PercentEncodedCharacterFinder { template<typename Iterator> boost::iterator_range<Iterator> operator()(Iterator begin, Iterator end) { - boost::iterator_range<Iterator> r = boost::first_finder("%")(begin, end); - if (r.end() == end) { - return r; - } - else { - if (r.end() + 1 == end || r.end() + 2 == end) { - throw std::runtime_error("Incomplete escape character"); - } - else { - r.advance_end(2); - return r; - } - } + boost::iterator_range<Iterator> r = boost::first_finder("%")(begin, end); + if (r.end() == end) { + return r; + } + else { + if (r.end() + 1 == end || r.end() + 2 == end) { + throw std::runtime_error("Incomplete escape character"); + } + else { + r.advance_end(2); + return r; + } + } } }; struct PercentUnencodeFormatter { template<typename FindResult> std::string operator()(const FindResult& match) const { - std::stringstream s; - s << std::hex << std::string(match.begin() + 1, match.end()); - unsigned int value; - s >> value; - if (s.fail() || s.bad()) { - throw std::runtime_error("Invalid escape character"); - } - unsigned char charValue = static_cast<unsigned char>(value); - return std::string(reinterpret_cast<const char*>(&charValue), 1); + std::stringstream s; + s << std::hex << std::string(match.begin() + 1, match.end()); + unsigned int value; + s >> value; + if (s.fail() || s.bad()) { + throw std::runtime_error("Invalid escape character"); + } + unsigned char charValue = static_cast<unsigned char>(value); + return std::string(reinterpret_cast<const char*>(&charValue), 1); } }; std::string unescape(const std::string& s) { - try { - return boost::find_format_all_copy(s, PercentEncodedCharacterFinder(), PercentUnencodeFormatter()); - } - catch (const std::exception&) { - return ""; - } + try { + return boost::find_format_all_copy(s, PercentEncodedCharacterFinder(), PercentUnencodeFormatter()); + } + catch (const std::exception&) { + return ""; + } } #endif std::string URL::unescape(const std::string& str) { - std::string result; - for (size_t i = 0; i < str.size(); ++i) { - if (str[i] == '%') { - if (i + 3 < str.size()) { - std::stringstream s; - s << std::hex << str.substr(i+1, 2); - unsigned int value; - s >> value; - if (s.fail() || s.bad()) { - return ""; - } - unsigned char charValue = static_cast<unsigned char>(value); - result += std::string(reinterpret_cast<const char*>(&charValue), 1); - i += 2; - } - else { - return ""; - } - } - else { - result += str[i]; - } - } - return result; + std::string result; + for (size_t i = 0; i < str.size(); ++i) { + if (str[i] == '%') { + if (i + 3 < str.size()) { + std::stringstream s; + s << std::hex << str.substr(i+1, 2); + unsigned int value; + s >> value; + if (s.fail() || s.bad()) { + return ""; + } + unsigned char charValue = static_cast<unsigned char>(value); + result += std::string(reinterpret_cast<const char*>(&charValue), 1); + i += 2; + } + else { + return ""; + } + } + else { + result += str[i]; + } + } + return result; } } diff --git a/Swiften/Base/URL.h b/Swiften/Base/URL.h index 75cf1a6..8fdb018 100644 --- a/Swiften/Base/URL.h +++ b/Swiften/Base/URL.h @@ -1,79 +1,81 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + #include <boost/lexical_cast.hpp> #include <boost/optional.hpp> + #include <Swiften/Base/API.h> namespace Swift { class SWIFTEN_API URL { - public: - - URL() : scheme(""), user(""), password(""), host(""), path(""), empty(true) { - } - - URL(const std::string& scheme, const std::string& host, int port, const std::string& path) : scheme(scheme), user(), password(), host(host), port(port), path(path), empty(false) { - } - - URL(const std::string& scheme, const std::string& host, const std::string& path) : scheme(scheme), user(), password(), host(host), path(path), empty(false) { - } - - /** - * Whether the URL is empty. - */ - bool isEmpty() const { - return empty; - } - - /** - * Scheme used for the URL (http, https etc.) - */ - const std::string& getScheme() const { - return scheme; - } - - /** - * Hostname - */ - const std::string& getHost() const { - return host; - } - - /** - * Port number - */ - boost::optional<int> getPort() const { - return port; - } - - /** - * Path - */ - const std::string& getPath() const { - return path; - } - - std::string toString() const; - - static int getPortOrDefaultPort(const URL& url); - static URL fromString(const std::string&); - static std::string unescape(const std::string&); - - - private: - std::string scheme; - std::string user; - std::string password; - std::string host; - boost::optional<int> port; - std::string path; - bool empty; - }; + public: + + URL() : scheme(""), user(""), password(""), host(""), path(""), empty(true) { + } + + URL(const std::string& scheme, const std::string& host, unsigned short port, const std::string& path) : scheme(scheme), user(), password(), host(host), port(port), path(path), empty(false) { + } + + URL(const std::string& scheme, const std::string& host, const std::string& path) : scheme(scheme), user(), password(), host(host), path(path), empty(false) { + } + + /** + * Whether the URL is empty. + */ + bool isEmpty() const { + return empty; + } + + /** + * Scheme used for the URL (http, https etc.) + */ + const std::string& getScheme() const { + return scheme; + } + + /** + * Hostname + */ + const std::string& getHost() const { + return host; + } + + /** + * Port number + */ + boost::optional<unsigned short> getPort() const { + return port; + } + + /** + * Path + */ + const std::string& getPath() const { + return path; + } + + std::string toString() const; + + static unsigned short getPortOrDefaultPort(const URL& url); + static URL fromString(const std::string&); + static std::string unescape(const std::string&); + + + private: + std::string scheme; + std::string user; + std::string password; + std::string host; + boost::optional<unsigned short> port; + std::string path; + bool empty; + }; } diff --git a/Swiften/Base/UnitTest/ByteArrayTest.cpp b/Swiften/Base/UnitTest/ByteArrayTest.cpp index ecd0439..f1732ae 100644 --- a/Swiften/Base/UnitTest/ByteArrayTest.cpp +++ b/Swiften/Base/UnitTest/ByteArrayTest.cpp @@ -1,56 +1,43 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> - -#include <Swiften/Base/ByteArray.h> #include <boost/lexical_cast.hpp> -using namespace Swift; +#include <gtest/gtest.h> -class ByteArrayTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ByteArrayTest); - CPPUNIT_TEST(testGetData_NoData); - CPPUNIT_TEST(testToString); - CPPUNIT_TEST(testToString_NullTerminated); - CPPUNIT_TEST(testToString_TwoNullTerminated); - CPPUNIT_TEST(testToString_AllNull); - CPPUNIT_TEST_SUITE_END(); +#include <Swiften/Base/ByteArray.h> - public: - void testGetData_NoData() { - ByteArray testling; +using namespace Swift; - CPPUNIT_ASSERT_EQUAL(reinterpret_cast<const char*>(NULL), reinterpret_cast<const char*>(vecptr(testling))); - } +TEST(ByteArrayTest, testGetData_NoData) { + ByteArray testling; - void testToString() { - ByteArray testling(createByteArray("abcde")); + ASSERT_EQ(reinterpret_cast<const char*>(NULL), reinterpret_cast<const char*>(vecptr(testling))); +} - CPPUNIT_ASSERT_EQUAL(std::string("abcde"), byteArrayToString(testling)); - } +TEST(ByteArrayTest, testToString) { + ByteArray testling(createByteArray("abcde")); - void testToString_NullTerminated() { - ByteArray testling(createByteArray("abcde\0", 6)); + ASSERT_EQ(std::string("abcde"), byteArrayToString(testling)); +} - CPPUNIT_ASSERT_EQUAL(std::string("abcde"), byteArrayToString(testling)); - } +TEST(ByteArrayTest, testToString_NullTerminated) { + ByteArray testling(createByteArray("abcde\0", 6)); - void testToString_TwoNullTerminated() { - ByteArray testling(createByteArray("abcde\0\0", 7)); + ASSERT_EQ(std::string("abcde"), byteArrayToString(testling)); +} - CPPUNIT_ASSERT_EQUAL(std::string("abcde"), byteArrayToString(testling)); - } +TEST(ByteArrayTest, testToString_TwoNullTerminated) { + ByteArray testling(createByteArray("abcde\0\0", 7)); - void testToString_AllNull() { - ByteArray testling(createByteArray("\0\0", 2)); + ASSERT_EQ(std::string("abcde"), byteArrayToString(testling)); +} - CPPUNIT_ASSERT_EQUAL(std::string(""), byteArrayToString(testling)); - } -}; +TEST(ByteArrayTest, testToString_AllNull) { + ByteArray testling(createByteArray("\0\0", 2)); -CPPUNIT_TEST_SUITE_REGISTRATION(ByteArrayTest); + ASSERT_EQ(std::string(""), byteArrayToString(testling)); +} diff --git a/Swiften/Base/UnitTest/DateTimeTest.cpp b/Swiften/Base/UnitTest/DateTimeTest.cpp index 8c3903a..6a82d96 100644 --- a/Swiften/Base/UnitTest/DateTimeTest.cpp +++ b/Swiften/Base/UnitTest/DateTimeTest.cpp @@ -1,43 +1,52 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> #include <string> + #include <boost/date_time/posix_time/posix_time.hpp> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + #include <Swiften/Base/DateTime.h> using namespace Swift; class DateTimeTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DateTimeTest); - CPPUNIT_TEST(testStringToDateTime_UTC); - CPPUNIT_TEST(testStringToDateTime_WithTimezone); - CPPUNIT_TEST(testDateTimeToString); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(DateTimeTest); + CPPUNIT_TEST(testStringToDateTime_UTC); + CPPUNIT_TEST(testStringToDateTime_WithTimezone); + CPPUNIT_TEST(testDateTimeToString); + CPPUNIT_TEST(testDateTimeToLocalStringNotThrowingException); + CPPUNIT_TEST_SUITE_END(); + + public: + void testStringToDateTime_UTC() { + boost::posix_time::ptime time = stringToDateTime("1969-07-21T02:56:15Z"); + + CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15"), boost::posix_time::to_iso_extended_string(time)); + } - public: - void testStringToDateTime_UTC() { - boost::posix_time::ptime time = stringToDateTime("1969-07-21T02:56:15Z"); + void testStringToDateTime_WithTimezone() { + boost::posix_time::ptime time = stringToDateTime("1969-07-20T21:56:15-05:00"); - CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15"), boost::posix_time::to_iso_extended_string(time)); - } + CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15"), boost::posix_time::to_iso_extended_string(time)); + } - void testStringToDateTime_WithTimezone() { - boost::posix_time::ptime time = stringToDateTime("1969-07-20T21:56:15-05:00"); + void testDateTimeToString() { + boost::posix_time::ptime time = stringToDateTime("1969-07-20T21:56:15-05:00"); - CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15"), boost::posix_time::to_iso_extended_string(time)); - } + CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15Z"), dateTimeToString(time)); + } - void testDateTimeToString() { - boost::posix_time::ptime time = stringToDateTime("1969-07-20T21:56:15-05:00"); + void testDateTimeToLocalStringNotThrowingException() { + boost::posix_time::ptime time = stringToDateTime("1954-07-20T21:56:15-05:00"); - CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15Z"), dateTimeToString(time)); - } + CPPUNIT_ASSERT_EQUAL(std::string(""), dateTimeToLocalString(time)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(DateTimeTest); diff --git a/Swiften/Base/UnitTest/IDGeneratorTest.cpp b/Swiften/Base/UnitTest/IDGeneratorTest.cpp index 610138f..08bd48b 100644 --- a/Swiften/Base/UnitTest/IDGeneratorTest.cpp +++ b/Swiften/Base/UnitTest/IDGeneratorTest.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <set> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <set> #include <Swiften/Base/IDGenerator.h> @@ -14,27 +15,27 @@ using namespace Swift; class IDGeneratorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IDGeneratorTest); - CPPUNIT_TEST(testGenerate); - CPPUNIT_TEST_SUITE_END(); - - public: - IDGeneratorTest() {} - - void setUp() { - generatedIDs_.clear(); - } - - void testGenerate() { - IDGenerator testling; - for (unsigned int i = 0; i < 26*4; ++i) { - std::string id = testling.generateID(); - CPPUNIT_ASSERT(generatedIDs_.insert(id).second); - } - } - - private: - std::set<std::string> generatedIDs_; + CPPUNIT_TEST_SUITE(IDGeneratorTest); + CPPUNIT_TEST(testGenerate); + CPPUNIT_TEST_SUITE_END(); + + public: + IDGeneratorTest() {} + + void setUp() { + generatedIDs_.clear(); + } + + void testGenerate() { + IDGenerator testling; + for (unsigned int i = 0; i < 26*4; ++i) { + std::string id = testling.generateID(); + CPPUNIT_ASSERT(generatedIDs_.insert(id).second); + } + } + + private: + std::set<std::string> generatedIDs_; }; CPPUNIT_TEST_SUITE_REGISTRATION(IDGeneratorTest); diff --git a/Swiften/Base/UnitTest/LRUCacheTest.cpp b/Swiften/Base/UnitTest/LRUCacheTest.cpp new file mode 100644 index 0000000..7d54c5c --- /dev/null +++ b/Swiften/Base/UnitTest/LRUCacheTest.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <string> + +#include <boost/optional.hpp> + +#include <Swiften/Base/LogSerializers.h> +#include <Swiften/Base/LRUCache.h> + +#include <gtest/gtest.h> // This has to go after Swiften/Base/LogSerializers.h. + +using namespace Swift; +namespace b = boost; + +TEST(LRUCacheTest, testCacheLimit) { + LRUCache<std::string, std::string, 3> testling; + + testling.insert("A", "AA"); + testling.insert("B", "BB"); + testling.insert("C", "CC"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>(), testling.get("D")); + + testling.insert("D", "DD"); + + ASSERT_EQ(b::optional<std::string>(), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>("DD"), testling.get("D")); +} + +TEST(LRUCacheTest, testMoveRecentToFrontOnGet) { + LRUCache<std::string, std::string, 3> testling; + + testling.insert("A", "AA"); + testling.insert("B", "BB"); + testling.insert("C", "CC"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>(), testling.get("D")); + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + + testling.insert("D", "DD"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>(), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>("DD"), testling.get("D")); +} + +TEST(LRUCacheTest, testMoveRecentToFrontOnReinsert) { + LRUCache<std::string, std::string, 3> testling; + + testling.insert("A", "AA"); + testling.insert("B", "BB"); + testling.insert("C", "CC"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>(), testling.get("D")); + + testling.insert("B", "BB"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>(), testling.get("D")); + + testling.insert("D", "DD"); + + ASSERT_EQ(b::optional<std::string>(), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>("DD"), testling.get("D")); +} + +TEST(LRUCacheTest, testCacheReturnsValuesPreviouslyInserted) { + LRUCache<std::string, std::string, 3> testling; + + testling.insert("A", "AA"); + testling.insert("B", "BB"); + testling.insert("C", "CC"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); +} + +TEST(LRUCacheTest, testCacheMissFunctionIsUsedOnCacheMiss) { + LRUCache<std::string, std::string, 3> testling; + + testling.insert("A", "AA"); + testling.insert("B", "BB"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C", [](const std::string&) { + return boost::optional<std::string>(std::string("CC")); + })); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + + ASSERT_EQ(b::optional<std::string>(), testling.get("D", [](const std::string&) { + return boost::optional<std::string>(); + })); + ASSERT_EQ(b::optional<std::string>(), testling.get("D")); +} diff --git a/Swiften/Base/UnitTest/LogTest.cpp b/Swiften/Base/UnitTest/LogTest.cpp new file mode 100644 index 0000000..5d710db --- /dev/null +++ b/Swiften/Base/UnitTest/LogTest.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <vector> + +#include <boost/algorithm/string/predicate.hpp> + +#include <gtest/gtest.h> + +#include <Swiften/Base/Log.h> + +using namespace Swift; + +struct LogEntry { + LogEntry(Log::Severity severity, std::string file, int line, std::string function, std::string message) : severity(severity), file(std::move(file)), line(line), function(std::move(function)), message(std::move(message)) {} + + Log::Severity severity; + std::string file; + int line; + std::string function; + std::string message; +}; + +// Helper class to set the logging callback. Using this class to set it will ensure the +// logCallback is reset to empty (its default state) after each test. +class LogCallbackSetter { +public: + LogCallbackSetter(Log::Callback callback) { + Log::setLogCallback(callback); + } + ~LogCallbackSetter() { + Log::setLogCallback({}); + } +}; + +TEST(LogTest, testCallback) { + std::vector<LogEntry> logEntries; + LogCallbackSetter callbackSetter = {[&](Log::Severity severity, const std::string& file, int line, const std::string& function, const std::string& message) { + logEntries.emplace_back(severity, file, line, function, message); + }}; + + SWIFT_LOG(error) << "An error"; + ASSERT_EQ(1, logEntries.size()); + ASSERT_EQ(Log::error, logEntries[0].severity); + ASSERT_EQ("An error", logEntries[0].message); +} diff --git a/Swiften/Base/UnitTest/PathTest.cpp b/Swiften/Base/UnitTest/PathTest.cpp index f5f99e7..dd2233b 100644 --- a/Swiften/Base/UnitTest/PathTest.cpp +++ b/Swiften/Base/UnitTest/PathTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,23 +13,23 @@ using namespace Swift; class PathTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PathTest); - CPPUNIT_TEST(testStringToPath); - CPPUNIT_TEST(testPathToString); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(PathTest); + CPPUNIT_TEST(testStringToPath); + CPPUNIT_TEST(testPathToString); + CPPUNIT_TEST_SUITE_END(); - public: - void testStringToPath() { + public: + void testStringToPath() { #ifdef SWIFTEN_PLATFORM_WINDOWS - CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == stringToPath("tron\xc3\xa7on").native()); + CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == stringToPath("tron\xc3\xa7on").native()); #else - CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), stringToPath("tron\xc3\xa7on").native()); + CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), stringToPath("tron\xc3\xa7on").native()); #endif - } + } - void testPathToString() { - CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), pathToString(stringToPath("tron\xc3\xa7on"))); - } + void testPathToString() { + CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), pathToString(stringToPath("tron\xc3\xa7on"))); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(PathTest); diff --git a/Swiften/Base/UnitTest/SimpleIDGeneratorTest.cpp b/Swiften/Base/UnitTest/SimpleIDGeneratorTest.cpp index 80aff02..9b49c0a 100644 --- a/Swiften/Base/UnitTest/SimpleIDGeneratorTest.cpp +++ b/Swiften/Base/UnitTest/SimpleIDGeneratorTest.cpp @@ -1,40 +1,41 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <set> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <set> -#include "Swiften/Base/SimpleIDGenerator.h" +#include <Swiften/Base/SimpleIDGenerator.h> using namespace Swift; class SimpleIDGeneratorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SimpleIDGeneratorTest); - CPPUNIT_TEST(testGenerate); - CPPUNIT_TEST_SUITE_END(); - - public: - SimpleIDGeneratorTest() {} - - void setUp() { - generatedIDs_.clear(); - } - - void testGenerate() { - SimpleIDGenerator testling; - for (unsigned int i = 0; i < 26*4; ++i) { - std::string id = testling.generateID(); - CPPUNIT_ASSERT(generatedIDs_.insert(id).second); - } - } - - private: - std::set<std::string> generatedIDs_; + CPPUNIT_TEST_SUITE(SimpleIDGeneratorTest); + CPPUNIT_TEST(testGenerate); + CPPUNIT_TEST_SUITE_END(); + + public: + SimpleIDGeneratorTest() {} + + void setUp() { + generatedIDs_.clear(); + } + + void testGenerate() { + SimpleIDGenerator testling; + for (unsigned int i = 0; i < 26*4; ++i) { + std::string id = testling.generateID(); + CPPUNIT_ASSERT(generatedIDs_.insert(id).second); + } + } + + private: + std::set<std::string> generatedIDs_; }; CPPUNIT_TEST_SUITE_REGISTRATION(SimpleIDGeneratorTest); diff --git a/Swiften/Base/UnitTest/StringTest.cpp b/Swiften/Base/UnitTest/StringTest.cpp index ffca98a..889c9c7 100644 --- a/Swiften/Base/UnitTest/StringTest.cpp +++ b/Swiften/Base/UnitTest/StringTest.cpp @@ -1,128 +1,171 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <string> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <string> -#include <Swiften/Base/String.h> #include <Swiften/Base/Platform.h> +#include <Swiften/Base/String.h> + +#include <boost/format.hpp> using namespace Swift; -class StringTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StringTest); - CPPUNIT_TEST(testGetUnicodeCodePoints); - CPPUNIT_TEST(testGetSplittedAtFirst); - CPPUNIT_TEST(testGetSplittedAtFirst_CharacterAtBegin); - CPPUNIT_TEST(testGetSplittedAtFirst_CharacterAtEnd); - CPPUNIT_TEST(testGetSplittedAtFirst_NoSuchCharacter); - CPPUNIT_TEST(testReplaceAll); - CPPUNIT_TEST(testReplaceAll_LastChar); - CPPUNIT_TEST(testReplaceAll_ConsecutiveChars); - CPPUNIT_TEST(testReplaceAll_MatchingReplace); - CPPUNIT_TEST(testSplit); + class StringTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(StringTest); + CPPUNIT_TEST(testGetUnicodeCodePoints); + CPPUNIT_TEST(testGetSplittedAtFirst); + CPPUNIT_TEST(testGetSplittedAtFirst_CharacterAtBegin); + CPPUNIT_TEST(testGetSplittedAtFirst_CharacterAtEnd); + CPPUNIT_TEST(testGetSplittedAtFirst_NoSuchCharacter); + CPPUNIT_TEST(testReplaceAll); + CPPUNIT_TEST(testReplaceAll_LastChar); + CPPUNIT_TEST(testReplaceAll_ConsecutiveChars); + CPPUNIT_TEST(testReplaceAll_MatchingReplace); + CPPUNIT_TEST(testIsValidXMPPCharacter); + CPPUNIT_TEST(testSanitizeXMPPString); + CPPUNIT_TEST(testSplit); #ifdef SWIFTEN_PLATFORM_WINDOWS - CPPUNIT_TEST(testConvertWStringToString); - CPPUNIT_TEST(testConvertStringToWString); + CPPUNIT_TEST(testConvertWStringToString); + CPPUNIT_TEST(testConvertStringToWString); #endif - CPPUNIT_TEST_SUITE_END(); - - public: - void testGetUnicodeCodePoints() { - std::string testling("$\xc2\xa2\xe2\x82\xac\xf4\x8a\xaf\x8d"); - std::vector<unsigned int> points = String::getUnicodeCodePoints(testling); - - CPPUNIT_ASSERT_EQUAL(0x24U, points[0]); - CPPUNIT_ASSERT_EQUAL(0xA2U, points[1]); - CPPUNIT_ASSERT_EQUAL(0x20ACU, points[2]); - CPPUNIT_ASSERT_EQUAL(0x10ABCDU, points[3]); - } - - void testGetSplittedAtFirst() { - std::string testling("ab@cd@ef"); - - std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); - CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); - CPPUNIT_ASSERT_EQUAL(std::string("cd@ef"), result.second); - } - - void testGetSplittedAtFirst_CharacterAtBegin() { - std::string testling(" ab"); - - std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, ' '); - CPPUNIT_ASSERT(result.first.empty()); - CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.second); - } - - void testGetSplittedAtFirst_CharacterAtEnd() { - std::string testling("ab@"); - - std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); - CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); - CPPUNIT_ASSERT(result.second.empty()); - } - - void testGetSplittedAtFirst_NoSuchCharacter() { - std::string testling("ab"); - - std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); - CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); - CPPUNIT_ASSERT(result.second.empty()); - } - - void testReplaceAll() { - std::string testling("abcbd"); - - String::replaceAll(testling, 'b', "xyz"); - - CPPUNIT_ASSERT_EQUAL(std::string("axyzcxyzd"), testling); - } - - void testReplaceAll_LastChar() { - std::string testling("abc"); - - String::replaceAll(testling, 'c', "xyz"); - - CPPUNIT_ASSERT_EQUAL(std::string("abxyz"), testling); - } - - void testReplaceAll_ConsecutiveChars() { - std::string testling("abbc"); - - String::replaceAll(testling, 'b',"xyz"); - - CPPUNIT_ASSERT_EQUAL(std::string("axyzxyzc"), testling); - } - - void testReplaceAll_MatchingReplace() { - std::string testling("abc"); - - String::replaceAll(testling, 'b',"bbb"); - - CPPUNIT_ASSERT_EQUAL(std::string("abbbc"), testling); - } - - void testSplit() { - std::vector<std::string> result = String::split("abc def ghi", ' '); + CPPUNIT_TEST_SUITE_END(); - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(result.size())); - CPPUNIT_ASSERT_EQUAL(std::string("abc"), result[0]); - CPPUNIT_ASSERT_EQUAL(std::string("def"), result[1]); - CPPUNIT_ASSERT_EQUAL(std::string("ghi"), result[2]); - } + public: + void testGetUnicodeCodePoints() { + std::string testling("$\xc2\xa2\xe2\x82\xac\xf4\x8a\xaf\x8d"); + std::vector<unsigned int> points = String::getUnicodeCodePoints(testling); + + CPPUNIT_ASSERT_EQUAL(0x24U, points[0]); + CPPUNIT_ASSERT_EQUAL(0xA2U, points[1]); + CPPUNIT_ASSERT_EQUAL(0x20ACU, points[2]); + CPPUNIT_ASSERT_EQUAL(0x10ABCDU, points[3]); + } + + void testGetSplittedAtFirst() { + std::string testling("ab@cd@ef"); + + std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); + CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); + CPPUNIT_ASSERT_EQUAL(std::string("cd@ef"), result.second); + } + + void testGetSplittedAtFirst_CharacterAtBegin() { + std::string testling(" ab"); + + std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, ' '); + CPPUNIT_ASSERT(result.first.empty()); + CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.second); + } + + void testGetSplittedAtFirst_CharacterAtEnd() { + std::string testling("ab@"); + + std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); + CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); + CPPUNIT_ASSERT(result.second.empty()); + } + + void testGetSplittedAtFirst_NoSuchCharacter() { + std::string testling("ab"); + + std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); + CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); + CPPUNIT_ASSERT(result.second.empty()); + } + + void testReplaceAll() { + std::string testling("abcbd"); + + String::replaceAll(testling, 'b', "xyz"); + + CPPUNIT_ASSERT_EQUAL(std::string("axyzcxyzd"), testling); + } + + void testReplaceAll_LastChar() { + std::string testling("abc"); + + String::replaceAll(testling, 'c', "xyz"); + + CPPUNIT_ASSERT_EQUAL(std::string("abxyz"), testling); + } + + void testReplaceAll_ConsecutiveChars() { + std::string testling("abbc"); + + String::replaceAll(testling, 'b',"xyz"); + + CPPUNIT_ASSERT_EQUAL(std::string("axyzxyzc"), testling); + } + + void testReplaceAll_MatchingReplace() { + std::string testling("abc"); + + String::replaceAll(testling, 'b',"bbb"); + + CPPUNIT_ASSERT_EQUAL(std::string("abbbc"), testling); + } + + void testIsValidXMPPCharacter() { + const std::uint32_t testCharacters[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x7F, 0x80, 0x84, 0x85, 0xFF }; + const auto testLength = sizeof(testCharacters) / sizeof(std::uint32_t); + const bool expectedValid[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 1 }; + static_assert(testLength == sizeof(expectedValid), "size of test data must match"); + + for (std::size_t i = 0; i != testLength; ++i) { + const auto c = testCharacters[i]; + CPPUNIT_ASSERT_EQUAL_MESSAGE(boost::str(boost::format("While testing at idx=%d: 0x%02x") % i % c), expectedValid[i], String::isValidXMPPCharacter(c)); + } + } + + void testSanitizeXMPPString() { + std::vector<std::pair<std::string, std::string>> testData = { + { "\0", "" }, + { std::string("\0\t", 3), "\t" }, + { "", "" }, + { std::string("\0", 1) , std::string() }, + { std::string("\0blah\0", 6) , std::string("blah", 4) }, + { "z\xC3\x9F\xE6\xB0\xB4\xF0\x9D\x84\x8B" , "z\xC3\x9F\xE6\xB0\xB4\xF0\x9D\x84\x8B" }, // or in u8 notation: u8"z\u00df\u6c34\U0001d10b" + { "\x7FT\t\x0c\xff\xfeT", "T\tT" }, + { "\x01Q\x0BW\x81T", "QWT" }, + { "\xF0\x9F\x98\x83" "ABC" "\xE2\xBE\xA6", "\xF0\x9F\x98\x83" "ABC" "\xE2\xBE\xA6" } + }; + + for (std::size_t i = 0; i != testData.size(); ++i) { + const auto & t = testData[i]; + const auto actual = String::sanitizeXMPPString(t.first); + CPPUNIT_ASSERT_EQUAL_MESSAGE(boost::str(boost::format("While testing string idx=%d") % i), std::string(actual), t.second); + } + } + + void testSplit() { + std::vector<std::string> result = String::split("abc def ghi", ' '); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(result.size())); + CPPUNIT_ASSERT_EQUAL(std::string("abc"), result[0]); + CPPUNIT_ASSERT_EQUAL(std::string("def"), result[1]); + CPPUNIT_ASSERT_EQUAL(std::string("ghi"), result[2]); + } #ifdef SWIFTEN_PLATFORM_WINDOWS - void testConvertWStringToString() { - CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), convertWStringToString(std::wstring(L"tron\xe7on"))); - } + void testConvertWStringToString() { + CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), convertWStringToString(std::wstring(L"tron\xe7on"))); + } - void testConvertStringToWString() { - CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == convertStringToWString(std::string("tron\xc3\xa7on"))); - } + void testConvertStringToWString() { + CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == convertStringToWString(std::string("tron\xc3\xa7on"))); + } #endif }; diff --git a/Swiften/Base/UnitTest/URLTest.cpp b/Swiften/Base/UnitTest/URLTest.cpp index e82321f..da9f15c 100644 --- a/Swiften/Base/UnitTest/URLTest.cpp +++ b/Swiften/Base/UnitTest/URLTest.cpp @@ -1,114 +1,238 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <boost/lexical_cast.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Base/URL.h> -#include <boost/lexical_cast.hpp> using namespace Swift; class URLTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(URLTest); - CPPUNIT_TEST(testFromString); - CPPUNIT_TEST(testFromString_WithoutPath); - CPPUNIT_TEST(testFromString_WithRootPath); - CPPUNIT_TEST(testFromString_WithPort); - CPPUNIT_TEST(testFromString_WithPortOnePartPath); - CPPUNIT_TEST(testFromString_WithPortWithoutPath); - CPPUNIT_TEST(testFromString_WithUserInfo); - CPPUNIT_TEST(testFromString_NonASCIIHost); - CPPUNIT_TEST(testFromString_NonASCIIPath); - CPPUNIT_TEST(testToString); - CPPUNIT_TEST(testToString_WithPort); - CPPUNIT_TEST_SUITE_END(); - - public: - void testFromString() { - URL url = URL::fromString("http://foo.bar/baz/bam"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT(!url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); - } - - void testFromString_WithoutPath() { - URL url = URL::fromString("http://foo.bar"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT(!url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); - } - - void testFromString_WithRootPath() { - URL url = URL::fromString("http://foo.bar/"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT(!url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("/"), url.getPath()); - } - - void testFromString_WithPort() { - URL url = URL::fromString("http://foo.bar:1234/baz/bam"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT_EQUAL(1234, *url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); - } - - void testFromString_WithPortOnePartPath() { - URL url = URL::fromString("http://foo.bar:11440/http-bind/"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT_EQUAL(11440, *url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("/http-bind/"), url.getPath()); - } - - void testFromString_WithPortWithoutPath() { - URL url = URL::fromString("http://foo.bar:1234"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT_EQUAL(1234, *url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); - } - - void testFromString_WithUserInfo() { - URL url = URL::fromString("http://user:pass@foo.bar/baz/bam"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); - } - - void testFromString_NonASCIIHost() { - URL url = URL::fromString("http://www.tron%C3%A7on.be/baz/bam"); - - CPPUNIT_ASSERT_EQUAL(std::string("www.tron\xc3\xa7on.be"), url.getHost()); - } - - void testFromString_NonASCIIPath() { - URL url = URL::fromString("http://foo.bar/baz/tron%C3%A7on/bam"); - - CPPUNIT_ASSERT_EQUAL(std::string("/baz/tron\xc3\xa7on/bam"), url.getPath()); - } - - void testToString() { - CPPUNIT_ASSERT_EQUAL(std::string("http://foo.bar/baz/bam"), URL("http", "foo.bar", "/baz/bam").toString()); - } - - void testToString_WithPort() { - CPPUNIT_ASSERT_EQUAL(std::string("http://foo.bar:1234/baz/bam"), URL("http", "foo.bar", 1234, "/baz/bam").toString()); - } + CPPUNIT_TEST_SUITE(URLTest); + CPPUNIT_TEST(testFromString); + CPPUNIT_TEST(testFromString_WithoutPath); + CPPUNIT_TEST(testFromString_WithRootPath); + CPPUNIT_TEST(testFromString_WithPort); + CPPUNIT_TEST(testFromString_WithPortOnePartPath); + CPPUNIT_TEST(testFromString_WithPortWithoutPath); + CPPUNIT_TEST(testFromString_WithUserInfo); + CPPUNIT_TEST(testFromString_NonASCIIHost); + CPPUNIT_TEST(testFromString_NonASCIIPath); + CPPUNIT_TEST(testFromString_IPv4Address); + CPPUNIT_TEST(testFromString_IPv4AddressWithPort); + CPPUNIT_TEST(testFromString_IPv6Address); + CPPUNIT_TEST(testFromString_IPv6AddressWithPort); + CPPUNIT_TEST(testToString); + CPPUNIT_TEST(testToString_WithPort); + CPPUNIT_TEST(test_FromString_ToString_IPv6RFC2732); + CPPUNIT_TEST_SUITE_END(); + + public: + void testFromString() { + URL url = URL::fromString("http://foo.bar/baz/bam"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT(!url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); + } + + void testFromString_WithoutPath() { + URL url = URL::fromString("http://foo.bar"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT(!url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); + } + + void testFromString_WithRootPath() { + URL url = URL::fromString("http://foo.bar/"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT(!url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string("/"), url.getPath()); + } + + void testFromString_WithPort() { + URL url = URL::fromString("http://foo.bar:1234/baz/bam"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(1234), *url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); + } + + void testFromString_WithPortOnePartPath() { + URL url = URL::fromString("http://foo.bar:11440/http-bind/"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(11440), *url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string("/http-bind/"), url.getPath()); + } + + void testFromString_WithPortWithoutPath() { + URL url = URL::fromString("http://foo.bar:1234"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(1234), *url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); + } + + void testFromString_WithUserInfo() { + URL url = URL::fromString("http://user:pass@foo.bar/baz/bam"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); + } + + void testFromString_NonASCIIHost() { + URL url = URL::fromString("http://www.tron%C3%A7on.be/baz/bam"); + + CPPUNIT_ASSERT_EQUAL(std::string("www.tron\xc3\xa7on.be"), url.getHost()); + } + + void testFromString_NonASCIIPath() { + URL url = URL::fromString("http://foo.bar/baz/tron%C3%A7on/bam"); + + CPPUNIT_ASSERT_EQUAL(std::string("/baz/tron\xc3\xa7on/bam"), url.getPath()); + } + + void testFromString_IPv4Address() { + URL url = URL::fromString("http://127.0.0.1/foobar"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(std::string("/foobar"), url.getPath()); + } + + void testFromString_IPv4AddressWithPort() { + URL url = URL::fromString("http://127.0.0.1:12345/foobar"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(12345), url.getPort().get_value_or(0)); + CPPUNIT_ASSERT_EQUAL(std::string("/foobar"), url.getPath()); + } + + void testFromString_IPv6Address() { + URL url = URL::fromString("http://[fdf8:f53b:82e4::53]/foobar"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("fdf8:f53b:82e4::53"), url.getHost()); + } + + void testFromString_IPv6AddressWithPort() { + URL url = URL::fromString("http://[fdf8:f53b:82e4::53]:12435/foobar"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("fdf8:f53b:82e4::53"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(12435), url.getPort().get_value_or(0)); + } + + void test_FromString_ToString_IPv6RFC2732() { + { + const char* testVector = "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(80), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string("/index.html"), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[1080:0:0:0:8:800:200C:417A]/index.html"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("1080:0:0:0:8:800:200C:417A"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string("/index.html"), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[3ffe:2a00:100:7031::1]"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("3ffe:2a00:100:7031::1"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[1080::8:800:200C:417A]/foo"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("1080::8:800:200C:417A"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string("/foo"), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[::192.9.5.5]/ipng"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("::192.9.5.5"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string("/ipng"), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[::FFFF:129.144.52.38]:80/index.html"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("::FFFF:129.144.52.38"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(80), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string("/index.html"), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[2010:836B:4179::836B:4179]"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("2010:836B:4179::836B:4179"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string(), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + } + + void testToString() { + CPPUNIT_ASSERT_EQUAL(std::string("http://foo.bar/baz/bam"), URL("http", "foo.bar", "/baz/bam").toString()); + } + + void testToString_WithPort() { + CPPUNIT_ASSERT_EQUAL(std::string("http://foo.bar:1234/baz/bam"), URL("http", "foo.bar", 1234, "/baz/bam").toString()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(URLTest); diff --git a/Swiften/Base/WindowsRegistry.h b/Swiften/Base/WindowsRegistry.h index 11a26b3..6243dd2 100644 --- a/Swiften/Base/WindowsRegistry.h +++ b/Swiften/Base/WindowsRegistry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,49 +9,49 @@ #include <windows.h> namespace Swift { - class WindowsRegistry { - public: - static bool isFIPSEnabled() { - char* pathForXP = "System\\CurrentControlSet\\Control\\Lsa"; - char* pathSinceVista = "System\\CurrentControlSet\\Control\\Lsa\\FIPSAlgorithmPolicy"; - char* keyForXP = "FIPSAlgorithmPolicy"; - char* keySinceVista = "Enabled"; - - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - - char* keyForOS = osvi.dwMajorVersion < 6 ? keyForXP : keySinceVista; - char* pathForOS = osvi.dwMajorVersion < 6 ? pathForXP : pathSinceVista; - - /* http://support.microsoft.com/kb/811833 */ - /* http://msdn.microsoft.com/en-us/library/ms724911%28VS.85%29.aspx */ - HKEY key; - bool result = false; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, - pathForOS, - 0, - KEY_READ, - &key) != ERROR_SUCCESS) { - /* If we can't find the key that says we're FIPS, we're not FIPS */ - return result; - } - DWORD keyType = REG_DWORD; - DWORD data; - DWORD length = sizeof(data); - - if (RegQueryValueEx(key, - keyForOS, - NULL, - &keyType, - (LPBYTE)&data, - &length) == ERROR_SUCCESS) { - result = data != 0; - } - - RegCloseKey(key); - return result; - } - }; + class WindowsRegistry { + public: + static bool isFIPSEnabled() { + char* pathForXP = "System\\CurrentControlSet\\Control\\Lsa"; + char* pathSinceVista = "System\\CurrentControlSet\\Control\\Lsa\\FIPSAlgorithmPolicy"; + char* keyForXP = "FIPSAlgorithmPolicy"; + char* keySinceVista = "Enabled"; + + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + char* keyForOS = osvi.dwMajorVersion < 6 ? keyForXP : keySinceVista; + char* pathForOS = osvi.dwMajorVersion < 6 ? pathForXP : pathSinceVista; + + /* http://support.microsoft.com/kb/811833 */ + /* http://msdn.microsoft.com/en-us/library/ms724911%28VS.85%29.aspx */ + HKEY key; + bool result = false; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, + pathForOS, + 0, + KEY_READ, + &key) != ERROR_SUCCESS) { + /* If we can't find the key that says we're FIPS, we're not FIPS */ + return result; + } + DWORD keyType = REG_DWORD; + DWORD data; + DWORD length = sizeof(data); + + if (RegQueryValueEx(key, + keyForOS, + NULL, + &keyType, + (LPBYTE)&data, + &length) == ERROR_SUCCESS) { + result = data != 0; + } + + RegCloseKey(key); + return result; + } + }; } diff --git a/Swiften/Base/boost_bsignals.h b/Swiften/Base/boost_bsignals.h deleted file mode 100644 index 7609c94..0000000 --- a/Swiften/Base/boost_bsignals.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -// Work around for the boost::signals / Qt signals keyword clash. -// Based on an example from Frank Hess, improved by Niels Dekker - -#pragma once - -#if defined(signals) && defined(Q_SIGNALS) && !defined(QT_MOC_CPP) -#undef signals -#define signals signals -#endif - -#include <boost/signal.hpp> - -namespace boost { - namespace bsignals = signals; -} - -#if defined(signals) && defined(Q_SIGNALS) && !defined(QT_MOC_CPP) -#undef signals -#define signals Q_SIGNALS -#endif diff --git a/Swiften/Base/foreach.h b/Swiften/Base/foreach.h deleted file mode 100644 index 3ad506d..0000000 --- a/Swiften/Base/foreach.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include <boost/foreach.hpp> - -#undef foreach -#define foreach BOOST_FOREACH -#define reverse_foreach BOOST_REVERSE_FOREACH diff --git a/Swiften/Base/format.h b/Swiften/Base/format.h index 0e49eaa..e5696b0 100644 --- a/Swiften/Base/format.h +++ b/Swiften/Base/format.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/format.hpp> #include <iostream> +#include <boost/format.hpp> + namespace Swift { - inline boost::format format(const std::string& s) { - using namespace boost::io; - try { - boost::format fmter(s); - fmter.exceptions(no_error_bits); - return fmter; - } - catch (...) { - std::cerr << "Error: Invalid translation: " << s << std::endl; - throw; - } - } + inline boost::format format(const std::string& s) { + using namespace boost::io; + try { + boost::format fmter(s); + fmter.exceptions(no_error_bits); + return fmter; + } + catch (...) { + std::cerr << "Error: Invalid translation: " << s << std::endl; + throw; + } + } } diff --git a/Swiften/Base/sleep.cpp b/Swiften/Base/sleep.cpp index 0f1937b..48eae51 100644 --- a/Swiften/Base/sleep.cpp +++ b/Swiften/Base/sleep.cpp @@ -1,25 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/sleep.h> -#include <boost/thread.hpp> -#include <boost/version.hpp> +#include <chrono> +#include <thread> namespace Swift { void sleep(unsigned int msecs) { - boost::xtime xt; -#if BOOST_VERSION >= 105000 - boost::xtime_get(&xt, boost::TIME_UTC_); -#else - boost::xtime_get(&xt, boost::TIME_UTC); -#endif - xt.nsec += msecs*1000000; - boost::thread::sleep(xt); + std::this_thread::sleep_for(std::chrono::milliseconds(msecs)); } } diff --git a/Swiften/Base/sleep.h b/Swiften/Base/sleep.h index afcf6c7..744e19f 100644 --- a/Swiften/Base/sleep.h +++ b/Swiften/Base/sleep.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,5 +9,5 @@ #include <Swiften/Base/API.h> namespace Swift { - SWIFTEN_API void sleep(unsigned int msecs); + SWIFTEN_API void sleep(unsigned int msecs); } diff --git a/Swiften/ChangeLog.md b/Swiften/ChangeLog.md new file mode 100644 index 0000000..60355b4 --- /dev/null +++ b/Swiften/ChangeLog.md @@ -0,0 +1,45 @@ +5-in-progress +------------- +- Update build system from scons 2.4.0 to 3.0.1 + +4.0.1 (2018-03-28) +------------------ +- Fix handling errors when fetching own vCard + +4.0 (2018-03-20) +---------------- +- Moved code-base to C++11 + - Use C++11 threading instead of Boost.Thread library + - Use C++11 smart pointers instead of Boost's +- Migrated from Boost.Signals to Boost.Signals2 +- Build without warnings on our CI platforms +- General cleanup like remove of superflous files and #include statements. This means header files that previously were included implictly need to be explicitly included now +- Support IPv6 addresses in URLs +- Handle sessions being closed by the server +- Verify certificates when using HTTPS in BOSH connections +- In memory caching of latest entity capabilites lookups +- Changed source code style to use soft tabs (4 spaces wide) instead of hard tabs. Custom patches for Swiften will need to be reformatted accordingly +- Require a TLS backend for building +- Update 3rdParty/lcov to version 1.12 +- Fix several possible race conditions, smaller leaks, and other small bugs + +4.0-rc1 ( 2017-05-17 ) +---------------------- +- Handle sessions being closed by the server +- Verify certificates when using HTTPS in BOSH connections +- In memory caching of latest entity capabilites lookups +- Fix several smaller leaks and other bugs + +4.0-beta1 ( 2016-07-15 ) +------------------------ +- Moved code-base to C++11 + - Use C++11 threading instead of Boost.Thread library + - Use C++11 smart pointers instead of Boost's +- Migrated from Boost.Signals to Boost.Signals2 +- Build without warnings on our CI platforms +- General cleanup like remove of superflous files and #include statements. This means header files that previously were included implictly need to be explicitly included now +- Support IPv6 addresses in URLs +- Changed source code style to use soft tabs (4 spaces wide) instead of hard tabs. Custom patches for Swiften will need to be reformatted accordingly +- Require a TLS backend for building +- Update 3rdParty/lcov to version 1.12 +- Fix several possible race conditions and other small bugs
\ No newline at end of file diff --git a/Swiften/Chat/ChatStateNotifier.cpp b/Swiften/Chat/ChatStateNotifier.cpp index d507c4d..48a65ab 100644 --- a/Swiften/Chat/ChatStateNotifier.cpp +++ b/Swiften/Chat/ChatStateNotifier.cpp @@ -1,93 +1,117 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Chat/ChatStateNotifier.h> +#include <cassert> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Elements/Message.h> -#include <Swiften/Elements/ChatState.h> #include <Swiften/Client/StanzaChannel.h> #include <Swiften/Disco/EntityCapsProvider.h> +#include <Swiften/Elements/ChatState.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Network/Timer.h> +#include <Swiften/Network/TimerFactory.h> + namespace Swift { -ChatStateNotifier::ChatStateNotifier(StanzaChannel* stanzaChannel, const JID& contact, EntityCapsProvider* entityCapsManager) : stanzaChannel_(stanzaChannel), entityCapsManager_(entityCapsManager), contact_(contact) { - setContact(contact); - entityCapsManager_->onCapsChanged.connect(boost::bind(&ChatStateNotifier::handleCapsChanged, this, _1)); + +ChatStateNotifier::ChatStateNotifier(StanzaChannel* stanzaChannel, const JID& contact, EntityCapsProvider* entityCapsManager, TimerFactory* timerFactory, int idleTimeInMilliSecs) : stanzaChannel_(stanzaChannel), entityCapsManager_(entityCapsManager), contact_(contact) { + setContact(contact); + entityCapsManager_->onCapsChanged.connect(boost::bind(&ChatStateNotifier::handleCapsChanged, this, _1)); + assert(timerFactory); + idleTimer_ = timerFactory->createTimer(idleTimeInMilliSecs); + assert(!!idleTimer_); + idleTimer_->onTick.connect(boost::bind(&ChatStateNotifier::userBecameIdleWhileTyping, this)); } ChatStateNotifier::~ChatStateNotifier() { - entityCapsManager_->onCapsChanged.disconnect(boost::bind(&ChatStateNotifier::handleCapsChanged, this, _1)); + entityCapsManager_->onCapsChanged.disconnect(boost::bind(&ChatStateNotifier::handleCapsChanged, this, _1)); + idleTimer_->stop(); + idleTimer_->onTick.disconnect(boost::bind(&ChatStateNotifier::userBecameIdleWhileTyping, this)); } void ChatStateNotifier::setContact(const JID& contact) { - contactHasSentActive_ = false; - userIsTyping_ = false; - contactIsOnline_ = false; - contact_ = contact; - handleCapsChanged(contact_); + contactHasSentActive_ = false; + userIsTyping_ = false; + contactIsOnline_ = false; + contact_ = contact; + handleCapsChanged(contact_); } void ChatStateNotifier::setContactIsOnline(bool online) { - contactIsOnline_ = online; + contactIsOnline_ = online; } void ChatStateNotifier::setUserIsTyping() { - bool should = contactShouldReceiveStates(); - if (should && !userIsTyping_) { - userIsTyping_ = true; - changeState(ChatState::Composing); - } + idleTimer_->stop(); + bool should = contactShouldReceiveStates(); + if (should && !userIsTyping_) { + userIsTyping_ = true; + changeState(ChatState::Composing); + } + if (should) { + idleTimer_->start(); + } } void ChatStateNotifier::userSentMessage() { - userIsTyping_ = false; + idleTimer_->stop(); + userIsTyping_ = false; } void ChatStateNotifier::userCancelledNewMessage() { - if (userIsTyping_) { - userIsTyping_ = false; - changeState(ChatState::Active); - } + idleTimer_->stop(); + if (userIsTyping_) { + userIsTyping_ = false; + changeState(ChatState::Active); + } +} + +void ChatStateNotifier::userBecameIdleWhileTyping() { + // For now we are returning to active state. When support for the Paused, Inactive and Gone states + // is implemeted, this function should Implement the Pause/Inactive functionality. + userCancelledNewMessage(); } void ChatStateNotifier::receivedMessageFromContact(bool hasActiveElement) { - contactHasSentActive_ = hasActiveElement; + contactHasSentActive_ = hasActiveElement; } bool ChatStateNotifier::contactShouldReceiveStates() { - /* So, yes, the XEP says to look at caps, but it also says that once you've - heard from the contact, the active state overrides this. - *HOWEVER* it says that the MUST NOT send csn if you haven't received - active is OPTIONAL behaviour for if you haven't got caps.*/ - return contactIsOnline_ && (contactHasSentActive_ || contactHas85Caps_); + /* So, yes, the XEP says to look at caps, but it also says that once you've + heard from the contact, the active state overrides this. + *HOWEVER* it says that the MUST NOT send csn if you haven't received + active is OPTIONAL behaviour for if you haven't got caps.*/ + return contactIsOnline_ && (contactHasSentActive_ || contactHas85Caps_); } void ChatStateNotifier::changeState(ChatState::ChatStateType state) { - boost::shared_ptr<Message> message(boost::make_shared<Message>()); - message->setTo(contact_); - message->addPayload(boost::make_shared<ChatState>(state)); - stanzaChannel_->sendMessage(message); + std::shared_ptr<Message> message(std::make_shared<Message>()); + message->setTo(contact_); + message->addPayload(std::make_shared<ChatState>(state)); + stanzaChannel_->sendMessage(message); } void ChatStateNotifier::addChatStateRequest(Message::ref message) { - if (contactShouldReceiveStates()) { - message->addPayload(boost::make_shared<ChatState>(ChatState::Active)); - } + if (contactShouldReceiveStates()) { + message->addPayload(std::make_shared<ChatState>(ChatState::Active)); + } } void ChatStateNotifier::handleCapsChanged(const JID& jid) { - if (jid == contact_) { - DiscoInfo::ref caps = entityCapsManager_->getCaps(contact_); - bool hasCSN = caps && caps->hasFeature(DiscoInfo::ChatStatesFeature); - contactHas85Caps_ = hasCSN; - } + if (jid == contact_) { + DiscoInfo::ref caps = entityCapsManager_->getCaps(contact_); + bool hasCSN = caps && caps->hasFeature(DiscoInfo::ChatStatesFeature); + contactHas85Caps_ = hasCSN; + } } } diff --git a/Swiften/Chat/ChatStateNotifier.h b/Swiften/Chat/ChatStateNotifier.h index 5b99266..2b24c76 100644 --- a/Swiften/Chat/ChatStateNotifier.h +++ b/Swiften/Chat/ChatStateNotifier.h @@ -1,51 +1,58 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Elements/Message.h> #include <Swiften/Elements/ChatState.h> +#include <Swiften/Elements/Message.h> #include <Swiften/JID/JID.h> namespace Swift { - class StanzaChannel; - class EntityCapsProvider; - - class SWIFTEN_API ChatStateNotifier { - public: - ChatStateNotifier(StanzaChannel* stanzaChannel, const JID& contact, EntityCapsProvider* entityCapsManager); - ~ChatStateNotifier(); - - void setContact(const JID& contact); - - void addChatStateRequest(Message::ref message); - - void setUserIsTyping(); - void userSentMessage(); - void userCancelledNewMessage(); - - void receivedMessageFromContact(bool hasActiveElement); - void setContactIsOnline(bool online); - - private: - bool contactShouldReceiveStates(); - void changeState(ChatState::ChatStateType type); - void handleCapsChanged(const JID& contact); - - private: - StanzaChannel* stanzaChannel_; - EntityCapsProvider* entityCapsManager_; - JID contact_; - bool contactHas85Caps_; - bool contactHasSentActive_; - bool userIsTyping_; - bool contactIsOnline_; - }; + class StanzaChannel; + class EntityCapsProvider; + class TimerFactory; + class Timer; + + + class SWIFTEN_API ChatStateNotifier { + public: + ChatStateNotifier(StanzaChannel* stanzaChannel, const JID& contact, EntityCapsProvider* entityCapsManager, TimerFactory* timerFactory, int idleTimeInMilliSecs); + ~ChatStateNotifier(); + + void setContact(const JID& contact); + + void addChatStateRequest(Message::ref message); + + void setUserIsTyping(); + void userSentMessage(); + void userCancelledNewMessage(); + + void receivedMessageFromContact(bool hasActiveElement); + void setContactIsOnline(bool online); + + private: + void userBecameIdleWhileTyping(); + bool contactShouldReceiveStates(); + void changeState(ChatState::ChatStateType type); + void handleCapsChanged(const JID& contact); + + private: + StanzaChannel* stanzaChannel_; + EntityCapsProvider* entityCapsManager_; + JID contact_; + bool contactHas85Caps_; + bool contactHasSentActive_; + bool userIsTyping_; + bool contactIsOnline_; + std::shared_ptr<Timer> idleTimer_; + + }; } diff --git a/Swiften/Chat/ChatStateTracker.cpp b/Swiften/Chat/ChatStateTracker.cpp index 27be86c..839f47d 100644 --- a/Swiften/Chat/ChatStateTracker.cpp +++ b/Swiften/Chat/ChatStateTracker.cpp @@ -1,37 +1,37 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Chat/ChatStateTracker.h> namespace Swift { ChatStateTracker::ChatStateTracker() { - currentState_ = ChatState::Gone; + currentState_ = ChatState::Gone; } -void ChatStateTracker::handleMessageReceived(boost::shared_ptr<Message> message) { - if (message->getType() == Message::Error) { - return; - } - boost::shared_ptr<ChatState> statePayload = message->getPayload<ChatState>(); - if (statePayload) { - changeState(statePayload->getChatState());; - } +void ChatStateTracker::handleMessageReceived(std::shared_ptr<Message> message) { + if (message->getType() == Message::Error) { + return; + } + std::shared_ptr<ChatState> statePayload = message->getPayload<ChatState>(); + if (statePayload) { + changeState(statePayload->getChatState()); + } } -void ChatStateTracker::handlePresenceChange(boost::shared_ptr<Presence> newPresence) { - if (newPresence->getType() == Presence::Unavailable) { - onChatStateChange(ChatState::Gone); - } +void ChatStateTracker::handlePresenceChange(std::shared_ptr<Presence> newPresence) { + if (newPresence->getType() == Presence::Unavailable) { + onChatStateChange(ChatState::Gone); + } } void ChatStateTracker::changeState(ChatState::ChatStateType state) { - if (state != currentState_) { - currentState_ = state; - onChatStateChange(state); - } + if (state != currentState_) { + currentState_ = state; + onChatStateChange(state); + } } } diff --git a/Swiften/Chat/ChatStateTracker.h b/Swiften/Chat/ChatStateTracker.h index e401b0a..c903e3a 100644 --- a/Swiften/Chat/ChatStateTracker.h +++ b/Swiften/Chat/ChatStateTracker.h @@ -1,28 +1,29 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/API.h> +#include <memory> + +#include <boost/signals2.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ChatState.h> #include <Swiften/Elements/Message.h> #include <Swiften/Elements/Presence.h> -#include <Swiften/Elements/ChatState.h> namespace Swift { - class SWIFTEN_API ChatStateTracker { - public: - ChatStateTracker(); - void handleMessageReceived(boost::shared_ptr<Message> message); - void handlePresenceChange(boost::shared_ptr<Presence> newPresence); - boost::signal<void (ChatState::ChatStateType)> onChatStateChange; - private: - void changeState(ChatState::ChatStateType state); - ChatState::ChatStateType currentState_; - }; + class SWIFTEN_API ChatStateTracker { + public: + ChatStateTracker(); + void handleMessageReceived(std::shared_ptr<Message> message); + void handlePresenceChange(std::shared_ptr<Presence> newPresence); + boost::signals2::signal<void (ChatState::ChatStateType)> onChatStateChange; + private: + void changeState(ChatState::ChatStateType state); + ChatState::ChatStateType currentState_; + }; } diff --git a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp index 1b91076..b6c909a 100644 --- a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp +++ b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp @@ -1,168 +1,186 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> #include <boost/bind.hpp> -#include <Swiften/Base/foreach.h> +#include <gtest/gtest.h> + #include <Swiften/Chat/ChatStateNotifier.h> #include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Disco/DummyEntityCapsProvider.h> +#include <Swiften/Network/DummyTimerFactory.h> + +// Clang wrongly things that tests for 0 are using 0 as null. +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" using namespace Swift; -class ChatStateNotifierTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ChatStateNotifierTest); - CPPUNIT_TEST(testStartTypingReply_CapsNotIncluded); - CPPUNIT_TEST(testStartTypingReply_CapsIncluded); - CPPUNIT_TEST(testCancelledNewMessage); - CPPUNIT_TEST(testContinueTypingReply_CapsIncluded); - CPPUNIT_TEST(testTypeReplies_WentOffline); - CPPUNIT_TEST(testContactShouldReceiveStates_CapsOnly); - CPPUNIT_TEST(testContactShouldReceiveStates_CapsNorActive); - CPPUNIT_TEST(testContactShouldReceiveStates_ActiveOverrideOn); - CPPUNIT_TEST(testContactShouldReceiveStates_ActiveOverrideOff); - CPPUNIT_TEST_SUITE_END(); - -public: - void setUp() { - stanzaChannel = new DummyStanzaChannel(); - stanzaChannel->setAvailable(true); - entityCapsProvider = new DummyEntityCapsProvider(); - notifier_ = new ChatStateNotifier(stanzaChannel, JID("foo@bar.com/baz"), entityCapsProvider); - notifier_->setContactIsOnline(true); - } - - void tearDown() { - delete notifier_; - delete entityCapsProvider; - delete stanzaChannel; - } - - void testStartTypingReply_CapsNotIncluded() { - notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(0, getComposingCount()); - } - - void testSendTwoMessages() { - setContactHas85Caps(); - notifier_->setUserIsTyping(); - notifier_->userSentMessage(); - notifier_->setUserIsTyping(); - notifier_->userSentMessage(); - CPPUNIT_ASSERT_EQUAL(2, getComposingCount()); - } - - void testCancelledNewMessage() { - setContactHas85Caps(); - notifier_->setUserIsTyping(); - notifier_->userCancelledNewMessage(); - CPPUNIT_ASSERT_EQUAL(1, getComposingCount()); - CPPUNIT_ASSERT_EQUAL(1, getActiveCount()); - CPPUNIT_ASSERT_EQUAL(ChatState::Active, stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getPayload<ChatState>()->getChatState()); - } - - - void testContactShouldReceiveStates_CapsOnly() { - setContactHas85Caps(); - boost::shared_ptr<Message> message(new Message()); - notifier_->addChatStateRequest(message); - CPPUNIT_ASSERT(message->getPayload<ChatState>()); - CPPUNIT_ASSERT_EQUAL(ChatState::Active, message->getPayload<ChatState>()->getChatState()); - } - - void testContactShouldReceiveStates_CapsNorActive() { - boost::shared_ptr<Message> message(new Message()); - notifier_->addChatStateRequest(message); - CPPUNIT_ASSERT(!message->getPayload<ChatState>()); - } - - void testContactShouldReceiveStates_ActiveOverrideOn() { - notifier_->receivedMessageFromContact(true); - boost::shared_ptr<Message> message(new Message()); - notifier_->addChatStateRequest(message); - CPPUNIT_ASSERT(message->getPayload<ChatState>()); - CPPUNIT_ASSERT_EQUAL(ChatState::Active, message->getPayload<ChatState>()->getChatState()); - } - - void testContactShouldReceiveStates_ActiveOverrideOff() { - setContactHas85Caps(); - notifier_->receivedMessageFromContact(false); - /* I originally read the MUST NOT send after receiving without Active and - * thought this should check for false, but I later found it was OPTIONAL - * (MAY) behaviour only for if you didn't receive caps. - */ - boost::shared_ptr<Message> message(new Message()); - notifier_->addChatStateRequest(message); - CPPUNIT_ASSERT(message->getPayload<ChatState>()); - CPPUNIT_ASSERT_EQUAL(ChatState::Active, message->getPayload<ChatState>()->getChatState()); - } - - - void testStartTypingReply_CapsIncluded() { - setContactHas85Caps(); - notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(1, getComposingCount()); - } - - void testContinueTypingReply_CapsIncluded() { - setContactHas85Caps(); - notifier_->setUserIsTyping(); - notifier_->setUserIsTyping(); - notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(1, getComposingCount()); - notifier_->userSentMessage(); - notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(2, getComposingCount()); - - } - - void testTypeReplies_WentOffline() { - setContactHas85Caps(); - notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(1, getComposingCount()); - notifier_->setContactIsOnline(false); - notifier_->userSentMessage(); - notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(1, getComposingCount()); - } - - private: - void setContactHas85Caps() { - DiscoInfo::ref caps(new DiscoInfo()); - caps->addFeature(DiscoInfo::ChatStatesFeature); - entityCapsProvider->caps[JID("foo@bar.com/baz")] = caps; - entityCapsProvider->onCapsChanged(JID("foo@bar.com/baz")); - } - - int getComposingCount() const { - int result = 0; - foreach(boost::shared_ptr<Stanza> stanza, stanzaChannel->sentStanzas) { - if (stanza->getPayload<ChatState>() && stanza->getPayload<ChatState>()->getChatState() == ChatState::Composing) { - result++; - } - } - return result; - } - - int getActiveCount() const { - int result = 0; - foreach(boost::shared_ptr<Stanza> stanza, stanzaChannel->sentStanzas) { - if (stanza->getPayload<ChatState>() && stanza->getPayload<ChatState>()->getChatState() == ChatState::Active) { - result++; - } - } - return result; - } - - private: - DummyStanzaChannel* stanzaChannel; - DummyEntityCapsProvider* entityCapsProvider; - ChatStateNotifier* notifier_; +class ChatStateNotifierTest : public ::testing::Test { + +protected: + virtual void SetUp() { + stanzaChannel = new DummyStanzaChannel(); + stanzaChannel->setAvailable(true); + entityCapsProvider = new DummyEntityCapsProvider(); + timerFactory_ = new DummyTimerFactory(); + notifier_ = new ChatStateNotifier(stanzaChannel, JID("foo@bar.com/baz"), entityCapsProvider, timerFactory_, 2); + notifier_->setContactIsOnline(true); + } + + virtual void TearDown() { + delete notifier_; + delete timerFactory_; + delete entityCapsProvider; + delete stanzaChannel; + } + + void setContactHas85Caps() { + DiscoInfo::ref caps(new DiscoInfo()); + caps->addFeature(DiscoInfo::ChatStatesFeature); + entityCapsProvider->caps[JID("foo@bar.com/baz")] = caps; + entityCapsProvider->onCapsChanged(JID("foo@bar.com/baz")); + } + + int getComposingCount() const { + int result = 0; + for (auto&& stanza : stanzaChannel->sentStanzas) { + if (stanza->getPayload<ChatState>() && stanza->getPayload<ChatState>()->getChatState() == ChatState::Composing) { + result++; + } + } + return result; + } + + int getActiveCount() const { + int result = 0; + for (auto&& stanza : stanzaChannel->sentStanzas) { + if (stanza->getPayload<ChatState>() && stanza->getPayload<ChatState>()->getChatState() == ChatState::Active) { + result++; + } + } + return result; + } + + DummyStanzaChannel* stanzaChannel; + DummyEntityCapsProvider* entityCapsProvider; + DummyTimerFactory* timerFactory_; + ChatStateNotifier* notifier_; }; -CPPUNIT_TEST_SUITE_REGISTRATION(ChatStateNotifierTest); +TEST_F(ChatStateNotifierTest, testStartTypingReply_CapsNotIncluded) { + notifier_->setUserIsTyping(); + ASSERT_EQ(0, getComposingCount()); +} + +TEST_F(ChatStateNotifierTest, testSendTwoMessages) { + setContactHas85Caps(); + notifier_->setUserIsTyping(); + notifier_->userSentMessage(); + notifier_->setUserIsTyping(); + notifier_->userSentMessage(); + ASSERT_EQ(2, getComposingCount()); +} + +TEST_F(ChatStateNotifierTest, testCancelledNewMessage) { + setContactHas85Caps(); + notifier_->setUserIsTyping(); + notifier_->userCancelledNewMessage(); + ASSERT_EQ(1, getComposingCount()); + ASSERT_EQ(1, getActiveCount()); + ASSERT_EQ(ChatState::Active, stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size() - 1]->getPayload<ChatState>()->getChatState()); +} + +TEST_F(ChatStateNotifierTest, testIdleWhileTypingNewMessage) { + setContactHas85Caps(); + //The channel should be empty + ASSERT_EQ(0, getComposingCount()); + ASSERT_EQ(0, getActiveCount()); + notifier_->setUserIsTyping(); + timerFactory_->setTime(1); + //1 Composing stanza is expected + ASSERT_EQ(1, getComposingCount()); + ASSERT_EQ(0, getActiveCount()); + timerFactory_->setTime(2); + //The idleTimer period has expired, the channel should have 1 composing and 1 active status stanza + ASSERT_EQ(1, getComposingCount()); + ASSERT_EQ(1, getActiveCount()); + ASSERT_EQ(ChatState::Active, stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size() - 1]->getPayload<ChatState>()->getChatState()); + timerFactory_->setTime(4); + //At the second tick no further state stanzas should be sent. + ASSERT_EQ(1, getComposingCount()); + ASSERT_EQ(1, getActiveCount()); + ASSERT_EQ(ChatState::Active, stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size() - 1]->getPayload<ChatState>()->getChatState()); +} + +TEST_F(ChatStateNotifierTest, testIdleWhileTypingNewMessageNoCaps) { + notifier_->setUserIsTyping(); + timerFactory_->setTime(3); + ASSERT_EQ(0, getComposingCount()); + ASSERT_EQ(0, getActiveCount()); +} +TEST_F(ChatStateNotifierTest, testContactShouldReceiveStates_CapsOnly) { + setContactHas85Caps(); + std::shared_ptr<Message> message(new Message()); + notifier_->addChatStateRequest(message); + EXPECT_TRUE(message->getPayload<ChatState>()); + ASSERT_EQ(ChatState::Active, message->getPayload<ChatState>()->getChatState()); +} + +TEST_F(ChatStateNotifierTest, testContactShouldReceiveStates_CapsNorActive) { + std::shared_ptr<Message> message(new Message()); + notifier_->addChatStateRequest(message); + EXPECT_TRUE(!message->getPayload<ChatState>()); +} + +TEST_F(ChatStateNotifierTest, testContactShouldReceiveStates_ActiveOverrideOn) { + notifier_->receivedMessageFromContact(true); + std::shared_ptr<Message> message(new Message()); + notifier_->addChatStateRequest(message); + EXPECT_TRUE(message->getPayload<ChatState>()); + ASSERT_EQ(ChatState::Active, message->getPayload<ChatState>()->getChatState()); +} + +TEST_F(ChatStateNotifierTest, testContactShouldReceiveStates_ActiveOverrideOff) { + setContactHas85Caps(); + notifier_->receivedMessageFromContact(false); + /* I originally read the MUST NOT send after receiving without Active and + * thought this should check for false, but I later found it was OPTIONAL + * (MAY) behaviour only for if you didn't receive caps. + */ + std::shared_ptr<Message> message(new Message()); + notifier_->addChatStateRequest(message); + EXPECT_TRUE(message->getPayload<ChatState>()); + ASSERT_EQ(ChatState::Active, message->getPayload<ChatState>()->getChatState()); +} + + +TEST_F(ChatStateNotifierTest, testStartTypingReply_CapsIncluded) { + setContactHas85Caps(); + notifier_->setUserIsTyping(); + ASSERT_EQ(1, getComposingCount()); +} + +TEST_F(ChatStateNotifierTest, testContinueTypingReply_CapsIncluded) { + setContactHas85Caps(); + notifier_->setUserIsTyping(); + notifier_->setUserIsTyping(); + notifier_->setUserIsTyping(); + ASSERT_EQ(1, getComposingCount()); + notifier_->userSentMessage(); + notifier_->setUserIsTyping(); + ASSERT_EQ(2, getComposingCount()); + +} + +TEST_F(ChatStateNotifierTest, testTypeReplies_WentOffline) { + setContactHas85Caps(); + notifier_->setUserIsTyping(); + ASSERT_EQ(1, getComposingCount()); + notifier_->setContactIsOnline(false); + notifier_->userSentMessage(); + notifier_->setUserIsTyping(); + ASSERT_EQ(1, getComposingCount()); +} diff --git a/Swiften/Client/BlockList.cpp b/Swiften/Client/BlockList.cpp index 3ee7864..cb77080 100644 --- a/Swiften/Client/BlockList.cpp +++ b/Swiften/Client/BlockList.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/BlockList.h> @@ -15,8 +15,8 @@ BlockList::~BlockList() { } bool BlockList::isBlocked(const JID& jid) const { - const std::vector<JID>& items = getItems(); - return (std::find(items.begin(), items.end(), jid.toBare()) != items.end()) || - (std::find(items.begin(), items.end(), JID(jid.getDomain())) != items.end()) || - (std::find(items.begin(), items.end(), jid) != items.end()); + const std::vector<JID>& items = getItems(); + return (std::find(items.begin(), items.end(), jid.toBare()) != items.end()) || + (std::find(items.begin(), items.end(), JID(jid.getDomain())) != items.end()) || + (std::find(items.begin(), items.end(), jid) != items.end()); } diff --git a/Swiften/Client/BlockList.h b/Swiften/Client/BlockList.h index 99c83c1..7a54626 100644 --- a/Swiften/Client/BlockList.h +++ b/Swiften/Client/BlockList.h @@ -1,36 +1,38 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <vector> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class BlockList { - public: - enum State { - Init, - Requesting, - Available, - Error - }; - virtual ~BlockList(); - - virtual State getState() const = 0; - - virtual const std::vector<JID>& getItems() const = 0; - - bool isBlocked(const JID& jid) const; - - public: - boost::signal<void ()> onStateChanged; - boost::signal<void (const JID&)> onItemAdded; - boost::signal<void (const JID&)> onItemRemoved; - }; + class SWIFTEN_API BlockList { + public: + enum State { + Init, + Requesting, + Available, + Error + }; + virtual ~BlockList(); + + virtual State getState() const = 0; + + virtual const std::vector<JID>& getItems() const = 0; + + bool isBlocked(const JID& jid) const; + + public: + boost::signals2::signal<void ()> onStateChanged; + boost::signals2::signal<void (const JID&)> onItemAdded; + boost::signals2::signal<void (const JID&)> onItemRemoved; + }; } diff --git a/Swiften/Client/BlockListImpl.cpp b/Swiften/Client/BlockListImpl.cpp index 5950233..54dcdf5 100644 --- a/Swiften/Client/BlockListImpl.cpp +++ b/Swiften/Client/BlockListImpl.cpp @@ -1,13 +1,11 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/BlockListImpl.h> -#include <Swiften/Base/foreach.h> - #include <algorithm> using namespace Swift; @@ -16,57 +14,59 @@ BlockListImpl::BlockListImpl() : state(Init) { } -void BlockListImpl::setItems(const std::vector<JID>& items) { - foreach (const JID& jid, this->items) { - if (std::find(items.begin(), items.end(), jid) != items.end()) { - onItemRemoved(jid); - } - } +void BlockListImpl::setItems(const std::vector<JID>& newItems) { + // JIDs which are in the current list but not in the new list, are removed. + for (const auto& jid : items) { + if (std::find(newItems.begin(), newItems.end(), jid) == newItems.end()) { + onItemRemoved(jid); + } + } - foreach (const JID& jid, items) { - if (std::find(this->items.begin(), this->items.end(), jid) != this->items.end()) { - onItemAdded(jid); - } - } - this->items = items; + // JIDs which are in the new list but not in the current list, are added. + for (const auto& jid : newItems) { + if (std::find(items.begin(), items.end(), jid) == items.end()) { + onItemAdded(jid); + } + } + items = newItems; } void BlockListImpl::addItem(const JID& item) { - if (std::find(items.begin(), items.end(), item) == items.end()) { - items.push_back(item); - onItemAdded(item); - } + if (std::find(items.begin(), items.end(), item) == items.end()) { + items.push_back(item); + onItemAdded(item); + } } void BlockListImpl::removeItem(const JID& item) { - size_t oldSize = items.size(); - items.erase(std::remove(items.begin(), items.end(), item), items.end()); - if (items.size() != oldSize) { - onItemRemoved(item); - } + size_t oldSize = items.size(); + items.erase(std::remove(items.begin(), items.end(), item), items.end()); + if (items.size() != oldSize) { + onItemRemoved(item); + } } void BlockListImpl::setState(State state) { - if (this->state != state) { - this->state = state; - onStateChanged(); - } + if (this->state != state) { + this->state = state; + onStateChanged(); + } } void BlockListImpl::addItems(const std::vector<JID>& items) { - foreach (const JID& item, items) { - addItem(item); - } + for (const auto& item : items) { + addItem(item); + } } void BlockListImpl::removeItems(const std::vector<JID>& items) { - std::vector<JID> itemsToRemove = items; - foreach (const JID& item, itemsToRemove) { - removeItem(item); - } + std::vector<JID> itemsToRemove = items; + for (const auto& item : itemsToRemove) { + removeItem(item); + } } void BlockListImpl::removeAllItems() { - removeItems(items); + removeItems(items); } diff --git a/Swiften/Client/BlockListImpl.h b/Swiften/Client/BlockListImpl.h index 2a799ae..edf459a 100644 --- a/Swiften/Client/BlockListImpl.h +++ b/Swiften/Client/BlockListImpl.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,29 +9,29 @@ #include <Swiften/Client/BlockList.h> namespace Swift { - class BlockListImpl : public BlockList { - public: - BlockListImpl(); - - virtual State getState() const { - return state; - } - - void setState(State state); - - virtual const std::vector<JID>& getItems() const { - return items; - } - - void setItems(const std::vector<JID>& items); - void addItem(const JID& item); - void removeItem(const JID& item); - void addItems(const std::vector<JID>& items); - void removeItems(const std::vector<JID>& items); - void removeAllItems(); - - private: - State state; - std::vector<JID> items; - }; + class BlockListImpl : public BlockList { + public: + BlockListImpl(); + + virtual State getState() const { + return state; + } + + void setState(State state); + + virtual const std::vector<JID>& getItems() const { + return items; + } + + void setItems(const std::vector<JID>& newItems); + void addItem(const JID& item); + void removeItem(const JID& item); + void addItems(const std::vector<JID>& items); + void removeItems(const std::vector<JID>& items); + void removeAllItems(); + + private: + State state; + std::vector<JID> items; + }; } diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp index f158370..8642a4e 100644 --- a/Swiften/Client/Client.cpp +++ b/Swiften/Client/Client.cpp @@ -1,37 +1,39 @@ /* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/Client.h> -#include <Swiften/Queries/Responders/SoftwareVersionResponder.h> -#include <Swiften/Roster/XMPPRosterImpl.h> -#include <Swiften/Roster/XMPPRosterController.h> -#include <Swiften/Presence/PresenceOracle.h> -#include <Swiften/Presence/StanzaChannelPresenceSender.h> -#include <Swiften/Presence/DirectedPresenceSender.h> -#include <Swiften/MUC/MUCRegistry.h> -#include <Swiften/MUC/MUCManager.h> -#include <Swiften/PubSub/PubSubManagerImpl.h> -#include <Swiften/Client/MemoryStorages.h> -#include <Swiften/VCards/VCardManager.h> -#include <Swiften/VCards/VCardManager.h> #include <Swiften/Avatars/AvatarManagerImpl.h> +#include <Swiften/Base/SafeString.h> +#include <Swiften/Client/ClientBlockListManager.h> +#include <Swiften/Client/ClientSession.h> +#include <Swiften/Client/MemoryStorages.h> +#include <Swiften/Client/NickManagerImpl.h> +#include <Swiften/Client/NickResolver.h> #include <Swiften/Disco/CapsManager.h> -#include <Swiften/Disco/EntityCapsManager.h> #include <Swiften/Disco/ClientDiscoManager.h> -#include <Swiften/Client/NickResolver.h> -#include <Swiften/Presence/SubscriptionManager.h> -#include <Swiften/TLS/BlindCertificateTrustChecker.h> -#include <Swiften/Client/NickManagerImpl.h> -#include <Swiften/Client/ClientSession.h> +#include <Swiften/Disco/EntityCapsManager.h> +#include <Swiften/FileTransfer/FileTransferManagerImpl.h> #include <Swiften/Jingle/JingleSessionManager.h> +#include <Swiften/MUC/MUCManager.h> +#include <Swiften/MUC/MUCRegistry.h> #include <Swiften/Network/NetworkFactories.h> -#include <Swiften/FileTransfer/FileTransferManagerImpl.h> +#include <Swiften/Presence/DirectedPresenceSender.h> +#include <Swiften/Presence/PresenceOracle.h> +#include <Swiften/Presence/StanzaChannelPresenceSender.h> +#include <Swiften/Presence/SubscriptionManager.h> +#include <Swiften/PubSub/PubSubManagerImpl.h> +#include <Swiften/Queries/Responders/SoftwareVersionResponder.h> +#include <Swiften/Roster/XMPPRosterController.h> +#include <Swiften/Roster/XMPPRosterImpl.h> +#include <Swiften/TLS/BlindCertificateTrustChecker.h> +#include <Swiften/VCards/VCardManager.h> +#include <Swiften/VCards/VCardManager.h> #include <Swiften/Whiteboard/WhiteboardSessionManager.h> -#include <Swiften/Client/ClientBlockListManager.h> + #ifndef SWIFT_EXPERIMENTAL_FT #include <Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h> #endif @@ -39,158 +41,160 @@ namespace Swift { Client::Client(const JID& jid, const SafeString& password, NetworkFactories* networkFactories, Storages* storages) : CoreClient(jid, password, networkFactories), storages(storages) { - memoryStorages = new MemoryStorages(networkFactories->getCryptoProvider()); + memoryStorages = new MemoryStorages(networkFactories->getCryptoProvider()); - softwareVersionResponder = new SoftwareVersionResponder(getIQRouter()); - softwareVersionResponder->start(); + softwareVersionResponder = new SoftwareVersionResponder(getIQRouter()); + softwareVersionResponder->start(); - roster = new XMPPRosterImpl(); - rosterController = new XMPPRosterController(getIQRouter(), roster, getStorages()->getRosterStorage()); + roster = new XMPPRosterImpl(); + rosterController = new XMPPRosterController(getIQRouter(), roster, getStorages()->getRosterStorage()); - subscriptionManager = new SubscriptionManager(getStanzaChannel()); + subscriptionManager = new SubscriptionManager(getStanzaChannel()); - presenceOracle = new PresenceOracle(getStanzaChannel()); - presenceOracle->onPresenceChange.connect(boost::ref(onPresenceChange)); + presenceOracle = new PresenceOracle(getStanzaChannel(), roster); + presenceOracle->onPresenceChange.connect(boost::ref(onPresenceChange)); - stanzaChannelPresenceSender = new StanzaChannelPresenceSender(getStanzaChannel()); - directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender); - discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender, networkFactories->getCryptoProvider()); + stanzaChannelPresenceSender = new StanzaChannelPresenceSender(getStanzaChannel()); + directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender); + discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender, networkFactories->getCryptoProvider()); - mucRegistry = new MUCRegistry(); - mucManager = new MUCManager(getStanzaChannel(), getIQRouter(), directedPresenceSender, mucRegistry); + mucRegistry = new MUCRegistry(); + mucManager = new MUCManager(getStanzaChannel(), getIQRouter(), directedPresenceSender, mucRegistry); - vcardManager = new VCardManager(jid, getIQRouter(), getStorages()->getVCardStorage()); - avatarManager = new AvatarManagerImpl(vcardManager, getStanzaChannel(), getStorages()->getAvatarStorage(), networkFactories->getCryptoProvider(), mucRegistry); - capsManager = new CapsManager(getStorages()->getCapsStorage(), getStanzaChannel(), getIQRouter(), networkFactories->getCryptoProvider()); - entityCapsManager = new EntityCapsManager(capsManager, getStanzaChannel()); + vcardManager = new VCardManager(jid, getIQRouter(), getStorages()->getVCardStorage()); + avatarManager = new AvatarManagerImpl(vcardManager, getStanzaChannel(), getStorages()->getAvatarStorage(), networkFactories->getCryptoProvider(), mucRegistry); + capsManager = new CapsManager(getStorages()->getCapsStorage(), getStanzaChannel(), getIQRouter(), networkFactories->getCryptoProvider()); + entityCapsManager = new EntityCapsManager(capsManager, getStanzaChannel()); - nickManager = new NickManagerImpl(jid.toBare(), vcardManager); - nickResolver = new NickResolver(jid.toBare(), roster, vcardManager, mucRegistry); + nickManager = new NickManagerImpl(jid.toBare(), vcardManager); + nickResolver = new NickResolver(jid.toBare(), roster, vcardManager, mucRegistry); - blindCertificateTrustChecker = new BlindCertificateTrustChecker(); - - jingleSessionManager = new JingleSessionManager(getIQRouter()); - blockListManager = new ClientBlockListManager(getIQRouter()); - fileTransferManager = NULL; + blindCertificateTrustChecker = new BlindCertificateTrustChecker(); - whiteboardSessionManager = NULL; + jingleSessionManager = new JingleSessionManager(getIQRouter()); + blockListManager = new ClientBlockListManager(getIQRouter()); + + whiteboardSessionManager = nullptr; #ifdef SWIFT_EXPERIMENTAL_WB - whiteboardSessionManager = new WhiteboardSessionManager(getIQRouter(), getStanzaChannel(), presenceOracle, getEntityCapsProvider()); + whiteboardSessionManager = new WhiteboardSessionManager(getIQRouter(), getStanzaChannel(), presenceOracle, getEntityCapsProvider()); #endif - pubsubManager = new PubSubManagerImpl(getStanzaChannel(), getIQRouter()); + pubsubManager = new PubSubManagerImpl(getStanzaChannel(), getIQRouter()); + +#ifdef SWIFT_EXPERIMENTAL_FT + fileTransferManager = new FileTransferManagerImpl( + getJID(), + jingleSessionManager, + getIQRouter(), + getEntityCapsProvider(), + presenceOracle, + getNetworkFactories()->getConnectionFactory(), + getNetworkFactories()->getConnectionServerFactory(), + getNetworkFactories()->getTimerFactory(), + getNetworkFactories()->getDomainNameResolver(), + getNetworkFactories()->getNetworkEnvironment(), + getNetworkFactories()->getNATTraverser(), + getNetworkFactories()->getCryptoProvider()); +#else + fileTransferManager = new DummyFileTransferManager(); +#endif } Client::~Client() { - delete pubsubManager; - delete whiteboardSessionManager; + delete pubsubManager; + delete whiteboardSessionManager; + + delete fileTransferManager; + delete blockListManager; + delete jingleSessionManager; - delete fileTransferManager; - delete jingleSessionManager; - - delete blindCertificateTrustChecker; + delete blindCertificateTrustChecker; - delete nickResolver; - delete nickManager; + delete nickResolver; + delete nickManager; - delete entityCapsManager; - delete capsManager; - delete avatarManager; - delete vcardManager; + delete entityCapsManager; + delete capsManager; + delete avatarManager; + delete vcardManager; - delete mucManager; - delete mucRegistry; + delete mucManager; + delete mucRegistry; - delete discoManager; - delete directedPresenceSender; - delete stanzaChannelPresenceSender; + delete discoManager; + delete directedPresenceSender; + delete stanzaChannelPresenceSender; - delete presenceOracle; - delete subscriptionManager; - delete rosterController; - delete roster; + delete presenceOracle; + delete subscriptionManager; + delete rosterController; + delete roster; - softwareVersionResponder->stop(); - delete softwareVersionResponder; + softwareVersionResponder->stop(); + delete softwareVersionResponder; - delete memoryStorages; + delete memoryStorages; } XMPPRoster* Client::getRoster() const { - return roster; + return roster; } void Client::setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os) { - softwareVersionResponder->setVersion(name, version, os); + softwareVersionResponder->setVersion(name, version, os); } void Client::handleConnected() { -#ifdef SWIFT_EXPERIMENTAL_FT - fileTransferManager = new FileTransferManagerImpl( - getJID(), - jingleSessionManager, - getIQRouter(), - getEntityCapsProvider(), - presenceOracle, - getNetworkFactories()->getConnectionFactory(), - getNetworkFactories()->getConnectionServerFactory(), - getNetworkFactories()->getTimerFactory(), - getNetworkFactories()->getNetworkEnvironment(), - getNetworkFactories()->getNATTraverser(), - getNetworkFactories()->getCryptoProvider()); -#else - fileTransferManager = new DummyFileTransferManager(); -#endif - discoManager->handleConnected(); + discoManager->handleConnected(); } void Client::requestRoster() { - // FIXME: We should set this once when the session is finished, but there - // is currently no callback for this - if (getSession()) { - rosterController->setUseVersioning(getSession()->getRosterVersioningSupported()); - } - rosterController->requestRoster(); + // FIXME: We should set this once when the session is finished, but there + // is currently no callback for this + if (getSession()) { + rosterController->setUseVersioning(getSession()->getRosterVersioningSupported()); + } + rosterController->requestRoster(); } Presence::ref Client::getLastPresence(const JID& jid) const { - return presenceOracle->getLastPresence(jid); + return presenceOracle->getLastPresence(jid); } Presence::ref Client::getHighestPriorityPresence(const JID& bareJID) const { - return presenceOracle->getHighestPriorityPresence(bareJID); + return presenceOracle->getHighestPriorityPresence(bareJID); } Storages* Client::getStorages() const { - if (storages) { - return storages; - } - return memoryStorages; + if (storages) { + return storages; + } + return memoryStorages; } PresenceSender* Client::getPresenceSender() const { - return discoManager->getPresenceSender(); + return discoManager->getPresenceSender(); } EntityCapsProvider* Client::getEntityCapsProvider() const { - return entityCapsManager; + return entityCapsManager; } void Client::setAlwaysTrustCertificates() { - setCertificateTrustChecker(blindCertificateTrustChecker); + setCertificateTrustChecker(blindCertificateTrustChecker); } NickManager* Client::getNickManager() const { - return nickManager; + return nickManager; } FileTransferManager* Client::getFileTransferManager() const { - return fileTransferManager; + return fileTransferManager; } WhiteboardSessionManager* Client::getWhiteboardSessionManager() const { - return whiteboardSessionManager; + return whiteboardSessionManager; } } diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h index 9253074..be4881a 100644 --- a/Swiften/Client/Client.h +++ b/Swiften/Client/Client.h @@ -1,206 +1,211 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> #include <Swiften/Client/CoreClient.h> -#include <Swiften/Base/SafeString.h> namespace Swift { - class SoftwareVersionResponder; - class BlindCertificateTrustChecker; - class XMPPRoster; - class XMPPRosterImpl; - class MUCManager; - class XMPPRosterController; - class PresenceOracle; - class PresenceSender; - class DirectedPresenceSender; - class StanzaChannelPresenceSender; - class MUCRegistry; - class Storages; - class MemoryStorages; - class VCardManager; - class AvatarManager; - class CapsManager; - class EntityCapsManager; - class EntityCapsProvider; - class NickResolver; - class SubscriptionManager; - class ClientDiscoManager; - class NickManager; - class FileTransferManager; - class JingleSessionManager; - class FileTransferManager; - class WhiteboardSessionManager; - class ClientBlockListManager; - class PubSubManager; - - /** - * Provides the core functionality for writing XMPP client software. - * - * Besides connecting to an XMPP server, this class also provides interfaces for - * performing most tasks on the XMPP network. - */ - class SWIFTEN_API Client : public CoreClient { - public: - /** - * Constructs a client for the given JID with the given password. - * - * \param storages The interfaces for storing cache information etc. If - * this is NULL, - * all data will be stored in memory (and be lost on shutdown) - */ - Client(const JID& jid, const SafeString& password, NetworkFactories* networkFactories, Storages* storages = NULL); - ~Client(); - - - /** - * Sets the software version of the client. - * - * This will be used to respond to version queries from other entities. - */ - void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os = ""); - - /** - * Returns a representation of the roster. - * - * The roster is initially empty. To populate it, call requestRoster(), - * which will request the roster from the server. When the roster has - * been requested, it will also be kept up to date when it is updated on - * the server side. - * - * This pointer remains the same across the lifetime of Client. All - * changes to the roster (e.g. after the initial roster request, or after - * subsequent roster updates) are notified through the XMPPRoster's - * signals. - * - * \see requestRoster() - */ - XMPPRoster* getRoster() const; - - /** - * Requests the roster from the server. - * - * \see getRoster() - */ - void requestRoster(); - - /** - * Returns the last received presence for the given (full) JID. - */ - boost::shared_ptr<Presence> getLastPresence(const JID& jid) const; - - /** - * Returns the presence with the highest priority received for the given JID. - */ - boost::shared_ptr<Presence> getHighestPriorityPresence(const JID& bareJID) const; - - PresenceOracle* getPresenceOracle() const { - return presenceOracle; - } - - PresenceSender* getPresenceSender() const; - - MUCManager* getMUCManager() const { - return mucManager; - } - - MUCRegistry* getMUCRegistry() const { - return mucRegistry; - } - - VCardManager* getVCardManager() const { - return vcardManager; - } - - AvatarManager* getAvatarManager() const { - return avatarManager; - } - - EntityCapsProvider* getEntityCapsProvider() const; - - NickManager* getNickManager() const; - - NickResolver* getNickResolver() const { - return nickResolver; - } - - SubscriptionManager* getSubscriptionManager() const { - return subscriptionManager; - } - - ClientDiscoManager* getDiscoManager() const { - return discoManager; - } - - ClientBlockListManager* getClientBlockListManager() const { - return blockListManager; - } - - /** - * Returns a FileTransferManager for the client. This is only available after the onConnected - * signal has been fired. - * - * WARNING: File transfer will only work if Swiften is built in 'experimental' mode. - */ - FileTransferManager* getFileTransferManager() const; - - /** - * Configures the client to always trust a non-validating - * TLS certificate from the server. - * This is equivalent to setting a BlindCertificateTrustChecker - * using setCertificateTrustChecker(). - */ - void setAlwaysTrustCertificates(); - - WhiteboardSessionManager* getWhiteboardSessionManager() const; - - PubSubManager* getPubSubManager() const { - return pubsubManager; - } - - - public: - /** - * This signal is emitted when a JID changes presence. - */ - boost::signal<void (boost::shared_ptr<Presence>)> onPresenceChange; - - private: - Storages* getStorages() const; - - protected: - void handleConnected(); - - private: - Storages* storages; - MemoryStorages* memoryStorages; - SoftwareVersionResponder* softwareVersionResponder; - XMPPRosterImpl* roster; - XMPPRosterController* rosterController; - PresenceOracle* presenceOracle; - DirectedPresenceSender* directedPresenceSender; - StanzaChannelPresenceSender* stanzaChannelPresenceSender; - MUCRegistry* mucRegistry; - VCardManager* vcardManager; - AvatarManager* avatarManager; - CapsManager* capsManager; - EntityCapsManager* entityCapsManager; - NickManager* nickManager; - NickResolver* nickResolver; - SubscriptionManager* subscriptionManager; - MUCManager* mucManager; - ClientDiscoManager* discoManager; - JingleSessionManager* jingleSessionManager; - FileTransferManager* fileTransferManager; - BlindCertificateTrustChecker* blindCertificateTrustChecker; - WhiteboardSessionManager* whiteboardSessionManager; - ClientBlockListManager* blockListManager; - PubSubManager* pubsubManager; - }; + class AvatarManager; + class BlindCertificateTrustChecker; + class CapsManager; + class ClientBlockListManager; + class ClientDiscoManager; + class DirectedPresenceSender; + class EntityCapsManager; + class EntityCapsProvider; + class FileTransferManager; + class FileTransferManager; + class JingleSessionManager; + class MUCManager; + class MUCRegistry; + class MemoryStorages; + class NickManager; + class NickResolver; + class PresenceOracle; + class PresenceSender; + class PubSubManager; + class SafeString; + class SoftwareVersionResponder; + class StanzaChannelPresenceSender; + class Storages; + class SubscriptionManager; + class VCardManager; + class WhiteboardSessionManager; + class XMPPRoster; + class XMPPRosterController; + class XMPPRosterImpl; + + /** + * Provides the core functionality for writing XMPP client software. + * + * Besides connecting to an XMPP server, this class also provides interfaces for + * performing most tasks on the XMPP network. + */ + class SWIFTEN_API Client : public CoreClient { + public: + /** + * Constructs a client for the given JID with the given password. + * + * \param jid The JID to be used for the login. If only a bare + * JID is give the server will be asked to generate a resource. + * \param password The password used for login given as a \ref SafeString. + * \param networkFactories The network factories that are used + * to handle any network related tasks. + * \param storages The interfaces for storing cache information etc. If + * this is NULL, + * all data will be stored in memory (and be lost on shutdown) + */ + Client(const JID& jid, const SafeString& password, NetworkFactories* networkFactories, Storages* storages = nullptr); + virtual ~Client(); + + + /** + * Sets the software version of the client. + * + * This will be used to respond to version queries from other entities. + */ + void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os = ""); + + /** + * Returns a representation of the roster. + * + * The roster is initially empty. To populate it, call requestRoster(), + * which will request the roster from the server. When the roster has + * been requested, it will also be kept up to date when it is updated on + * the server side. + * + * This pointer remains the same across the lifetime of Client. All + * changes to the roster (e.g. after the initial roster request, or after + * subsequent roster updates) are notified through the XMPPRoster's + * signals. + * + * \see requestRoster() + */ + XMPPRoster* getRoster() const; + + /** + * Requests the roster from the server. + * + * \see getRoster() + */ + void requestRoster(); + + /** + * Returns the last received presence for the given (full) JID. + */ + std::shared_ptr<Presence> getLastPresence(const JID& jid) const; + + /** + * Returns the presence with the highest priority received for the given JID. + */ + std::shared_ptr<Presence> getHighestPriorityPresence(const JID& bareJID) const; + + PresenceOracle* getPresenceOracle() const { + return presenceOracle; + } + + PresenceSender* getPresenceSender() const; + + MUCManager* getMUCManager() const { + return mucManager; + } + + MUCRegistry* getMUCRegistry() const { + return mucRegistry; + } + + VCardManager* getVCardManager() const { + return vcardManager; + } + + AvatarManager* getAvatarManager() const { + return avatarManager; + } + + EntityCapsProvider* getEntityCapsProvider() const; + + NickManager* getNickManager() const; + + NickResolver* getNickResolver() const { + return nickResolver; + } + + SubscriptionManager* getSubscriptionManager() const { + return subscriptionManager; + } + + ClientDiscoManager* getDiscoManager() const { + return discoManager; + } + + ClientBlockListManager* getClientBlockListManager() const { + return blockListManager; + } + + /** + * Returns a FileTransferManager for the client. This is only available after the onConnected + * signal has been fired. + * + * WARNING: File transfer will only work if Swiften is built in 'experimental' mode. + */ + FileTransferManager* getFileTransferManager() const; + + /** + * Configures the client to always trust a non-validating + * TLS certificate from the server. + * This is equivalent to setting a BlindCertificateTrustChecker + * using setCertificateTrustChecker(). + */ + void setAlwaysTrustCertificates(); + + WhiteboardSessionManager* getWhiteboardSessionManager() const; + + PubSubManager* getPubSubManager() const { + return pubsubManager; + } + + + public: + /** + * This signal is emitted when a JID changes presence. + */ + boost::signals2::signal<void (std::shared_ptr<Presence>)> onPresenceChange; + + private: + Storages* getStorages() const; + + protected: + void handleConnected(); + + private: + Storages* storages; + MemoryStorages* memoryStorages; + SoftwareVersionResponder* softwareVersionResponder; + XMPPRosterImpl* roster; + XMPPRosterController* rosterController; + PresenceOracle* presenceOracle; + DirectedPresenceSender* directedPresenceSender; + StanzaChannelPresenceSender* stanzaChannelPresenceSender; + MUCRegistry* mucRegistry; + VCardManager* vcardManager; + AvatarManager* avatarManager; + CapsManager* capsManager; + EntityCapsManager* entityCapsManager; + NickManager* nickManager; + NickResolver* nickResolver; + SubscriptionManager* subscriptionManager; + MUCManager* mucManager; + ClientDiscoManager* discoManager; + JingleSessionManager* jingleSessionManager; + FileTransferManager* fileTransferManager; + BlindCertificateTrustChecker* blindCertificateTrustChecker; + WhiteboardSessionManager* whiteboardSessionManager; + ClientBlockListManager* blockListManager; + PubSubManager* pubsubManager; + }; } diff --git a/Swiften/Client/ClientBlockListManager.cpp b/Swiften/Client/ClientBlockListManager.cpp index 6646a5c..bfdec30 100644 --- a/Swiften/Client/ClientBlockListManager.cpp +++ b/Swiften/Client/ClientBlockListManager.cpp @@ -1,68 +1,69 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/ClientBlockListManager.h> -#include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <cassert> +#include <memory> + +#include <boost/bind.hpp> #include <Swiften/Client/BlockListImpl.h> using namespace Swift; namespace { - class BlockResponder : public SetResponder<BlockPayload> { - public: - BlockResponder(boost::shared_ptr<BlockListImpl> blockList, IQRouter* iqRouter) : SetResponder<BlockPayload>(iqRouter), blockList(blockList) { - } - - virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<BlockPayload> payload) { - if (getIQRouter()->isAccountJID(from)) { - if (payload) { - blockList->addItems(payload->getItems()); - } - sendResponse(from, id, boost::shared_ptr<BlockPayload>()); - } - else { - sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); - } - return true; - } - - private: - boost::shared_ptr<BlockListImpl> blockList; - }; - - class UnblockResponder : public SetResponder<UnblockPayload> { - public: - UnblockResponder(boost::shared_ptr<BlockListImpl> blockList, IQRouter* iqRouter) : SetResponder<UnblockPayload>(iqRouter), blockList(blockList) { - } - - virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<UnblockPayload> payload) { - if (getIQRouter()->isAccountJID(from)) { - if (payload) { - if (payload->getItems().empty()) { - blockList->removeAllItems(); - } - else { - blockList->removeItems(payload->getItems()); - } - } - sendResponse(from, id, boost::shared_ptr<UnblockPayload>()); - } - else { - sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); - } - return true; - } - - private: - boost::shared_ptr<BlockListImpl> blockList; - }; + class BlockResponder : public SetResponder<BlockPayload> { + public: + BlockResponder(std::shared_ptr<BlockListImpl> blockList, IQRouter* iqRouter) : SetResponder<BlockPayload>(iqRouter), blockList(blockList) { + } + + virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, std::shared_ptr<BlockPayload> payload) { + if (getIQRouter()->isAccountJID(from)) { + if (payload) { + blockList->addItems(payload->getItems()); + } + sendResponse(from, id, std::shared_ptr<BlockPayload>()); + } + else { + sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); + } + return true; + } + + private: + std::shared_ptr<BlockListImpl> blockList; + }; + + class UnblockResponder : public SetResponder<UnblockPayload> { + public: + UnblockResponder(std::shared_ptr<BlockListImpl> blockList, IQRouter* iqRouter) : SetResponder<UnblockPayload>(iqRouter), blockList(blockList) { + } + + virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, std::shared_ptr<UnblockPayload> payload) { + if (getIQRouter()->isAccountJID(from)) { + if (payload) { + if (payload->getItems().empty()) { + blockList->removeAllItems(); + } + else { + blockList->removeItems(payload->getItems()); + } + } + sendResponse(from, id, std::shared_ptr<UnblockPayload>()); + } + else { + sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); + } + return true; + } + + private: + std::shared_ptr<BlockListImpl> blockList; + }; } ClientBlockListManager::ClientBlockListManager(IQRouter* iqRouter) : iqRouter(iqRouter) { @@ -70,61 +71,69 @@ ClientBlockListManager::ClientBlockListManager(IQRouter* iqRouter) : iqRouter(iq } ClientBlockListManager::~ClientBlockListManager() { - if (blockList && blockList->getState() == BlockList::Available) { - unblockResponder->stop(); - blockResponder->stop(); - } - if (getRequest) { - getRequest->onResponse.disconnect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); - } + if (blockList && blockList->getState() == BlockList::Available) { + unblockResponder->stop(); + blockResponder->stop(); + } +} + +std::shared_ptr<BlockList> ClientBlockListManager::getBlockList() { + if (!blockList) { + blockList = std::make_shared<BlockListImpl>(); + blockList->setState(BlockList::Init); + } + return blockList; } -boost::shared_ptr<BlockList> ClientBlockListManager::getBlockList() { - if (!blockList) { - blockList = boost::make_shared<BlockListImpl>(); - blockList->setState(BlockList::Requesting); - assert(!getRequest); - getRequest = boost::make_shared< GenericRequest<BlockListPayload> >(IQ::Get, JID(), boost::make_shared<BlockListPayload>(), iqRouter); - getRequest->onResponse.connect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); - getRequest->send(); - } - return blockList; +std::shared_ptr<BlockList> ClientBlockListManager::requestBlockList() { + if (!blockList) { + blockList = std::make_shared<BlockListImpl>(); + } + blockList->setState(BlockList::Requesting); + std::shared_ptr<GenericRequest<BlockListPayload> > getRequest = std::make_shared< GenericRequest<BlockListPayload> >(IQ::Get, JID(), std::make_shared<BlockListPayload>(), iqRouter); + getRequest->onResponse.connect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); + getRequest->send(); + return blockList; } GenericRequest<BlockPayload>::ref ClientBlockListManager::createBlockJIDRequest(const JID& jid) { - return createBlockJIDsRequest(std::vector<JID>(1, jid)); + return createBlockJIDsRequest(std::vector<JID>(1, jid)); } GenericRequest<BlockPayload>::ref ClientBlockListManager::createBlockJIDsRequest(const std::vector<JID>& jids) { - boost::shared_ptr<BlockPayload> payload = boost::make_shared<BlockPayload>(jids); - return boost::make_shared< GenericRequest<BlockPayload> >(IQ::Set, JID(), payload, iqRouter); + std::shared_ptr<BlockPayload> payload = std::make_shared<BlockPayload>(jids); + return std::make_shared< GenericRequest<BlockPayload> >(IQ::Set, JID(), payload, iqRouter); } GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockJIDRequest(const JID& jid) { - return createUnblockJIDsRequest(std::vector<JID>(1, jid)); + return createUnblockJIDsRequest(std::vector<JID>(1, jid)); } GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockJIDsRequest(const std::vector<JID>& jids) { - boost::shared_ptr<UnblockPayload> payload = boost::make_shared<UnblockPayload>(jids); - return boost::make_shared< GenericRequest<UnblockPayload> >(IQ::Set, JID(), payload, iqRouter); + std::shared_ptr<UnblockPayload> payload = std::make_shared<UnblockPayload>(jids); + return std::make_shared< GenericRequest<UnblockPayload> >(IQ::Set, JID(), payload, iqRouter); } GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockAllRequest() { - return createUnblockJIDsRequest(std::vector<JID>()); + return createUnblockJIDsRequest(std::vector<JID>()); } -void ClientBlockListManager::handleBlockListReceived(boost::shared_ptr<BlockListPayload> payload, ErrorPayload::ref error) { - if (error || !payload) { - blockList->setState(BlockList::Error); - } - else { - blockList->setItems(payload->getItems()); - blockList->setState(BlockList::Available); - blockResponder = boost::make_shared<BlockResponder>(blockList, iqRouter); - blockResponder->start(); - unblockResponder = boost::make_shared<UnblockResponder>(blockList, iqRouter); - unblockResponder->start(); - } +void ClientBlockListManager::handleBlockListReceived(std::shared_ptr<BlockListPayload> payload, ErrorPayload::ref error) { + if (error || !payload) { + blockList->setState(BlockList::Error); + } + else { + blockList->setItems(payload->getItems()); + blockList->setState(BlockList::Available); + if (!blockResponder) { + blockResponder = std::make_shared<BlockResponder>(blockList, iqRouter); + blockResponder->start(); + } + if (!unblockResponder) { + unblockResponder = std::make_shared<UnblockResponder>(blockList, iqRouter); + unblockResponder->start(); + } + } } diff --git a/Swiften/Client/ClientBlockListManager.h b/Swiften/Client/ClientBlockListManager.h index e8d4ac6..5fc1335 100644 --- a/Swiften/Client/ClientBlockListManager.h +++ b/Swiften/Client/ClientBlockListManager.h @@ -1,52 +1,58 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Elements/BlockPayload.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Client/BlockList.h> +#include <Swiften/Client/BlockListImpl.h> #include <Swiften/Elements/BlockListPayload.h> -#include <Swiften/Elements/UnblockPayload.h> +#include <Swiften/Elements/BlockPayload.h> #include <Swiften/Elements/DiscoInfo.h> -#include <Swiften/Queries/SetResponder.h> +#include <Swiften/Elements/UnblockPayload.h> #include <Swiften/Queries/GenericRequest.h> -#include <Swiften/Client/BlockList.h> -#include <Swiften/Client/BlockListImpl.h> +#include <Swiften/Queries/SetResponder.h> namespace Swift { - class IQRouter; - - class ClientBlockListManager { - public: - ClientBlockListManager(IQRouter *iqRouter); - ~ClientBlockListManager(); - - /** - * Returns the blocklist. - */ - boost::shared_ptr<BlockList> getBlockList(); - - GenericRequest<BlockPayload>::ref createBlockJIDRequest(const JID& jid); - GenericRequest<BlockPayload>::ref createBlockJIDsRequest(const std::vector<JID>& jids); - - GenericRequest<UnblockPayload>::ref createUnblockJIDRequest(const JID& jid); - GenericRequest<UnblockPayload>::ref createUnblockJIDsRequest(const std::vector<JID>& jids); - GenericRequest<UnblockPayload>::ref createUnblockAllRequest(); - - private: - void handleBlockListReceived(boost::shared_ptr<BlockListPayload> payload, ErrorPayload::ref); - - private: - IQRouter* iqRouter; - boost::shared_ptr<GenericRequest<BlockListPayload> > getRequest; - boost::shared_ptr<SetResponder<BlockPayload> > blockResponder; - boost::shared_ptr<SetResponder<UnblockPayload> > unblockResponder; - boost::shared_ptr<BlockListImpl> blockList; - }; + class IQRouter; + + class SWIFTEN_API ClientBlockListManager { + public: + ClientBlockListManager(IQRouter *iqRouter); + ~ClientBlockListManager(); + + /** + * Returns the blocklist. + */ + std::shared_ptr<BlockList> getBlockList(); + + /** + * Get the blocklist from the server. + */ + std::shared_ptr<BlockList> requestBlockList(); + + GenericRequest<BlockPayload>::ref createBlockJIDRequest(const JID& jid); + GenericRequest<BlockPayload>::ref createBlockJIDsRequest(const std::vector<JID>& jids); + + GenericRequest<UnblockPayload>::ref createUnblockJIDRequest(const JID& jid); + GenericRequest<UnblockPayload>::ref createUnblockJIDsRequest(const std::vector<JID>& jids); + GenericRequest<UnblockPayload>::ref createUnblockAllRequest(); + + private: + void handleBlockListReceived(std::shared_ptr<BlockListPayload> payload, ErrorPayload::ref); + + private: + IQRouter* iqRouter; + std::shared_ptr<SetResponder<BlockPayload> > blockResponder; + std::shared_ptr<SetResponder<UnblockPayload> > unblockResponder; + std::shared_ptr<BlockListImpl> blockList; + }; } diff --git a/Swiften/Client/ClientError.h b/Swiften/Client/ClientError.h index a4dc040..3453611 100644 --- a/Swiften/Client/ClientError.h +++ b/Swiften/Client/ClientError.h @@ -1,57 +1,66 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> + +#include <boost/system/system_error.hpp> + namespace Swift { - class ClientError { - public: - enum Type { - UnknownError, - DomainNameResolveError, - ConnectionError, - ConnectionReadError, - ConnectionWriteError, - XMLError, - AuthenticationFailedError, - CompressionFailedError, - ServerVerificationFailedError, - NoSupportedAuthMechanismsError, - UnexpectedElementError, - ResourceBindError, - SessionStartError, - StreamError, - TLSError, - ClientCertificateLoadError, - ClientCertificateError, - - // Certifate on smartcard was removed - CertificateCardRemoved, - - // Certificate verification errors - UnknownCertificateError, - CertificateExpiredError, - CertificateNotYetValidError, - CertificateSelfSignedError, - CertificateRejectedError, - CertificateUntrustedError, - InvalidCertificatePurposeError, - CertificatePathLengthExceededError, - InvalidCertificateSignatureError, - InvalidCAError, - InvalidServerIdentityError, - RevokedError, - RevocationCheckFailedError - }; - - ClientError(Type type = UnknownError) : type_(type) {} - - Type getType() const { return type_; } - - private: - Type type_; - }; + class ClientError { + public: + enum Type { + UnknownError, + DomainNameResolveError, + ConnectionError, + ConnectionReadError, + ConnectionWriteError, + XMLError, + AuthenticationFailedError, + CompressionFailedError, + ServerVerificationFailedError, + NoSupportedAuthMechanismsError, + UnexpectedElementError, + ResourceBindError, + SessionStartError, + StreamError, + TLSError, + ClientCertificateLoadError, + ClientCertificateError, + + // Certifate on smartcard was removed + CertificateCardRemoved, + + // Certificate verification errors + UnknownCertificateError, + CertificateExpiredError, + CertificateNotYetValidError, + CertificateSelfSignedError, + CertificateRejectedError, + CertificateUntrustedError, + InvalidCertificatePurposeError, + CertificatePathLengthExceededError, + InvalidCertificateSignatureError, + InvalidCAError, + InvalidServerIdentityError, + RevokedError, + RevocationCheckFailedError + }; + + ClientError(Type type = UnknownError) : type_(type) {} + + Type getType() const { return type_; } + + void setErrorCode(std::shared_ptr<boost::system::error_code> errorCode) { errorCode_ = errorCode; } + + std::shared_ptr<boost::system::error_code> getErrorCode() const { return errorCode_; } + + private: + Type type_; + std::shared_ptr<boost::system::error_code> errorCode_; + }; } diff --git a/Swiften/Client/ClientOptions.h b/Swiften/Client/ClientOptions.h index e5fcda9..1a337b6 100644 --- a/Swiften/Client/ClientOptions.h +++ b/Swiften/Client/ClientOptions.h @@ -1,138 +1,154 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/URL.h> +#include <memory> + +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeString.h> +#include <Swiften/Base/URL.h> +#include <Swiften/TLS/TLSOptions.h> namespace Swift { - struct ClientOptions { - enum UseTLS { - NeverUseTLS, - UseTLSWhenAvailable, - RequireTLS - }; - - enum ProxyType { - NoProxy, - SystemConfiguredProxy, - SOCKS5Proxy, - HTTPConnectProxy - }; - - ClientOptions() : - useStreamCompression(true), - useTLS(UseTLSWhenAvailable), - allowPLAINWithoutTLS(false), - useStreamResumption(false), - forgetPassword(false), - useAcks(true), - manualHostname(""), - manualPort(-1), - proxyType(SystemConfiguredProxy), - manualProxyHostname(""), - manualProxyPort(-1), - boshHTTPConnectProxyAuthID(""), - boshHTTPConnectProxyAuthPassword("") { - } - - /** - * Whether ZLib stream compression should be used when available. - * - * Default: true - */ - bool useStreamCompression; - - /** - * Sets whether TLS encryption should be used. - * - * Default: UseTLSWhenAvailable - */ - UseTLS useTLS; - - /** - * Sets whether plaintext authentication is - * allowed over non-TLS-encrypted connections. - * - * Default: false - */ - bool allowPLAINWithoutTLS; - - /** - * Use XEP-196 stream resumption when available. - * - * Default: false - */ - bool useStreamResumption; - - /** - * Forget the password once it's used. - * This makes the Client useless after the first login attempt. - * - * FIXME: This is a temporary workaround. - * - * Default: false - */ - bool forgetPassword; - - /** - * Use XEP-0198 acks in the stream when available. - * Default: true - */ - bool useAcks; - - /** - * The hostname to connect to. - * Leave this empty for standard XMPP connection, based on the JID domain. - */ - std::string manualHostname; - - /** - * The port to connect to. - * Leave this to -1 to use the port discovered by SRV lookups, and 5222 as a - * fallback. - */ - int manualPort; - - /** - * The type of proxy to use for connecting to the XMPP - * server. - */ - ProxyType proxyType; - - /** - * Override the system-configured proxy hostname. - */ - std::string manualProxyHostname; - - /** - * Override the system-configured proxy port. - */ - int manualProxyPort; - - /** - * If non-empty, use BOSH instead of direct TCP, with the given URL. - * Default: empty (no BOSH) - */ - URL boshURL; - - /** - * If non-empty, BOSH connections will try to connect over this HTTP CONNECT - * proxy instead of directly. - * Default: empty (no proxy) - */ - URL boshHTTPConnectProxyURL; - - /** - * If this and matching Password are non-empty, BOSH connections over - * HTTP CONNECT proxies will use these credentials for proxy access. - * Default: empty (no authentication needed by the proxy) - */ - SafeString boshHTTPConnectProxyAuthID; - SafeString boshHTTPConnectProxyAuthPassword; - }; + class HTTPTrafficFilter; + + struct SWIFTEN_API ClientOptions { + enum UseTLS { + NeverUseTLS, + UseTLSWhenAvailable, + RequireTLS + }; + + enum ProxyType { + NoProxy, + SystemConfiguredProxy, + SOCKS5Proxy, + HTTPConnectProxy + }; + + ClientOptions() { + } + + /** + * Whether ZLib stream compression should be used when available. + * + * Default: true + */ + bool useStreamCompression = true; + + /** + * Sets whether TLS encryption should be used. + * + * Default: UseTLSWhenAvailable + */ + UseTLS useTLS = UseTLSWhenAvailable; + + /** + * Sets whether plaintext authentication is + * allowed over non-TLS-encrypted connections. + * + * Default: false + */ + bool allowPLAINWithoutTLS = false; + + /** + * Use XEP-196 stream resumption when available. + * + * Default: false + */ + bool useStreamResumption = false; + + /** + * Forget the password once it's used. + * This makes the Client useless after the first login attempt. + * + * FIXME: This is a temporary workaround. + * + * Default: false + */ + bool forgetPassword = false; + + /** + * Use XEP-0198 acks in the stream when available. + * Default: true + */ + bool useAcks = true; + + /** + * Use Single Sign On. + * Default: false + */ + bool singleSignOn = false; + + /** + * The hostname to connect to. + * Leave this empty for standard XMPP connection, based on the JID domain. + */ + std::string manualHostname = ""; + + /** + * The port to connect to. + * Leave this to -1 to use the port discovered by SRV lookups, and 5222 as a + * fallback. + */ + int manualPort = -1; + + /** + * The type of proxy to use for connecting to the XMPP + * server. + */ + ProxyType proxyType = SystemConfiguredProxy; + + /** + * Override the system-configured proxy hostname. + */ + std::string manualProxyHostname = ""; + + /** + * Override the system-configured proxy port. + */ + int manualProxyPort = -1; + + /** + * If non-empty, use BOSH instead of direct TCP, with the given URL. + * Default: empty (no BOSH) + */ + URL boshURL = URL(); + + /** + * If non-empty, BOSH connections will try to connect over this HTTP CONNECT + * proxy instead of directly. + * Default: empty (no proxy) + */ + URL boshHTTPConnectProxyURL = URL(); + + /** + * If this and matching Password are non-empty, BOSH connections over + * HTTP CONNECT proxies will use these credentials for proxy access. + * Default: empty (no authentication needed by the proxy) + */ + SafeString boshHTTPConnectProxyAuthID = SafeString(""); + SafeString boshHTTPConnectProxyAuthPassword = SafeString(""); + + /** + * This can be initialized with a custom HTTPTrafficFilter, which allows HTTP CONNECT + * proxy initialization to be customized. + */ + std::shared_ptr<HTTPTrafficFilter> httpTrafficFilter; + + /** + * Options passed to the TLS stack + */ + TLSOptions tlsOptions; + + /** + * Session shutdown timeout in milliseconds. This is the maximum time Swiften + * waits from a session close to the socket close. + */ + int sessionShutdownTimeoutInMilliseconds = 10000; + }; } diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp index f03cbaa..1114336 100644 --- a/Swiften/Client/ClientSession.cpp +++ b/Swiften/Client/ClientSession.cpp @@ -1,83 +1,94 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/ClientSession.h> +#include <memory> + #include <boost/bind.hpp> #include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid_io.hpp> #include <boost/uuid/uuid_generators.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Base/Platform.h> #include <Swiften/Base/Log.h> -#include <Swiften/Elements/ProtocolHeader.h> -#include <Swiften/Elements/StreamFeatures.h> -#include <Swiften/Elements/StreamError.h> -#include <Swiften/Elements/StartTLSRequest.h> -#include <Swiften/Elements/StartTLSFailure.h> -#include <Swiften/Elements/TLSProceed.h> -#include <Swiften/Elements/AuthRequest.h> -#include <Swiften/Elements/AuthSuccess.h> -#include <Swiften/Elements/AuthFailure.h> +#include <Swiften/Base/Platform.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Elements/AuthChallenge.h> +#include <Swiften/Elements/AuthFailure.h> +#include <Swiften/Elements/AuthRequest.h> #include <Swiften/Elements/AuthResponse.h> -#include <Swiften/Elements/Compressed.h> +#include <Swiften/Elements/AuthSuccess.h> #include <Swiften/Elements/CompressFailure.h> #include <Swiften/Elements/CompressRequest.h> +#include <Swiften/Elements/Compressed.h> #include <Swiften/Elements/EnableStreamManagement.h> -#include <Swiften/Elements/StreamManagementEnabled.h> -#include <Swiften/Elements/StreamManagementFailed.h> -#include <Swiften/Elements/StartSession.h> -#include <Swiften/Elements/StanzaAck.h> -#include <Swiften/Elements/StanzaAckRequest.h> #include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/ProtocolHeader.h> #include <Swiften/Elements/ResourceBind.h> -#include <Swiften/SASL/PLAINClientAuthenticator.h> +#include <Swiften/Elements/StanzaAck.h> +#include <Swiften/Elements/StanzaAckRequest.h> +#include <Swiften/Elements/StartSession.h> +#include <Swiften/Elements/StartTLSFailure.h> +#include <Swiften/Elements/StartTLSRequest.h> +#include <Swiften/Elements/StreamError.h> +#include <Swiften/Elements/StreamFeatures.h> +#include <Swiften/Elements/StreamManagementEnabled.h> +#include <Swiften/Elements/StreamManagementFailed.h> +#include <Swiften/Elements/TLSProceed.h> +#include <Swiften/Network/Timer.h> +#include <Swiften/Network/TimerFactory.h> +#include <Swiften/SASL/DIGESTMD5ClientAuthenticator.h> #include <Swiften/SASL/EXTERNALClientAuthenticator.h> +#include <Swiften/SASL/PLAINClientAuthenticator.h> #include <Swiften/SASL/SCRAMSHA1ClientAuthenticator.h> -#include <Swiften/SASL/DIGESTMD5ClientAuthenticator.h> -#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Session/SessionStream.h> +#include <Swiften/Session/BasicSessionStream.h> +#include <Swiften/Session/BOSHSessionStream.h> +#include <Swiften/StreamManagement/StanzaAckRequester.h> +#include <Swiften/StreamManagement/StanzaAckResponder.h> #include <Swiften/TLS/CertificateTrustChecker.h> #include <Swiften/TLS/ServerIdentityVerifier.h> -#include <Swiften/Base/Log.h> #ifdef SWIFTEN_PLATFORM_WIN32 #include <Swiften/Base/WindowsRegistry.h> +#include <Swiften/SASL/WindowsGSSAPIClientAuthenticator.h> #endif #define CHECK_STATE_OR_RETURN(a) \ - if (!checkState(a)) { return; } + if (!checkState(a)) { return; } namespace Swift { ClientSession::ClientSession( - const JID& jid, - boost::shared_ptr<SessionStream> stream, - IDNConverter* idnConverter, - CryptoProvider* crypto) : - localJID(jid), - state(Initial), - stream(stream), - idnConverter(idnConverter), - crypto(crypto), - allowPLAINOverNonTLS(false), - useStreamCompression(true), - useTLS(UseTLSWhenAvailable), - useAcks(true), - needSessionStart(false), - needResourceBind(false), - needAcking(false), - rosterVersioningSupported(false), - authenticator(NULL), - certificateTrustChecker(NULL) { + const JID& jid, + std::shared_ptr<SessionStream> stream, + IDNConverter* idnConverter, + CryptoProvider* crypto, + TimerFactory* timerFactory) : + localJID(jid), + state(State::Initial), + stream(stream), + idnConverter(idnConverter), + crypto(crypto), + timerFactory(timerFactory), + allowPLAINOverNonTLS(false), + useStreamCompression(true), + useTLS(UseTLSWhenAvailable), + useAcks(true), + needSessionStart(false), + needResourceBind(false), + needAcking(false), + rosterVersioningSupported(false), + authenticator(nullptr), + certificateTrustChecker(nullptr), + singleSignOn(false), + authenticationPort(-1) { #ifdef SWIFTEN_PLATFORM_WIN32 if (WindowsRegistry::isFIPSEnabled()) { - SWIFT_LOG(info) << "Windows is running in FIPS-140 mode. Some authentication methods will be unavailable." << std::endl; + SWIFT_LOG(info) << "Windows is running in FIPS-140 mode. Some authentication methods will be unavailable."; } #endif } @@ -86,393 +97,488 @@ ClientSession::~ClientSession() { } void ClientSession::start() { - stream->onStreamStartReceived.connect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); - stream->onElementReceived.connect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); - stream->onClosed.connect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1)); - stream->onTLSEncrypted.connect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); - - assert(state == Initial); - state = WaitingForStreamStart; - sendStreamHeader(); + stream->onStreamStartReceived.connect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); + stream->onStreamEndReceived.connect(boost::bind(&ClientSession::handleStreamEnd, shared_from_this())); + stream->onElementReceived.connect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); + stream->onClosed.connect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1)); + stream->onTLSEncrypted.connect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); + + assert(state == State::Initial); + state = State::WaitingForStreamStart; + sendStreamHeader(); } void ClientSession::sendStreamHeader() { - ProtocolHeader header; - header.setTo(getRemoteJID()); - stream->writeHeader(header); + ProtocolHeader header; + header.setTo(getRemoteJID()); + stream->writeHeader(header); } -void ClientSession::sendStanza(boost::shared_ptr<Stanza> stanza) { - stream->writeElement(stanza); - if (stanzaAckRequester_) { - stanzaAckRequester_->handleStanzaSent(stanza); - } +void ClientSession::sendStanza(std::shared_ptr<Stanza> stanza) { + stream->writeElement(stanza); + if (stanzaAckRequester_) { + stanzaAckRequester_->handleStanzaSent(stanza); + } } void ClientSession::handleStreamStart(const ProtocolHeader&) { - CHECK_STATE_OR_RETURN(WaitingForStreamStart); - state = Negotiating; + CHECK_STATE_OR_RETURN(State::WaitingForStreamStart) + state = State::Negotiating; +} + +void ClientSession::handleStreamEnd() { + if (state == State::Finishing) { + // We are already in finishing state if we iniated the close of the session. + stream->close(); + } + else { + state = State::Finishing; + initiateShutdown(true); + } } -void ClientSession::handleElement(boost::shared_ptr<Element> element) { - if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) { - if (stanzaAckResponder_) { - stanzaAckResponder_->handleStanzaReceived(); - } - if (getState() == Initialized) { - onStanzaReceived(stanza); - } - else if (boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(element)) { - if (state == BindingResource) { - boost::shared_ptr<ResourceBind> resourceBind(iq->getPayload<ResourceBind>()); - if (iq->getType() == IQ::Error && iq->getID() == "session-bind") { - finishSession(Error::ResourceBindError); - } - else if (!resourceBind) { - finishSession(Error::UnexpectedElementError); - } - else if (iq->getType() == IQ::Result) { - localJID = resourceBind->getJID(); - if (!localJID.isValid()) { - finishSession(Error::ResourceBindError); - } - needResourceBind = false; - continueSessionInitialization(); - } - else { - finishSession(Error::UnexpectedElementError); - } - } - else if (state == StartingSession) { - if (iq->getType() == IQ::Result) { - needSessionStart = false; - continueSessionInitialization(); - } - else if (iq->getType() == IQ::Error) { - finishSession(Error::SessionStartError); - } - else { - finishSession(Error::UnexpectedElementError); - } - } - else { - finishSession(Error::UnexpectedElementError); - } - } - } - else if (boost::dynamic_pointer_cast<StanzaAckRequest>(element)) { - if (stanzaAckResponder_) { - stanzaAckResponder_->handleAckRequestReceived(); - } - } - else if (boost::shared_ptr<StanzaAck> ack = boost::dynamic_pointer_cast<StanzaAck>(element)) { - if (stanzaAckRequester_) { - if (ack->isValid()) { - stanzaAckRequester_->handleAckReceived(ack->getHandledStanzasCount()); - } - else { - std::cerr << "Warning: Got invalid ack from server" << std::endl; - } - } - else { - std::cerr << "Warning: Ignoring ack" << std::endl; - } - } - else if (StreamError::ref streamError = boost::dynamic_pointer_cast<StreamError>(element)) { - finishSession(Error::StreamError); - } - else if (getState() == Initialized) { - boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element); - if (stanza) { - if (stanzaAckResponder_) { - stanzaAckResponder_->handleStanzaReceived(); - } - onStanzaReceived(stanza); - } - } - else if (StreamFeatures* streamFeatures = dynamic_cast<StreamFeatures*>(element.get())) { - CHECK_STATE_OR_RETURN(Negotiating); - - if (streamFeatures->hasStartTLS() && stream->supportsTLSEncryption() && useTLS != NeverUseTLS) { - state = WaitingForEncrypt; - stream->writeElement(boost::make_shared<StartTLSRequest>()); - } - else if (useTLS == RequireTLS && !stream->isTLSEncrypted()) { - finishSession(Error::NoSupportedAuthMechanismsError); - } - else if (useStreamCompression && stream->supportsZLibCompression() && streamFeatures->hasCompressionMethod("zlib")) { - state = Compressing; - stream->writeElement(boost::make_shared<CompressRequest>("zlib")); - } - else if (streamFeatures->hasAuthenticationMechanisms()) { - if (stream->hasTLSCertificate()) { - if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { - authenticator = new EXTERNALClientAuthenticator(); - state = Authenticating; - stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray(""))); - } - else { - finishSession(Error::TLSClientCertificateError); - } - } - else if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { - authenticator = new EXTERNALClientAuthenticator(); - state = Authenticating; - stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray(""))); - } - else if (streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1") || streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS")) { - std::ostringstream s; - ByteArray finishMessage; - bool plus = stream->isTLSEncrypted() && streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS"); - if (plus) { - finishMessage = stream->getTLSFinishMessage(); - plus &= !finishMessage.empty(); - } - s << boost::uuids::random_generator()(); - SCRAMSHA1ClientAuthenticator* scramAuthenticator = new SCRAMSHA1ClientAuthenticator(s.str(), plus, idnConverter, crypto); - if (plus) { - scramAuthenticator->setTLSChannelBindingData(finishMessage); - } - authenticator = scramAuthenticator; - state = WaitingForCredentials; - onNeedCredentials(); - } - else if ((stream->isTLSEncrypted() || allowPLAINOverNonTLS) && streamFeatures->hasAuthenticationMechanism("PLAIN")) { - authenticator = new PLAINClientAuthenticator(); - state = WaitingForCredentials; - onNeedCredentials(); - } - else if (streamFeatures->hasAuthenticationMechanism("DIGEST-MD5") && crypto->isMD5AllowedForCrypto()) { - std::ostringstream s; - s << boost::uuids::random_generator()(); - // FIXME: Host should probably be the actual host - authenticator = new DIGESTMD5ClientAuthenticator(localJID.getDomain(), s.str(), crypto); - state = WaitingForCredentials; - onNeedCredentials(); - } - else { - finishSession(Error::NoSupportedAuthMechanismsError); - } - } - else { - // Start the session - rosterVersioningSupported = streamFeatures->hasRosterVersioning(); - stream->setWhitespacePingEnabled(true); - needSessionStart = streamFeatures->hasSession(); - needResourceBind = streamFeatures->hasResourceBind(); - needAcking = streamFeatures->hasStreamManagement() && useAcks; - if (!needResourceBind) { - // Resource binding is a MUST - finishSession(Error::ResourceBindError); - } - else { - continueSessionInitialization(); - } - } - } - else if (boost::dynamic_pointer_cast<Compressed>(element)) { - CHECK_STATE_OR_RETURN(Compressing); - state = WaitingForStreamStart; - stream->addZLibCompression(); - stream->resetXMPPParser(); - sendStreamHeader(); - } - else if (boost::dynamic_pointer_cast<CompressFailure>(element)) { - finishSession(Error::CompressionFailedError); - } - else if (boost::dynamic_pointer_cast<StreamManagementEnabled>(element)) { - stanzaAckRequester_ = boost::make_shared<StanzaAckRequester>(); - stanzaAckRequester_->onRequestAck.connect(boost::bind(&ClientSession::requestAck, shared_from_this())); - stanzaAckRequester_->onStanzaAcked.connect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1)); - stanzaAckResponder_ = boost::make_shared<StanzaAckResponder>(); - stanzaAckResponder_->onAck.connect(boost::bind(&ClientSession::ack, shared_from_this(), _1)); - needAcking = false; - continueSessionInitialization(); - } - else if (boost::dynamic_pointer_cast<StreamManagementFailed>(element)) { - needAcking = false; - continueSessionInitialization(); - } - else if (AuthChallenge* challenge = dynamic_cast<AuthChallenge*>(element.get())) { - CHECK_STATE_OR_RETURN(Authenticating); - assert(authenticator); - if (authenticator->setChallenge(challenge->getValue())) { - stream->writeElement(boost::make_shared<AuthResponse>(authenticator->getResponse())); - } - else { - finishSession(Error::AuthenticationFailedError); - } - } - else if (AuthSuccess* authSuccess = dynamic_cast<AuthSuccess*>(element.get())) { - CHECK_STATE_OR_RETURN(Authenticating); - assert(authenticator); - if (!authenticator->setChallenge(authSuccess->getValue())) { - finishSession(Error::ServerVerificationFailedError); - } - else { - state = WaitingForStreamStart; - delete authenticator; - authenticator = NULL; - stream->resetXMPPParser(); - sendStreamHeader(); - } - } - else if (dynamic_cast<AuthFailure*>(element.get())) { - finishSession(Error::AuthenticationFailedError); - } - else if (dynamic_cast<TLSProceed*>(element.get())) { - CHECK_STATE_OR_RETURN(WaitingForEncrypt); - state = Encrypting; - stream->addTLSEncryption(); - } - else if (dynamic_cast<StartTLSFailure*>(element.get())) { - finishSession(Error::TLSError); - } - else { - // FIXME Not correct? - state = Initialized; - onInitialized(); - } +void ClientSession::handleElement(std::shared_ptr<ToplevelElement> element) { + if (std::shared_ptr<Stanza> stanza = std::dynamic_pointer_cast<Stanza>(element)) { + if (stanzaAckResponder_) { + stanzaAckResponder_->handleStanzaReceived(); + } + if (getState() == State::Initialized) { + onStanzaReceived(stanza); + } + else if (std::shared_ptr<IQ> iq = std::dynamic_pointer_cast<IQ>(element)) { + if (state == State::BindingResource) { + std::shared_ptr<ResourceBind> resourceBind(iq->getPayload<ResourceBind>()); + if (iq->getType() == IQ::Error && iq->getID() == "session-bind") { + finishSession(Error::ResourceBindError); + } + else if (!resourceBind) { + finishSession(Error::UnexpectedElementError); + } + else if (iq->getType() == IQ::Result) { + localJID = resourceBind->getJID(); + if (!localJID.isValid()) { + finishSession(Error::ResourceBindError); + } + needResourceBind = false; + continueSessionInitialization(); + } + else { + finishSession(Error::UnexpectedElementError); + } + } + else if (state == State::StartingSession) { + if (iq->getType() == IQ::Result) { + needSessionStart = false; + continueSessionInitialization(); + } + else if (iq->getType() == IQ::Error) { + finishSession(Error::SessionStartError); + } + else { + finishSession(Error::UnexpectedElementError); + } + } + else { + finishSession(Error::UnexpectedElementError); + } + } + } + else if (std::dynamic_pointer_cast<StanzaAckRequest>(element)) { + if (stanzaAckResponder_) { + stanzaAckResponder_->handleAckRequestReceived(); + } + } + else if (std::shared_ptr<StanzaAck> ack = std::dynamic_pointer_cast<StanzaAck>(element)) { + if (stanzaAckRequester_) { + if (ack->isValid()) { + stanzaAckRequester_->handleAckReceived(ack->getHandledStanzasCount()); + } + else { + SWIFT_LOG(warning) << "Got invalid ack from server"; + } + } + else { + SWIFT_LOG(warning) << "Ignoring ack"; + } + } + else if (StreamError::ref streamError = std::dynamic_pointer_cast<StreamError>(element)) { + finishSession(Error::StreamError); + } + else if (getState() == State::Initialized) { + std::shared_ptr<Stanza> stanza = std::dynamic_pointer_cast<Stanza>(element); + if (stanza) { + if (stanzaAckResponder_) { + stanzaAckResponder_->handleStanzaReceived(); + } + onStanzaReceived(stanza); + } + } + else if (StreamFeatures* streamFeatures = dynamic_cast<StreamFeatures*>(element.get())) { + CHECK_STATE_OR_RETURN(State::Negotiating) + + if (streamFeatures->hasStartTLS() && stream->supportsTLSEncryption() && useTLS != NeverUseTLS) { + state = State::WaitingForEncrypt; + stream->writeElement(std::make_shared<StartTLSRequest>()); + } + else if (useTLS == RequireTLS && !stream->isTLSEncrypted()) { + finishSession(Error::NoSupportedAuthMechanismsError); + } + else if (useStreamCompression && stream->supportsZLibCompression() && streamFeatures->hasCompressionMethod("zlib")) { + state = State::Compressing; + stream->writeElement(std::make_shared<CompressRequest>("zlib")); + } + else if (streamFeatures->hasAuthenticationMechanisms()) { +#ifdef SWIFTEN_PLATFORM_WIN32 + if (singleSignOn) { + const boost::optional<std::string> authenticationHostname = streamFeatures->getAuthenticationHostname(); + bool gssapiSupported = streamFeatures->hasAuthenticationMechanism("GSSAPI"); + + if (!gssapiSupported) { + finishSession(Error::NoSupportedAuthMechanismsError); + } + else { + WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = new WindowsGSSAPIClientAuthenticator(authenticationHostname.value_or(""), localJID.getDomain(), authenticationPort); + std::shared_ptr<Error> error = std::make_shared<Error>(Error::AuthenticationFailedError); + + authenticator = gssapiAuthenticator; + + if (!gssapiAuthenticator->isError()) { + state = State::Authenticating; + stream->writeElement(std::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse())); + } + else { + error->errorCode = gssapiAuthenticator->getErrorCode(); + finishSession(error); + } + } + } + else +#endif + if (stream->hasTLSCertificate()) { + if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { + authenticator = new EXTERNALClientAuthenticator(); + state = State::Authenticating; + stream->writeElement(std::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray(""))); + } + else { + finishSession(Error::TLSClientCertificateError); + } + } + else if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { + authenticator = new EXTERNALClientAuthenticator(); + state = State::Authenticating; + stream->writeElement(std::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray(""))); + } + else if (streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1") || streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS")) { + std::ostringstream s; + ByteArray finishMessage; + bool plus = streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS"); + if (stream->isTLSEncrypted()) { + finishMessage = stream->getTLSFinishMessage(); + plus &= !finishMessage.empty(); + } + s << boost::uuids::random_generator()(); + SCRAMSHA1ClientAuthenticator* scramAuthenticator = new SCRAMSHA1ClientAuthenticator(s.str(), plus, idnConverter, crypto); + if (!finishMessage.empty()) { + scramAuthenticator->setTLSChannelBindingData(finishMessage); + } + authenticator = scramAuthenticator; + state = State::WaitingForCredentials; + onNeedCredentials(); + } + else if ((stream->isTLSEncrypted() || allowPLAINOverNonTLS) && streamFeatures->hasAuthenticationMechanism("PLAIN")) { + authenticator = new PLAINClientAuthenticator(); + state = State::WaitingForCredentials; + onNeedCredentials(); + } + else if (streamFeatures->hasAuthenticationMechanism("DIGEST-MD5") && crypto->isMD5AllowedForCrypto()) { + std::ostringstream s; + s << boost::uuids::random_generator()(); + // FIXME: Host should probably be the actual host + authenticator = new DIGESTMD5ClientAuthenticator(localJID.getDomain(), s.str(), crypto); + state = State::WaitingForCredentials; + onNeedCredentials(); + } + else { + finishSession(Error::NoSupportedAuthMechanismsError); + } + } + else { + // Start the session + rosterVersioningSupported = streamFeatures->hasRosterVersioning(); + stream->setWhitespacePingEnabled(true); + needSessionStart = streamFeatures->hasSession(); + needResourceBind = streamFeatures->hasResourceBind(); + needAcking = streamFeatures->hasStreamManagement() && useAcks; + if (!needResourceBind) { + // Resource binding is a MUST + finishSession(Error::ResourceBindError); + } + else { + continueSessionInitialization(); + } + } + } + else if (std::dynamic_pointer_cast<Compressed>(element)) { + CHECK_STATE_OR_RETURN(State::Compressing) + state = State::WaitingForStreamStart; + stream->addZLibCompression(); + stream->resetXMPPParser(); + sendStreamHeader(); + } + else if (std::dynamic_pointer_cast<CompressFailure>(element)) { + finishSession(Error::CompressionFailedError); + } + else if (std::dynamic_pointer_cast<StreamManagementEnabled>(element)) { + stanzaAckRequester_ = std::make_shared<StanzaAckRequester>(); + stanzaAckRequester_->onRequestAck.connect(boost::bind(&ClientSession::requestAck, shared_from_this())); + stanzaAckRequester_->onStanzaAcked.connect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1)); + stanzaAckResponder_ = std::make_shared<StanzaAckResponder>(); + stanzaAckResponder_->onAck.connect(boost::bind(&ClientSession::ack, shared_from_this(), _1)); + needAcking = false; + continueSessionInitialization(); + } + else if (std::dynamic_pointer_cast<StreamManagementFailed>(element)) { + needAcking = false; + continueSessionInitialization(); + } + else if (AuthChallenge* challenge = dynamic_cast<AuthChallenge*>(element.get())) { + CHECK_STATE_OR_RETURN(State::Authenticating) + assert(authenticator); + if (authenticator->setChallenge(challenge->getValue())) { + stream->writeElement(std::make_shared<AuthResponse>(authenticator->getResponse())); + } +#ifdef SWIFTEN_PLATFORM_WIN32 + else if (WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = dynamic_cast<WindowsGSSAPIClientAuthenticator*>(authenticator)) { + std::shared_ptr<Error> error = std::make_shared<Error>(Error::AuthenticationFailedError); + + error->errorCode = gssapiAuthenticator->getErrorCode(); + finishSession(error); + } +#endif + else { + finishSession(Error::AuthenticationFailedError); + } + } + else if (AuthSuccess* authSuccess = dynamic_cast<AuthSuccess*>(element.get())) { + CHECK_STATE_OR_RETURN(State::Authenticating) + assert(authenticator); + if (!authenticator->setChallenge(authSuccess->getValue())) { + finishSession(Error::ServerVerificationFailedError); + } + else { + state = State::WaitingForStreamStart; + delete authenticator; + authenticator = nullptr; + stream->resetXMPPParser(); + sendStreamHeader(); + } + } + else if (dynamic_cast<AuthFailure*>(element.get())) { + finishSession(Error::AuthenticationFailedError); + } + else if (dynamic_cast<TLSProceed*>(element.get())) { + CHECK_STATE_OR_RETURN(State::WaitingForEncrypt) + state = State::Encrypting; + stream->addTLSEncryption(); + } + else if (dynamic_cast<StartTLSFailure*>(element.get())) { + finishSession(Error::TLSError); + } + else { + // FIXME Not correct? + state = State::Initialized; + onInitialized(); + } } void ClientSession::continueSessionInitialization() { - if (needResourceBind) { - state = BindingResource; - boost::shared_ptr<ResourceBind> resourceBind(boost::make_shared<ResourceBind>()); - if (!localJID.getResource().empty()) { - resourceBind->setResource(localJID.getResource()); - } - sendStanza(IQ::createRequest(IQ::Set, JID(), "session-bind", resourceBind)); - } - else if (needAcking) { - state = EnablingSessionManagement; - stream->writeElement(boost::make_shared<EnableStreamManagement>()); - } - else if (needSessionStart) { - state = StartingSession; - sendStanza(IQ::createRequest(IQ::Set, JID(), "session-start", boost::make_shared<StartSession>())); - } - else { - state = Initialized; - onInitialized(); - } + if (needResourceBind) { + state = State::BindingResource; + std::shared_ptr<ResourceBind> resourceBind(std::make_shared<ResourceBind>()); + if (!localJID.getResource().empty()) { + resourceBind->setResource(localJID.getResource()); + } + sendStanza(IQ::createRequest(IQ::Set, JID(), "session-bind", resourceBind)); + } + else if (needAcking) { + state = State::EnablingSessionManagement; + stream->writeElement(std::make_shared<EnableStreamManagement>()); + } + else if (needSessionStart) { + state = State::StartingSession; + sendStanza(IQ::createRequest(IQ::Set, JID(), "session-start", std::make_shared<StartSession>())); + } + else { + state = State::Initialized; + onInitialized(); + } } bool ClientSession::checkState(State state) { - if (this->state != state) { - finishSession(Error::UnexpectedElementError); - return false; - } - return true; + if (this->state != state) { + finishSession(Error::UnexpectedElementError); + return false; + } + return true; } void ClientSession::sendCredentials(const SafeByteArray& password) { - assert(WaitingForCredentials); - assert(authenticator); - state = Authenticating; - authenticator->setCredentials(localJID.getNode(), password); - stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse())); + assert(state == State::WaitingForCredentials); + assert(authenticator); + state = State::Authenticating; + authenticator->setCredentials(localJID.getNode(), password); + stream->writeElement(std::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse())); } void ClientSession::handleTLSEncrypted() { - CHECK_STATE_OR_RETURN(Encrypting); - - std::vector<Certificate::ref> certificateChain = stream->getPeerCertificateChain(); - boost::shared_ptr<CertificateVerificationError> verificationError = stream->getPeerCertificateVerificationError(); - if (verificationError) { - checkTrustOrFinish(certificateChain, verificationError); - } - else { - ServerIdentityVerifier identityVerifier(localJID, idnConverter); - if (!certificateChain.empty() && identityVerifier.certificateVerifies(certificateChain[0])) { - continueAfterTLSEncrypted(); - } - else { - checkTrustOrFinish(certificateChain, boost::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidServerIdentity)); - } - } + if (!std::dynamic_pointer_cast<BOSHSessionStream>(stream)) { + CHECK_STATE_OR_RETURN(State::Encrypting) + } + + std::vector<Certificate::ref> certificateChain = stream->getPeerCertificateChain(); + std::shared_ptr<CertificateVerificationError> verificationError = stream->getPeerCertificateVerificationError(); + if (verificationError) { + checkTrustOrFinish(certificateChain, verificationError); + } + else { + ServerIdentityVerifier identityVerifier(localJID, idnConverter); + if (!certificateChain.empty() && identityVerifier.certificateVerifies(certificateChain[0])) { + continueAfterTLSEncrypted(); + } + else { + checkTrustOrFinish(certificateChain, std::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidServerIdentity)); + } + } +} + +void ClientSession::checkTrustOrFinish(const std::vector<Certificate::ref>& certificateChain, std::shared_ptr<CertificateVerificationError> error) { + if (certificateTrustChecker && certificateTrustChecker->isCertificateTrusted(certificateChain)) { + if (!std::dynamic_pointer_cast<BOSHSessionStream>(stream)) { + continueAfterTLSEncrypted(); + } + } + else { + finishSession(error); + } } -void ClientSession::checkTrustOrFinish(const std::vector<Certificate::ref>& certificateChain, boost::shared_ptr<CertificateVerificationError> error) { - if (certificateTrustChecker && certificateTrustChecker->isCertificateTrusted(certificateChain)) { - continueAfterTLSEncrypted(); - } - else { - finishSession(error); - } +void ClientSession::initiateShutdown(bool sendFooter) { + if (!streamShutdownTimeout) { + streamShutdownTimeout = timerFactory->createTimer(sessionShutdownTimeoutInMilliseconds); + streamShutdownTimeout->onTick.connect(boost::bind(&ClientSession::handleStreamShutdownTimeout, shared_from_this())); + streamShutdownTimeout->start(); + } + if (sendFooter) { + stream->writeFooter(); + } + if (state == State::Finishing) { + // The other side already send </stream>; we can close the socket. + stream->close(); + } + else { + state = State::Finishing; + } } void ClientSession::continueAfterTLSEncrypted() { - state = WaitingForStreamStart; - stream->resetXMPPParser(); - sendStreamHeader(); + if (!std::dynamic_pointer_cast<BOSHSessionStream>(stream)) { + state = State::WaitingForStreamStart; + stream->resetXMPPParser(); + sendStreamHeader(); + } +} + +void ClientSession::handleStreamClosed(std::shared_ptr<Swift::Error> streamError) { + State previousState = state; + state = State::Finished; + + if (streamShutdownTimeout) { + streamShutdownTimeout->stop(); + streamShutdownTimeout.reset(); + } + + if (stanzaAckRequester_) { + stanzaAckRequester_->onRequestAck.disconnect(boost::bind(&ClientSession::requestAck, shared_from_this())); + stanzaAckRequester_->onStanzaAcked.disconnect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1)); + stanzaAckRequester_.reset(); + } + if (stanzaAckResponder_) { + stanzaAckResponder_->onAck.disconnect(boost::bind(&ClientSession::ack, shared_from_this(), _1)); + stanzaAckResponder_.reset(); + } + stream->setWhitespacePingEnabled(false); + stream->onStreamStartReceived.disconnect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); + stream->onStreamEndReceived.disconnect(boost::bind(&ClientSession::handleStreamEnd, shared_from_this())); + stream->onElementReceived.disconnect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); + stream->onClosed.disconnect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1)); + stream->onTLSEncrypted.disconnect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); + + if (previousState == State::Finishing) { + onFinished(error_); + } + else { + onFinished(streamError); + } } -void ClientSession::handleStreamClosed(boost::shared_ptr<Swift::Error> streamError) { - State previousState = state; - state = Finished; - - if (stanzaAckRequester_) { - stanzaAckRequester_->onRequestAck.disconnect(boost::bind(&ClientSession::requestAck, shared_from_this())); - stanzaAckRequester_->onStanzaAcked.disconnect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1)); - stanzaAckRequester_.reset(); - } - if (stanzaAckResponder_) { - stanzaAckResponder_->onAck.disconnect(boost::bind(&ClientSession::ack, shared_from_this(), _1)); - stanzaAckResponder_.reset(); - } - stream->setWhitespacePingEnabled(false); - stream->onStreamStartReceived.disconnect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); - stream->onElementReceived.disconnect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); - stream->onClosed.disconnect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1)); - stream->onTLSEncrypted.disconnect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); - - if (previousState == Finishing) { - onFinished(error_); - } - else { - onFinished(streamError); - } +void ClientSession::handleStreamShutdownTimeout() { + handleStreamClosed(std::shared_ptr<Swift::Error>()); } void ClientSession::finish() { - finishSession(boost::shared_ptr<Error>()); + if (state != State::Finishing && state != State::Finished) { + finishSession(std::shared_ptr<Error>()); + } + else { + SWIFT_LOG(warning) << "Session already finished or finishing."; + } } void ClientSession::finishSession(Error::Type error) { - finishSession(boost::make_shared<Swift::ClientSession::Error>(error)); + finishSession(std::make_shared<Swift::ClientSession::Error>(error)); } -void ClientSession::finishSession(boost::shared_ptr<Swift::Error> error) { - state = Finishing; - if (!error_) { - error_ = error; - } - else { - SWIFT_LOG(warning) << "Session finished twice"; - } - assert(stream->isOpen()); - if (stanzaAckResponder_) { - stanzaAckResponder_->handleAckRequestReceived(); - } - if (authenticator) { - delete authenticator; - authenticator = NULL; - } - stream->writeFooter(); - stream->close(); +void ClientSession::finishSession(std::shared_ptr<Swift::Error> error) { + if (!error_) { + error_ = error; + } + else { + SWIFT_LOG(warning) << "Session finished twice"; + } + assert(stream->isOpen()); + if (stanzaAckResponder_) { + stanzaAckResponder_->handleAckRequestReceived(); + } + if (authenticator) { + delete authenticator; + authenticator = nullptr; + } + // Immidiately close TCP connection without stream closure. + if (std::dynamic_pointer_cast<CertificateVerificationError>(error)) { + state = State::Finishing; + initiateShutdown(false); + } + else { + if (state == State::Finishing) { + initiateShutdown(true); + } + else if (state != State::Finished) { + initiateShutdown(true); + } + } } void ClientSession::requestAck() { - stream->writeElement(boost::make_shared<StanzaAckRequest>()); + stream->writeElement(std::make_shared<StanzaAckRequest>()); } -void ClientSession::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) { - onStanzaAcked(stanza); +void ClientSession::handleStanzaAcked(std::shared_ptr<Stanza> stanza) { + onStanzaAcked(stanza); } void ClientSession::ack(unsigned int handledStanzasCount) { - stream->writeElement(boost::make_shared<StanzaAck>(handledStanzasCount)); + stream->writeElement(std::make_shared<StanzaAck>(handledStanzasCount)); } } diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h index 4b944fc..c7b3658 100644 --- a/Swiften/Client/ClientSession.h +++ b/Swiften/Client/ClientSession.h @@ -1,186 +1,215 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <memory> +#include <string> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/Error.h> -#include <Swiften/Session/SessionStream.h> -#include <string> +#include <Swiften/Elements/ToplevelElement.h> #include <Swiften/JID/JID.h> -#include <Swiften/Elements/Element.h> -#include <Swiften/StreamManagement/StanzaAckRequester.h> -#include <Swiften/StreamManagement/StanzaAckResponder.h> +#include <Swiften/Session/SessionStream.h> namespace Swift { - class ClientAuthenticator; - class CertificateTrustChecker; - class IDNConverter; - class CryptoProvider; - - class SWIFTEN_API ClientSession : public boost::enable_shared_from_this<ClientSession> { - public: - enum State { - Initial, - WaitingForStreamStart, - Negotiating, - Compressing, - WaitingForEncrypt, - Encrypting, - WaitingForCredentials, - Authenticating, - EnablingSessionManagement, - BindingResource, - StartingSession, - Initialized, - Finishing, - Finished - }; - - struct Error : public Swift::Error { - enum Type { - AuthenticationFailedError, - CompressionFailedError, - ServerVerificationFailedError, - NoSupportedAuthMechanismsError, - UnexpectedElementError, - ResourceBindError, - SessionStartError, - TLSClientCertificateError, - TLSError, - StreamError - } type; - Error(Type type) : type(type) {} - }; - - enum UseTLS { - NeverUseTLS, - UseTLSWhenAvailable, - RequireTLS - }; - - ~ClientSession(); - - static boost::shared_ptr<ClientSession> create(const JID& jid, boost::shared_ptr<SessionStream> stream, IDNConverter* idnConverter, CryptoProvider* crypto) { - return boost::shared_ptr<ClientSession>(new ClientSession(jid, stream, idnConverter, crypto)); - } - - State getState() const { - return state; - } - - void setAllowPLAINOverNonTLS(bool b) { - allowPLAINOverNonTLS = b; - } - - void setUseStreamCompression(bool b) { - useStreamCompression = b; - } - - void setUseTLS(UseTLS b) { - useTLS = b; - } - - void setUseAcks(bool b) { - useAcks = b; - } - - - bool getStreamManagementEnabled() const { - // Explicitly convert to bool. In C++11, it would be cleaner to - // compare to nullptr. - return static_cast<bool>(stanzaAckRequester_); - } - - bool getRosterVersioningSupported() const { - return rosterVersioningSupported; - } - - std::vector<Certificate::ref> getPeerCertificateChain() const { - return stream->getPeerCertificateChain(); - } - - const JID& getLocalJID() const { - return localJID; - } - - void start(); - void finish(); - - bool isFinished() const { - return getState() == Finished; - } - - void sendCredentials(const SafeByteArray& password); - void sendStanza(boost::shared_ptr<Stanza>); - - void setCertificateTrustChecker(CertificateTrustChecker* checker) { - certificateTrustChecker = checker; - } - - public: - boost::signal<void ()> onNeedCredentials; - boost::signal<void ()> onInitialized; - boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished; - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked; - - private: - ClientSession( - const JID& jid, - boost::shared_ptr<SessionStream>, - IDNConverter* idnConverter, - CryptoProvider* crypto); - - void finishSession(Error::Type error); - void finishSession(boost::shared_ptr<Swift::Error> error); - - JID getRemoteJID() const { - return JID("", localJID.getDomain()); - } - - void sendStreamHeader(); - - void handleElement(boost::shared_ptr<Element>); - void handleStreamStart(const ProtocolHeader&); - void handleStreamClosed(boost::shared_ptr<Swift::Error>); - - void handleTLSEncrypted(); - - bool checkState(State); - void continueSessionInitialization(); - - void requestAck(); - void handleStanzaAcked(boost::shared_ptr<Stanza> stanza); - void ack(unsigned int handledStanzasCount); - void continueAfterTLSEncrypted(); - void checkTrustOrFinish(const std::vector<Certificate::ref>& certificateChain, boost::shared_ptr<CertificateVerificationError> error); - - private: - JID localJID; - State state; - boost::shared_ptr<SessionStream> stream; - IDNConverter* idnConverter; - CryptoProvider* crypto; - bool allowPLAINOverNonTLS; - bool useStreamCompression; - UseTLS useTLS; - bool useAcks; - bool needSessionStart; - bool needResourceBind; - bool needAcking; - bool rosterVersioningSupported; - ClientAuthenticator* authenticator; - boost::shared_ptr<StanzaAckRequester> stanzaAckRequester_; - boost::shared_ptr<StanzaAckResponder> stanzaAckResponder_; - boost::shared_ptr<Swift::Error> error_; - CertificateTrustChecker* certificateTrustChecker; - }; + class CertificateTrustChecker; + class ClientAuthenticator; + class CryptoProvider; + class IDNConverter; + class Stanza; + class StanzaAckRequester; + class StanzaAckResponder; + class TimerFactory; + class Timer; + + class SWIFTEN_API ClientSession : public std::enable_shared_from_this<ClientSession> { + public: + enum class State { + Initial, + WaitingForStreamStart, + Negotiating, + Compressing, + WaitingForEncrypt, + Encrypting, + WaitingForCredentials, + Authenticating, + EnablingSessionManagement, + BindingResource, + StartingSession, + Initialized, + Finishing, + Finished + }; + + struct Error : public Swift::Error { + enum Type { + AuthenticationFailedError, + CompressionFailedError, + ServerVerificationFailedError, + NoSupportedAuthMechanismsError, + UnexpectedElementError, + ResourceBindError, + SessionStartError, + TLSClientCertificateError, + TLSError, + StreamError, + StreamEndError, // The server send a closing stream tag. + } type; + std::shared_ptr<boost::system::error_code> errorCode; + Error(Type type) : type(type) {} + }; + + enum UseTLS { + NeverUseTLS, + UseTLSWhenAvailable, + RequireTLS + }; + + ~ClientSession(); + + static std::shared_ptr<ClientSession> create(const JID& jid, std::shared_ptr<SessionStream> stream, IDNConverter* idnConverter, CryptoProvider* crypto, TimerFactory* timerFactory) { + return std::shared_ptr<ClientSession>(new ClientSession(jid, stream, idnConverter, crypto, timerFactory)); + } + + State getState() const { + return state; + } + + void setAllowPLAINOverNonTLS(bool b) { + allowPLAINOverNonTLS = b; + } + + void setUseStreamCompression(bool b) { + useStreamCompression = b; + } + + void setUseTLS(UseTLS b) { + useTLS = b; + } + + void setUseAcks(bool b) { + useAcks = b; + } + + bool getStreamManagementEnabled() const { + // Explicitly convert to bool. In C++11, it would be cleaner to + // compare to nullptr. + return static_cast<bool>(stanzaAckRequester_); + } + + bool getRosterVersioningSupported() const { + return rosterVersioningSupported; + } + + std::vector<Certificate::ref> getPeerCertificateChain() const { + return stream->getPeerCertificateChain(); + } + + const JID& getLocalJID() const { + return localJID; + } + + void start(); + void finish(); + + bool isFinished() const { + return getState() == State::Finished; + } + + void sendCredentials(const SafeByteArray& password); + void sendStanza(std::shared_ptr<Stanza>); + + void setCertificateTrustChecker(CertificateTrustChecker* checker) { + certificateTrustChecker = checker; + } + + void setSingleSignOn(bool b) { + singleSignOn = b; + } + + /** + * Sets the port number used in Kerberos authentication + * Does not affect network connectivity. + */ + void setAuthenticationPort(int i) { + authenticationPort = i; + } + + void setSessionShutdownTimeout(int timeoutInMilliseconds) { + sessionShutdownTimeoutInMilliseconds = timeoutInMilliseconds; + } + + public: + boost::signals2::signal<void ()> onNeedCredentials; + boost::signals2::signal<void ()> onInitialized; + boost::signals2::signal<void (std::shared_ptr<Swift::Error>)> onFinished; + boost::signals2::signal<void (std::shared_ptr<Stanza>)> onStanzaReceived; + boost::signals2::signal<void (std::shared_ptr<Stanza>)> onStanzaAcked; + + private: + ClientSession( + const JID& jid, + std::shared_ptr<SessionStream>, + IDNConverter* idnConverter, + CryptoProvider* crypto, + TimerFactory* timerFactory); + + void finishSession(Error::Type error); + void finishSession(std::shared_ptr<Swift::Error> error); + + JID getRemoteJID() const { + return JID("", localJID.getDomain()); + } + + void sendStreamHeader(); + + void handleElement(std::shared_ptr<ToplevelElement>); + void handleStreamStart(const ProtocolHeader&); + void handleStreamEnd(); + void handleStreamClosed(std::shared_ptr<Swift::Error>); + void handleStreamShutdownTimeout(); + + void handleTLSEncrypted(); + + bool checkState(State); + void continueSessionInitialization(); + + void requestAck(); + void handleStanzaAcked(std::shared_ptr<Stanza> stanza); + void ack(unsigned int handledStanzasCount); + void continueAfterTLSEncrypted(); + void checkTrustOrFinish(const std::vector<Certificate::ref>& certificateChain, std::shared_ptr<CertificateVerificationError> error); + void initiateShutdown(bool sendFooter); + + private: + JID localJID; + State state; + std::shared_ptr<SessionStream> stream; + IDNConverter* idnConverter = nullptr; + CryptoProvider* crypto = nullptr; + TimerFactory* timerFactory = nullptr; + std::shared_ptr<Timer> streamShutdownTimeout; + int sessionShutdownTimeoutInMilliseconds = 10000; + bool allowPLAINOverNonTLS; + bool useStreamCompression; + UseTLS useTLS; + bool useAcks; + bool needSessionStart; + bool needResourceBind; + bool needAcking; + bool rosterVersioningSupported; + ClientAuthenticator* authenticator; + std::shared_ptr<StanzaAckRequester> stanzaAckRequester_; + std::shared_ptr<StanzaAckResponder> stanzaAckResponder_; + std::shared_ptr<Swift::Error> error_; + CertificateTrustChecker* certificateTrustChecker; + bool singleSignOn; + int authenticationPort; + }; } diff --git a/Swiften/Client/ClientSessionStanzaChannel.cpp b/Swiften/Client/ClientSessionStanzaChannel.cpp index 8d85953..6a5d07d 100644 --- a/Swiften/Client/ClientSessionStanzaChannel.cpp +++ b/Swiften/Client/ClientSessionStanzaChannel.cpp @@ -1,101 +1,112 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/ClientSessionStanzaChannel.h> #include <boost/bind.hpp> -#include <iostream> + +#include <Swiften/Base/Log.h> namespace Swift { -void ClientSessionStanzaChannel::setSession(boost::shared_ptr<ClientSession> session) { - assert(!this->session); - this->session = session; - session->onInitialized.connect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); - session->onFinished.connect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); - session->onStanzaReceived.connect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); - session->onStanzaAcked.connect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); +ClientSessionStanzaChannel::~ClientSessionStanzaChannel() { + if (session) { + session->onFinished.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); + session->onStanzaAcked.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); + session->onInitialized.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); + session.reset(); + } +} + +void ClientSessionStanzaChannel::setSession(std::shared_ptr<ClientSession> session) { + assert(!this->session); + this->session = session; + session->onInitialized.connect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); + session->onFinished.connect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.connect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); + session->onStanzaAcked.connect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); } -void ClientSessionStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) { - send(iq); +void ClientSessionStanzaChannel::sendIQ(std::shared_ptr<IQ> iq) { + send(iq); } -void ClientSessionStanzaChannel::sendMessage(boost::shared_ptr<Message> message) { - send(message); +void ClientSessionStanzaChannel::sendMessage(std::shared_ptr<Message> message) { + send(message); } -void ClientSessionStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) { - send(presence); +void ClientSessionStanzaChannel::sendPresence(std::shared_ptr<Presence> presence) { + send(presence); } std::string ClientSessionStanzaChannel::getNewIQID() { - return idGenerator.generateID(); + return idGenerator.generateID(); } -void ClientSessionStanzaChannel::send(boost::shared_ptr<Stanza> stanza) { - if (!isAvailable()) { - std::cerr << "Warning: Client: Trying to send a stanza while disconnected." << std::endl; - return; - } - session->sendStanza(stanza); +void ClientSessionStanzaChannel::send(std::shared_ptr<Stanza> stanza) { + if (!isAvailable()) { + SWIFT_LOG(warning) << "Client: Trying to send a stanza while disconnected."; + return; + } + session->sendStanza(stanza); } -void ClientSessionStanzaChannel::handleSessionFinished(boost::shared_ptr<Error>) { - session->onFinished.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); - session->onStanzaReceived.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); - session->onStanzaAcked.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); - session->onInitialized.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); - session.reset(); +void ClientSessionStanzaChannel::handleSessionFinished(std::shared_ptr<Error>) { + session->onFinished.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); + session->onStanzaAcked.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); + session->onInitialized.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); + session.reset(); - onAvailableChanged(false); + onAvailableChanged(false); } -void ClientSessionStanzaChannel::handleStanza(boost::shared_ptr<Stanza> stanza) { - boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(stanza); - if (message) { - onMessageReceived(message); - return; - } - - boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza); - if (presence) { - onPresenceReceived(presence); - return; - } - - boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza); - if (iq) { - onIQReceived(iq); - return; - } +void ClientSessionStanzaChannel::handleStanza(std::shared_ptr<Stanza> stanza) { + std::shared_ptr<Message> message = std::dynamic_pointer_cast<Message>(stanza); + if (message) { + onMessageReceived(message); + return; + } + + std::shared_ptr<Presence> presence = std::dynamic_pointer_cast<Presence>(stanza); + if (presence) { + onPresenceReceived(presence); + return; + } + + std::shared_ptr<IQ> iq = std::dynamic_pointer_cast<IQ>(stanza); + if (iq) { + onIQReceived(iq); + return; + } } bool ClientSessionStanzaChannel::getStreamManagementEnabled() const { - if (session) { - return session->getStreamManagementEnabled(); - } - return false; + if (session) { + return session->getStreamManagementEnabled(); + } + return false; } std::vector<Certificate::ref> ClientSessionStanzaChannel::getPeerCertificateChain() const { - if (session) { - return session->getPeerCertificateChain(); - } - return std::vector<Certificate::ref>(); + if (session) { + return session->getPeerCertificateChain(); + } + return std::vector<Certificate::ref>(); } -void ClientSessionStanzaChannel::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) { - onStanzaAcked(stanza); +void ClientSessionStanzaChannel::handleStanzaAcked(std::shared_ptr<Stanza> stanza) { + onStanzaAcked(stanza); } void ClientSessionStanzaChannel::handleSessionInitialized() { - onAvailableChanged(true); + onAvailableChanged(true); } } diff --git a/Swiften/Client/ClientSessionStanzaChannel.h b/Swiften/Client/ClientSessionStanzaChannel.h index 2743a16..c4ee393 100644 --- a/Swiften/Client/ClientSessionStanzaChannel.h +++ b/Swiften/Client/ClientSessionStanzaChannel.h @@ -1,49 +1,52 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Base/IDGenerator.h> #include <Swiften/Client/ClientSession.h> #include <Swiften/Client/StanzaChannel.h> -#include <Swiften/Elements/Message.h> #include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> #include <Swiften/Elements/Presence.h> namespace Swift { - /** - * StanzaChannel implementation around a ClientSession. - */ - class ClientSessionStanzaChannel : public StanzaChannel { - public: - void setSession(boost::shared_ptr<ClientSession> session); - - void sendIQ(boost::shared_ptr<IQ> iq); - void sendMessage(boost::shared_ptr<Message> message); - void sendPresence(boost::shared_ptr<Presence> presence); - bool getStreamManagementEnabled() const; - virtual std::vector<Certificate::ref> getPeerCertificateChain() const; - - bool isAvailable() const { - return session && session->getState() == ClientSession::Initialized; - } - - private: - std::string getNewIQID(); - void send(boost::shared_ptr<Stanza> stanza); - void handleSessionFinished(boost::shared_ptr<Error> error); - void handleStanza(boost::shared_ptr<Stanza> stanza); - void handleStanzaAcked(boost::shared_ptr<Stanza> stanza); - void handleSessionInitialized(); - - private: - IDGenerator idGenerator; - boost::shared_ptr<ClientSession> session; - }; + /** + * StanzaChannel implementation around a ClientSession. + */ + class SWIFTEN_API ClientSessionStanzaChannel : public StanzaChannel { + public: + virtual ~ClientSessionStanzaChannel(); + + void setSession(std::shared_ptr<ClientSession> session); + + void sendIQ(std::shared_ptr<IQ> iq); + void sendMessage(std::shared_ptr<Message> message); + void sendPresence(std::shared_ptr<Presence> presence); + bool getStreamManagementEnabled() const; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const; + + bool isAvailable() const { + return session && session->getState() == ClientSession::State::Initialized; + } + + private: + std::string getNewIQID(); + void send(std::shared_ptr<Stanza> stanza); + void handleSessionFinished(std::shared_ptr<Error> error); + void handleStanza(std::shared_ptr<Stanza> stanza); + void handleStanzaAcked(std::shared_ptr<Stanza> stanza); + void handleSessionInitialized(); + + private: + IDGenerator idGenerator; + std::shared_ptr<ClientSession> session; + }; } diff --git a/Swiften/Client/ClientXMLTracer.cpp b/Swiften/Client/ClientXMLTracer.cpp index b413f40..e1b9e0c 100644 --- a/Swiften/Client/ClientXMLTracer.cpp +++ b/Swiften/Client/ClientXMLTracer.cpp @@ -1,55 +1,61 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/ClientXMLTracer.h> #include <iostream> + #include <boost/bind.hpp> #include <Swiften/Base/Platform.h> namespace Swift { -ClientXMLTracer::ClientXMLTracer(CoreClient* client, bool bosh) : bosh(bosh) { +ClientXMLTracer::ClientXMLTracer(CoreClient* client, bool bosh) : bosh_(bosh) { #ifdef SWIFTEN_PLATFORM_WIN32 - beautifier = new XMLBeautifier(true, false); + beautifier_ = std::make_unique<XMLBeautifier>(true, false); #else - beautifier = new XMLBeautifier(true, true); + beautifier_ = std::make_unique<XMLBeautifier>(true, true); #endif - client->onDataRead.connect(boost::bind(&ClientXMLTracer::printData, this, '<', _1)); - client->onDataWritten.connect(boost::bind(&ClientXMLTracer::printData, this, '>', _1)); -} - -ClientXMLTracer::~ClientXMLTracer() { - delete beautifier; + onDataReadConnection_ = client->onDataRead.connect(boost::bind(&ClientXMLTracer::printData, this, '<', _1)); + onDataWrittenConnection_ = client->onDataWritten.connect(boost::bind(&ClientXMLTracer::printData, this, '>', _1)); } void ClientXMLTracer::printData(char direction, const SafeByteArray& data) { - printLine(direction); - if (bosh) { - std::string line = byteArrayToString(ByteArray(data.begin(), data.end())); + if (bosh_) { + printLine(direction); + std::string line = byteArrayToString(ByteArray(data.begin(), data.end())); // Disabled because it swallows bits of XML (namespaces, if I recall) -// size_t endOfHTTP = line.find("\r\n\r\n"); -// if (false && endOfHTTP != std::string::npos) { -// std::cerr << line.substr(0, endOfHTTP) << std::endl << beautifier->beautify(line.substr(endOfHTTP)) << std::endl; -// } -// else { - std::cerr << line << std::endl; -// } - } - else { - std::cerr << beautifier->beautify(byteArrayToString(ByteArray(data.begin(), data.end()))) << std::endl; - } +// size_t endOfHTTP = line.find("\r\n\r\n"); +// if (false && endOfHTTP != std::string::npos) { +// std::cerr << line.substr(0, endOfHTTP) << std::endl << beautifier->beautify(line.substr(endOfHTTP)) << std::endl; +// } +// else { + std::cerr << line << std::endl; +// } + } + else { + const auto& str = beautifier_->beautify(byteArrayToString(ByteArray(data.begin(), data.end()))); + + if (beautifier_->wasReset()) { + printLine(direction); + } + std::cerr << str; + if (beautifier_->getLevel() <= 1) { + std::cerr << std::endl; + } + + } } void ClientXMLTracer::printLine(char c) { - for (unsigned int i = 0; i < 80; ++i) { - std::cerr << c; - } - std::cerr << std::endl; + for (unsigned int i = 0; i < 80; ++i) { + std::cerr << c; + } + std::cerr << std::endl; } } diff --git a/Swiften/Client/ClientXMLTracer.h b/Swiften/Client/ClientXMLTracer.h index 91cfe22..d3aeb0c 100644 --- a/Swiften/Client/ClientXMLTracer.h +++ b/Swiften/Client/ClientXMLTracer.h @@ -1,27 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <Swiften/Base/API.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/Client/CoreClient.h> #include <Swiften/Client/XMLBeautifier.h> -#include <Swiften/Base/SafeByteArray.h> namespace Swift { - class SWIFTEN_API ClientXMLTracer { - public: - ClientXMLTracer(CoreClient* client, bool bosh = false); - ~ClientXMLTracer(); - private: - void printData(char direction, const SafeByteArray& data); - void printLine(char c); + class SWIFTEN_API ClientXMLTracer { + public: + ClientXMLTracer(CoreClient* client, bool bosh = false); + + private: + void printData(char direction, const SafeByteArray& data); + void printLine(char c); - private: - XMLBeautifier *beautifier; - bool bosh; - }; + private: + std::unique_ptr<XMLBeautifier> beautifier_; + bool bosh_; + boost::signals2::scoped_connection onDataReadConnection_; + boost::signals2::scoped_connection onDataWrittenConnection_; + }; } diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp index 4438135..7579bca 100644 --- a/Swiften/Client/CoreClient.cpp +++ b/Swiften/Client/CoreClient.cpp @@ -1,457 +1,519 @@ /* - * Copyright (c) 2010-2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/CoreClient.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <boost/optional.hpp> +#include <Swiften/Base/Algorithm.h> #include <Swiften/Base/IDGenerator.h> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Base/Algorithm.h> #include <Swiften/Client/ClientSession.h> -#include <Swiften/TLS/CertificateVerificationError.h> -#include <Swiften/TLS/TLSError.h> +#include <Swiften/Client/ClientSessionStanzaChannel.h> #include <Swiften/Network/ChainedConnector.h> +#include <Swiften/Network/DomainNameResolveError.h> +#include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h> #include <Swiften/Network/NetworkFactories.h> #include <Swiften/Network/ProxyProvider.h> -#include <Swiften/Network/DomainNameResolveError.h> -#include <Swiften/TLS/PKCS12Certificate.h> -#include <Swiften/Session/BasicSessionStream.h> -#include <Swiften/Session/BOSHSessionStream.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Client/ClientSessionStanzaChannel.h> #include <Swiften/Network/SOCKS5ProxiedConnectionFactory.h> -#include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Session/BOSHSessionStream.h> +#include <Swiften/Session/BasicSessionStream.h> +#include <Swiften/TLS/CertificateVerificationError.h> +#include <Swiften/TLS/PKCS12Certificate.h> +#include <Swiften/TLS/TLSError.h> namespace Swift { -CoreClient::CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), disconnectRequested_(false), certificateTrustChecker(NULL) { - stanzaChannel_ = new ClientSessionStanzaChannel(); - stanzaChannel_->onMessageReceived.connect(boost::bind(&CoreClient::handleMessageReceived, this, _1)); - stanzaChannel_->onPresenceReceived.connect(boost::bind(&CoreClient::handlePresenceReceived, this, _1)); - stanzaChannel_->onStanzaAcked.connect(boost::bind(&CoreClient::handleStanzaAcked, this, _1)); - stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1)); +CoreClient::CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), disconnectRequested_(false), certificateTrustChecker(nullptr) { + stanzaChannel_ = new ClientSessionStanzaChannel(); + stanzaChannel_->onMessageReceived.connect(boost::bind(&CoreClient::handleMessageReceived, this, _1)); + stanzaChannel_->onPresenceReceived.connect(boost::bind(&CoreClient::handlePresenceReceived, this, _1)); + stanzaChannel_->onStanzaAcked.connect(boost::bind(&CoreClient::handleStanzaAcked, this, _1)); + stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1)); - iqRouter_ = new IQRouter(stanzaChannel_); - iqRouter_->setJID(jid); + iqRouter_ = new IQRouter(stanzaChannel_); + iqRouter_->setJID(jid); } CoreClient::~CoreClient() { - forceReset(); - delete iqRouter_; - - stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1)); - stanzaChannel_->onMessageReceived.disconnect(boost::bind(&CoreClient::handleMessageReceived, this, _1)); - stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&CoreClient::handlePresenceReceived, this, _1)); - stanzaChannel_->onStanzaAcked.disconnect(boost::bind(&CoreClient::handleStanzaAcked, this, _1)); - delete stanzaChannel_; + forceReset(); + delete iqRouter_; + + stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1)); + stanzaChannel_->onMessageReceived.disconnect(boost::bind(&CoreClient::handleMessageReceived, this, _1)); + stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&CoreClient::handlePresenceReceived, this, _1)); + stanzaChannel_->onStanzaAcked.disconnect(boost::bind(&CoreClient::handleStanzaAcked, this, _1)); + delete stanzaChannel_; } void CoreClient::connect(const ClientOptions& o) { - SWIFT_LOG(debug) << "Connecting "; - - forceReset(); - disconnectRequested_ = false; - - options = o; - - - // Determine connection types to use - assert(proxyConnectionFactories.empty()); - bool useDirectConnection = true; - HostAddressPort systemSOCKS5Proxy = networkFactories->getProxyProvider()->getSOCKS5Proxy(); - HostAddressPort systemHTTPConnectProxy = networkFactories->getProxyProvider()->getHTTPConnectProxy(); - switch (o.proxyType) { - case ClientOptions::NoProxy: - SWIFT_LOG(debug) << " without a proxy" << std::endl; - break; - case ClientOptions::SystemConfiguredProxy: - SWIFT_LOG(debug) << " with a system configured proxy" << std::endl; - if (systemSOCKS5Proxy.isValid()) { - SWIFT_LOG(debug) << "Found SOCK5 Proxy: " << systemSOCKS5Proxy.getAddress().toString() << ":" << systemHTTPConnectProxy.getPort() << std::endl; - proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), systemSOCKS5Proxy.getAddress().toString(), systemSOCKS5Proxy.getPort())); - } - if (systemHTTPConnectProxy.isValid()) { - SWIFT_LOG(debug) << "Found HTTPConnect Proxy: " << systemHTTPConnectProxy.getAddress().toString() << ":" << systemHTTPConnectProxy.getPort() << std::endl; - proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), systemHTTPConnectProxy.getAddress().toString(), systemHTTPConnectProxy.getPort())); - } - break; - case ClientOptions::SOCKS5Proxy: { - SWIFT_LOG(debug) << " with manual configured SOCKS5 proxy" << std::endl; - std::string proxyHostname = o.manualProxyHostname.empty() ? systemSOCKS5Proxy.getAddress().toString() : o.manualProxyHostname; - int proxyPort = o.manualProxyPort == -1 ? systemSOCKS5Proxy.getPort() : o.manualProxyPort; - SWIFT_LOG(debug) << "Proxy: " << proxyHostname << ":" << proxyPort << std::endl; - proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), proxyHostname, proxyPort)); - useDirectConnection = false; - break; - } - case ClientOptions::HTTPConnectProxy: { - SWIFT_LOG(debug) << " with manual configured HTTPConnect proxy" << std::endl; - std::string proxyHostname = o.manualProxyHostname.empty() ? systemHTTPConnectProxy.getAddress().toString() : o.manualProxyHostname; - int proxyPort = o.manualProxyPort == -1 ? systemHTTPConnectProxy.getPort() : o.manualProxyPort; - SWIFT_LOG(debug) << "Proxy: " << proxyHostname << ":" << proxyPort << std::endl; - proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), proxyHostname, proxyPort)); - useDirectConnection = false; - break; - } - } - std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories); - if (useDirectConnection) { - connectionFactories.push_back(networkFactories->getConnectionFactory()); - } - - // Create connector - std::string host = o.manualHostname.empty() ? jid_.getDomain() : o.manualHostname; - int port = o.manualPort; - assert(!connector_); - if (options.boshURL.isEmpty()) { - connector_ = boost::make_shared<ChainedConnector>(host, port, o.manualHostname.empty(), networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory()); - connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1, _2)); - connector_->setTimeoutMilliseconds(2*60*1000); - connector_->start(); - } - else { - /* Autodiscovery of which proxy works is largely ok with a TCP session, because this is a one-off. With BOSH - * it would be quite painful given that potentially every stanza could be sent on a new connection. - */ - //sessionStream_ = boost::make_shared<BOSHSessionStream>(boost::make_shared<BOSHConnectionFactory>(options.boshURL, networkFactories->getConnectionFactory(), networkFactories->getXMLParserFactory(), networkFactories->getTLSContextFactory()), getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), networkFactories->getEventLoop(), host, options.boshHTTPConnectProxyURL, options.boshHTTPConnectProxyAuthID, options.boshHTTPConnectProxyAuthPassword); - sessionStream_ = boost::shared_ptr<BOSHSessionStream>(new BOSHSessionStream( - options.boshURL, - getPayloadParserFactories(), - getPayloadSerializers(), - networkFactories->getConnectionFactory(), - networkFactories->getTLSContextFactory(), - networkFactories->getTimerFactory(), - networkFactories->getXMLParserFactory(), - networkFactories->getEventLoop(), - networkFactories->getDomainNameResolver(), - host, - options.boshHTTPConnectProxyURL, - options.boshHTTPConnectProxyAuthID, - options.boshHTTPConnectProxyAuthPassword)); - sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); - sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); - bindSessionToStream(); - } + SWIFT_LOG(debug) << "Connecting "; + + forceReset(); + disconnectRequested_ = false; + + options = o; + + + // Determine connection types to use + assert(proxyConnectionFactories.empty()); + bool useDirectConnection = true; + HostAddressPort systemSOCKS5Proxy = networkFactories->getProxyProvider()->getSOCKS5Proxy(); + HostAddressPort systemHTTPConnectProxy = networkFactories->getProxyProvider()->getHTTPConnectProxy(); + switch (o.proxyType) { + case ClientOptions::NoProxy: + SWIFT_LOG(debug) << " without a proxy"; + break; + case ClientOptions::SystemConfiguredProxy: + SWIFT_LOG(debug) << " with a system configured proxy"; + if (systemSOCKS5Proxy.isValid()) { + SWIFT_LOG(debug) << "Found SOCK5 Proxy: " << systemSOCKS5Proxy.getAddress().toString() << ":" << systemSOCKS5Proxy.getPort(); + proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), systemSOCKS5Proxy.getAddress().toString(), systemSOCKS5Proxy.getPort())); + } + if (systemHTTPConnectProxy.isValid()) { + SWIFT_LOG(debug) << "Found HTTPConnect Proxy: " << systemHTTPConnectProxy.getAddress().toString() << ":" << systemHTTPConnectProxy.getPort(); + proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), systemHTTPConnectProxy.getAddress().toString(), systemHTTPConnectProxy.getPort())); + } + break; + case ClientOptions::SOCKS5Proxy: { + SWIFT_LOG(debug) << " with manual configured SOCKS5 proxy"; + std::string proxyHostname = o.manualProxyHostname.empty() ? systemSOCKS5Proxy.getAddress().toString() : o.manualProxyHostname; + auto proxyPort = systemSOCKS5Proxy.getPort(); + if (o.manualProxyPort != -1) { + try { + proxyPort = boost::numeric_cast<unsigned short>(o.manualProxyPort); + } + catch (const boost::numeric::bad_numeric_cast& e) { + SWIFT_LOG(warning) << "Manual proxy port " << o.manualProxyPort << " is invalid: " << e.what(); + onDisconnected(boost::optional<ClientError>(ClientError::ConnectionError)); + return; + } + } + SWIFT_LOG(debug) << "Proxy: " << proxyHostname << ":" << proxyPort; + proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), proxyHostname, proxyPort)); + useDirectConnection = false; + break; + } + case ClientOptions::HTTPConnectProxy: { + SWIFT_LOG(debug) << " with manual configured HTTPConnect proxy"; + std::string proxyHostname = o.manualProxyHostname.empty() ? systemHTTPConnectProxy.getAddress().toString() : o.manualProxyHostname; + unsigned short proxyPort = systemHTTPConnectProxy.getPort(); + if (o.manualProxyPort != -1) { + try { + proxyPort = boost::numeric_cast<unsigned short>(o.manualProxyPort); + } + catch (const boost::numeric::bad_numeric_cast& e) { + SWIFT_LOG(warning) << "Manual proxy port " << o.manualProxyPort << " is invalid: " << e.what(); + onDisconnected(boost::optional<ClientError>(ClientError::ConnectionError)); + return; + } + } + SWIFT_LOG(debug) << "Proxy: " << proxyHostname << ":" << proxyPort; + proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), proxyHostname, proxyPort, o.httpTrafficFilter)); + useDirectConnection = false; + break; + } + } + std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories); + if (useDirectConnection) { + connectionFactories.push_back(networkFactories->getConnectionFactory()); + } + + // Create connector + std::string host = o.manualHostname.empty() ? jid_.getDomain() : o.manualHostname; + unsigned short port = 0; + if (o.manualPort != -1) { + try { + port = boost::numeric_cast<unsigned short>(o.manualPort); + } + catch (const boost::numeric::bad_numeric_cast& e) { + SWIFT_LOG(warning) << "Invalid manual port " << o.manualPort << ": " << e.what(); + onDisconnected(boost::optional<ClientError>(ClientError::ConnectionError)); + return; + } + } + boost::optional<std::string> serviceLookupPrefix; + if (o.manualHostname.empty()) { + serviceLookupPrefix = "_xmpp-client._tcp."; + } + assert(!connector_); + if (options.boshURL.isEmpty()) { + connector_ = std::make_shared<ChainedConnector>(host, port, serviceLookupPrefix, networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory()); + connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1, _2)); + connector_->setTimeoutMilliseconds(2*60*1000); + connector_->start(); + } + else { + /* Autodiscovery of which proxy works is largely ok with a TCP session, because this is a one-off. With BOSH + * it would be quite painful given that potentially every stanza could be sent on a new connection. + */ + std::shared_ptr<BOSHSessionStream> boshSessionStream_ = std::shared_ptr<BOSHSessionStream>(new BOSHSessionStream( + options.boshURL, + getPayloadParserFactories(), + getPayloadSerializers(), + networkFactories->getConnectionFactory(), + networkFactories->getTLSContextFactory(), + networkFactories->getTimerFactory(), + networkFactories->getXMLParserFactory(), + networkFactories->getEventLoop(), + networkFactories->getDomainNameResolver(), + host, + options.boshHTTPConnectProxyURL, + options.boshHTTPConnectProxyAuthID, + options.boshHTTPConnectProxyAuthPassword, + options.tlsOptions, + options.httpTrafficFilter)); + sessionStream_ = boshSessionStream_; + sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); + sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); + if (certificate_ && !certificate_->isNull()) { + SWIFT_LOG(debug) << "set certificate"; + sessionStream_->setTLSCertificate(certificate_); + } + boshSessionStream_->open(); + bindSessionToStream(); + } } void CoreClient::bindSessionToStream() { - session_ = ClientSession::create(jid_, sessionStream_, networkFactories->getIDNConverter(), networkFactories->getCryptoProvider()); - session_->setCertificateTrustChecker(certificateTrustChecker); - session_->setUseStreamCompression(options.useStreamCompression); - session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS); - switch(options.useTLS) { - case ClientOptions::UseTLSWhenAvailable: - session_->setUseTLS(ClientSession::UseTLSWhenAvailable); - break; - case ClientOptions::NeverUseTLS: - session_->setUseTLS(ClientSession::NeverUseTLS); - break; - case ClientOptions::RequireTLS: - session_->setUseTLS(ClientSession::RequireTLS); - break; - } - session_->setUseAcks(options.useAcks); - stanzaChannel_->setSession(session_); - session_->onFinished.connect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); - session_->onNeedCredentials.connect(boost::bind(&CoreClient::handleNeedCredentials, this)); - session_->start(); + session_ = ClientSession::create(jid_, sessionStream_, networkFactories->getIDNConverter(), networkFactories->getCryptoProvider(), networkFactories->getTimerFactory()); + session_->setCertificateTrustChecker(certificateTrustChecker); + session_->setUseStreamCompression(options.useStreamCompression); + session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS); + session_->setSingleSignOn(options.singleSignOn); + session_->setAuthenticationPort(options.manualPort); + session_->setSessionShutdownTimeout(options.sessionShutdownTimeoutInMilliseconds); + switch(options.useTLS) { + case ClientOptions::UseTLSWhenAvailable: + session_->setUseTLS(ClientSession::UseTLSWhenAvailable); + break; + case ClientOptions::NeverUseTLS: + session_->setUseTLS(ClientSession::NeverUseTLS); + break; + case ClientOptions::RequireTLS: + session_->setUseTLS(ClientSession::RequireTLS); + break; + } + session_->setUseAcks(options.useAcks); + stanzaChannel_->setSession(session_); + session_->onFinished.connect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); + session_->onNeedCredentials.connect(boost::bind(&CoreClient::handleNeedCredentials, this)); + session_->start(); } /** * Only called for TCP sessions. BOSH is handled inside the BOSHSessionStream. */ -void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error> error) { - resetConnector(); - if (!connection) { - if (options.forgetPassword) { - purgePassword(); - } - boost::optional<ClientError> clientError; - if (!disconnectRequested_) { - clientError = boost::dynamic_pointer_cast<DomainNameResolveError>(error) ? boost::optional<ClientError>(ClientError::DomainNameResolveError) : boost::optional<ClientError>(ClientError::ConnectionError); - } - onDisconnected(clientError); - } - else { - assert(!connection_); - connection_ = connection; - - assert(!sessionStream_); - sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory()); - if (certificate_ && !certificate_->isNull()) { - sessionStream_->setTLSCertificate(certificate_); - } - sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); - sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); - - bindSessionToStream(); - } +void CoreClient::handleConnectorFinished(std::shared_ptr<Connection> connection, std::shared_ptr<Error> error) { + resetConnector(); + if (!connection) { + if (options.forgetPassword) { + purgePassword(); + } + boost::optional<ClientError> clientError; + if (!disconnectRequested_) { + clientError = std::dynamic_pointer_cast<DomainNameResolveError>(error) ? boost::optional<ClientError>(ClientError::DomainNameResolveError) : boost::optional<ClientError>(ClientError::ConnectionError); + } + onDisconnected(clientError); + } + else { + assert(!connection_); + assert(!sessionStream_); + + if (certificate_ && certificate_->isNull()) { + //certificate cannot be read so do not initailise session + onDisconnected(boost::optional<ClientError>(ClientError::ClientCertificateLoadError)); + return; + } + + connection_ = connection; + + sessionStream_ = std::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), options.tlsOptions); + if (certificate_) { + sessionStream_->setTLSCertificate(certificate_); + } + sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); + sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); + + bindSessionToStream(); + } } void CoreClient::disconnect() { - // FIXME: We should be able to do without this boolean. We just have to make sure we can tell the difference between - // connector finishing without a connection due to an error or because of a disconnect. - disconnectRequested_ = true; - if (session_ && !session_->isFinished()) { - session_->finish(); - } - else if (connector_) { - connector_->stop(); - } + // FIXME: We should be able to do without this boolean. We just have to make sure we can tell the difference between + // connector finishing without a connection due to an error or because of a disconnect. + disconnectRequested_ = true; + if (session_ && !session_->isFinished()) { + session_->finish(); + } + else if (connector_) { + connector_->stop(); + } } void CoreClient::setCertificate(CertificateWithKey::ref certificate) { - certificate_ = certificate; + certificate_ = certificate; } -void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) { - if (options.forgetPassword) { - purgePassword(); - } - resetSession(); - - boost::optional<ClientError> actualError; - if (error) { - ClientError clientError; - if (boost::shared_ptr<ClientSession::Error> actualError = boost::dynamic_pointer_cast<ClientSession::Error>(error)) { - switch(actualError->type) { - case ClientSession::Error::AuthenticationFailedError: - clientError = ClientError(ClientError::AuthenticationFailedError); - break; - case ClientSession::Error::CompressionFailedError: - clientError = ClientError(ClientError::CompressionFailedError); - break; - case ClientSession::Error::ServerVerificationFailedError: - clientError = ClientError(ClientError::ServerVerificationFailedError); - break; - case ClientSession::Error::NoSupportedAuthMechanismsError: - clientError = ClientError(ClientError::NoSupportedAuthMechanismsError); - break; - case ClientSession::Error::UnexpectedElementError: - clientError = ClientError(ClientError::UnexpectedElementError); - break; - case ClientSession::Error::ResourceBindError: - clientError = ClientError(ClientError::ResourceBindError); - break; - case ClientSession::Error::SessionStartError: - clientError = ClientError(ClientError::SessionStartError); - break; - case ClientSession::Error::TLSError: - clientError = ClientError(ClientError::TLSError); - break; - case ClientSession::Error::TLSClientCertificateError: - clientError = ClientError(ClientError::ClientCertificateError); - break; - case ClientSession::Error::StreamError: - clientError = ClientError(ClientError::StreamError); - break; - } - } - else if (boost::shared_ptr<TLSError> actualError = boost::dynamic_pointer_cast<TLSError>(error)) { - switch(actualError->getType()) { - case TLSError::CertificateCardRemoved: - clientError = ClientError(ClientError::CertificateCardRemoved); - break; - case TLSError::UnknownError: - clientError = ClientError(ClientError::TLSError); - break; - } - } - else if (boost::shared_ptr<SessionStream::SessionStreamError> actualError = boost::dynamic_pointer_cast<SessionStream::SessionStreamError>(error)) { - switch(actualError->type) { - case SessionStream::SessionStreamError::ParseError: - clientError = ClientError(ClientError::XMLError); - break; - case SessionStream::SessionStreamError::TLSError: - clientError = ClientError(ClientError::TLSError); - break; - case SessionStream::SessionStreamError::InvalidTLSCertificateError: - clientError = ClientError(ClientError::ClientCertificateLoadError); - break; - case SessionStream::SessionStreamError::ConnectionReadError: - clientError = ClientError(ClientError::ConnectionReadError); - break; - case SessionStream::SessionStreamError::ConnectionWriteError: - clientError = ClientError(ClientError::ConnectionWriteError); - break; - } - } - else if (boost::shared_ptr<CertificateVerificationError> verificationError = boost::dynamic_pointer_cast<CertificateVerificationError>(error)) { - switch(verificationError->getType()) { - case CertificateVerificationError::UnknownError: - clientError = ClientError(ClientError::UnknownCertificateError); - break; - case CertificateVerificationError::Expired: - clientError = ClientError(ClientError::CertificateExpiredError); - break; - case CertificateVerificationError::NotYetValid: - clientError = ClientError(ClientError::CertificateNotYetValidError); - break; - case CertificateVerificationError::SelfSigned: - clientError = ClientError(ClientError::CertificateSelfSignedError); - break; - case CertificateVerificationError::Rejected: - clientError = ClientError(ClientError::CertificateRejectedError); - break; - case CertificateVerificationError::Untrusted: - clientError = ClientError(ClientError::CertificateUntrustedError); - break; - case CertificateVerificationError::InvalidPurpose: - clientError = ClientError(ClientError::InvalidCertificatePurposeError); - break; - case CertificateVerificationError::PathLengthExceeded: - clientError = ClientError(ClientError::CertificatePathLengthExceededError); - break; - case CertificateVerificationError::InvalidSignature: - clientError = ClientError(ClientError::InvalidCertificateSignatureError); - break; - case CertificateVerificationError::InvalidCA: - clientError = ClientError(ClientError::InvalidCAError); - break; - case CertificateVerificationError::InvalidServerIdentity: - clientError = ClientError(ClientError::InvalidServerIdentityError); - break; - case CertificateVerificationError::Revoked: - clientError = ClientError(ClientError::RevokedError); - break; - case CertificateVerificationError::RevocationCheckFailed: - clientError = ClientError(ClientError::RevocationCheckFailedError); - break; - } - } - actualError = boost::optional<ClientError>(clientError); - } - onDisconnected(actualError); +void CoreClient::handleSessionFinished(std::shared_ptr<Error> error) { + if (options.forgetPassword) { + purgePassword(); + } + resetSession(); + + boost::optional<ClientError> actualError; + if (error) { + ClientError clientError; + if (std::shared_ptr<ClientSession::Error> actualError = std::dynamic_pointer_cast<ClientSession::Error>(error)) { + switch(actualError->type) { + case ClientSession::Error::AuthenticationFailedError: + clientError = ClientError(ClientError::AuthenticationFailedError); + break; + case ClientSession::Error::CompressionFailedError: + clientError = ClientError(ClientError::CompressionFailedError); + break; + case ClientSession::Error::ServerVerificationFailedError: + clientError = ClientError(ClientError::ServerVerificationFailedError); + break; + case ClientSession::Error::NoSupportedAuthMechanismsError: + clientError = ClientError(ClientError::NoSupportedAuthMechanismsError); + break; + case ClientSession::Error::UnexpectedElementError: + clientError = ClientError(ClientError::UnexpectedElementError); + break; + case ClientSession::Error::ResourceBindError: + clientError = ClientError(ClientError::ResourceBindError); + break; + case ClientSession::Error::SessionStartError: + clientError = ClientError(ClientError::SessionStartError); + break; + case ClientSession::Error::TLSError: + clientError = ClientError(ClientError::TLSError); + break; + case ClientSession::Error::TLSClientCertificateError: + clientError = ClientError(ClientError::ClientCertificateError); + break; + case ClientSession::Error::StreamError: + clientError = ClientError(ClientError::StreamError); + break; + case ClientSession::Error::StreamEndError: + clientError = ClientError(ClientError::StreamError); + break; + } + clientError.setErrorCode(actualError->errorCode); + } + else if (std::shared_ptr<TLSError> actualError = std::dynamic_pointer_cast<TLSError>(error)) { + switch(actualError->getType()) { + case TLSError::CertificateCardRemoved: + clientError = ClientError(ClientError::CertificateCardRemoved); + break; + case TLSError::UnknownError: + case TLSError::AcceptFailed: + case TLSError::ConnectFailed: + clientError = ClientError(ClientError::TLSError); + break; + } + } + else if (std::shared_ptr<SessionStream::SessionStreamError> actualError = std::dynamic_pointer_cast<SessionStream::SessionStreamError>(error)) { + switch(actualError->type) { + case SessionStream::SessionStreamError::ParseError: + clientError = ClientError(ClientError::XMLError); + break; + case SessionStream::SessionStreamError::TLSError: + clientError = ClientError(ClientError::TLSError); + break; + case SessionStream::SessionStreamError::InvalidTLSCertificateError: + clientError = ClientError(ClientError::ClientCertificateLoadError); + break; + case SessionStream::SessionStreamError::ConnectionReadError: + clientError = ClientError(ClientError::ConnectionReadError); + break; + case SessionStream::SessionStreamError::ConnectionWriteError: + clientError = ClientError(ClientError::ConnectionWriteError); + break; + } + } + else if (std::shared_ptr<CertificateVerificationError> verificationError = std::dynamic_pointer_cast<CertificateVerificationError>(error)) { + switch(verificationError->getType()) { + case CertificateVerificationError::UnknownError: + clientError = ClientError(ClientError::UnknownCertificateError); + break; + case CertificateVerificationError::Expired: + clientError = ClientError(ClientError::CertificateExpiredError); + break; + case CertificateVerificationError::NotYetValid: + clientError = ClientError(ClientError::CertificateNotYetValidError); + break; + case CertificateVerificationError::SelfSigned: + clientError = ClientError(ClientError::CertificateSelfSignedError); + break; + case CertificateVerificationError::Rejected: + clientError = ClientError(ClientError::CertificateRejectedError); + break; + case CertificateVerificationError::Untrusted: + clientError = ClientError(ClientError::CertificateUntrustedError); + break; + case CertificateVerificationError::InvalidPurpose: + clientError = ClientError(ClientError::InvalidCertificatePurposeError); + break; + case CertificateVerificationError::PathLengthExceeded: + clientError = ClientError(ClientError::CertificatePathLengthExceededError); + break; + case CertificateVerificationError::InvalidSignature: + clientError = ClientError(ClientError::InvalidCertificateSignatureError); + break; + case CertificateVerificationError::InvalidCA: + clientError = ClientError(ClientError::InvalidCAError); + break; + case CertificateVerificationError::InvalidServerIdentity: + clientError = ClientError(ClientError::InvalidServerIdentityError); + break; + case CertificateVerificationError::Revoked: + clientError = ClientError(ClientError::RevokedError); + break; + case CertificateVerificationError::RevocationCheckFailed: + clientError = ClientError(ClientError::RevocationCheckFailedError); + break; + } + } + actualError = boost::optional<ClientError>(clientError); + } + onDisconnected(actualError); } void CoreClient::handleNeedCredentials() { - assert(session_); - session_->sendCredentials(password_); - if (options.forgetPassword) { - purgePassword(); - } + assert(session_); + session_->sendCredentials(password_); + if (options.forgetPassword) { + purgePassword(); + } } void CoreClient::handleDataRead(const SafeByteArray& data) { - onDataRead(data); + onDataRead(data); } void CoreClient::handleDataWritten(const SafeByteArray& data) { - onDataWritten(data); + onDataWritten(data); } void CoreClient::handleStanzaChannelAvailableChanged(bool available) { - if (available) { - iqRouter_->setJID(session_->getLocalJID()); - handleConnected(); - onConnected(); - } + if (available) { + iqRouter_->setJID(session_->getLocalJID()); + handleConnected(); + onConnected(); + } } -void CoreClient::sendMessage(boost::shared_ptr<Message> message) { - stanzaChannel_->sendMessage(message); +void CoreClient::sendMessage(std::shared_ptr<Message> message) { + stanzaChannel_->sendMessage(message); } -void CoreClient::sendPresence(boost::shared_ptr<Presence> presence) { - stanzaChannel_->sendPresence(presence); +void CoreClient::sendPresence(std::shared_ptr<Presence> presence) { + stanzaChannel_->sendPresence(presence); } void CoreClient::sendData(const std::string& data) { - sessionStream_->writeData(data); + if (!sessionStream_) { + SWIFT_LOG(warning) << "Client: Trying to send data while disconnected."; + return; + } + sessionStream_->writeData(data); } bool CoreClient::isActive() const { - return (session_ && !session_->isFinished()) || connector_; + return (session_ && !session_->isFinished()) || connector_; } void CoreClient::setCertificateTrustChecker(CertificateTrustChecker* checker) { - certificateTrustChecker = checker; + certificateTrustChecker = checker; } void CoreClient::handlePresenceReceived(Presence::ref presence) { - onPresenceReceived(presence); + onPresenceReceived(presence); } void CoreClient::handleMessageReceived(Message::ref message) { - onMessageReceived(message); + onMessageReceived(message); } void CoreClient::handleStanzaAcked(Stanza::ref stanza) { - onStanzaAcked(stanza); + onStanzaAcked(stanza); } bool CoreClient::isAvailable() const { - return stanzaChannel_->isAvailable(); + return stanzaChannel_->isAvailable(); } bool CoreClient::getStreamManagementEnabled() const { - return stanzaChannel_->getStreamManagementEnabled(); + return stanzaChannel_->getStreamManagementEnabled(); } bool CoreClient::isStreamEncrypted() const { - return sessionStream_->isTLSEncrypted(); + return sessionStream_->isTLSEncrypted(); } StanzaChannel* CoreClient::getStanzaChannel() const { - return stanzaChannel_; + return stanzaChannel_; } const JID& CoreClient::getJID() const { - if (session_) { - return session_->getLocalJID(); - } - else { - return jid_; - } + if (session_) { + return session_->getLocalJID(); + } + else { + return jid_; + } } void CoreClient::purgePassword() { - safeClear(password_); + safeClear(password_); } void CoreClient::resetConnector() { - connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1, _2)); - connector_.reset(); - foreach(ConnectionFactory* f, proxyConnectionFactories) { - delete f; - } - proxyConnectionFactories.clear(); + connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1, _2)); + connector_.reset(); + for (auto f : proxyConnectionFactories) { + delete f; + } + proxyConnectionFactories.clear(); } void CoreClient::resetSession() { - session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); - session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this)); - - sessionStream_->onDataRead.disconnect(boost::bind(&CoreClient::handleDataRead, this, _1)); - sessionStream_->onDataWritten.disconnect(boost::bind(&CoreClient::handleDataWritten, this, _1)); - - if (connection_) { - connection_->disconnect(); - } - else if (boost::dynamic_pointer_cast<BOSHSessionStream>(sessionStream_)) { - sessionStream_->close(); - } - sessionStream_.reset(); - connection_.reset(); + session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); + session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this)); + + sessionStream_->onDataRead.disconnect(boost::bind(&CoreClient::handleDataRead, this, _1)); + sessionStream_->onDataWritten.disconnect(boost::bind(&CoreClient::handleDataWritten, this, _1)); + + if (connection_) { + connection_->disconnect(); + } + else if (std::dynamic_pointer_cast<BOSHSessionStream>(sessionStream_)) { + sessionStream_->close(); + } + sessionStream_.reset(); + connection_.reset(); } void CoreClient::forceReset() { - if (connector_) { - std::cerr << "Warning: Client not disconnected properly: Connector still active" << std::endl; - resetConnector(); - } - if (sessionStream_ || connection_) { - std::cerr << "Warning: Client not disconnected properly: Session still active" << std::endl; - resetSession(); - } + if (connector_) { + SWIFT_LOG(warning) << "Client not disconnected properly: Connector still active"; + resetConnector(); + } + if (sessionStream_ || connection_) { + SWIFT_LOG(warning) << "Client not disconnected properly: Session still active"; + resetSession(); + } } } diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h index eadfd9d..8168e7b 100644 --- a/Swiften/Client/CoreClient.h +++ b/Swiften/Client/CoreClient.h @@ -1,241 +1,240 @@ /* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <string> -#include <boost/shared_ptr.hpp> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Entity/Entity.h> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/Client/ClientError.h> #include <Swiften/Client/ClientOptions.h> -#include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Entity/Entity.h> +#include <Swiften/JID/JID.h> #include <Swiften/TLS/CertificateWithKey.h> namespace Swift { - class ChainedConnector; - class Message; - class Presence; - class Error; - class IQRouter; - class TLSContextFactory; - class ConnectionFactory; - class Connection; - class TimerFactory; - class ClientSession; - class StanzaChannel; - class Stanza; - class SessionStream; - class CertificateTrustChecker; - class NetworkFactories; - class ClientSessionStanzaChannel; - - /** - * The central class for communicating with an XMPP server. - * - * This class is responsible for setting up the connection with the XMPP - * server, authenticating, and initializing the session. - * - * This class can be used directly in your application, although the Client - * subclass provides more functionality and interfaces, and is better suited - * for most needs. - */ - class SWIFTEN_API CoreClient : public Entity { - public: - /** - * Constructs a client for the given JID with the given password. - */ - CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories); - ~CoreClient(); - - /** - * Set a client certificate to use for strong authentication with the server. - * Ensure that it is of the correct type for the TLS engine in use. - * This means, largely, PKCS12Certificate for OpenSSL and CAPICertificate for CAPI. - */ - void setCertificate(CertificateWithKey::ref certificate); - - /** - * Connects the client to the server. - * - * After the connection is established, the client will set - * initialize the stream and authenticate. - */ - void connect(const ClientOptions& = ClientOptions()); - - /** - * Disconnects the client from the server. - */ - void disconnect(); - - /** - * Sends a message. - */ - void sendMessage(boost::shared_ptr<Message>); - - /** - * Sends a presence stanza. - */ - void sendPresence(boost::shared_ptr<Presence>); - - /** - * Sends raw, unchecked data. - */ - void sendData(const std::string& data); - - /** - * Returns the IQ router for this client. - */ - IQRouter* getIQRouter() const { - return iqRouter_; - } - - /** - * Checks whether the client is connected to the server, - * and stanzas can be sent. - */ - bool isAvailable() const; - - /** - * Checks whether the client is active. - * - * A client is active when it is connected or connecting to the server. - */ - bool isActive() const; - - /** - * Returns the JID of the client. - * After the session was initialized, this returns the bound JID. - */ - const JID& getJID() const; - - /** - * Checks whether stream management is enabled. - * - * If stream management is enabled, onStanzaAcked will be - * emitted when a stanza is received by the server. - * - * \see onStanzaAcked - */ - bool getStreamManagementEnabled() const; - - /** - * Checks whether stream encryption (TLS) is currently active. - */ - bool isStreamEncrypted() const; - - StanzaChannel* getStanzaChannel() const; - - /** - * Sets the certificate trust checker. - * - * This checker will be called when the server sends a - * TLS certificate that does not validate. If the trust checker - * says the certificate is trusted, then connecting will proceed; - * if not, the connection will end with an error. - */ - void setCertificateTrustChecker(CertificateTrustChecker*); - - public: - /** - * Emitted when the client was disconnected from the network. - * - * If the connection was due to a non-recoverable error, the type - * of error will be passed as a parameter. - */ - boost::signal<void (const boost::optional<ClientError>&)> onDisconnected; - - /** - * Emitted when the client is connected and authenticated, - * and stanzas can be sent. - */ - boost::signal<void ()> onConnected; - - /** - * Emitted when the client receives data. - * - * This signal is emitted before the XML data is parsed, - * so this data is unformatted. - */ - boost::signal<void (const SafeByteArray&)> onDataRead; - - /** - * Emitted when the client sends data. - * - * This signal is emitted after the XML was serialized, and - * is unformatted. - */ - boost::signal<void (const SafeByteArray&)> onDataWritten; - - /** - * Emitted when a message is received. - */ - boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived; - - /** - * Emitted when a presence stanza is received. - */ - boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived; - - /** - * Emitted when the server acknowledges receipt of a - * stanza (if acknowledgements are available). - * - * \see getStreamManagementEnabled() - */ - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked; - - protected: - boost::shared_ptr<ClientSession> getSession() const { - return session_; - } - - NetworkFactories* getNetworkFactories() const { - return networkFactories; - } - - /** - * Called before onConnected signal is emmitted. - */ - virtual void handleConnected() {} - - private: - void handleConnectorFinished(boost::shared_ptr<Connection>, boost::shared_ptr<Error> error); - void handleStanzaChannelAvailableChanged(bool available); - void handleSessionFinished(boost::shared_ptr<Error>); - void handleNeedCredentials(); - void handleDataRead(const SafeByteArray&); - void handleDataWritten(const SafeByteArray&); - void handlePresenceReceived(boost::shared_ptr<Presence>); - void handleMessageReceived(boost::shared_ptr<Message>); - void handleStanzaAcked(boost::shared_ptr<Stanza>); - void purgePassword(); - void bindSessionToStream(); - - void resetConnector(); - void resetSession(); - void forceReset(); - - private: - JID jid_; - SafeByteArray password_; - NetworkFactories* networkFactories; - ClientSessionStanzaChannel* stanzaChannel_; - IQRouter* iqRouter_; - ClientOptions options; - boost::shared_ptr<ChainedConnector> connector_; - std::vector<ConnectionFactory*> proxyConnectionFactories; - boost::shared_ptr<Connection> connection_; - boost::shared_ptr<SessionStream> sessionStream_; - boost::shared_ptr<ClientSession> session_; - CertificateWithKey::ref certificate_; - bool disconnectRequested_; - CertificateTrustChecker* certificateTrustChecker; - }; + class CertificateTrustChecker; + class ChainedConnector; + class ClientSession; + class ClientSessionStanzaChannel; + class Connection; + class ConnectionFactory; + class Error; + class IQRouter; + class Message; + class NetworkFactories; + class Presence; + class SessionStream; + class Stanza; + class StanzaChannel; + + /** + * The central class for communicating with an XMPP server. + * + * This class is responsible for setting up the connection with the XMPP + * server, authenticating, and initializing the session. + * + * This class can be used directly in your application, although the Client + * subclass provides more functionality and interfaces, and is better suited + * for most needs. + */ + class SWIFTEN_API CoreClient : public Entity { + public: + /** + * Constructs a client for the given JID with the given password. + */ + CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories); + virtual ~CoreClient(); + + /** + * Set a client certificate to use for strong authentication with the server. + * Ensure that it is of the correct type for the TLS engine in use. + * This means, largely, PKCS12Certificate for OpenSSL and CAPICertificate for CAPI. + */ + void setCertificate(CertificateWithKey::ref certificate); + + /** + * Connects the client to the server. + * + * After the connection is established, the client will set + * initialize the stream and authenticate. + */ + void connect(const ClientOptions& = ClientOptions()); + + /** + * Disconnects the client from the server. + */ + void disconnect(); + + /** + * Sends a message. + */ + void sendMessage(std::shared_ptr<Message>); + + /** + * Sends a presence stanza. + */ + void sendPresence(std::shared_ptr<Presence>); + + /** + * Sends raw, unchecked data. + */ + void sendData(const std::string& data); + + /** + * Returns the IQ router for this client. + */ + IQRouter* getIQRouter() const { + return iqRouter_; + } + + /** + * Checks whether the client is connected to the server, + * and stanzas can be sent. + */ + bool isAvailable() const; + + /** + * Checks whether the client is active. + * + * A client is active when it is connected or connecting to the server. + */ + bool isActive() const; + + /** + * Returns the JID of the client. + * After the session was initialized, this returns the bound JID. + */ + const JID& getJID() const; + + /** + * Checks whether stream management is enabled. + * + * If stream management is enabled, onStanzaAcked will be + * emitted when a stanza is received by the server. + * + * \see onStanzaAcked + */ + bool getStreamManagementEnabled() const; + + /** + * Checks whether stream encryption (TLS) is currently active. + */ + bool isStreamEncrypted() const; + + StanzaChannel* getStanzaChannel() const; + + /** + * Sets the certificate trust checker. + * + * This checker will be called when the server sends a + * TLS certificate that does not validate. If the trust checker + * says the certificate is trusted, then connecting will proceed; + * if not, the connection will end with an error. + */ + void setCertificateTrustChecker(CertificateTrustChecker*); + + public: + /** + * Emitted when the client was disconnected from the network. + * + * If the connection was due to a non-recoverable error, the type + * of error will be passed as a parameter. + */ + boost::signals2::signal<void (const boost::optional<ClientError>&)> onDisconnected; + + /** + * Emitted when the client is connected and authenticated, + * and stanzas can be sent. + */ + boost::signals2::signal<void ()> onConnected; + + /** + * Emitted when the client receives data. + * + * This signal is emitted before the XML data is parsed, + * so this data is unformatted. + */ + boost::signals2::signal<void (const SafeByteArray&)> onDataRead; + + /** + * Emitted when the client sends data. + * + * This signal is emitted after the XML was serialized, and + * is unformatted. + */ + boost::signals2::signal<void (const SafeByteArray&)> onDataWritten; + + /** + * Emitted when a message is received. + */ + boost::signals2::signal<void (std::shared_ptr<Message>)> onMessageReceived; + + /** + * Emitted when a presence stanza is received. + */ + boost::signals2::signal<void (std::shared_ptr<Presence>) > onPresenceReceived; + + /** + * Emitted when the server acknowledges receipt of a + * stanza (if acknowledgements are available). + * + * \see getStreamManagementEnabled() + */ + boost::signals2::signal<void (std::shared_ptr<Stanza>)> onStanzaAcked; + + protected: + std::shared_ptr<ClientSession> getSession() const { + return session_; + } + + NetworkFactories* getNetworkFactories() const { + return networkFactories; + } + + /** + * Called before onConnected signal is emmitted. + */ + virtual void handleConnected() {} + + private: + void handleConnectorFinished(std::shared_ptr<Connection>, std::shared_ptr<Error> error); + void handleStanzaChannelAvailableChanged(bool available); + void handleSessionFinished(std::shared_ptr<Error>); + void handleNeedCredentials(); + void handleDataRead(const SafeByteArray&); + void handleDataWritten(const SafeByteArray&); + void handlePresenceReceived(std::shared_ptr<Presence>); + void handleMessageReceived(std::shared_ptr<Message>); + void handleStanzaAcked(std::shared_ptr<Stanza>); + void purgePassword(); + void bindSessionToStream(); + + void resetConnector(); + void resetSession(); + void forceReset(); + + private: + JID jid_; + SafeByteArray password_; + NetworkFactories* networkFactories; + ClientSessionStanzaChannel* stanzaChannel_; + IQRouter* iqRouter_; + ClientOptions options; + std::shared_ptr<ChainedConnector> connector_; + std::vector<ConnectionFactory*> proxyConnectionFactories; + std::shared_ptr<Connection> connection_; + std::shared_ptr<SessionStream> sessionStream_; + std::shared_ptr<ClientSession> session_; + CertificateWithKey::ref certificate_; + bool disconnectRequested_; + CertificateTrustChecker* certificateTrustChecker; + }; } diff --git a/Swiften/Client/DummyNickManager.h b/Swiften/Client/DummyNickManager.h index 0e3ff50..8ed7701 100644 --- a/Swiften/Client/DummyNickManager.h +++ b/Swiften/Client/DummyNickManager.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,15 +9,13 @@ #include <Swiften/Client/NickManager.h> namespace Swift { - class VCardManager; + class DummyNickManager : public NickManager { + public: + std::string getOwnNick() const { + return ""; + } - class DummyNickManager : public NickManager { - public: - std::string getOwnNick() const { - return ""; - } - - void setOwnNick(const std::string&) { - } - }; + void setOwnNick(const std::string&) { + } + }; } diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h index 5cdedba..1ba70ad 100644 --- a/Swiften/Client/DummyStanzaChannel.h +++ b/Swiften/Client/DummyStanzaChannel.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,79 +11,100 @@ #include <Swiften/Client/StanzaChannel.h> namespace Swift { - class DummyStanzaChannel : public StanzaChannel { - public: - DummyStanzaChannel() : available_(true) {} - - virtual void sendStanza(boost::shared_ptr<Stanza> stanza) { - sentStanzas.push_back(stanza); - } - - void setAvailable(bool available) { - available_ = available; - onAvailableChanged(available); - } - - virtual void sendIQ(boost::shared_ptr<IQ> iq) { - sentStanzas.push_back(iq); - } - - virtual void sendMessage(boost::shared_ptr<Message> message) { - sentStanzas.push_back(message); - } - - virtual void sendPresence(boost::shared_ptr<Presence> presence) { - sentStanzas.push_back(presence); - } - - virtual std::string getNewIQID() { - return "test-id"; - } - - virtual bool isAvailable() const { - return available_; - } - - virtual bool getStreamManagementEnabled() const { - return false; - } - - template<typename T> bool isRequestAtIndex(size_t index, const JID& jid, IQ::Type type) { - if (index >= sentStanzas.size()) { - return false; - } - boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]); - return iqStanza && iqStanza->getType() == type && iqStanza->getTo() == jid && iqStanza->getPayload<T>(); - } - - bool isResultAtIndex(size_t index, const std::string& id) { - if (index >= sentStanzas.size()) { - return false; - } - boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]); - return iqStanza && iqStanza->getType() == IQ::Result && iqStanza->getID() == id; - } - - bool isErrorAtIndex(size_t index, const std::string& id) { - if (index >= sentStanzas.size()) { - return false; - } - boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]); - return iqStanza && iqStanza->getType() == IQ::Error && iqStanza->getID() == id; - } - - template<typename T> boost::shared_ptr<T> getStanzaAtIndex(size_t index) { - if (sentStanzas.size() <= index) { - return boost::shared_ptr<T>(); - } - return boost::dynamic_pointer_cast<T>(sentStanzas[index]); - } - - std::vector<Certificate::ref> getPeerCertificateChain() const { - return std::vector<Certificate::ref>(); - } - - std::vector<boost::shared_ptr<Stanza> > sentStanzas; - bool available_; - }; + class DummyStanzaChannel : public StanzaChannel { + public: + DummyStanzaChannel() {} + + virtual void sendStanza(std::shared_ptr<Stanza> stanza) { + sentStanzas.push_back(stanza); + } + + void setAvailable(bool available) { + available_ = available; + onAvailableChanged(available); + } + + virtual void sendIQ(std::shared_ptr<IQ> iq) { + sentStanzas.push_back(iq); + } + + virtual void sendMessage(std::shared_ptr<Message> message) { + sentStanzas.push_back(message); + } + + virtual void sendPresence(std::shared_ptr<Presence> presence) { + sentStanzas.push_back(presence); + } + + virtual std::string getNewIQID() { + std::string id = "test-id"; + if (uniqueIDs_) { + id += "-" + std::to_string(idCounter_++); + } + return id; + } + + virtual bool isAvailable() const { + return available_; + } + + virtual void setStreamManagementEnabled(bool enable) { + streamManagement_ = enable; + } + + virtual bool getStreamManagementEnabled() const { + return streamManagement_; + } + + template<typename T> bool isRequestAtIndex(size_t index, const JID& jid, IQ::Type type) { + if (index >= sentStanzas.size()) { + return false; + } + std::shared_ptr<IQ> iqStanza = std::dynamic_pointer_cast<IQ>(sentStanzas[index]); + return iqStanza && iqStanza->getType() == type && iqStanza->getTo() == jid && iqStanza->getPayload<T>(); + } + + bool isResultAtIndex(size_t index, const std::string& id) { + if (index >= sentStanzas.size()) { + return false; + } + std::shared_ptr<IQ> iqStanza = std::dynamic_pointer_cast<IQ>(sentStanzas[index]); + return iqStanza && iqStanza->getType() == IQ::Result && iqStanza->getID() == id; + } + + bool isErrorAtIndex(size_t index, const std::string& id) { + if (index >= sentStanzas.size()) { + return false; + } + std::shared_ptr<IQ> iqStanza = std::dynamic_pointer_cast<IQ>(sentStanzas[index]); + return iqStanza && iqStanza->getType() == IQ::Error && iqStanza->getID() == id; + } + + template<typename T> std::shared_ptr<T> getStanzaAtIndex(size_t index) { + if (sentStanzas.size() <= index) { + return std::shared_ptr<T>(); + } + return std::dynamic_pointer_cast<T>(sentStanzas[index]); + } + + template<typename T> size_t countSentStanzaOfType() { + size_t count = 0; + for (auto& stanza : sentStanzas) { + if (std::dynamic_pointer_cast<T>(stanza)) { + count++; + } + } + return count; + } + + std::vector<Certificate::ref> getPeerCertificateChain() const { + return std::vector<Certificate::ref>(); + } + + std::vector<std::shared_ptr<Stanza> > sentStanzas; + bool available_ = true; + bool uniqueIDs_ = false; + unsigned int idCounter_ = 0; + bool streamManagement_ = false; + }; } diff --git a/Swiften/Client/MemoryStorages.cpp b/Swiften/Client/MemoryStorages.cpp index 885d74f..5e52799 100644 --- a/Swiften/Client/MemoryStorages.cpp +++ b/Swiften/Client/MemoryStorages.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/MemoryStorages.h> @@ -9,51 +9,55 @@ #include <Swiften/Avatars/AvatarMemoryStorage.h> #include <Swiften/Disco/CapsMemoryStorage.h> #include <Swiften/Roster/RosterMemoryStorage.h> +#ifdef SWIFT_EXPERIMENTAL_HISTORY #include <Swiften/History/SQLiteHistoryStorage.h> +#endif namespace Swift { MemoryStorages::MemoryStorages(CryptoProvider* crypto) { - vcardStorage = new VCardMemoryStorage(crypto); - capsStorage = new CapsMemoryStorage(); - avatarStorage = new AvatarMemoryStorage(); - rosterStorage = new RosterMemoryStorage(); + vcardStorage = new VCardMemoryStorage(crypto); + capsStorage = new CapsMemoryStorage(); + avatarStorage = new AvatarMemoryStorage(); + rosterStorage = new RosterMemoryStorage(); #ifdef SWIFT_EXPERIMENTAL_HISTORY - historyStorage = new SQLiteHistoryStorage(":memory:"); + historyStorage = new SQLiteHistoryStorage(":memory:"); +#else + historyStorage = nullptr; #endif } MemoryStorages::~MemoryStorages() { - delete rosterStorage; - delete avatarStorage; - delete capsStorage; - delete vcardStorage; + delete rosterStorage; + delete avatarStorage; + delete capsStorage; + delete vcardStorage; #ifdef SWIFT_EXPERIMENTAL_HISTORY - delete historyStorage; + delete historyStorage; #endif } VCardStorage* MemoryStorages::getVCardStorage() const { - return vcardStorage; + return vcardStorage; } CapsStorage* MemoryStorages::getCapsStorage() const { - return capsStorage; + return capsStorage; } AvatarStorage* MemoryStorages::getAvatarStorage() const { - return avatarStorage; + return avatarStorage; } RosterStorage* MemoryStorages::getRosterStorage() const { - return rosterStorage; + return rosterStorage; } HistoryStorage* MemoryStorages::getHistoryStorage() const { #ifdef SWIFT_EXPERIMENTAL_HISTORY - return historyStorage; + return historyStorage; #else - return NULL; + return nullptr; #endif } diff --git a/Swiften/Client/MemoryStorages.h b/Swiften/Client/MemoryStorages.h index 68ec285..b905ed9 100644 --- a/Swiften/Client/MemoryStorages.h +++ b/Swiften/Client/MemoryStorages.h @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Client/Storages.h> namespace Swift { - class VCardMemoryStorage; - class CryptoProvider; + class VCardMemoryStorage; + class CryptoProvider; - /** - * An implementation of Storages for storing all - * controller data in memory. - */ - class MemoryStorages : public Storages { - public: - MemoryStorages(CryptoProvider*); - ~MemoryStorages(); + /** + * An implementation of Storages for storing all + * controller data in memory. + */ + class SWIFTEN_API MemoryStorages : public Storages { + public: + MemoryStorages(CryptoProvider*); + virtual ~MemoryStorages(); - virtual VCardStorage* getVCardStorage() const; - virtual AvatarStorage* getAvatarStorage() const; - virtual CapsStorage* getCapsStorage() const; - virtual RosterStorage* getRosterStorage() const; - virtual HistoryStorage* getHistoryStorage() const; + virtual VCardStorage* getVCardStorage() const; + virtual AvatarStorage* getAvatarStorage() const; + virtual CapsStorage* getCapsStorage() const; + virtual RosterStorage* getRosterStorage() const; + virtual HistoryStorage* getHistoryStorage() const; - private: - VCardMemoryStorage* vcardStorage; - AvatarStorage* avatarStorage; - CapsStorage* capsStorage; - RosterStorage* rosterStorage; - HistoryStorage* historyStorage; - }; + private: + VCardMemoryStorage* vcardStorage; + AvatarStorage* avatarStorage; + CapsStorage* capsStorage; + RosterStorage* rosterStorage; + HistoryStorage* historyStorage; + }; } diff --git a/Swiften/Client/NickManager.cpp b/Swiften/Client/NickManager.cpp index 90e3217..87b5509 100644 --- a/Swiften/Client/NickManager.cpp +++ b/Swiften/Client/NickManager.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/NickManager.h> diff --git a/Swiften/Client/NickManager.h b/Swiften/Client/NickManager.h index c5a452e..c5f0e58 100644 --- a/Swiften/Client/NickManager.h +++ b/Swiften/Client/NickManager.h @@ -1,23 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <string> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> + namespace Swift { - class SWIFTEN_API NickManager { - public: - virtual ~NickManager(); + class SWIFTEN_API NickManager { + public: + virtual ~NickManager(); - virtual std::string getOwnNick() const = 0; - virtual void setOwnNick(const std::string& nick) = 0; + virtual std::string getOwnNick() const = 0; + virtual void setOwnNick(const std::string& nick) = 0; - boost::signal<void (const std::string&)> onOwnNickChanged; - }; + boost::signals2::signal<void (const std::string&)> onOwnNickChanged; + }; } diff --git a/Swiften/Client/NickManagerImpl.cpp b/Swiften/Client/NickManagerImpl.cpp index b9ebcde..f8fef39 100644 --- a/Swiften/Client/NickManagerImpl.cpp +++ b/Swiften/Client/NickManagerImpl.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/NickManagerImpl.h> @@ -13,38 +13,38 @@ namespace Swift { NickManagerImpl::NickManagerImpl(const JID& ownJID, VCardManager* vcardManager) : ownJID(ownJID), vcardManager(vcardManager) { - vcardManager->onVCardChanged.connect(boost::bind(&NickManagerImpl::handleVCardReceived, this, _1, _2)); + vcardManager->onVCardChanged.connect(boost::bind(&NickManagerImpl::handleVCardReceived, this, _1, _2)); - updateOwnNickFromVCard(vcardManager->getVCard(ownJID.toBare())); + updateOwnNickFromVCard(vcardManager->getVCard(ownJID.toBare())); } NickManagerImpl::~NickManagerImpl() { - vcardManager->onVCardChanged.disconnect(boost::bind(&NickManagerImpl::handleVCardReceived, this, _1, _2)); + vcardManager->onVCardChanged.disconnect(boost::bind(&NickManagerImpl::handleVCardReceived, this, _1, _2)); } std::string NickManagerImpl::getOwnNick() const { - return ownNick; + return ownNick; } void NickManagerImpl::setOwnNick(const std::string&) { } void NickManagerImpl::handleVCardReceived(const JID& jid, VCard::ref vcard) { - if (!jid.equals(ownJID, JID::WithoutResource)) { - return; - } - updateOwnNickFromVCard(vcard); + if (!jid.equals(ownJID, JID::WithoutResource)) { + return; + } + updateOwnNickFromVCard(vcard); } void NickManagerImpl::updateOwnNickFromVCard(VCard::ref vcard) { - std::string nick; - if (vcard && !vcard->getNickname().empty()) { - nick = vcard->getNickname(); - } - if (ownNick != nick) { - ownNick = nick; - onOwnNickChanged(ownNick); - } + std::string nick; + if (vcard && !vcard->getNickname().empty()) { + nick = vcard->getNickname(); + } + if (ownNick != nick) { + ownNick = nick; + onOwnNickChanged(ownNick); + } } } diff --git a/Swiften/Client/NickManagerImpl.h b/Swiften/Client/NickManagerImpl.h index d732987..a413378 100644 --- a/Swiften/Client/NickManagerImpl.h +++ b/Swiften/Client/NickManagerImpl.h @@ -1,34 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <string> + #include <Swiften/Client/NickManager.h> #include <Swiften/Elements/VCard.h> #include <Swiften/JID/JID.h> -#include <string> namespace Swift { - class VCardManager; + class VCardManager; - class NickManagerImpl : public NickManager { - public: - NickManagerImpl(const JID& ownJID, VCardManager* vcardManager); - ~NickManagerImpl(); + class NickManagerImpl : public NickManager { + public: + NickManagerImpl(const JID& ownJID, VCardManager* vcardManager); + virtual ~NickManagerImpl(); - std::string getOwnNick() const; - void setOwnNick(const std::string& nick); + std::string getOwnNick() const; + void setOwnNick(const std::string& nick); - private: - void handleVCardReceived(const JID& jid, VCard::ref vCard); - void updateOwnNickFromVCard(VCard::ref vcard); + private: + void handleVCardReceived(const JID& jid, VCard::ref vCard); + void updateOwnNickFromVCard(VCard::ref vcard); - private: - JID ownJID; - VCardManager* vcardManager; - std::string ownNick; - }; + private: + JID ownJID; + VCardManager* vcardManager; + std::string ownNick; + }; } diff --git a/Swiften/Client/NickResolver.cpp b/Swiften/Client/NickResolver.cpp index e6f2e41..394d490 100644 --- a/Swiften/Client/NickResolver.cpp +++ b/Swiften/Client/NickResolver.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/NickResolver.h> -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/bind.hpp> #include <Swiften/MUC/MUCRegistry.h> @@ -21,59 +22,59 @@ namespace Swift { NickResolver::NickResolver(const JID& ownJID, XMPPRoster* xmppRoster, VCardManager* vcardManager, MUCRegistry* mucRegistry) : ownJID_(ownJID) { - xmppRoster_ = xmppRoster; - vcardManager_ = vcardManager; - if (vcardManager_) { - vcardManager_->onVCardChanged.connect(boost::bind(&NickResolver::handleVCardReceived, this, _1, _2)); - } - mucRegistry_ = mucRegistry; - xmppRoster_->onJIDUpdated.connect(boost::bind(&NickResolver::handleJIDUpdated, this, _1, _2, _3)); - xmppRoster_->onJIDAdded.connect(boost::bind(&NickResolver::handleJIDAdded, this, _1)); + xmppRoster_ = xmppRoster; + vcardManager_ = vcardManager; + if (vcardManager_) { + vcardManager_->onVCardChanged.connect(boost::bind(&NickResolver::handleVCardReceived, this, _1, _2)); + } + mucRegistry_ = mucRegistry; + xmppRoster_->onJIDUpdated.connect(boost::bind(&NickResolver::handleJIDUpdated, this, _1, _2, _3)); + xmppRoster_->onJIDAdded.connect(boost::bind(&NickResolver::handleJIDAdded, this, _1)); } void NickResolver::handleJIDUpdated(const JID& jid, const std::string& previousNick, const std::vector<std::string>& /*groups*/) { - onNickChanged(jid, previousNick); + onNickChanged(jid, previousNick); } void NickResolver::handleJIDAdded(const JID& jid) { - std::string oldNick(jidToNick(jid)); - onNickChanged(jid, oldNick); + std::string oldNick(jidToNick(jid)); + onNickChanged(jid, oldNick); } std::string NickResolver::jidToNick(const JID& jid) { - if (jid.toBare() == ownJID_) { - if (!ownNick_.empty()) { - return ownNick_; - } - } - std::string nick; - - if (mucRegistry_ && mucRegistry_->isMUC(jid.toBare()) ) { - return jid.getResource().empty() ? jid.toBare().toString() : jid.getResource(); - } - - if (xmppRoster_->containsJID(jid) && !xmppRoster_->getNameForJID(jid).empty()) { - return xmppRoster_->getNameForJID(jid); - } - - return jid.toBare(); + if (jid.toBare() == ownJID_) { + if (!ownNick_.empty()) { + return ownNick_; + } + } + std::string nick; + + if (mucRegistry_ && mucRegistry_->isMUC(jid.toBare()) ) { + return jid.getResource().empty() ? jid.toBare().toString() : jid.getResource(); + } + + if (xmppRoster_->containsJID(jid) && !xmppRoster_->getNameForJID(jid).empty()) { + return xmppRoster_->getNameForJID(jid); + } + + return jid.toBare(); } void NickResolver::handleVCardReceived(const JID& jid, VCard::ref ownVCard) { - if (!jid.equals(ownJID_, JID::WithoutResource)) { - return; - } - std::string initialNick = ownNick_; - ownNick_ = ownJID_.toString(); - if (ownVCard) { - if (!ownVCard->getNickname().empty()) { - ownNick_ = ownVCard->getNickname(); - } else if (!ownVCard->getGivenName().empty()) { - ownNick_ = ownVCard->getGivenName(); - } else if (!ownVCard->getFullName().empty()) { - ownNick_ = ownVCard->getFullName(); - } - } + if (!jid.equals(ownJID_, JID::WithoutResource)) { + return; + } + std::string initialNick = ownNick_; + ownNick_ = ownJID_.toString(); + if (ownVCard) { + if (!ownVCard->getNickname().empty()) { + ownNick_ = ownVCard->getNickname(); + } else if (!ownVCard->getGivenName().empty()) { + ownNick_ = ownVCard->getGivenName(); + } else if (!ownVCard->getFullName().empty()) { + ownNick_ = ownVCard->getFullName(); + } + } } } diff --git a/Swiften/Client/NickResolver.h b/Swiften/Client/NickResolver.h index 306703e..a19c244 100644 --- a/Swiften/Client/NickResolver.h +++ b/Swiften/Client/NickResolver.h @@ -1,42 +1,44 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#pragma once + #include <map> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/JID/JID.h> #include <Swiften/Elements/VCard.h> +#include <Swiften/JID/JID.h> namespace Swift { - class XMPPRoster; - class MUCRegistry; - class VCardManager; - - class SWIFTEN_API NickResolver { - public: - NickResolver(const JID& ownJID, XMPPRoster* xmppRoster, VCardManager* vcardManager, MUCRegistry* mucRegistry); - - std::string jidToNick(const JID& jid); - - boost::signal<void (const JID&, const std::string& /*previousNick*/)> onNickChanged; - - private: - void handleVCardReceived(const JID& jid, VCard::ref vCard); - void handleJIDUpdated(const JID& jid, const std::string& previousNick, const std::vector<std::string>& groups); - void handleJIDAdded(const JID& jid); - - private: - JID ownJID_; - std::string ownNick_; - XMPPRoster* xmppRoster_; - MUCRegistry* mucRegistry_; - VCardManager* vcardManager_; - }; + class XMPPRoster; + class MUCRegistry; + class VCardManager; + + class SWIFTEN_API NickResolver { + public: + NickResolver(const JID& ownJID, XMPPRoster* xmppRoster, VCardManager* vcardManager, MUCRegistry* mucRegistry); + + std::string jidToNick(const JID& jid); + + boost::signals2::signal<void (const JID&, const std::string& /*previousNick*/)> onNickChanged; + + private: + void handleVCardReceived(const JID& jid, VCard::ref vCard); + void handleJIDUpdated(const JID& jid, const std::string& previousNick, const std::vector<std::string>& groups); + void handleJIDAdded(const JID& jid); + + private: + JID ownJID_; + std::string ownNick_; + XMPPRoster* xmppRoster_; + MUCRegistry* mucRegistry_; + VCardManager* vcardManager_; + }; } - diff --git a/Swiften/Client/StanzaChannel.h b/Swiften/Client/StanzaChannel.h index 5e85d3c..930bae1 100644 --- a/Swiften/Client/StanzaChannel.h +++ b/Swiften/Client/StanzaChannel.h @@ -1,31 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Queries/IQChannel.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Message.h> #include <Swiften/Elements/Presence.h> +#include <Swiften/Queries/IQChannel.h> #include <Swiften/TLS/Certificate.h> namespace Swift { - class StanzaChannel : public IQChannel { - public: - virtual void sendMessage(boost::shared_ptr<Message>) = 0; - virtual void sendPresence(boost::shared_ptr<Presence>) = 0; - virtual bool isAvailable() const = 0; - virtual bool getStreamManagementEnabled() const = 0; - virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; + class SWIFTEN_API StanzaChannel : public IQChannel { + public: + virtual void sendMessage(std::shared_ptr<Message>) = 0; + virtual void sendPresence(std::shared_ptr<Presence>) = 0; + virtual bool isAvailable() const = 0; + virtual bool getStreamManagementEnabled() const = 0; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; - boost::signal<void (bool /* isAvailable */)> onAvailableChanged; - boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived; - boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived; - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked; - }; + boost::signals2::signal<void (bool /* isAvailable */)> onAvailableChanged; + boost::signals2::signal<void (std::shared_ptr<Message>)> onMessageReceived; + boost::signals2::signal<void (std::shared_ptr<Presence>) > onPresenceReceived; + boost::signals2::signal<void (std::shared_ptr<Stanza>)> onStanzaAcked; + }; } diff --git a/Swiften/Client/Storages.cpp b/Swiften/Client/Storages.cpp index 3c2dbc5..7825d95 100644 --- a/Swiften/Client/Storages.cpp +++ b/Swiften/Client/Storages.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Client/Storages.h> diff --git a/Swiften/Client/Storages.h b/Swiften/Client/Storages.h index 76650a6..9485831 100644 --- a/Swiften/Client/Storages.h +++ b/Swiften/Client/Storages.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,24 +9,24 @@ #include <Swiften/Base/API.h> namespace Swift { - class VCardStorage; - class AvatarStorage; - class CapsStorage; - class RosterStorage; - class HistoryStorage; + class VCardStorage; + class AvatarStorage; + class CapsStorage; + class RosterStorage; + class HistoryStorage; - /** - * An interface to hold storage classes for different - * controllers. - */ - class SWIFTEN_API Storages { - public: - virtual ~Storages(); + /** + * An interface to hold storage classes for different + * controllers. + */ + class SWIFTEN_API Storages { + public: + virtual ~Storages(); - virtual VCardStorage* getVCardStorage() const = 0; - virtual AvatarStorage* getAvatarStorage() const = 0; - virtual CapsStorage* getCapsStorage() const = 0; - virtual RosterStorage* getRosterStorage() const = 0; - virtual HistoryStorage* getHistoryStorage() const = 0; - }; + virtual VCardStorage* getVCardStorage() const = 0; + virtual AvatarStorage* getAvatarStorage() const = 0; + virtual CapsStorage* getCapsStorage() const = 0; + virtual RosterStorage* getRosterStorage() const = 0; + virtual HistoryStorage* getHistoryStorage() const = 0; + }; } diff --git a/Swiften/Client/UnitTest/BlockListImplTest.cpp b/Swiften/Client/UnitTest/BlockListImplTest.cpp new file mode 100644 index 0000000..b2e45e2 --- /dev/null +++ b/Swiften/Client/UnitTest/BlockListImplTest.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <vector> + +#include <boost/bind.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Client/BlockListImpl.h> +#include <Swiften/JID/JID.h> + +using namespace Swift; + +class BlockListImplTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(BlockListImplTest); + CPPUNIT_TEST(testSetItemsToSubset); + CPPUNIT_TEST(testSetItemsToSuperset); + CPPUNIT_TEST(testSetItemsAllDifferent); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testSetItemsToSubset() { + std::vector<JID> subset; + subset.push_back(JID("a@example.com")); + + blockList_->setItems(subset); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), addedJIDs_.size()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), removedJIDs_.size()); + } + + void testSetItemsToSuperset() { + std::vector<JID> superset; + superset.push_back(JID("a@example.com")); + superset.push_back(JID("b@example.com")); + superset.push_back(JID("c@example.com")); + + blockList_->setItems(superset); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), addedJIDs_.size()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), removedJIDs_.size()); + } + + void testSetItemsAllDifferent() { + std::vector<JID> newBlockList; + newBlockList.push_back(JID("x@example.com")); + newBlockList.push_back(JID("y@example.com")); + newBlockList.push_back(JID("z@example.com")); + + blockList_->setItems(newBlockList); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), addedJIDs_.size()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), removedJIDs_.size()); + } + + void setUp() { + blockList_ = std::make_shared<BlockListImpl>(); + addedJIDs_.clear(); + removedJIDs_.clear(); + blockList_->addItem(JID("a@example.com")); + blockList_->addItem(JID("b@example.com")); + + blockList_->onItemAdded.connect(boost::bind(&BlockListImplTest::handleBlockListItemAdded, this, _1)); + blockList_->onItemRemoved.connect(boost::bind(&BlockListImplTest::handleBlockListItemRemoved, this, _1)); + } + + void tearDown() { + blockList_.reset(); + } + + void handleBlockListItemAdded(const JID& jid) { + addedJIDs_.push_back(jid); + } + + void handleBlockListItemRemoved(const JID& jid) { + removedJIDs_.push_back(jid); + } + + private: + std::shared_ptr<BlockListImpl> blockList_; + std::vector<JID> addedJIDs_; + std::vector<JID> removedJIDs_; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BlockListImplTest); diff --git a/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp b/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp index 9010042..5d22cac 100644 --- a/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp +++ b/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp @@ -4,186 +4,190 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ #include <algorithm> -#include <Swiften/Base/foreach.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Client/StanzaChannel.h> -#include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Client/ClientBlockListManager.h> -#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Client/StanzaChannel.h> #include <Swiften/Elements/IQ.h> +#include <Swiften/Queries/IQRouter.h> using namespace Swift; class ClientBlockListManagerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ClientBlockListManagerTest); - CPPUNIT_TEST(testFetchBlockList); - CPPUNIT_TEST(testBlockCommand); - CPPUNIT_TEST(testUnblockCommand); - CPPUNIT_TEST(testUnblockAllCommand); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - ownJID_ = JID("kev@wonderland.lit"); - stanzaChannel_ = new DummyStanzaChannel(); - iqRouter_ = new IQRouter(stanzaChannel_); - iqRouter_->setJID(ownJID_); - clientBlockListManager_ = new ClientBlockListManager(iqRouter_); - } - - void testFetchBlockList() { - std::vector<JID> blockJids; - blockJids.push_back(JID("romeo@montague.net")); - blockJids.push_back(JID("iago@shakespeare.lit")); - helperInitialBlockListFetch(blockJids); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); - } - - void testBlockCommand() { - // start with an already fetched block list - helperInitialBlockListFetch(std::vector<JID>(1, JID("iago@shakespeare.lit"))); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), clientBlockListManager_->getBlockList()->getItems().size()); - CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); - - GenericRequest<BlockPayload>::ref blockRequest = clientBlockListManager_->createBlockJIDRequest(JID("romeo@montague.net")); - blockRequest->send(); - IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); - CPPUNIT_ASSERT(request.get() != NULL); - boost::shared_ptr<BlockPayload> blockPayload = request->getPayload<BlockPayload>(); - CPPUNIT_ASSERT(blockPayload.get() != NULL); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), blockPayload->getItems().at(0)); - - IQ::ref blockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); - stanzaChannel_->sendIQ(blockRequestResponse); - stanzaChannel_->onIQReceived(blockRequestResponse); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), clientBlockListManager_->getBlockList()->getItems().size()); - - // send block push - boost::shared_ptr<BlockPayload> pushPayload = boost::make_shared<BlockPayload>(); - pushPayload->addItem(JID("romeo@montague.net")); - IQ::ref blockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); - stanzaChannel_->sendIQ(blockPush); - stanzaChannel_->onIQReceived(blockPush); - - std::vector<JID> blockedJIDs = clientBlockListManager_->getBlockList()->getItems(); - CPPUNIT_ASSERT(blockedJIDs.end() != std::find(blockedJIDs.begin(), blockedJIDs.end(), JID("romeo@montague.net"))); - } - - void testUnblockCommand() { - // start with an already fetched block list - std::vector<JID> initialBlockList = std::vector<JID>(1, JID("iago@shakespeare.lit")); - initialBlockList.push_back(JID("romeo@montague.net")); - helperInitialBlockListFetch(initialBlockList); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); - CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); - - GenericRequest<UnblockPayload>::ref unblockRequest = clientBlockListManager_->createUnblockJIDRequest(JID("romeo@montague.net")); - unblockRequest->send(); - IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); - CPPUNIT_ASSERT(request.get() != NULL); - boost::shared_ptr<UnblockPayload> unblockPayload = request->getPayload<UnblockPayload>(); - CPPUNIT_ASSERT(unblockPayload.get() != NULL); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), unblockPayload->getItems().at(0)); - - IQ::ref unblockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); - stanzaChannel_->sendIQ(unblockRequestResponse); - stanzaChannel_->onIQReceived(unblockRequestResponse); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); - - // send block push - boost::shared_ptr<UnblockPayload> pushPayload = boost::make_shared<UnblockPayload>(); - pushPayload->addItem(JID("romeo@montague.net")); - IQ::ref unblockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); - stanzaChannel_->sendIQ(unblockPush); - stanzaChannel_->onIQReceived(unblockPush); - - std::vector<JID> blockedJIDs = clientBlockListManager_->getBlockList()->getItems(); - CPPUNIT_ASSERT(blockedJIDs.end() == std::find(blockedJIDs.begin(), blockedJIDs.end(), JID("romeo@montague.net"))); - } - - void testUnblockAllCommand() { - // start with an already fetched block list - std::vector<JID> initialBlockList = std::vector<JID>(1, JID("iago@shakespeare.lit")); - initialBlockList.push_back(JID("romeo@montague.net")); - initialBlockList.push_back(JID("benvolio@montague.net")); - helperInitialBlockListFetch(initialBlockList); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), clientBlockListManager_->getBlockList()->getItems().size()); - CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); - - GenericRequest<UnblockPayload>::ref unblockRequest = clientBlockListManager_->createUnblockAllRequest(); - unblockRequest->send(); - IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); - CPPUNIT_ASSERT(request.get() != NULL); - boost::shared_ptr<UnblockPayload> unblockPayload = request->getPayload<UnblockPayload>(); - CPPUNIT_ASSERT(unblockPayload.get() != NULL); - CPPUNIT_ASSERT_EQUAL(true, unblockPayload->getItems().empty()); - - IQ::ref unblockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); - stanzaChannel_->sendIQ(unblockRequestResponse); - stanzaChannel_->onIQReceived(unblockRequestResponse); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), clientBlockListManager_->getBlockList()->getItems().size()); - - // send block push - boost::shared_ptr<UnblockPayload> pushPayload = boost::make_shared<UnblockPayload>(); - IQ::ref unblockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); - stanzaChannel_->sendIQ(unblockPush); - stanzaChannel_->onIQReceived(unblockPush); - - CPPUNIT_ASSERT_EQUAL(true, clientBlockListManager_->getBlockList()->getItems().empty()); - } - - void tearDown() { - delete clientBlockListManager_; - delete iqRouter_; - delete stanzaChannel_; - } - - private: - void helperInitialBlockListFetch(const std::vector<JID>& blockedJids) { - boost::shared_ptr<BlockList> blockList = clientBlockListManager_->getBlockList(); - CPPUNIT_ASSERT(blockList); - - // check for IQ request - IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(0); - CPPUNIT_ASSERT(request.get() != NULL); - boost::shared_ptr<BlockListPayload> requestPayload = request->getPayload<BlockListPayload>(); - CPPUNIT_ASSERT(requestPayload.get() != NULL); - - CPPUNIT_ASSERT_EQUAL(BlockList::Requesting, blockList->getState()); - CPPUNIT_ASSERT_EQUAL(BlockList::Requesting, clientBlockListManager_->getBlockList()->getState()); - - // build IQ response - boost::shared_ptr<BlockListPayload> responsePayload = boost::make_shared<BlockListPayload>(); - foreach(const JID& jid, blockedJids) { - responsePayload->addItem(jid); - } - - IQ::ref response = IQ::createResult(ownJID_, JID(), request->getID(), responsePayload); - stanzaChannel_->sendIQ(response); - stanzaChannel_->onIQReceived(response); - - CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); - CPPUNIT_ASSERT(responsePayload->getItems() == clientBlockListManager_->getBlockList()->getItems()); - } - - - private: - JID ownJID_; - IQRouter* iqRouter_; - DummyStanzaChannel* stanzaChannel_; - ClientBlockListManager* clientBlockListManager_; + CPPUNIT_TEST_SUITE(ClientBlockListManagerTest); + CPPUNIT_TEST(testFetchBlockList); + CPPUNIT_TEST(testBlockCommand); + CPPUNIT_TEST(testUnblockCommand); + CPPUNIT_TEST(testUnblockAllCommand); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + ownJID_ = JID("kev@wonderland.lit"); + stanzaChannel_ = new DummyStanzaChannel(); + iqRouter_ = new IQRouter(stanzaChannel_); + iqRouter_->setJID(ownJID_); + clientBlockListManager_ = new ClientBlockListManager(iqRouter_); + } + + void testFetchBlockList() { + std::vector<JID> blockJids; + blockJids.push_back(JID("romeo@montague.net")); + blockJids.push_back(JID("iago@shakespeare.lit")); + helperInitialBlockListFetch(blockJids); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); + } + + void testBlockCommand() { + // start with an already fetched block list + helperInitialBlockListFetch(std::vector<JID>(1, JID("iago@shakespeare.lit"))); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), clientBlockListManager_->getBlockList()->getItems().size()); + CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); + + GenericRequest<BlockPayload>::ref blockRequest = clientBlockListManager_->createBlockJIDRequest(JID("romeo@montague.net")); + blockRequest->send(); + IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); + CPPUNIT_ASSERT(request.get() != nullptr); + std::shared_ptr<BlockPayload> blockPayload = request->getPayload<BlockPayload>(); + CPPUNIT_ASSERT(blockPayload.get() != nullptr); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), blockPayload->getItems().at(0)); + + IQ::ref blockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); + stanzaChannel_->sendIQ(blockRequestResponse); + stanzaChannel_->onIQReceived(blockRequestResponse); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), clientBlockListManager_->getBlockList()->getItems().size()); + + // send block push + std::shared_ptr<BlockPayload> pushPayload = std::make_shared<BlockPayload>(); + pushPayload->addItem(JID("romeo@montague.net")); + IQ::ref blockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); + stanzaChannel_->sendIQ(blockPush); + stanzaChannel_->onIQReceived(blockPush); + + std::vector<JID> blockedJIDs = clientBlockListManager_->getBlockList()->getItems(); + CPPUNIT_ASSERT(blockedJIDs.end() != std::find(blockedJIDs.begin(), blockedJIDs.end(), JID("romeo@montague.net"))); + } + + void testUnblockCommand() { + // start with an already fetched block list + std::vector<JID> initialBlockList = std::vector<JID>(1, JID("iago@shakespeare.lit")); + initialBlockList.push_back(JID("romeo@montague.net")); + helperInitialBlockListFetch(initialBlockList); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); + CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); + + GenericRequest<UnblockPayload>::ref unblockRequest = clientBlockListManager_->createUnblockJIDRequest(JID("romeo@montague.net")); + unblockRequest->send(); + IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); + CPPUNIT_ASSERT(request.get() != nullptr); + std::shared_ptr<UnblockPayload> unblockPayload = request->getPayload<UnblockPayload>(); + CPPUNIT_ASSERT(unblockPayload.get() != nullptr); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), unblockPayload->getItems().at(0)); + + IQ::ref unblockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); + stanzaChannel_->sendIQ(unblockRequestResponse); + stanzaChannel_->onIQReceived(unblockRequestResponse); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); + + // send block push + std::shared_ptr<UnblockPayload> pushPayload = std::make_shared<UnblockPayload>(); + pushPayload->addItem(JID("romeo@montague.net")); + IQ::ref unblockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); + stanzaChannel_->sendIQ(unblockPush); + stanzaChannel_->onIQReceived(unblockPush); + + std::vector<JID> blockedJIDs = clientBlockListManager_->getBlockList()->getItems(); + CPPUNIT_ASSERT(blockedJIDs.end() == std::find(blockedJIDs.begin(), blockedJIDs.end(), JID("romeo@montague.net"))); + } + + void testUnblockAllCommand() { + // start with an already fetched block list + std::vector<JID> initialBlockList = std::vector<JID>(1, JID("iago@shakespeare.lit")); + initialBlockList.push_back(JID("romeo@montague.net")); + initialBlockList.push_back(JID("benvolio@montague.net")); + helperInitialBlockListFetch(initialBlockList); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), clientBlockListManager_->getBlockList()->getItems().size()); + CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); + + GenericRequest<UnblockPayload>::ref unblockRequest = clientBlockListManager_->createUnblockAllRequest(); + unblockRequest->send(); + IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); + CPPUNIT_ASSERT(request.get() != nullptr); + std::shared_ptr<UnblockPayload> unblockPayload = request->getPayload<UnblockPayload>(); + CPPUNIT_ASSERT(unblockPayload.get() != nullptr); + CPPUNIT_ASSERT_EQUAL(true, unblockPayload->getItems().empty()); + + IQ::ref unblockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); + stanzaChannel_->sendIQ(unblockRequestResponse); + stanzaChannel_->onIQReceived(unblockRequestResponse); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), clientBlockListManager_->getBlockList()->getItems().size()); + + // send block push + std::shared_ptr<UnblockPayload> pushPayload = std::make_shared<UnblockPayload>(); + IQ::ref unblockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); + stanzaChannel_->sendIQ(unblockPush); + stanzaChannel_->onIQReceived(unblockPush); + + CPPUNIT_ASSERT_EQUAL(true, clientBlockListManager_->getBlockList()->getItems().empty()); + } + + void tearDown() { + delete clientBlockListManager_; + delete iqRouter_; + delete stanzaChannel_; + } + + private: + void helperInitialBlockListFetch(const std::vector<JID>& blockedJids) { + std::shared_ptr<BlockList> blockList = clientBlockListManager_->requestBlockList(); + CPPUNIT_ASSERT(blockList); + + // check for IQ request + IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(0); + CPPUNIT_ASSERT(request.get() != nullptr); + std::shared_ptr<BlockListPayload> requestPayload = request->getPayload<BlockListPayload>(); + CPPUNIT_ASSERT(requestPayload.get() != nullptr); + + CPPUNIT_ASSERT_EQUAL(BlockList::Requesting, blockList->getState()); + CPPUNIT_ASSERT_EQUAL(BlockList::Requesting, clientBlockListManager_->getBlockList()->getState()); + + // build IQ response + std::shared_ptr<BlockListPayload> responsePayload = std::make_shared<BlockListPayload>(); + for (const auto& jid : blockedJids) { + responsePayload->addItem(jid); + } + + IQ::ref response = IQ::createResult(ownJID_, JID(), request->getID(), responsePayload); + stanzaChannel_->sendIQ(response); + stanzaChannel_->onIQReceived(response); + + CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); + CPPUNIT_ASSERT(responsePayload->getItems() == clientBlockListManager_->getBlockList()->getItems()); + } + + + private: + JID ownJID_; + IQRouter* iqRouter_; + DummyStanzaChannel* stanzaChannel_; + ClientBlockListManager* clientBlockListManager_; }; CPPUNIT_TEST_SUITE_REGISTRATION(ClientBlockListManagerTest); diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp index 4ef6727..44df961 100644 --- a/Swiften/Client/UnitTest/ClientSessionTest.cpp +++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp @@ -1,827 +1,908 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> #include <deque> +#include <memory> + #include <boost/bind.hpp> #include <boost/optional.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/IDN/IDNConverter.h> -#include <Swiften/IDN/PlatformIDNConverter.h> -#include <Swiften/Session/SessionStream.h> +#include <Swiften/Base/Debug.h> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + #include <Swiften/Client/ClientSession.h> -#include <Swiften/Elements/Message.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/Elements/AuthChallenge.h> -#include <Swiften/Elements/StartTLSRequest.h> -#include <Swiften/Elements/StreamFeatures.h> -#include <Swiften/Elements/StreamError.h> -#include <Swiften/Elements/TLSProceed.h> -#include <Swiften/Elements/StartTLSFailure.h> +#include <Swiften/Elements/AuthFailure.h> #include <Swiften/Elements/AuthRequest.h> #include <Swiften/Elements/AuthSuccess.h> -#include <Swiften/Elements/AuthFailure.h> -#include <Swiften/Elements/StreamManagementEnabled.h> -#include <Swiften/Elements/StreamManagementFailed.h> -#include <Swiften/Elements/StanzaAck.h> #include <Swiften/Elements/EnableStreamManagement.h> #include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> #include <Swiften/Elements/ResourceBind.h> -#include <Swiften/TLS/SimpleCertificate.h> +#include <Swiften/Elements/StanzaAck.h> +#include <Swiften/Elements/StartTLSFailure.h> +#include <Swiften/Elements/StartTLSRequest.h> +#include <Swiften/Elements/StreamError.h> +#include <Swiften/Elements/StreamFeatures.h> +#include <Swiften/Elements/StreamManagementEnabled.h> +#include <Swiften/Elements/StreamManagementFailed.h> +#include <Swiften/Elements/TLSProceed.h> +#include <Swiften/IDN/IDNConverter.h> +#include <Swiften/IDN/PlatformIDNConverter.h> +#include <Swiften/Network/DummyTimerFactory.h> +#include <Swiften/Session/SessionStream.h> #include <Swiften/TLS/BlindCertificateTrustChecker.h> -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/TLS/SimpleCertificate.h> using namespace Swift; class ClientSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ClientSessionTest); - CPPUNIT_TEST(testStart_Error); - CPPUNIT_TEST(testStart_StreamError); - CPPUNIT_TEST(testStartTLS); - CPPUNIT_TEST(testStartTLS_ServerError); - CPPUNIT_TEST(testStartTLS_ConnectError); - CPPUNIT_TEST(testStartTLS_InvalidIdentity); - CPPUNIT_TEST(testStart_StreamFeaturesWithoutResourceBindingFails); - CPPUNIT_TEST(testAuthenticate); - CPPUNIT_TEST(testAuthenticate_Unauthorized); - CPPUNIT_TEST(testAuthenticate_NoValidAuthMechanisms); - CPPUNIT_TEST(testAuthenticate_PLAINOverNonTLS); - CPPUNIT_TEST(testAuthenticate_RequireTLS); - CPPUNIT_TEST(testAuthenticate_EXTERNAL); - CPPUNIT_TEST(testStreamManagement); - CPPUNIT_TEST(testStreamManagement_Failed); - CPPUNIT_TEST(testUnexpectedChallenge); - CPPUNIT_TEST(testFinishAcksStanzas); - /* - CPPUNIT_TEST(testResourceBind); - CPPUNIT_TEST(testResourceBind_ChangeResource); - CPPUNIT_TEST(testResourceBind_EmptyResource); - CPPUNIT_TEST(testResourceBind_Error); - CPPUNIT_TEST(testSessionStart); - CPPUNIT_TEST(testSessionStart_Error); - CPPUNIT_TEST(testSessionStart_AfterResourceBind); - CPPUNIT_TEST(testWhitespacePing); - CPPUNIT_TEST(testReceiveElementAfterSessionStarted); - CPPUNIT_TEST(testSendElement); - */ - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); - server = boost::make_shared<MockSessionStream>(); - sessionFinishedReceived = false; - needCredentials = false; - blindCertificateTrustChecker = new BlindCertificateTrustChecker(); - } - - void tearDown() { - delete blindCertificateTrustChecker; - } - - void testStart_Error() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->breakConnection(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStart_StreamError() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->sendStreamStart(); - server->sendStreamError(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStartTLS() { - boost::shared_ptr<ClientSession> session(createSession()); - session->setCertificateTrustChecker(blindCertificateTrustChecker); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithStartTLS(); - server->receiveStartTLS(); - CPPUNIT_ASSERT(!server->tlsEncrypted); - server->sendTLSProceed(); - CPPUNIT_ASSERT(server->tlsEncrypted); - server->onTLSEncrypted(); - server->receiveStreamStart(); - server->sendStreamStart(); - - session->finish(); - } - - void testStartTLS_ServerError() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithStartTLS(); - server->receiveStartTLS(); - server->sendTLSFailure(); - - CPPUNIT_ASSERT(!server->tlsEncrypted); - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStartTLS_ConnectError() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithStartTLS(); - server->receiveStartTLS(); - server->sendTLSProceed(); - server->breakTLS(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStartTLS_InvalidIdentity() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithStartTLS(); - server->receiveStartTLS(); - CPPUNIT_ASSERT(!server->tlsEncrypted); - server->sendTLSProceed(); - CPPUNIT_ASSERT(server->tlsEncrypted); - server->onTLSEncrypted(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::InvalidServerIdentity, boost::dynamic_pointer_cast<CertificateVerificationError>(sessionFinishedError)->getType()); - } - - void testStart_StreamFeaturesWithoutResourceBindingFails() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendEmptyStreamFeatures(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testAuthenticate() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - CPPUNIT_ASSERT(needCredentials); - CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState()); - session->sendCredentials(createSafeByteArray("mypass")); - server->receiveAuthRequest("PLAIN"); - server->sendAuthSuccess(); - server->receiveStreamStart(); - - session->finish(); - } - - void testAuthenticate_Unauthorized() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - CPPUNIT_ASSERT(needCredentials); - CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState()); - session->sendCredentials(createSafeByteArray("mypass")); - server->receiveAuthRequest("PLAIN"); - server->sendAuthFailure(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testAuthenticate_PLAINOverNonTLS() { - boost::shared_ptr<ClientSession> session(createSession()); - session->setAllowPLAINOverNonTLS(false); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testAuthenticate_RequireTLS() { - boost::shared_ptr<ClientSession> session(createSession()); - session->setUseTLS(ClientSession::RequireTLS); - session->setAllowPLAINOverNonTLS(true); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithMultipleAuthentication(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testAuthenticate_NoValidAuthMechanisms() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithUnknownAuthentication(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testAuthenticate_EXTERNAL() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithEXTERNALAuthentication(); - server->receiveAuthRequest("EXTERNAL"); - server->sendAuthSuccess(); - server->receiveStreamStart(); - - session->finish(); - } - - void testUnexpectedChallenge() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithEXTERNALAuthentication(); - server->receiveAuthRequest("EXTERNAL"); - server->sendChallenge(); - server->sendChallenge(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStreamManagement() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - session->sendCredentials(createSafeByteArray("mypass")); - server->receiveAuthRequest("PLAIN"); - server->sendAuthSuccess(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithBindAndStreamManagement(); - server->receiveBind(); - server->sendBindResult(); - server->receiveStreamManagementEnable(); - server->sendStreamManagementEnabled(); - - CPPUNIT_ASSERT(session->getStreamManagementEnabled()); - // TODO: Test if the requesters & responders do their work - CPPUNIT_ASSERT_EQUAL(ClientSession::Initialized, session->getState()); - - session->finish(); - } - - void testStreamManagement_Failed() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - session->sendCredentials(createSafeByteArray("mypass")); - server->receiveAuthRequest("PLAIN"); - server->sendAuthSuccess(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithBindAndStreamManagement(); - server->receiveBind(); - server->sendBindResult(); - server->receiveStreamManagementEnable(); - server->sendStreamManagementFailed(); - - CPPUNIT_ASSERT(!session->getStreamManagementEnabled()); - CPPUNIT_ASSERT_EQUAL(ClientSession::Initialized, session->getState()); - - session->finish(); - } - - void testFinishAcksStanzas() { - boost::shared_ptr<ClientSession> session(createSession()); - initializeSession(session); - server->sendMessage(); - server->sendMessage(); - server->sendMessage(); - - session->finish(); - - server->receiveAck(3); - } - - private: - boost::shared_ptr<ClientSession> createSession() { - boost::shared_ptr<ClientSession> session = ClientSession::create(JID("me@foo.com"), server, idnConverter.get(), crypto.get()); - session->onFinished.connect(boost::bind(&ClientSessionTest::handleSessionFinished, this, _1)); - session->onNeedCredentials.connect(boost::bind(&ClientSessionTest::handleSessionNeedCredentials, this)); - session->setAllowPLAINOverNonTLS(true); - return session; - } - - void initializeSession(boost::shared_ptr<ClientSession> session) { - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - session->sendCredentials(createSafeByteArray("mypass")); - server->receiveAuthRequest("PLAIN"); - server->sendAuthSuccess(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithBindAndStreamManagement(); - server->receiveBind(); - server->sendBindResult(); - server->receiveStreamManagementEnable(); - server->sendStreamManagementEnabled(); - } - - void handleSessionFinished(boost::shared_ptr<Error> error) { - sessionFinishedReceived = true; - sessionFinishedError = error; - } - - void handleSessionNeedCredentials() { - needCredentials = true; - } - - class MockSessionStream : public SessionStream { - public: - struct Event { - Event(boost::shared_ptr<Element> element) : element(element), footer(false) {} - Event(const ProtocolHeader& header) : header(header), footer(false) {} - Event() : footer(true) {} - - boost::shared_ptr<Element> element; - boost::optional<ProtocolHeader> header; - bool footer; - }; - - MockSessionStream() : available(true), canTLSEncrypt(true), tlsEncrypted(false), compressed(false), whitespacePingEnabled(false), resetCount(0) { - } - - virtual void close() { - onClosed(boost::shared_ptr<Error>()); - } - - virtual bool isOpen() { - return available; - } - - virtual void writeHeader(const ProtocolHeader& header) { - receivedEvents.push_back(Event(header)); - } - - virtual void writeFooter() { - receivedEvents.push_back(Event()); - } - - virtual void writeElement(boost::shared_ptr<Element> element) { - receivedEvents.push_back(Event(element)); - } - - virtual void writeData(const std::string&) { - } - - virtual bool supportsTLSEncryption() { - return canTLSEncrypt; - } - - virtual void addTLSEncryption() { - tlsEncrypted = true; - } - - virtual bool isTLSEncrypted() { - return tlsEncrypted; - } - - virtual ByteArray getTLSFinishMessage() const { - return ByteArray(); - } - - virtual Certificate::ref getPeerCertificate() const { - return Certificate::ref(new SimpleCertificate()); - } - - virtual std::vector<Certificate::ref> getPeerCertificateChain() const { - return std::vector<Certificate::ref>(); - } - - virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const { - return boost::shared_ptr<CertificateVerificationError>(); - } - - virtual bool supportsZLibCompression() { - return true; - } - - virtual void addZLibCompression() { - compressed = true; - } - - virtual void setWhitespacePingEnabled(bool enabled) { - whitespacePingEnabled = enabled; - } - - virtual void resetXMPPParser() { - resetCount++; - } - - void breakConnection() { - onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::ConnectionReadError)); - } - - void breakTLS() { - onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::TLSError)); - } - - - void sendStreamStart() { - ProtocolHeader header; - header.setTo("foo.com"); - return onStreamStartReceived(header); - } - - void sendStreamFeaturesWithStartTLS() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->setHasStartTLS(); - onElementReceived(streamFeatures); - } - - void sendChallenge() { - onElementReceived(boost::make_shared<AuthChallenge>()); - } - - void sendStreamError() { - onElementReceived(boost::make_shared<StreamError>()); - } - - void sendTLSProceed() { - onElementReceived(boost::make_shared<TLSProceed>()); - } - - void sendTLSFailure() { - onElementReceived(boost::make_shared<StartTLSFailure>()); - } - - void sendStreamFeaturesWithMultipleAuthentication() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->addAuthenticationMechanism("PLAIN"); - streamFeatures->addAuthenticationMechanism("DIGEST-MD5"); - streamFeatures->addAuthenticationMechanism("SCRAM-SHA1"); - onElementReceived(streamFeatures); - } - - void sendStreamFeaturesWithPLAINAuthentication() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->addAuthenticationMechanism("PLAIN"); - onElementReceived(streamFeatures); - } - - void sendStreamFeaturesWithEXTERNALAuthentication() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->addAuthenticationMechanism("EXTERNAL"); - onElementReceived(streamFeatures); - } - - void sendStreamFeaturesWithUnknownAuthentication() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->addAuthenticationMechanism("UNKNOWN"); - onElementReceived(streamFeatures); - } - - void sendStreamFeaturesWithBindAndStreamManagement() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->setHasResourceBind(); - streamFeatures->setHasStreamManagement(); - onElementReceived(streamFeatures); - } - - void sendEmptyStreamFeatures() { - onElementReceived(boost::make_shared<StreamFeatures>()); - } - - void sendAuthSuccess() { - onElementReceived(boost::make_shared<AuthSuccess>()); - } - - void sendAuthFailure() { - onElementReceived(boost::make_shared<AuthFailure>()); - } - - void sendStreamManagementEnabled() { - onElementReceived(boost::make_shared<StreamManagementEnabled>()); - } - - void sendStreamManagementFailed() { - onElementReceived(boost::make_shared<StreamManagementFailed>()); - } - - void sendBindResult() { - boost::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); - resourceBind->setJID(JID("foo@bar.com/bla")); - boost::shared_ptr<IQ> iq = IQ::createResult(JID("foo@bar.com"), bindID, resourceBind); - onElementReceived(iq); - } - - void sendMessage() { - boost::shared_ptr<Message> message = boost::make_shared<Message>(); - message->setTo(JID("foo@bar.com/bla")); - onElementReceived(message); - } - - void receiveStreamStart() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.header); - } - - void receiveStartTLS() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<StartTLSRequest>(event.element)); - } - - void receiveAuthRequest(const std::string& mech) { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - boost::shared_ptr<AuthRequest> request(boost::dynamic_pointer_cast<AuthRequest>(event.element)); - CPPUNIT_ASSERT(request); - CPPUNIT_ASSERT_EQUAL(mech, request->getMechanism()); - } - - void receiveStreamManagementEnable() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<EnableStreamManagement>(event.element)); - } - - void receiveBind() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(event.element); - CPPUNIT_ASSERT(iq); - CPPUNIT_ASSERT(iq->getPayload<ResourceBind>()); - bindID = iq->getID(); - } - - void receiveAck(unsigned int n) { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - boost::shared_ptr<StanzaAck> ack = boost::dynamic_pointer_cast<StanzaAck>(event.element); - CPPUNIT_ASSERT(ack); - CPPUNIT_ASSERT_EQUAL(n, ack->getHandledStanzasCount()); - } - - Event popEvent() { - CPPUNIT_ASSERT(!receivedEvents.empty()); - Event event = receivedEvents.front(); - receivedEvents.pop_front(); - return event; - } - - bool available; - bool canTLSEncrypt; - bool tlsEncrypted; - bool compressed; - bool whitespacePingEnabled; - std::string bindID; - int resetCount; - std::deque<Event> receivedEvents; - }; - - boost::shared_ptr<IDNConverter> idnConverter; - boost::shared_ptr<MockSessionStream> server; - bool sessionFinishedReceived; - bool needCredentials; - boost::shared_ptr<Error> sessionFinishedError; - BlindCertificateTrustChecker* blindCertificateTrustChecker; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(ClientSessionTest); + CPPUNIT_TEST(testStart_Error); + CPPUNIT_TEST(testStart_StreamError); + CPPUNIT_TEST(testStartTLS); + CPPUNIT_TEST(testStartTLS_ServerError); + CPPUNIT_TEST(testStartTLS_ConnectError); + CPPUNIT_TEST(testStartTLS_InvalidIdentity); + CPPUNIT_TEST(testStart_StreamFeaturesWithoutResourceBindingFails); + CPPUNIT_TEST(testAuthenticate); + CPPUNIT_TEST(testAuthenticate_Unauthorized); + CPPUNIT_TEST(testAuthenticate_NoValidAuthMechanisms); + CPPUNIT_TEST(testAuthenticate_PLAINOverNonTLS); + CPPUNIT_TEST(testAuthenticate_RequireTLS); + CPPUNIT_TEST(testAuthenticate_EXTERNAL); + CPPUNIT_TEST(testStreamManagement); + CPPUNIT_TEST(testStreamManagement_Failed); + CPPUNIT_TEST(testUnexpectedChallenge); + CPPUNIT_TEST(testFinishAcksStanzas); + + CPPUNIT_TEST(testServerInitiatedSessionClose); + CPPUNIT_TEST(testClientInitiatedSessionClose); + CPPUNIT_TEST(testTimeoutOnShutdown); + + /* + CPPUNIT_TEST(testResourceBind); + CPPUNIT_TEST(testResourceBind_ChangeResource); + CPPUNIT_TEST(testResourceBind_EmptyResource); + CPPUNIT_TEST(testResourceBind_Error); + CPPUNIT_TEST(testSessionStart); + CPPUNIT_TEST(testSessionStart_Error); + CPPUNIT_TEST(testSessionStart_AfterResourceBind); + CPPUNIT_TEST(testWhitespacePing); + CPPUNIT_TEST(testReceiveElementAfterSessionStarted); + CPPUNIT_TEST(testSendElement); + */ + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + idnConverter = std::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); + timerFactory = std::make_shared<DummyTimerFactory>(); + server = std::make_shared<MockSessionStream>(); + sessionFinishedReceived = false; + needCredentials = false; + blindCertificateTrustChecker = new BlindCertificateTrustChecker(); + } + + void tearDown() { + delete blindCertificateTrustChecker; + } + + void testStart_Error() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->breakConnection(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStart_StreamError() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->sendStreamStart(); + server->sendStreamError(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finishing, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + + server->onStreamEndReceived(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStartTLS() { + std::shared_ptr<ClientSession> session(createSession()); + session->setCertificateTrustChecker(blindCertificateTrustChecker); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithStartTLS(); + server->receiveStartTLS(); + CPPUNIT_ASSERT(!server->tlsEncrypted); + server->sendTLSProceed(); + CPPUNIT_ASSERT(server->tlsEncrypted); + server->onTLSEncrypted(); + server->receiveStreamStart(); + server->sendStreamStart(); + + session->finish(); + } + + void testStartTLS_ServerError() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithStartTLS(); + server->receiveStartTLS(); + server->sendTLSFailure(); + + CPPUNIT_ASSERT(!server->tlsEncrypted); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finishing, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + + server->onStreamEndReceived(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStartTLS_ConnectError() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithStartTLS(); + server->receiveStartTLS(); + server->sendTLSProceed(); + server->breakTLS(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStartTLS_InvalidIdentity() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithStartTLS(); + server->receiveStartTLS(); + CPPUNIT_ASSERT(!server->tlsEncrypted); + server->sendTLSProceed(); + CPPUNIT_ASSERT(server->tlsEncrypted); + server->onTLSEncrypted(); + server->close(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + CPPUNIT_ASSERT(std::dynamic_pointer_cast<CertificateVerificationError>(sessionFinishedError)); + CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::InvalidServerIdentity, std::dynamic_pointer_cast<CertificateVerificationError>(sessionFinishedError)->getType()); + } + + void testStart_StreamFeaturesWithoutResourceBindingFails() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendEmptyStreamFeatures(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finishing, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + + server->onStreamEndReceived(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testAuthenticate() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + CPPUNIT_ASSERT(needCredentials); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::WaitingForCredentials, session->getState()); + session->sendCredentials(createSafeByteArray("mypass")); + server->receiveAuthRequest("PLAIN"); + server->sendAuthSuccess(); + server->receiveStreamStart(); + + session->finish(); + } + + void testAuthenticate_Unauthorized() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + CPPUNIT_ASSERT(needCredentials); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::WaitingForCredentials, session->getState()); + session->sendCredentials(createSafeByteArray("mypass")); + server->receiveAuthRequest("PLAIN"); + server->sendAuthFailure(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finishing, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + + server->onStreamEndReceived(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testAuthenticate_PLAINOverNonTLS() { + std::shared_ptr<ClientSession> session(createSession()); + session->setAllowPLAINOverNonTLS(false); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finishing, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + + server->onStreamEndReceived(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testAuthenticate_RequireTLS() { + std::shared_ptr<ClientSession> session(createSession()); + session->setUseTLS(ClientSession::RequireTLS); + session->setAllowPLAINOverNonTLS(true); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithMultipleAuthentication(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finishing, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + + server->onStreamEndReceived(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testAuthenticate_NoValidAuthMechanisms() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithUnknownAuthentication(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finishing, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + + server->onStreamEndReceived(); + server->close(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testAuthenticate_EXTERNAL() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithEXTERNALAuthentication(); + server->receiveAuthRequest("EXTERNAL"); + server->sendAuthSuccess(); + server->receiveStreamStart(); + + session->finish(); + } + + void testUnexpectedChallenge() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithEXTERNALAuthentication(); + server->receiveAuthRequest("EXTERNAL"); + server->sendChallenge(); + server->sendChallenge(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finishing, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + + server->onStreamEndReceived(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStreamManagement() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + session->sendCredentials(createSafeByteArray("mypass")); + server->receiveAuthRequest("PLAIN"); + server->sendAuthSuccess(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithBindAndStreamManagement(); + server->receiveBind(); + server->sendBindResult(); + server->receiveStreamManagementEnable(); + server->sendStreamManagementEnabled(); + + CPPUNIT_ASSERT(session->getStreamManagementEnabled()); + // TODO: Test if the requesters & responders do their work + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Initialized, session->getState()); + + session->finish(); + } + + void testStreamManagement_Failed() { + std::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + session->sendCredentials(createSafeByteArray("mypass")); + server->receiveAuthRequest("PLAIN"); + server->sendAuthSuccess(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithBindAndStreamManagement(); + server->receiveBind(); + server->sendBindResult(); + server->receiveStreamManagementEnable(); + server->sendStreamManagementFailed(); + + CPPUNIT_ASSERT(!session->getStreamManagementEnabled()); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Initialized, session->getState()); + + session->finish(); + } + + void testFinishAcksStanzas() { + std::shared_ptr<ClientSession> session(createSession()); + initializeSession(session); + server->sendMessage(); + server->sendMessage(); + server->sendMessage(); + + session->finish(); + + server->receiveAck(3); + } + + void testServerInitiatedSessionClose() { + std::shared_ptr<ClientSession> session(createSession()); + initializeSession(session); + + server->onStreamEndReceived(); + server->close(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + } + + void testClientInitiatedSessionClose() { + std::shared_ptr<ClientSession> session(createSession()); + initializeSession(session); + + session->finish(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finishing, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + + server->onStreamEndReceived(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + } + + void testTimeoutOnShutdown() { + std::shared_ptr<ClientSession> session(createSession()); + initializeSession(session); + + session->finish(); + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finishing, session->getState()); + CPPUNIT_ASSERT_EQUAL(true, server->receivedEvents.back().footer); + timerFactory->setTime(60000); + + CPPUNIT_ASSERT_EQUAL(ClientSession::State::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + } + + private: + std::shared_ptr<ClientSession> createSession() { + std::shared_ptr<ClientSession> session = ClientSession::create(JID("me@foo.com"), server, idnConverter.get(), crypto.get(), timerFactory.get()); + session->onFinished.connect(boost::bind(&ClientSessionTest::handleSessionFinished, this, _1)); + session->onNeedCredentials.connect(boost::bind(&ClientSessionTest::handleSessionNeedCredentials, this)); + session->setAllowPLAINOverNonTLS(true); + return session; + } + + void initializeSession(std::shared_ptr<ClientSession> session) { + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + session->sendCredentials(createSafeByteArray("mypass")); + server->receiveAuthRequest("PLAIN"); + server->sendAuthSuccess(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithBindAndStreamManagement(); + server->receiveBind(); + server->sendBindResult(); + server->receiveStreamManagementEnable(); + server->sendStreamManagementEnabled(); + } + + void handleSessionFinished(std::shared_ptr<Error> error) { + sessionFinishedReceived = true; + sessionFinishedError = error; + } + + void handleSessionNeedCredentials() { + needCredentials = true; + } + + class MockSessionStream : public SessionStream { + public: + struct Event { + Event(std::shared_ptr<ToplevelElement> element) : element(element), footer(false) {} + Event(const ProtocolHeader& header) : header(header), footer(false) {} + Event() : footer(true) {} + + std::shared_ptr<ToplevelElement> element; + boost::optional<ProtocolHeader> header; + bool footer; + }; + + MockSessionStream() : available(true), canTLSEncrypt(true), tlsEncrypted(false), compressed(false), whitespacePingEnabled(false), resetCount(0) { + } + + virtual void close() { + onClosed(std::shared_ptr<Error>()); + } + + virtual bool isOpen() { + return available; + } + + virtual void writeHeader(const ProtocolHeader& header) { + receivedEvents.push_back(Event(header)); + } + + virtual void writeFooter() { + receivedEvents.push_back(Event()); + } + + virtual void writeElement(std::shared_ptr<ToplevelElement> element) { + receivedEvents.push_back(Event(element)); + } + + virtual void writeData(const std::string&) { + } + + virtual bool supportsTLSEncryption() { + return canTLSEncrypt; + } + + virtual void addTLSEncryption() { + tlsEncrypted = true; + } + + virtual bool isTLSEncrypted() { + return tlsEncrypted; + } + + virtual ByteArray getTLSFinishMessage() const { + return ByteArray(); + } + + virtual Certificate::ref getPeerCertificate() const { + return Certificate::ref(new SimpleCertificate()); + } + + virtual std::vector<Certificate::ref> getPeerCertificateChain() const { + return std::vector<Certificate::ref>(); + } + + virtual std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const { + return std::shared_ptr<CertificateVerificationError>(); + } + + virtual bool supportsZLibCompression() { + return true; + } + + virtual void addZLibCompression() { + compressed = true; + } + + virtual void setWhitespacePingEnabled(bool enabled) { + whitespacePingEnabled = enabled; + } + + virtual void resetXMPPParser() { + resetCount++; + } + + void breakConnection() { + onClosed(std::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::ConnectionReadError)); + } + + void breakTLS() { + onClosed(std::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::TLSError)); + } + + + void sendStreamStart() { + ProtocolHeader header; + header.setTo("foo.com"); + return onStreamStartReceived(header); + } + + void sendStreamFeaturesWithStartTLS() { + std::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->setHasStartTLS(); + onElementReceived(streamFeatures); + } + + void sendChallenge() { + onElementReceived(std::make_shared<AuthChallenge>()); + } + + void sendStreamError() { + onElementReceived(std::make_shared<StreamError>()); + } + + void sendTLSProceed() { + onElementReceived(std::make_shared<TLSProceed>()); + } + + void sendTLSFailure() { + onElementReceived(std::make_shared<StartTLSFailure>()); + } + + void sendStreamFeaturesWithMultipleAuthentication() { + std::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->addAuthenticationMechanism("PLAIN"); + streamFeatures->addAuthenticationMechanism("DIGEST-MD5"); + streamFeatures->addAuthenticationMechanism("SCRAM-SHA1"); + onElementReceived(streamFeatures); + } + + void sendStreamFeaturesWithPLAINAuthentication() { + std::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->addAuthenticationMechanism("PLAIN"); + onElementReceived(streamFeatures); + } + + void sendStreamFeaturesWithEXTERNALAuthentication() { + std::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->addAuthenticationMechanism("EXTERNAL"); + onElementReceived(streamFeatures); + } + + void sendStreamFeaturesWithUnknownAuthentication() { + std::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->addAuthenticationMechanism("UNKNOWN"); + onElementReceived(streamFeatures); + } + + void sendStreamFeaturesWithBindAndStreamManagement() { + std::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->setHasResourceBind(); + streamFeatures->setHasStreamManagement(); + onElementReceived(streamFeatures); + } + + void sendEmptyStreamFeatures() { + onElementReceived(std::make_shared<StreamFeatures>()); + } + + void sendAuthSuccess() { + onElementReceived(std::make_shared<AuthSuccess>()); + } + + void sendAuthFailure() { + onElementReceived(std::make_shared<AuthFailure>()); + } + + void sendStreamManagementEnabled() { + onElementReceived(std::make_shared<StreamManagementEnabled>()); + } + + void sendStreamManagementFailed() { + onElementReceived(std::make_shared<StreamManagementFailed>()); + } + + void sendBindResult() { + std::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); + resourceBind->setJID(JID("foo@bar.com/bla")); + std::shared_ptr<IQ> iq = IQ::createResult(JID("foo@bar.com"), bindID, resourceBind); + onElementReceived(iq); + } + + void sendMessage() { + std::shared_ptr<Message> message = std::make_shared<Message>(); + message->setTo(JID("foo@bar.com/bla")); + onElementReceived(message); + } + + void receiveStreamStart() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.header); + } + + void receiveStartTLS() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + CPPUNIT_ASSERT(std::dynamic_pointer_cast<StartTLSRequest>(event.element)); + } + + void receiveAuthRequest(const std::string& mech) { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + std::shared_ptr<AuthRequest> request(std::dynamic_pointer_cast<AuthRequest>(event.element)); + CPPUNIT_ASSERT(request); + CPPUNIT_ASSERT_EQUAL(mech, request->getMechanism()); + } + + void receiveStreamManagementEnable() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + CPPUNIT_ASSERT(std::dynamic_pointer_cast<EnableStreamManagement>(event.element)); + } + + void receiveBind() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + std::shared_ptr<IQ> iq = std::dynamic_pointer_cast<IQ>(event.element); + CPPUNIT_ASSERT(iq); + CPPUNIT_ASSERT(iq->getPayload<ResourceBind>()); + bindID = iq->getID(); + } + + void receiveAck(unsigned int n) { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + std::shared_ptr<StanzaAck> ack = std::dynamic_pointer_cast<StanzaAck>(event.element); + CPPUNIT_ASSERT(ack); + CPPUNIT_ASSERT_EQUAL(n, ack->getHandledStanzasCount()); + } + + Event popEvent() { + CPPUNIT_ASSERT(!receivedEvents.empty()); + Event event = receivedEvents.front(); + receivedEvents.pop_front(); + return event; + } + + bool available; + bool canTLSEncrypt; + bool tlsEncrypted; + bool compressed; + bool whitespacePingEnabled; + std::string bindID; + int resetCount; + std::deque<Event> receivedEvents; + }; + + std::shared_ptr<IDNConverter> idnConverter; + std::shared_ptr<MockSessionStream> server; + bool sessionFinishedReceived; + bool needCredentials; + std::shared_ptr<Error> sessionFinishedError; + BlindCertificateTrustChecker* blindCertificateTrustChecker; + std::shared_ptr<CryptoProvider> crypto; + std::shared_ptr<DummyTimerFactory> timerFactory; }; CPPUNIT_TEST_SUITE_REGISTRATION(ClientSessionTest); #if 0 - void testAuthenticate() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - session->onNeedCredentials.connect(boost::bind(&ClientSessionTest::setNeedCredentials, this)); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithAuthentication(); - session->startSession(); - processEvents(); - CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState()); - CPPUNIT_ASSERT(needCredentials_); - - getMockServer()->expectAuth("me", "mypass"); - getMockServer()->sendAuthSuccess(); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - session->sendCredentials("mypass"); - CPPUNIT_ASSERT_EQUAL(ClientSession::Authenticating, session->getState()); - processEvents(); - CPPUNIT_ASSERT_EQUAL(ClientSession::Negotiating, session->getState()); - } - - void testAuthenticate_Unauthorized() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithAuthentication(); - session->startSession(); - processEvents(); - - getMockServer()->expectAuth("me", "mypass"); - getMockServer()->sendAuthFailure(); - session->sendCredentials("mypass"); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); - CPPUNIT_ASSERT_EQUAL(ClientSession::AuthenticationFailedError, *session->getError()); - } - - void testAuthenticate_NoValidAuthMechanisms() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithUnsupportedAuthentication(); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); - CPPUNIT_ASSERT_EQUAL(ClientSession::NoSupportedAuthMechanismsError, *session->getError()); - } - - void testResourceBind() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithResourceBind(); - getMockServer()->expectResourceBind("Bar", "session-bind"); - // FIXME: Check CPPUNIT_ASSERT_EQUAL(ClientSession::BindingResource, session->getState()); - getMockServer()->sendResourceBindResponse("me@foo.com/Bar", "session-bind"); - session->startSession(); - - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); - CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/Bar"), session->getLocalJID()); - } - - void testResourceBind_ChangeResource() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithResourceBind(); - getMockServer()->expectResourceBind("Bar", "session-bind"); - getMockServer()->sendResourceBindResponse("me@foo.com/Bar123", "session-bind"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); - CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/Bar123"), session->getLocalJID()); - } - - void testResourceBind_EmptyResource() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithResourceBind(); - getMockServer()->expectResourceBind("", "session-bind"); - getMockServer()->sendResourceBindResponse("me@foo.com/NewResource", "session-bind"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); - CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/NewResource"), session->getLocalJID()); - } - - void testResourceBind_Error() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithResourceBind(); - getMockServer()->expectResourceBind("", "session-bind"); - getMockServer()->sendError("session-bind"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); - CPPUNIT_ASSERT_EQUAL(ClientSession::ResourceBindError, *session->getError()); - } - - void testSessionStart() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - session->onSessionStarted.connect(boost::bind(&ClientSessionTest::setSessionStarted, this)); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithSession(); - getMockServer()->expectSessionStart("session-start"); - // FIXME: Check CPPUNIT_ASSERT_EQUAL(ClientSession::StartingSession, session->getState()); - getMockServer()->sendSessionStartResponse("session-start"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); - CPPUNIT_ASSERT(sessionStarted_); - } - - void testSessionStart_Error() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithSession(); - getMockServer()->expectSessionStart("session-start"); - getMockServer()->sendError("session-start"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStartError, *session->getError()); - } - - void testSessionStart_AfterResourceBind() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - session->onSessionStarted.connect(boost::bind(&ClientSessionTest::setSessionStarted, this)); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithResourceBindAndSession(); - getMockServer()->expectResourceBind("Bar", "session-bind"); - getMockServer()->sendResourceBindResponse("me@foo.com/Bar", "session-bind"); - getMockServer()->expectSessionStart("session-start"); - getMockServer()->sendSessionStartResponse("session-start"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); - CPPUNIT_ASSERT(sessionStarted_); - } - - void testWhitespacePing() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeatures(); - session->startSession(); - processEvents(); - CPPUNIT_ASSERT(session->getWhitespacePingLayer()); - } - - void testReceiveElementAfterSessionStarted() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeatures(); - session->startSession(); - processEvents(); - - getMockServer()->expectMessage(); - session->sendElement(boost::make_shared<Message>())); - } - - void testSendElement() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - session->onElementReceived.connect(boost::bind(&ClientSessionTest::addReceivedElement, this, _1)); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeatures(); - getMockServer()->sendMessage(); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedElements_.size())); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<Message>(receivedElements_[0])); - } + void testAuthenticate() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + session->onNeedCredentials.connect(boost::bind(&ClientSessionTest::setNeedCredentials, this)); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithAuthentication(); + session->startSession(); + processEvents(); + CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState()); + CPPUNIT_ASSERT(needCredentials_); + + getMockServer()->expectAuth("me", "mypass"); + getMockServer()->sendAuthSuccess(); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + session->sendCredentials("mypass"); + CPPUNIT_ASSERT_EQUAL(ClientSession::Authenticating, session->getState()); + processEvents(); + CPPUNIT_ASSERT_EQUAL(ClientSession::Negotiating, session->getState()); + } + + void testAuthenticate_Unauthorized() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithAuthentication(); + session->startSession(); + processEvents(); + + getMockServer()->expectAuth("me", "mypass"); + getMockServer()->sendAuthFailure(); + session->sendCredentials("mypass"); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); + CPPUNIT_ASSERT_EQUAL(ClientSession::AuthenticationFailedError, *session->getError()); + } + + void testAuthenticate_NoValidAuthMechanisms() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithUnsupportedAuthentication(); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); + CPPUNIT_ASSERT_EQUAL(ClientSession::NoSupportedAuthMechanismsError, *session->getError()); + } + + void testResourceBind() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithResourceBind(); + getMockServer()->expectResourceBind("Bar", "session-bind"); + // FIXME: Check CPPUNIT_ASSERT_EQUAL(ClientSession::BindingResource, session->getState()); + getMockServer()->sendResourceBindResponse("me@foo.com/Bar", "session-bind"); + session->startSession(); + + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); + CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/Bar"), session->getLocalJID()); + } + + void testResourceBind_ChangeResource() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithResourceBind(); + getMockServer()->expectResourceBind("Bar", "session-bind"); + getMockServer()->sendResourceBindResponse("me@foo.com/Bar123", "session-bind"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); + CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/Bar123"), session->getLocalJID()); + } + + void testResourceBind_EmptyResource() { + std::shared_ptr<MockSession> session(createSession("me@foo.com")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithResourceBind(); + getMockServer()->expectResourceBind("", "session-bind"); + getMockServer()->sendResourceBindResponse("me@foo.com/NewResource", "session-bind"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); + CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/NewResource"), session->getLocalJID()); + } + + void testResourceBind_Error() { + std::shared_ptr<MockSession> session(createSession("me@foo.com")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithResourceBind(); + getMockServer()->expectResourceBind("", "session-bind"); + getMockServer()->sendError("session-bind"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); + CPPUNIT_ASSERT_EQUAL(ClientSession::ResourceBindError, *session->getError()); + } + + void testSessionStart() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + session->onSessionStarted.connect(boost::bind(&ClientSessionTest::setSessionStarted, this)); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithSession(); + getMockServer()->expectSessionStart("session-start"); + // FIXME: Check CPPUNIT_ASSERT_EQUAL(ClientSession::StartingSession, session->getState()); + getMockServer()->sendSessionStartResponse("session-start"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); + CPPUNIT_ASSERT(sessionStarted_); + } + + void testSessionStart_Error() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithSession(); + getMockServer()->expectSessionStart("session-start"); + getMockServer()->sendError("session-start"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStartError, *session->getError()); + } + + void testSessionStart_AfterResourceBind() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + session->onSessionStarted.connect(boost::bind(&ClientSessionTest::setSessionStarted, this)); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithResourceBindAndSession(); + getMockServer()->expectResourceBind("Bar", "session-bind"); + getMockServer()->sendResourceBindResponse("me@foo.com/Bar", "session-bind"); + getMockServer()->expectSessionStart("session-start"); + getMockServer()->sendSessionStartResponse("session-start"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); + CPPUNIT_ASSERT(sessionStarted_); + } + + void testWhitespacePing() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeatures(); + session->startSession(); + processEvents(); + CPPUNIT_ASSERT(session->getWhitespacePingLayer()); + } + + void testReceiveElementAfterSessionStarted() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeatures(); + session->startSession(); + processEvents(); + + getMockServer()->expectMessage(); + session->sendElement(std::make_shared<Message>())); + } + + void testSendElement() { + std::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + session->onElementReceived.connect(boost::bind(&ClientSessionTest::addReceivedElement, this, _1)); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeatures(); + getMockServer()->sendMessage(); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedElements_.size())); + CPPUNIT_ASSERT(std::dynamic_pointer_cast<Message>(receivedElements_[0])); + } #endif diff --git a/Swiften/Client/UnitTest/NickResolverTest.cpp b/Swiften/Client/UnitTest/NickResolverTest.cpp index a8b011c..2846173 100644 --- a/Swiften/Client/UnitTest/NickResolverTest.cpp +++ b/Swiften/Client/UnitTest/NickResolverTest.cpp @@ -1,159 +1,153 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -/* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2010-2016 Isode Limited. + * All right reserved. * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Client/NickResolver.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/MUC/MUCRegistry.h> +#include <Swiften/Queries/IQRouter.h> #include <Swiften/Roster/XMPPRosterImpl.h> #include <Swiften/VCards/VCardManager.h> #include <Swiften/VCards/VCardMemoryStorage.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Client/DummyStanzaChannel.h> -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Crypto/PlatformCryptoProvider.h> using namespace Swift; class NickResolverTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(NickResolverTest); - CPPUNIT_TEST(testNoMatch); - CPPUNIT_TEST(testZeroLengthMatch); - CPPUNIT_TEST(testMatch); - CPPUNIT_TEST(testOverwrittenMatch); - CPPUNIT_TEST(testRemovedMatch); - CPPUNIT_TEST(testMUCNick); - CPPUNIT_TEST(testMUCNoNick); - CPPUNIT_TEST(testRemovedMatch); - CPPUNIT_TEST(testOwnNickFullOnly); - CPPUNIT_TEST(testOwnNickGivenAndFull); - CPPUNIT_TEST(testOwnNickNickEtAl); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - ownJID_ = JID("kev@wonderland.lit"); - xmppRoster_ = new XMPPRosterImpl(); - stanzaChannel_ = new DummyStanzaChannel(); - iqRouter_ = new IQRouter(stanzaChannel_); - vCardStorage_ = new VCardMemoryStorage(crypto.get()); - vCardManager_ = new VCardManager(ownJID_, iqRouter_, vCardStorage_); - registry_ = new MUCRegistry(); - resolver_ = new NickResolver(ownJID_, xmppRoster_, vCardManager_, registry_); - } - - void tearDown() { - delete resolver_; - delete registry_; - delete vCardManager_; - delete iqRouter_; - delete stanzaChannel_; - delete vCardStorage_; - delete xmppRoster_; - } - - void testMUCNick() { - registry_->addMUC(JID("foo@bar")); - JID testJID("foo@bar/baz"); - - CPPUNIT_ASSERT_EQUAL(std::string("baz"), resolver_->jidToNick(testJID)); - } - - void testMUCNoNick() { - registry_->addMUC(JID("foo@bar")); - JID testJID("foo@bar"); - - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); - } - - - void testNoMatch() { - JID testJID("foo@bar/baz"); - - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); - } - - void testZeroLengthMatch() { - JID testJID("foo@bar/baz"); - xmppRoster_->addContact(testJID, "", groups_, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); - } - - void testMatch() { - JID testJID("foo@bar/baz"); - xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both); - - CPPUNIT_ASSERT_EQUAL(std::string("Test"), resolver_->jidToNick(testJID)); - } - - void testOverwrittenMatch() { - JID testJID("foo@bar/baz"); - xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both); - xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both); - - CPPUNIT_ASSERT_EQUAL(std::string("Test"), resolver_->jidToNick(testJID)); - } - - void testRemovedMatch() { - JID testJID("foo@bar/baz"); - xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both); - xmppRoster_->removeContact(testJID); - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); - } - - void testOwnNickFullOnly() { - populateOwnVCard("", "", "Kevin Smith"); - CPPUNIT_ASSERT_EQUAL(std::string("Kevin Smith"), resolver_->jidToNick(ownJID_)); - } - - void testOwnNickGivenAndFull() { - populateOwnVCard("", "Kevin", "Kevin Smith"); - CPPUNIT_ASSERT_EQUAL(std::string("Kevin"), resolver_->jidToNick(ownJID_)); - } - - void testOwnNickNickEtAl() { - populateOwnVCard("Kev", "Kevin", "Kevin Smith"); - CPPUNIT_ASSERT_EQUAL(std::string("Kev"), resolver_->jidToNick(ownJID_)); - } - - void populateOwnVCard(const std::string& nick, const std::string& given, const std::string& full) { - VCard::ref vcard(new VCard()); - if (!nick.empty()) { - vcard->setNickname(nick); - } - if (!given.empty()) { - vcard->setGivenName(given); - } - if (!full.empty()) { - vcard->setFullName(full); - } - vCardManager_->requestVCard(ownJID_); - IQ::ref result(IQ::createResult(JID(), stanzaChannel_->sentStanzas[0]->getID(), vcard)); - stanzaChannel_->onIQReceived(result); - } - - private: - std::vector<std::string> groups_; - XMPPRosterImpl* xmppRoster_; - VCardStorage* vCardStorage_; - IQRouter* iqRouter_; - DummyStanzaChannel* stanzaChannel_; - VCardManager* vCardManager_; - MUCRegistry* registry_; - NickResolver* resolver_; - JID ownJID_; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(NickResolverTest); + CPPUNIT_TEST(testNoMatch); + CPPUNIT_TEST(testZeroLengthMatch); + CPPUNIT_TEST(testMatch); + CPPUNIT_TEST(testOverwrittenMatch); + CPPUNIT_TEST(testRemovedMatch); + CPPUNIT_TEST(testMUCNick); + CPPUNIT_TEST(testMUCNoNick); + CPPUNIT_TEST(testRemovedMatch); + CPPUNIT_TEST(testOwnNickFullOnly); + CPPUNIT_TEST(testOwnNickGivenAndFull); + CPPUNIT_TEST(testOwnNickNickEtAl); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + ownJID_ = JID("kev@wonderland.lit"); + xmppRoster_ = new XMPPRosterImpl(); + stanzaChannel_ = new DummyStanzaChannel(); + iqRouter_ = new IQRouter(stanzaChannel_); + vCardStorage_ = new VCardMemoryStorage(crypto.get()); + vCardManager_ = new VCardManager(ownJID_, iqRouter_, vCardStorage_); + registry_ = new MUCRegistry(); + resolver_ = new NickResolver(ownJID_, xmppRoster_, vCardManager_, registry_); + } + + void tearDown() { + delete resolver_; + delete registry_; + delete vCardManager_; + delete iqRouter_; + delete stanzaChannel_; + delete vCardStorage_; + delete xmppRoster_; + } + + void testMUCNick() { + registry_->addMUC(JID("foo@bar")); + JID testJID("foo@bar/baz"); + + CPPUNIT_ASSERT_EQUAL(std::string("baz"), resolver_->jidToNick(testJID)); + } + + void testMUCNoNick() { + registry_->addMUC(JID("foo@bar")); + JID testJID("foo@bar"); + + CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); + } + + + void testNoMatch() { + JID testJID("foo@bar/baz"); + + CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); + } + + void testZeroLengthMatch() { + JID testJID("foo@bar/baz"); + xmppRoster_->addContact(testJID, "", groups_, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); + } + + void testMatch() { + JID testJID("foo@bar/baz"); + xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both); + + CPPUNIT_ASSERT_EQUAL(std::string("Test"), resolver_->jidToNick(testJID)); + } + + void testOverwrittenMatch() { + JID testJID("foo@bar/baz"); + xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both); + xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both); + + CPPUNIT_ASSERT_EQUAL(std::string("Test"), resolver_->jidToNick(testJID)); + } + + void testRemovedMatch() { + JID testJID("foo@bar/baz"); + xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both); + xmppRoster_->removeContact(testJID); + CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); + } + + void testOwnNickFullOnly() { + populateOwnVCard("", "", "Kevin Smith"); + CPPUNIT_ASSERT_EQUAL(std::string("Kevin Smith"), resolver_->jidToNick(ownJID_)); + } + + void testOwnNickGivenAndFull() { + populateOwnVCard("", "Kevin", "Kevin Smith"); + CPPUNIT_ASSERT_EQUAL(std::string("Kevin"), resolver_->jidToNick(ownJID_)); + } + + void testOwnNickNickEtAl() { + populateOwnVCard("Kev", "Kevin", "Kevin Smith"); + CPPUNIT_ASSERT_EQUAL(std::string("Kev"), resolver_->jidToNick(ownJID_)); + } + + void populateOwnVCard(const std::string& nick, const std::string& given, const std::string& full) { + VCard::ref vcard(new VCard()); + if (!nick.empty()) { + vcard->setNickname(nick); + } + if (!given.empty()) { + vcard->setGivenName(given); + } + if (!full.empty()) { + vcard->setFullName(full); + } + vCardManager_->requestVCard(ownJID_); + IQ::ref result(IQ::createResult(JID(), stanzaChannel_->sentStanzas[0]->getID(), vcard)); + stanzaChannel_->onIQReceived(result); + } + + private: + std::vector<std::string> groups_; + XMPPRosterImpl* xmppRoster_; + VCardStorage* vCardStorage_; + IQRouter* iqRouter_; + DummyStanzaChannel* stanzaChannel_; + VCardManager* vCardManager_; + MUCRegistry* registry_; + NickResolver* resolver_; + JID ownJID_; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(NickResolverTest); diff --git a/Swiften/Client/UnitTest/XMLBeautifierTest.cpp b/Swiften/Client/UnitTest/XMLBeautifierTest.cpp new file mode 100644 index 0000000..2a639ea --- /dev/null +++ b/Swiften/Client/UnitTest/XMLBeautifierTest.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include "gtest/gtest.h" +#include <Swiften/Client/XMLBeautifier.h> +#include <iostream> + +// Clang wrongly things that tests for 0 are using 0 as null. +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" + +using namespace Swift; + +namespace { + const static std::string FULL_FORMATTED_OUTPUT("<list>\n <el>aqq</el>\n <el>bzz</el>\n</list>"); +} + +TEST(XMLBeautifierTest, testBeautify) { + auto beautifier = std::make_unique<XMLBeautifier>(true, false); + + ASSERT_EQ(FULL_FORMATTED_OUTPUT, beautifier->beautify("<list><el>aqq</el><el>bzz</el></list>")); + ASSERT_TRUE(beautifier->wasReset()); + ASSERT_EQ(0, beautifier->getLevel()); + ASSERT_EQ(FULL_FORMATTED_OUTPUT, beautifier->beautify("<list><el>aqq</el><el>bzz</el></list>")); + ASSERT_TRUE(beautifier->wasReset()); + ASSERT_EQ(0, beautifier->getLevel()); +} + +TEST(XMLBeautifierTest, testBeautifyMultipleChunks) { + auto beautifier = std::make_unique<XMLBeautifier>(true, false); + + auto result = beautifier->beautify("<list><el>aqq</el>"); + ASSERT_TRUE(beautifier->wasReset()); + ASSERT_EQ(1, beautifier->getLevel()); + + result += beautifier->beautify("<el>bzz</el></list>"); + ASSERT_FALSE(beautifier->wasReset()); + ASSERT_EQ(0, beautifier->getLevel()); + + ASSERT_EQ(FULL_FORMATTED_OUTPUT, result); +} + +TEST(XMLBeautifierTest, testBeautifyMultipleChunksMiddleElement) { + auto beautifier = std::make_unique<XMLBeautifier>(true, false); + + auto result = beautifier->beautify("<l"); + ASSERT_TRUE(beautifier->wasReset()); + ASSERT_EQ(0, beautifier->getLevel()); + + result += beautifier->beautify("ist><el>aqq</el><el>bzz</el></list>"); + ASSERT_FALSE(beautifier->wasReset()); + ASSERT_EQ(0, beautifier->getLevel()); + + ASSERT_EQ(FULL_FORMATTED_OUTPUT, result); +} + +TEST(XMLBeautifierTest, testBeautifyInvalidMultipleChunks) { + auto beautifier = std::make_unique<XMLBeautifier>(true, false); + + ASSERT_EQ(std::string("<list>\n <el>aqq"), beautifier->beautify("<list><el>aqq<")); + ASSERT_TRUE(beautifier->wasReset()); + ASSERT_EQ(2, beautifier->getLevel()); + + ASSERT_EQ(FULL_FORMATTED_OUTPUT, beautifier->beautify("<list><el>aqq</el><el>bzz</el></list>")); + ASSERT_TRUE(beautifier->wasReset()); + ASSERT_EQ(0, beautifier->getLevel()); +} diff --git a/Swiften/Client/XMLBeautifier.cpp b/Swiften/Client/XMLBeautifier.cpp index b70fc48..97a228f 100644 --- a/Swiften/Client/XMLBeautifier.cpp +++ b/Swiften/Client/XMLBeautifier.cpp @@ -4,123 +4,147 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Client/XMLBeautifier.h> + #include <sstream> #include <stack> +#include <iostream> -#include <Swiften/Base/foreach.h> #include <Swiften/Base/Log.h> -#include <Swiften/Client/XMLBeautifier.h> #include <Swiften/Parser/PlatformXMLParserFactory.h> namespace Swift { -XMLBeautifier::XMLBeautifier(bool indention, bool coloring) : doIndention(indention), doColoring(coloring), intLevel(0), parser(NULL), lastWasStepDown(false) { - factory = new PlatformXMLParserFactory(); +XMLBeautifier::XMLBeautifier(bool indention, bool coloring) : doIndention_(indention), doColoring_(coloring), factory_(new PlatformXMLParserFactory()) { } -XMLBeautifier::~XMLBeautifier() { - delete factory; -} std::string XMLBeautifier::beautify(const std::string &text) { - parser = factory->createXMLParser(this); - intLevel = 0; - buffer.str(std::string()); - parser->parse(text); - delete parser; - return buffer.str(); + wasReset_ = false; + if (!parser_) { + reset(); + } + buffer_.str(std::string()); + if (!parser_->parse(text)) { + reset(); + parser_->parse(text); + } + return buffer_.str(); +} + +bool XMLBeautifier::wasReset() const { + return wasReset_; +} + +int XMLBeautifier::getLevel() const { + return intLevel_; } void XMLBeautifier::indent() { - for (int i = 0; i < intLevel; ++i) { - buffer << " "; - } + for (int i = 0; i < intLevel_; ++i) { + buffer_ << " "; + } +} + +void XMLBeautifier::reset() { + parser_ = factory_->createXMLParser(this); + intLevel_ = 0; + lastWasStepDown_ = false; + std::stack<std::string>().swap(parentNSs_); + buffer_.str(std::string()); + wasReset_ = true; } // all bold but reset -const char colorBlue[] = "\x1b[01;34m"; -const char colorCyan[] = "\x1b[01;36m"; -const char colorGreen[] = "\x1b[01;32m"; -const char colorMagenta[] = "\x1b[01;35m"; -const char colorRed[] = "\x1b[01;31m"; -const char colorReset[] = "\x1b[0m"; -const char colorYellow[] = "\x1b[01;33m"; +// static const char colorBlue[] = "\x1b[01;34m"; +static const char colorCyan[] = "\x1b[01;36m"; +static const char colorGreen[] = "\x1b[01;32m"; +// static const char colorMagenta[] = "\x1b[01;35m"; +static const char colorRed[] = "\x1b[01;31m"; +static const char colorReset[] = "\x1b[0m"; +static const char colorYellow[] = "\x1b[01;33m"; std::string XMLBeautifier::styleTag(const std::string& text) const { - std::string result; - result += colorYellow; - result += text; - result += colorReset; - return result; + std::string result; + result += colorYellow; + result += text; + result += colorReset; + return result; } std::string XMLBeautifier::styleNamespace(const std::string& text) const { - std::string result; - result += colorRed; - result += text; - result += colorReset; - return result; + std::string result; + result += colorRed; + result += text; + result += colorReset; + return result; } std::string XMLBeautifier::styleAttribute(const std::string& text) const { - std::string result; - result += colorGreen; - result += text; - result += colorReset; - return result; + std::string result; + result += colorGreen; + result += text; + result += colorReset; + return result; } std::string XMLBeautifier::styleValue(const std::string& text) const { - std::string result; - result += colorCyan; - result += text; - result += colorReset; - return result; + std::string result; + result += colorCyan; + result += text; + result += colorReset; + return result; } void XMLBeautifier::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (doIndention) { - if (intLevel) buffer << std::endl; - } - indent(); - buffer << "<" << (doColoring ? styleTag(element) : element); - if (!ns.empty() && (!parentNSs.empty() && parentNSs.top() != ns)) { - buffer << " "; - buffer << (doColoring ? styleAttribute("xmlns") : "xmlns"); - buffer << "="; - buffer << "\"" << (doColoring ? styleNamespace(ns) : ns) << "\""; - } - if (!attributes.getEntries().empty()) { - foreach(AttributeMap::Entry entry, attributes.getEntries()) { - buffer << " "; - buffer << (doColoring ? styleAttribute(entry.getAttribute().getName()) : entry.getAttribute().getName()); - buffer << "="; - buffer << "\"" << (doColoring ? styleValue(entry.getValue()) : entry.getValue()) << "\""; - } - } - buffer << ">"; - ++intLevel; - lastWasStepDown = false; - parentNSs.push(ns); + if (doIndention_) { + if (intLevel_) buffer_ << std::endl; + } + indent(); + buffer_ << "<" << (doColoring_ ? styleTag(element) : element); + if (!ns.empty() && (!parentNSs_.empty() && parentNSs_.top() != ns)) { + buffer_ << " "; + buffer_ << (doColoring_ ? styleAttribute("xmlns") : "xmlns"); + buffer_ << "="; + buffer_ << "\"" << (doColoring_ ? styleNamespace(ns) : ns) << "\""; + } + if (!attributes.getEntries().empty()) { + for (const auto& entry : attributes.getEntries()) { + buffer_ << " "; + buffer_ << (doColoring_ ? styleAttribute(entry.getAttribute().getName()) : entry.getAttribute().getName()); + buffer_ << "="; + buffer_ << "\"" << (doColoring_ ? styleValue(entry.getValue()) : entry.getValue()) << "\""; + } + } + buffer_ << ">"; + ++intLevel_; + lastWasStepDown_ = false; + parentNSs_.push(ns); } void XMLBeautifier::handleEndElement(const std::string& element, const std::string& /* ns */) { - --intLevel; - parentNSs.pop(); - if (/*hadCDATA.top() ||*/ lastWasStepDown) { - if (doIndention) { - buffer << std::endl; - } - indent(); - } - buffer << "</" << (doColoring ? styleTag(element) : element) << ">"; - lastWasStepDown = true; + --intLevel_; + parentNSs_.pop(); + if (/*hadCDATA.top() ||*/ lastWasStepDown_) { + if (doIndention_) { + buffer_ << std::endl; + } + indent(); + } + buffer_ << "</" << (doColoring_ ? styleTag(element) : element) << ">"; + lastWasStepDown_ = true; } void XMLBeautifier::handleCharacterData(const std::string& data) { - buffer << data; - lastWasStepDown = false; + buffer_ << data; + lastWasStepDown_ = false; } } diff --git a/Swiften/Client/XMLBeautifier.h b/Swiften/Client/XMLBeautifier.h index 44dfd20..7458211 100644 --- a/Swiften/Client/XMLBeautifier.h +++ b/Swiften/Client/XMLBeautifier.h @@ -4,50 +4,63 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <string> +#include <memory> +#include <sstream> #include <stack> +#include <string> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Parser/XMLParserFactory.h> -#include <Swiften/Parser/XMLParserClient.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Parser/XMLParser.h> +#include <Swiften/Parser/XMLParserClient.h> +#include <Swiften/Parser/XMLParserFactory.h> namespace Swift { -class XMLBeautifier : public XMLParserClient { +class SWIFTEN_API XMLBeautifier : public XMLParserClient { public: - XMLBeautifier(bool indention, bool coloring); - virtual ~XMLBeautifier(); - std::string beautify(const std::string&); + XMLBeautifier(bool indention, bool coloring); + + std::string beautify(const std::string&); + bool wasReset() const; + int getLevel() const; private: - void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); - void handleEndElement(const std::string& element, const std::string& ns); - void handleCharacterData(const std::string& data); + void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); + void handleEndElement(const std::string& element, const std::string& ns); + void handleCharacterData(const std::string& data); private: - void indent(); + void indent(); + void reset(); private: - std::string styleTag(const std::string& text) const; - std::string styleNamespace(const std::string& text) const; - std::string styleAttribute(const std::string& text) const; - std::string styleValue(const std::string& text) const; + std::string styleTag(const std::string& text) const; + std::string styleNamespace(const std::string& text) const; + std::string styleAttribute(const std::string& text) const; + std::string styleValue(const std::string& text) const; private: - bool doIndention; - bool doColoring; + const bool doIndention_; + const bool doColoring_; - int intLevel; - std::string inputBuffer; - std::stringstream buffer; - XMLParserFactory* factory; - XMLParser* parser; + std::unique_ptr<XMLParserFactory> factory_; + std::unique_ptr<XMLParser> parser_; - bool lastWasStepDown; - std::stack<std::string> parentNSs; + bool wasReset_ = true; + int intLevel_ = 0; + bool lastWasStepDown_ = false; + std::stringstream buffer_; + std::stack<std::string> parentNSs_; }; } diff --git a/Swiften/Component/Component.cpp b/Swiften/Component/Component.cpp index a53f514..e6835bd 100644 --- a/Swiften/Component/Component.cpp +++ b/Swiften/Component/Component.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Component/Component.h> @@ -11,17 +11,17 @@ namespace Swift { Component::Component(const JID& jid, const std::string& secret, NetworkFactories* networkFactories) : CoreComponent(jid, secret, networkFactories) { - softwareVersionResponder = new SoftwareVersionResponder(getIQRouter()); - softwareVersionResponder->start(); + softwareVersionResponder = new SoftwareVersionResponder(getIQRouter()); + softwareVersionResponder->start(); } Component::~Component() { - softwareVersionResponder->stop(); - delete softwareVersionResponder; + softwareVersionResponder->stop(); + delete softwareVersionResponder; } void Component::setSoftwareVersion(const std::string& name, const std::string& version) { - softwareVersionResponder->setVersion(name, version); + softwareVersionResponder->setVersion(name, version); } } diff --git a/Swiften/Component/Component.h b/Swiften/Component/Component.h index 3ead1a5..a7ef621 100644 --- a/Swiften/Component/Component.h +++ b/Swiften/Component/Component.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,27 +10,27 @@ #include <Swiften/Component/CoreComponent.h> namespace Swift { - class SoftwareVersionResponder; + class SoftwareVersionResponder; - /** - * Provides the core functionality for writing XMPP component software. - * - * Besides connecting to an XMPP server, this class also provides interfaces for - * performing most component tasks on the XMPP network. - */ - class SWIFTEN_API Component : public CoreComponent { - public: - Component(const JID& jid, const std::string& secret, NetworkFactories* networkFactories); - ~Component(); + /** + * Provides the core functionality for writing XMPP component software. + * + * Besides connecting to an XMPP server, this class also provides interfaces for + * performing most component tasks on the XMPP network. + */ + class SWIFTEN_API Component : public CoreComponent { + public: + Component(const JID& jid, const std::string& secret, NetworkFactories* networkFactories); + virtual ~Component(); - /** - * Sets the software version of the client. - * - * This will be used to respond to version queries from other entities. - */ - void setSoftwareVersion(const std::string& name, const std::string& version); + /** + * Sets the software version of the client. + * + * This will be used to respond to version queries from other entities. + */ + void setSoftwareVersion(const std::string& name, const std::string& version); - private: - SoftwareVersionResponder* softwareVersionResponder; - }; + private: + SoftwareVersionResponder* softwareVersionResponder; + }; } diff --git a/Swiften/Component/ComponentConnector.cpp b/Swiften/Component/ComponentConnector.cpp index 0dd8e82..7789c4c 100644 --- a/Swiften/Component/ComponentConnector.cpp +++ b/Swiften/Component/ComponentConnector.cpp @@ -1,107 +1,106 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Component/ComponentConnector.h> #include <boost/bind.hpp> -#include <iostream> #include <Swiften/Network/ConnectionFactory.h> -#include <Swiften/Network/DomainNameResolver.h> #include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/Network/DomainNameResolver.h> #include <Swiften/Network/TimerFactory.h> namespace Swift { -ComponentConnector::ComponentConnector(const std::string& hostname, int port, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) : hostname(hostname), port(port), resolver(resolver), connectionFactory(connectionFactory), timerFactory(timerFactory), timeoutMilliseconds(0) { +ComponentConnector::ComponentConnector(const std::string& hostname, unsigned short port, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) : hostname(hostname), port(port), resolver(resolver), connectionFactory(connectionFactory), timerFactory(timerFactory), timeoutMilliseconds(0) { } void ComponentConnector::setTimeoutMilliseconds(int milliseconds) { - timeoutMilliseconds = milliseconds; + timeoutMilliseconds = milliseconds; } void ComponentConnector::start() { - assert(!currentConnection); - assert(!timer); - assert(!addressQuery); - addressQuery = resolver->createAddressQuery(hostname); - addressQuery->onResult.connect(boost::bind(&ComponentConnector::handleAddressQueryResult, shared_from_this(), _1, _2)); - if (timeoutMilliseconds > 0) { - timer = timerFactory->createTimer(timeoutMilliseconds); - timer->onTick.connect(boost::bind(&ComponentConnector::handleTimeout, shared_from_this())); - timer->start(); - } - addressQuery->run(); + assert(!currentConnection); + assert(!timer); + assert(!addressQuery); + addressQuery = resolver->createAddressQuery(hostname); + addressQuery->onResult.connect(boost::bind(&ComponentConnector::handleAddressQueryResult, shared_from_this(), _1, _2)); + if (timeoutMilliseconds > 0) { + timer = timerFactory->createTimer(timeoutMilliseconds); + timer->onTick.connect(boost::bind(&ComponentConnector::handleTimeout, shared_from_this())); + timer->start(); + } + addressQuery->run(); } void ComponentConnector::stop() { - finish(boost::shared_ptr<Connection>()); + finish(std::shared_ptr<Connection>()); } void ComponentConnector::handleAddressQueryResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error) { - addressQuery.reset(); - if (error || addresses.empty()) { - finish(boost::shared_ptr<Connection>()); - } - else { - addressQueryResults = std::deque<HostAddress>(addresses.begin(), addresses.end()); - tryNextAddress(); - } + addressQuery.reset(); + if (error || addresses.empty()) { + finish(std::shared_ptr<Connection>()); + } + else { + addressQueryResults = std::deque<HostAddress>(addresses.begin(), addresses.end()); + tryNextAddress(); + } } void ComponentConnector::tryNextAddress() { - assert(!addressQueryResults.empty()); - HostAddress address = addressQueryResults.front(); - addressQueryResults.pop_front(); - tryConnect(HostAddressPort(address, port)); + assert(!addressQueryResults.empty()); + HostAddress address = addressQueryResults.front(); + addressQueryResults.pop_front(); + tryConnect(HostAddressPort(address, port)); } void ComponentConnector::tryConnect(const HostAddressPort& target) { - assert(!currentConnection); - currentConnection = connectionFactory->createConnection(); - currentConnection->onConnectFinished.connect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); - currentConnection->connect(target); + assert(!currentConnection); + currentConnection = connectionFactory->createConnection(); + currentConnection->onConnectFinished.connect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); + currentConnection->connect(target); } void ComponentConnector::handleConnectionConnectFinished(bool error) { - currentConnection->onConnectFinished.disconnect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); - if (error) { - currentConnection.reset(); - if (!addressQueryResults.empty()) { - tryNextAddress(); - } - else { - finish(boost::shared_ptr<Connection>()); - } - } - else { - finish(currentConnection); - } + currentConnection->onConnectFinished.disconnect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); + if (error) { + currentConnection.reset(); + if (!addressQueryResults.empty()) { + tryNextAddress(); + } + else { + finish(std::shared_ptr<Connection>()); + } + } + else { + finish(currentConnection); + } } -void ComponentConnector::finish(boost::shared_ptr<Connection> connection) { - if (timer) { - timer->stop(); - timer->onTick.disconnect(boost::bind(&ComponentConnector::handleTimeout, shared_from_this())); - timer.reset(); - } - if (addressQuery) { - addressQuery->onResult.disconnect(boost::bind(&ComponentConnector::handleAddressQueryResult, shared_from_this(), _1, _2)); - addressQuery.reset(); - } - if (currentConnection) { - currentConnection->onConnectFinished.disconnect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); - currentConnection.reset(); - } - onConnectFinished(connection); +void ComponentConnector::finish(std::shared_ptr<Connection> connection) { + if (timer) { + timer->stop(); + timer->onTick.disconnect(boost::bind(&ComponentConnector::handleTimeout, shared_from_this())); + timer.reset(); + } + if (addressQuery) { + addressQuery->onResult.disconnect(boost::bind(&ComponentConnector::handleAddressQueryResult, shared_from_this(), _1, _2)); + addressQuery.reset(); + } + if (currentConnection) { + currentConnection->onConnectFinished.disconnect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); + currentConnection.reset(); + } + onConnectFinished(connection); } void ComponentConnector::handleTimeout() { - finish(boost::shared_ptr<Connection>()); + finish(std::shared_ptr<Connection>()); } } diff --git a/Swiften/Component/ComponentConnector.h b/Swiften/Component/ComponentConnector.h index 0e35ab2..cfd49fe 100644 --- a/Swiften/Component/ComponentConnector.h +++ b/Swiften/Component/ComponentConnector.h @@ -1,65 +1,66 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <deque> -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> #include <Swiften/Network/Connection.h> -#include <Swiften/Network/Timer.h> -#include <Swiften/Network/HostAddressPort.h> -#include <string> #include <Swiften/Network/DomainNameResolveError.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Network/Timer.h> namespace Swift { - class DomainNameAddressQuery; - class DomainNameResolver; - class ConnectionFactory; - class TimerFactory; + class DomainNameAddressQuery; + class DomainNameResolver; + class ConnectionFactory; + class TimerFactory; - class SWIFTEN_API ComponentConnector : public boost::bsignals::trackable, public boost::enable_shared_from_this<ComponentConnector> { - public: - typedef boost::shared_ptr<ComponentConnector> ref; + class SWIFTEN_API ComponentConnector : public boost::signals2::trackable, public std::enable_shared_from_this<ComponentConnector> { + public: + typedef std::shared_ptr<ComponentConnector> ref; - static ComponentConnector::ref create(const std::string& hostname, int port, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) { - return ref(new ComponentConnector(hostname, port, resolver, connectionFactory, timerFactory)); - } + static ComponentConnector::ref create(const std::string& hostname, unsigned short port, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) { + return ref(new ComponentConnector(hostname, port, resolver, connectionFactory, timerFactory)); + } - void setTimeoutMilliseconds(int milliseconds); + void setTimeoutMilliseconds(int milliseconds); - void start(); - void stop(); + void start(); + void stop(); - boost::signal<void (boost::shared_ptr<Connection>)> onConnectFinished; + boost::signals2::signal<void (std::shared_ptr<Connection>)> onConnectFinished; - private: - ComponentConnector(const std::string& hostname, int port, DomainNameResolver*, ConnectionFactory*, TimerFactory*); + private: + ComponentConnector(const std::string& hostname, unsigned short port, DomainNameResolver*, ConnectionFactory*, TimerFactory*); - void handleAddressQueryResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error); - void tryNextAddress(); - void tryConnect(const HostAddressPort& target); + void handleAddressQueryResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error); + void tryNextAddress(); + void tryConnect(const HostAddressPort& target); - void handleConnectionConnectFinished(bool error); - void finish(boost::shared_ptr<Connection>); - void handleTimeout(); + void handleConnectionConnectFinished(bool error); + void finish(std::shared_ptr<Connection>); + void handleTimeout(); - private: - std::string hostname; - int port; - DomainNameResolver* resolver; - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; - int timeoutMilliseconds; - boost::shared_ptr<Timer> timer; - boost::shared_ptr<DomainNameAddressQuery> addressQuery; - std::deque<HostAddress> addressQueryResults; - boost::shared_ptr<Connection> currentConnection; - }; + private: + std::string hostname; + unsigned short port; + DomainNameResolver* resolver; + ConnectionFactory* connectionFactory; + TimerFactory* timerFactory; + int timeoutMilliseconds; + std::shared_ptr<Timer> timer; + std::shared_ptr<DomainNameAddressQuery> addressQuery; + std::deque<HostAddress> addressQueryResults; + std::shared_ptr<Connection> currentConnection; + }; } diff --git a/Swiften/Component/ComponentError.h b/Swiften/Component/ComponentError.h index 9c54b53..dca8c99 100644 --- a/Swiften/Component/ComponentError.h +++ b/Swiften/Component/ComponentError.h @@ -1,29 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> + namespace Swift { - class ComponentError { - public: - enum Type { - UnknownError, - ConnectionError, - ConnectionReadError, - ConnectionWriteError, - XMLError, - AuthenticationFailedError, - UnexpectedElementError - }; + class SWIFTEN_API ComponentError { + public: + enum Type { + UnknownError, + ConnectionError, + ConnectionReadError, + ConnectionWriteError, + XMLError, + AuthenticationFailedError, + UnexpectedElementError + }; - ComponentError(Type type = UnknownError) : type_(type) {} + ComponentError(Type type = UnknownError) : type_(type) {} - Type getType() const { return type_; } + Type getType() const { return type_; } - private: - Type type_; - }; + private: + Type type_; + }; } diff --git a/Swiften/Component/ComponentHandshakeGenerator.cpp b/Swiften/Component/ComponentHandshakeGenerator.cpp index 495d530..647b3da 100644 --- a/Swiften/Component/ComponentHandshakeGenerator.cpp +++ b/Swiften/Component/ComponentHandshakeGenerator.cpp @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Component/ComponentHandshakeGenerator.h> -#include <Swiften/StringCodecs/Hexify.h> + #include <Swiften/Base/String.h> #include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/StringCodecs/Hexify.h> namespace Swift { std::string ComponentHandshakeGenerator::getHandshake(const std::string& streamID, const std::string& secret, CryptoProvider* crypto) { - std::string concatenatedString = streamID + secret; - String::replaceAll(concatenatedString, '&', "&"); - String::replaceAll(concatenatedString, '<', "<"); - String::replaceAll(concatenatedString, '>', ">"); - String::replaceAll(concatenatedString, '\'', "'"); - String::replaceAll(concatenatedString, '"', """); - return Hexify::hexify(crypto->getSHA1Hash(createByteArray(concatenatedString))); + std::string concatenatedString = streamID + secret; + String::replaceAll(concatenatedString, '&', "&"); + String::replaceAll(concatenatedString, '<', "<"); + String::replaceAll(concatenatedString, '>', ">"); + String::replaceAll(concatenatedString, '\'', "'"); + String::replaceAll(concatenatedString, '"', """); + return Hexify::hexify(crypto->getSHA1Hash(createByteArray(concatenatedString))); } } diff --git a/Swiften/Component/ComponentHandshakeGenerator.h b/Swiften/Component/ComponentHandshakeGenerator.h index e0e3ef8..0aafb83 100644 --- a/Swiften/Component/ComponentHandshakeGenerator.h +++ b/Swiften/Component/ComponentHandshakeGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,11 +11,11 @@ #include <Swiften/Base/API.h> namespace Swift { - class CryptoProvider; + class CryptoProvider; - class SWIFTEN_API ComponentHandshakeGenerator { - public: - static std::string getHandshake(const std::string& streamID, const std::string& secret, CryptoProvider* crypto); - }; + class SWIFTEN_API ComponentHandshakeGenerator { + public: + static std::string getHandshake(const std::string& streamID, const std::string& secret, CryptoProvider* crypto); + }; } diff --git a/Swiften/Component/ComponentSession.cpp b/Swiften/Component/ComponentSession.cpp index 7925b23..0805ac1 100644 --- a/Swiften/Component/ComponentSession.cpp +++ b/Swiften/Component/ComponentSession.cpp @@ -1,122 +1,123 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Component/ComponentSession.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Component/ComponentHandshakeGenerator.h> +#include <Swiften/Elements/ComponentHandshake.h> #include <Swiften/Elements/ProtocolHeader.h> #include <Swiften/Elements/StreamFeatures.h> -#include <Swiften/Elements/ComponentHandshake.h> #include <Swiften/Session/SessionStream.h> -#include <Swiften/Component/ComponentHandshakeGenerator.h> namespace Swift { -ComponentSession::ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream> stream, CryptoProvider* crypto) : jid(jid), secret(secret), stream(stream), crypto(crypto), state(Initial) { +ComponentSession::ComponentSession(const JID& jid, const std::string& secret, std::shared_ptr<SessionStream> stream, CryptoProvider* crypto) : jid(jid), secret(secret), stream(stream), crypto(crypto), state(Initial) { } ComponentSession::~ComponentSession() { } void ComponentSession::start() { - stream->onStreamStartReceived.connect(boost::bind(&ComponentSession::handleStreamStart, shared_from_this(), _1)); - stream->onElementReceived.connect(boost::bind(&ComponentSession::handleElement, shared_from_this(), _1)); - stream->onClosed.connect(boost::bind(&ComponentSession::handleStreamClosed, shared_from_this(), _1)); + stream->onStreamStartReceived.connect(boost::bind(&ComponentSession::handleStreamStart, shared_from_this(), _1)); + stream->onElementReceived.connect(boost::bind(&ComponentSession::handleElement, shared_from_this(), _1)); + stream->onClosed.connect(boost::bind(&ComponentSession::handleStreamClosed, shared_from_this(), _1)); - assert(state == Initial); - state = WaitingForStreamStart; - sendStreamHeader(); + assert(state == Initial); + state = WaitingForStreamStart; + sendStreamHeader(); } void ComponentSession::sendStreamHeader() { - ProtocolHeader header; - header.setTo(jid); - stream->writeHeader(header); + ProtocolHeader header; + header.setTo(jid); + stream->writeHeader(header); } -void ComponentSession::sendStanza(boost::shared_ptr<Stanza> stanza) { - stream->writeElement(stanza); +void ComponentSession::sendStanza(std::shared_ptr<Stanza> stanza) { + stream->writeElement(stanza); } void ComponentSession::handleStreamStart(const ProtocolHeader& header) { - checkState(WaitingForStreamStart); - state = Authenticating; - stream->writeElement(ComponentHandshake::ref(new ComponentHandshake(ComponentHandshakeGenerator::getHandshake(header.getID(), secret, crypto)))); + checkState(WaitingForStreamStart); + state = Authenticating; + stream->writeElement(ComponentHandshake::ref(new ComponentHandshake(ComponentHandshakeGenerator::getHandshake(header.getID(), secret, crypto)))); } -void ComponentSession::handleElement(boost::shared_ptr<Element> element) { - if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) { - if (getState() == Initialized) { - onStanzaReceived(stanza); - } - else { - finishSession(Error::UnexpectedElementError); - } - } - else if (boost::dynamic_pointer_cast<ComponentHandshake>(element)) { - if (!checkState(Authenticating)) { - return; - } - stream->setWhitespacePingEnabled(true); - state = Initialized; - onInitialized(); - } - else if (getState() == Authenticating) { - if (boost::dynamic_pointer_cast<StreamFeatures>(element)) { - // M-Link sends stream features, so swallow that. - } - else { - // FIXME: We should actually check the element received - finishSession(Error::AuthenticationFailedError); - } - } - else { - finishSession(Error::UnexpectedElementError); - } +void ComponentSession::handleElement(std::shared_ptr<ToplevelElement> element) { + if (std::shared_ptr<Stanza> stanza = std::dynamic_pointer_cast<Stanza>(element)) { + if (getState() == Initialized) { + onStanzaReceived(stanza); + } + else { + finishSession(Error::UnexpectedElementError); + } + } + else if (std::dynamic_pointer_cast<ComponentHandshake>(element)) { + if (!checkState(Authenticating)) { + return; + } + stream->setWhitespacePingEnabled(true); + state = Initialized; + onInitialized(); + } + else if (getState() == Authenticating) { + if (std::dynamic_pointer_cast<StreamFeatures>(element)) { + // M-Link sends stream features, so swallow that. + } + else { + // FIXME: We should actually check the element received + finishSession(Error::AuthenticationFailedError); + } + } + else { + finishSession(Error::UnexpectedElementError); + } } bool ComponentSession::checkState(State state) { - if (this->state != state) { - finishSession(Error::UnexpectedElementError); - return false; - } - return true; + if (this->state != state) { + finishSession(Error::UnexpectedElementError); + return false; + } + return true; } -void ComponentSession::handleStreamClosed(boost::shared_ptr<Swift::Error> streamError) { - State oldState = state; - state = Finished; - stream->setWhitespacePingEnabled(false); - stream->onStreamStartReceived.disconnect(boost::bind(&ComponentSession::handleStreamStart, shared_from_this(), _1)); - stream->onElementReceived.disconnect(boost::bind(&ComponentSession::handleElement, shared_from_this(), _1)); - stream->onClosed.disconnect(boost::bind(&ComponentSession::handleStreamClosed, shared_from_this(), _1)); - if (oldState == Finishing) { - onFinished(error); - } - else { - onFinished(streamError); - } +void ComponentSession::handleStreamClosed(std::shared_ptr<Swift::Error> streamError) { + State oldState = state; + state = Finished; + stream->setWhitespacePingEnabled(false); + stream->onStreamStartReceived.disconnect(boost::bind(&ComponentSession::handleStreamStart, shared_from_this(), _1)); + stream->onElementReceived.disconnect(boost::bind(&ComponentSession::handleElement, shared_from_this(), _1)); + stream->onClosed.disconnect(boost::bind(&ComponentSession::handleStreamClosed, shared_from_this(), _1)); + if (oldState == Finishing) { + onFinished(error); + } + else { + onFinished(streamError); + } } void ComponentSession::finish() { - finishSession(boost::shared_ptr<Error>()); + finishSession(std::shared_ptr<Error>()); } void ComponentSession::finishSession(Error::Type error) { - finishSession(boost::make_shared<Swift::ComponentSession::Error>(error)); + finishSession(std::make_shared<Swift::ComponentSession::Error>(error)); } -void ComponentSession::finishSession(boost::shared_ptr<Swift::Error> finishError) { - state = Finishing; - error = finishError; - assert(stream->isOpen()); - stream->writeFooter(); - stream->close(); +void ComponentSession::finishSession(std::shared_ptr<Swift::Error> finishError) { + state = Finishing; + error = finishError; + assert(stream->isOpen()); + stream->writeFooter(); + stream->close(); } } diff --git a/Swiften/Component/ComponentSession.h b/Swiften/Component/ComponentSession.h index 3103335..dcb9b4a 100644 --- a/Swiften/Component/ComponentSession.h +++ b/Swiften/Component/ComponentSession.h @@ -1,86 +1,85 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <memory> +#include <string> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Base/Error.h> -#include <string> -#include <Swiften/Elements/Element.h> #include <Swiften/Elements/Stanza.h> +#include <Swiften/Elements/ToplevelElement.h> +#include <Swiften/JID/JID.h> #include <Swiften/Session/SessionStream.h> namespace Swift { - class ComponentAuthenticator; - class CryptoProvider; - - class SWIFTEN_API ComponentSession : public boost::enable_shared_from_this<ComponentSession> { - public: - enum State { - Initial, - WaitingForStreamStart, - Authenticating, - Initialized, - Finishing, - Finished - }; - - struct Error : public Swift::Error { - enum Type { - AuthenticationFailedError, - UnexpectedElementError - } type; - Error(Type type) : type(type) {} - }; - - ~ComponentSession(); - - static boost::shared_ptr<ComponentSession> create(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream> stream, CryptoProvider* crypto) { - return boost::shared_ptr<ComponentSession>(new ComponentSession(jid, secret, stream, crypto)); - } - - State getState() const { - return state; - } - - void start(); - void finish(); - - void sendStanza(boost::shared_ptr<Stanza>); - - public: - boost::signal<void ()> onInitialized; - boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished; - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; - - private: - ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream>, CryptoProvider*); - - void finishSession(Error::Type error); - void finishSession(boost::shared_ptr<Swift::Error> error); - - void sendStreamHeader(); - - void handleElement(boost::shared_ptr<Element>); - void handleStreamStart(const ProtocolHeader&); - void handleStreamClosed(boost::shared_ptr<Swift::Error>); - - bool checkState(State); - - private: - JID jid; - std::string secret; - boost::shared_ptr<SessionStream> stream; - CryptoProvider* crypto; - boost::shared_ptr<Swift::Error> error; - State state; - }; + class CryptoProvider; + + class SWIFTEN_API ComponentSession : public std::enable_shared_from_this<ComponentSession> { + public: + enum State { + Initial, + WaitingForStreamStart, + Authenticating, + Initialized, + Finishing, + Finished + }; + + struct Error : public Swift::Error { + enum Type { + AuthenticationFailedError, + UnexpectedElementError + } type; + Error(Type type) : type(type) {} + }; + + ~ComponentSession(); + + static std::shared_ptr<ComponentSession> create(const JID& jid, const std::string& secret, std::shared_ptr<SessionStream> stream, CryptoProvider* crypto) { + return std::shared_ptr<ComponentSession>(new ComponentSession(jid, secret, stream, crypto)); + } + + State getState() const { + return state; + } + + void start(); + void finish(); + + void sendStanza(std::shared_ptr<Stanza>); + + public: + boost::signals2::signal<void ()> onInitialized; + boost::signals2::signal<void (std::shared_ptr<Swift::Error>)> onFinished; + boost::signals2::signal<void (std::shared_ptr<Stanza>)> onStanzaReceived; + + private: + ComponentSession(const JID& jid, const std::string& secret, std::shared_ptr<SessionStream>, CryptoProvider*); + + void finishSession(Error::Type error); + void finishSession(std::shared_ptr<Swift::Error> error); + + void sendStreamHeader(); + + void handleElement(std::shared_ptr<ToplevelElement>); + void handleStreamStart(const ProtocolHeader&); + void handleStreamClosed(std::shared_ptr<Swift::Error>); + + bool checkState(State); + + private: + JID jid; + std::string secret; + std::shared_ptr<SessionStream> stream; + CryptoProvider* crypto; + std::shared_ptr<Swift::Error> error; + State state; + }; } diff --git a/Swiften/Component/ComponentSessionStanzaChannel.cpp b/Swiften/Component/ComponentSessionStanzaChannel.cpp index 3e96dce..deac8b2 100644 --- a/Swiften/Component/ComponentSessionStanzaChannel.cpp +++ b/Swiften/Component/ComponentSessionStanzaChannel.cpp @@ -1,79 +1,89 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Component/ComponentSessionStanzaChannel.h> #include <boost/bind.hpp> -#include <iostream> + +#include <Swiften/Base/Log.h> namespace Swift { -void ComponentSessionStanzaChannel::setSession(boost::shared_ptr<ComponentSession> session) { - assert(!this->session); - this->session = session; - session->onInitialized.connect(boost::bind(&ComponentSessionStanzaChannel::handleSessionInitialized, this)); - session->onFinished.connect(boost::bind(&ComponentSessionStanzaChannel::handleSessionFinished, this, _1)); - session->onStanzaReceived.connect(boost::bind(&ComponentSessionStanzaChannel::handleStanza, this, _1)); +ComponentSessionStanzaChannel::~ComponentSessionStanzaChannel() { + if (session) { + session->onInitialized.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleSessionInitialized, this)); + session->onFinished.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleStanza, this, _1)); + session.reset(); + } +} + +void ComponentSessionStanzaChannel::setSession(std::shared_ptr<ComponentSession> session) { + assert(!this->session); + this->session = session; + session->onInitialized.connect(boost::bind(&ComponentSessionStanzaChannel::handleSessionInitialized, this)); + session->onFinished.connect(boost::bind(&ComponentSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.connect(boost::bind(&ComponentSessionStanzaChannel::handleStanza, this, _1)); } -void ComponentSessionStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) { - send(iq); +void ComponentSessionStanzaChannel::sendIQ(std::shared_ptr<IQ> iq) { + send(iq); } -void ComponentSessionStanzaChannel::sendMessage(boost::shared_ptr<Message> message) { - send(message); +void ComponentSessionStanzaChannel::sendMessage(std::shared_ptr<Message> message) { + send(message); } -void ComponentSessionStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) { - send(presence); +void ComponentSessionStanzaChannel::sendPresence(std::shared_ptr<Presence> presence) { + send(presence); } std::string ComponentSessionStanzaChannel::getNewIQID() { - return idGenerator.generateID(); + return idGenerator.generateID(); } -void ComponentSessionStanzaChannel::send(boost::shared_ptr<Stanza> stanza) { - if (!isAvailable()) { - std::cerr << "Warning: Component: Trying to send a stanza while disconnected." << std::endl; - return; - } - session->sendStanza(stanza); +void ComponentSessionStanzaChannel::send(std::shared_ptr<Stanza> stanza) { + if (!isAvailable()) { + SWIFT_LOG(warning) << "Component: Trying to send a stanza while disconnected."; + return; + } + session->sendStanza(stanza); } -void ComponentSessionStanzaChannel::handleSessionFinished(boost::shared_ptr<Error>) { - session->onFinished.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleSessionFinished, this, _1)); - session->onStanzaReceived.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleStanza, this, _1)); - session->onInitialized.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleSessionInitialized, this)); - session.reset(); +void ComponentSessionStanzaChannel::handleSessionFinished(std::shared_ptr<Error>) { + session->onFinished.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleStanza, this, _1)); + session->onInitialized.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleSessionInitialized, this)); + session.reset(); - onAvailableChanged(false); + onAvailableChanged(false); } -void ComponentSessionStanzaChannel::handleStanza(boost::shared_ptr<Stanza> stanza) { - boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(stanza); - if (message) { - onMessageReceived(message); - return; - } - - boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza); - if (presence) { - onPresenceReceived(presence); - return; - } - - boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza); - if (iq) { - onIQReceived(iq); - return; - } +void ComponentSessionStanzaChannel::handleStanza(std::shared_ptr<Stanza> stanza) { + std::shared_ptr<Message> message = std::dynamic_pointer_cast<Message>(stanza); + if (message) { + onMessageReceived(message); + return; + } + + std::shared_ptr<Presence> presence = std::dynamic_pointer_cast<Presence>(stanza); + if (presence) { + onPresenceReceived(presence); + return; + } + + std::shared_ptr<IQ> iq = std::dynamic_pointer_cast<IQ>(stanza); + if (iq) { + onIQReceived(iq); + return; + } } void ComponentSessionStanzaChannel::handleSessionInitialized() { - onAvailableChanged(true); + onAvailableChanged(true); } } diff --git a/Swiften/Component/ComponentSessionStanzaChannel.h b/Swiften/Component/ComponentSessionStanzaChannel.h index 4e133b8..d8a4501 100644 --- a/Swiften/Component/ComponentSessionStanzaChannel.h +++ b/Swiften/Component/ComponentSessionStanzaChannel.h @@ -1,55 +1,58 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Base/IDGenerator.h> -#include <Swiften/Component/ComponentSession.h> #include <Swiften/Client/StanzaChannel.h> -#include <Swiften/Elements/Message.h> +#include <Swiften/Component/ComponentSession.h> #include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> #include <Swiften/Elements/Presence.h> namespace Swift { - /** - * StanzaChannel implementation around a ComponentSession. - */ - class ComponentSessionStanzaChannel : public StanzaChannel { - public: - void setSession(boost::shared_ptr<ComponentSession> session); - - void sendIQ(boost::shared_ptr<IQ> iq); - void sendMessage(boost::shared_ptr<Message> message); - void sendPresence(boost::shared_ptr<Presence> presence); - - bool getStreamManagementEnabled() const { - return false; - } - - std::vector<Certificate::ref> getPeerCertificateChain() const { - // TODO: actually implement this method - return std::vector<Certificate::ref>(); - } - - bool isAvailable() const { - return session && session->getState() == ComponentSession::Initialized; - } - - private: - std::string getNewIQID(); - void send(boost::shared_ptr<Stanza> stanza); - void handleSessionFinished(boost::shared_ptr<Error> error); - void handleStanza(boost::shared_ptr<Stanza> stanza); - void handleSessionInitialized(); - - private: - IDGenerator idGenerator; - boost::shared_ptr<ComponentSession> session; - }; + /** + * StanzaChannel implementation around a ComponentSession. + */ + class SWIFTEN_API ComponentSessionStanzaChannel : public StanzaChannel { + public: + virtual ~ComponentSessionStanzaChannel(); + + void setSession(std::shared_ptr<ComponentSession> session); + + void sendIQ(std::shared_ptr<IQ> iq); + void sendMessage(std::shared_ptr<Message> message); + void sendPresence(std::shared_ptr<Presence> presence); + + bool getStreamManagementEnabled() const { + return false; + } + + std::vector<Certificate::ref> getPeerCertificateChain() const { + // TODO: actually implement this method + return std::vector<Certificate::ref>(); + } + + bool isAvailable() const { + return session && session->getState() == ComponentSession::Initialized; + } + + private: + std::string getNewIQID(); + void send(std::shared_ptr<Stanza> stanza); + void handleSessionFinished(std::shared_ptr<Error> error); + void handleStanza(std::shared_ptr<Stanza> stanza); + void handleSessionInitialized(); + + private: + IDGenerator idGenerator; + std::shared_ptr<ComponentSession> session; + }; } diff --git a/Swiften/Component/ComponentXMLTracer.cpp b/Swiften/Component/ComponentXMLTracer.cpp index d77eef7..94d4ec2 100644 --- a/Swiften/Component/ComponentXMLTracer.cpp +++ b/Swiften/Component/ComponentXMLTracer.cpp @@ -1,31 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Component/ComponentXMLTracer.h> #include <iostream> + #include <boost/bind.hpp> namespace Swift { ComponentXMLTracer::ComponentXMLTracer(CoreComponent* client) { - client->onDataRead.connect(boost::bind(&ComponentXMLTracer::printData, '<', _1)); - client->onDataWritten.connect(boost::bind(&ComponentXMLTracer::printData, '>', _1)); + client->onDataRead.connect(boost::bind(&ComponentXMLTracer::printData, '<', _1)); + client->onDataWritten.connect(boost::bind(&ComponentXMLTracer::printData, '>', _1)); } void ComponentXMLTracer::printData(char direction, const SafeByteArray& data) { - printLine(direction); - std::cerr << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl; + printLine(direction); + std::cerr << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl; } void ComponentXMLTracer::printLine(char c) { - for (unsigned int i = 0; i < 80; ++i) { - std::cerr << c; - } - std::cerr << std::endl; + for (unsigned int i = 0; i < 80; ++i) { + std::cerr << c; + } + std::cerr << std::endl; } } diff --git a/Swiften/Component/ComponentXMLTracer.h b/Swiften/Component/ComponentXMLTracer.h index 57b9dcf..d34930b 100644 --- a/Swiften/Component/ComponentXMLTracer.h +++ b/Swiften/Component/ComponentXMLTracer.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,12 +10,12 @@ #include <Swiften/Component/Component.h> namespace Swift { - class SWIFTEN_API ComponentXMLTracer { - public: - ComponentXMLTracer(CoreComponent* component); + class SWIFTEN_API ComponentXMLTracer { + public: + ComponentXMLTracer(CoreComponent* component); - private: - static void printData(char direction, const SafeByteArray& data); - static void printLine(char c); - }; + private: + static void printData(char direction, const SafeByteArray& data); + static void printLine(char c); + }; } diff --git a/Swiften/Component/CoreComponent.cpp b/Swiften/Component/CoreComponent.cpp index d2cc7aa..ef7d3a4 100644 --- a/Swiften/Component/CoreComponent.cpp +++ b/Swiften/Component/CoreComponent.cpp @@ -1,164 +1,177 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Component/CoreComponent.h> #include <boost/bind.hpp> -#include <iostream> +#include <Swiften/Base/IDGenerator.h> +#include <Swiften/Base/Log.h> #include <Swiften/Component/ComponentSession.h> +#include <Swiften/Component/ComponentSessionStanzaChannel.h> #include <Swiften/Network/Connector.h> #include <Swiften/Network/NetworkFactories.h> -#include <Swiften/TLS/PKCS12Certificate.h> -#include <Swiften/Session/BasicSessionStream.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Base/IDGenerator.h> -#include <Swiften/Component/ComponentSessionStanzaChannel.h> +#include <Swiften/Session/BasicSessionStream.h> +#include <Swiften/TLS/PKCS12Certificate.h> +#include <Swiften/TLS/TLSOptions.h> namespace Swift { CoreComponent::CoreComponent(const JID& jid, const std::string& secret, NetworkFactories* networkFactories) : networkFactories(networkFactories), jid_(jid), secret_(secret), disconnectRequested_(false) { - stanzaChannel_ = new ComponentSessionStanzaChannel(); - stanzaChannel_->onMessageReceived.connect(boost::ref(onMessageReceived)); - stanzaChannel_->onPresenceReceived.connect(boost::ref(onPresenceReceived)); - stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreComponent::handleStanzaChannelAvailableChanged, this, _1)); + stanzaChannel_ = new ComponentSessionStanzaChannel(); + stanzaChannel_->onMessageReceived.connect(boost::ref(onMessageReceived)); + stanzaChannel_->onPresenceReceived.connect(boost::ref(onPresenceReceived)); + stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreComponent::handleStanzaChannelAvailableChanged, this, _1)); - iqRouter_ = new IQRouter(stanzaChannel_); - iqRouter_->setFrom(jid); + iqRouter_ = new IQRouter(stanzaChannel_); + iqRouter_->setFrom(jid); } CoreComponent::~CoreComponent() { - if (session_ || connection_) { - std::cerr << "Warning: Component not disconnected properly" << std::endl; - } - delete iqRouter_; - - stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreComponent::handleStanzaChannelAvailableChanged, this, _1)); - stanzaChannel_->onMessageReceived.disconnect(boost::ref(onMessageReceived)); - stanzaChannel_->onPresenceReceived.disconnect(boost::ref(onPresenceReceived)); - delete stanzaChannel_; + if (session_ || connection_) { + SWIFT_LOG(warning) << "Component not disconnected properly"; + } + delete iqRouter_; + + stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreComponent::handleStanzaChannelAvailableChanged, this, _1)); + stanzaChannel_->onMessageReceived.disconnect(boost::ref(onMessageReceived)); + stanzaChannel_->onPresenceReceived.disconnect(boost::ref(onPresenceReceived)); + delete stanzaChannel_; } -void CoreComponent::connect(const std::string& host, int port) { - assert(!connector_); - connector_ = ComponentConnector::create(host, port, networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory()); - connector_->onConnectFinished.connect(boost::bind(&CoreComponent::handleConnectorFinished, this, _1)); - connector_->setTimeoutMilliseconds(60*1000); - connector_->start(); +void CoreComponent::connect(const std::string& host, unsigned short port) { + assert(!connector_); + connector_ = ComponentConnector::create(host, port, networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory()); + connector_->onConnectFinished.connect(boost::bind(&CoreComponent::handleConnectorFinished, this, _1)); + connector_->setTimeoutMilliseconds(60*1000); + connector_->start(); } -void CoreComponent::handleConnectorFinished(boost::shared_ptr<Connection> connection) { - connector_->onConnectFinished.disconnect(boost::bind(&CoreComponent::handleConnectorFinished, this, _1)); - connector_.reset(); - if (!connection) { - if (!disconnectRequested_) { - onError(ComponentError::ConnectionError); - } - } - else { - assert(!connection_); - connection_ = connection; - - assert(!sessionStream_); - sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(ComponentStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), NULL, networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory())); - sessionStream_->onDataRead.connect(boost::bind(&CoreComponent::handleDataRead, this, _1)); - sessionStream_->onDataWritten.connect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); - - session_ = ComponentSession::create(jid_, secret_, sessionStream_, networkFactories->getCryptoProvider()); - stanzaChannel_->setSession(session_); - session_->onFinished.connect(boost::bind(&CoreComponent::handleSessionFinished, this, _1)); - session_->start(); - } +void CoreComponent::handleConnectorFinished(std::shared_ptr<Connection> connection) { + connector_->onConnectFinished.disconnect(boost::bind(&CoreComponent::handleConnectorFinished, this, _1)); + connector_.reset(); + if (!connection) { + if (!disconnectRequested_) { + onError(ComponentError::ConnectionError); + } + } + else { + assert(!connection_); + connection_ = connection; + + assert(!sessionStream_); + sessionStream_ = std::make_shared<BasicSessionStream>(ComponentStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), nullptr, networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), TLSOptions()); + sessionStream_->onDataRead.connect(boost::bind(&CoreComponent::handleDataRead, this, _1)); + sessionStream_->onDataWritten.connect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); + + session_ = ComponentSession::create(jid_, secret_, sessionStream_, networkFactories->getCryptoProvider()); + stanzaChannel_->setSession(session_); + session_->onFinished.connect(boost::bind(&CoreComponent::handleSessionFinished, this, _1)); + session_->start(); + } } void CoreComponent::disconnect() { - // FIXME: We should be able to do without this boolean. We just have to make sure we can tell the difference between - // connector finishing without a connection due to an error or because of a disconnect. - disconnectRequested_ = true; - if (session_) { - session_->finish(); - } - else if (connector_) { - connector_->stop(); - assert(!session_); - } - //assert(!session_); /* commenting out until we have time to refactor to be like CoreClient */ - //assert(!sessionStream_); - //assert(!connector_); - disconnectRequested_ = false; + // FIXME: We should be able to do without this boolean. We just have to make sure we can tell the difference between + // connector finishing without a connection due to an error or because of a disconnect. + disconnectRequested_ = true; + if (session_) { + session_->finish(); + } + else if (connector_) { + connector_->stop(); + assert(!session_); + } + //assert(!session_); /* commenting out until we have time to refactor to be like CoreClient */ + //assert(!sessionStream_); + //assert(!connector_); + disconnectRequested_ = false; } -void CoreComponent::handleSessionFinished(boost::shared_ptr<Error> error) { - session_->onFinished.disconnect(boost::bind(&CoreComponent::handleSessionFinished, this, _1)); - session_.reset(); - - sessionStream_->onDataRead.disconnect(boost::bind(&CoreComponent::handleDataRead, this, _1)); - sessionStream_->onDataWritten.disconnect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); - sessionStream_.reset(); - - connection_->disconnect(); - connection_.reset(); - - if (error) { - ComponentError componentError; - if (boost::shared_ptr<ComponentSession::Error> actualError = boost::dynamic_pointer_cast<ComponentSession::Error>(error)) { - switch(actualError->type) { - case ComponentSession::Error::AuthenticationFailedError: - componentError = ComponentError(ComponentError::AuthenticationFailedError); - break; - case ComponentSession::Error::UnexpectedElementError: - componentError = ComponentError(ComponentError::UnexpectedElementError); - break; - } - } - else if (boost::shared_ptr<SessionStream::SessionStreamError> actualError = boost::dynamic_pointer_cast<SessionStream::SessionStreamError>(error)) { - switch(actualError->type) { - case SessionStream::SessionStreamError::ParseError: - componentError = ComponentError(ComponentError::XMLError); - break; - case SessionStream::SessionStreamError::TLSError: - assert(false); - componentError = ComponentError(ComponentError::UnknownError); - break; - case SessionStream::SessionStreamError::InvalidTLSCertificateError: - assert(false); - componentError = ComponentError(ComponentError::UnknownError); - break; - case SessionStream::SessionStreamError::ConnectionReadError: - componentError = ComponentError(ComponentError::ConnectionReadError); - break; - case SessionStream::SessionStreamError::ConnectionWriteError: - componentError = ComponentError(ComponentError::ConnectionWriteError); - break; - } - } - onError(componentError); - } +void CoreComponent::handleSessionFinished(std::shared_ptr<Error> error) { + session_->onFinished.disconnect(boost::bind(&CoreComponent::handleSessionFinished, this, _1)); + session_.reset(); + + sessionStream_->onDataRead.disconnect(boost::bind(&CoreComponent::handleDataRead, this, _1)); + sessionStream_->onDataWritten.disconnect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); + sessionStream_.reset(); + + connection_->disconnect(); + connection_.reset(); + + if (error) { + ComponentError componentError; + if (std::shared_ptr<ComponentSession::Error> actualError = std::dynamic_pointer_cast<ComponentSession::Error>(error)) { + switch(actualError->type) { + case ComponentSession::Error::AuthenticationFailedError: + componentError = ComponentError(ComponentError::AuthenticationFailedError); + break; + case ComponentSession::Error::UnexpectedElementError: + componentError = ComponentError(ComponentError::UnexpectedElementError); + break; + } + } + else if (std::shared_ptr<SessionStream::SessionStreamError> actualError = std::dynamic_pointer_cast<SessionStream::SessionStreamError>(error)) { + switch(actualError->type) { + case SessionStream::SessionStreamError::ParseError: + componentError = ComponentError(ComponentError::XMLError); + break; + case SessionStream::SessionStreamError::TLSError: + assert(false); + componentError = ComponentError(ComponentError::UnknownError); + break; + case SessionStream::SessionStreamError::InvalidTLSCertificateError: + assert(false); + componentError = ComponentError(ComponentError::UnknownError); + break; + case SessionStream::SessionStreamError::ConnectionReadError: + componentError = ComponentError(ComponentError::ConnectionReadError); + break; + case SessionStream::SessionStreamError::ConnectionWriteError: + componentError = ComponentError(ComponentError::ConnectionWriteError); + break; + } + } + onError(componentError); + } } void CoreComponent::handleDataRead(const SafeByteArray& data) { - onDataRead(data); + onDataRead(data); } void CoreComponent::handleDataWritten(const SafeByteArray& data) { - onDataWritten(data); + onDataWritten(data); } void CoreComponent::handleStanzaChannelAvailableChanged(bool available) { - if (available) { - onConnected(); - } + if (available) { + onConnected(); + } +} + +void CoreComponent::sendMessage(std::shared_ptr<Message> message) { + stanzaChannel_->sendMessage(message); +} + +void CoreComponent::sendPresence(std::shared_ptr<Presence> presence) { + stanzaChannel_->sendPresence(presence); +} + +void CoreComponent::sendData(const std::string& data) { + sessionStream_->writeData(data); } -void CoreComponent::sendMessage(boost::shared_ptr<Message> message) { - stanzaChannel_->sendMessage(message); +bool CoreComponent::isActive() const { + return session_ || connector_; } -void CoreComponent::sendPresence(boost::shared_ptr<Presence> presence) { - stanzaChannel_->sendPresence(presence); +bool CoreComponent::isAvailable() const { + return stanzaChannel_->isAvailable(); } } diff --git a/Swiften/Component/CoreComponent.h b/Swiften/Component/CoreComponent.h index 63b68f6..7565d00 100644 --- a/Swiften/Component/CoreComponent.h +++ b/Swiften/Component/CoreComponent.h @@ -1,102 +1,112 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Base/Error.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/Component/ComponentConnector.h> -#include <Swiften/Component/ComponentSession.h> #include <Swiften/Component/ComponentError.h> -#include <Swiften/Elements/Presence.h> +#include <Swiften/Component/ComponentSession.h> +#include <Swiften/Component/ComponentSessionStanzaChannel.h> #include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Entity/Entity.h> #include <Swiften/JID/JID.h> -#include <string> #include <Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h> #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> -#include <Swiften/Component/ComponentSessionStanzaChannel.h> -#include <Swiften/Entity/Entity.h> -#include <Swiften/Base/SafeByteArray.h> namespace Swift { - class EventLoop; - class IQRouter; - class NetworkFactories; - class ComponentSession; - class BasicSessionStream; - - /** - * The central class for communicating with an XMPP server as a component. - * - * This class is responsible for setting up the connection with the XMPP - * server and authenticating the component. - * - * This class can be used directly in your application, although the Component - * subclass provides more functionality and interfaces, and is better suited - * for most needs. - */ - class SWIFTEN_API CoreComponent : public Entity { - public: - CoreComponent(const JID& jid, const std::string& secret, NetworkFactories* networkFactories); - ~CoreComponent(); - - void connect(const std::string& host, int port); - void disconnect(); - - void sendMessage(boost::shared_ptr<Message>); - void sendPresence(boost::shared_ptr<Presence>); - - IQRouter* getIQRouter() const { - return iqRouter_; - } - - StanzaChannel* getStanzaChannel() const { - return stanzaChannel_; - } - - bool isAvailable() const { - return stanzaChannel_->isAvailable(); - } - - /** - * Returns the JID of the component - */ - const JID& getJID() const { - return jid_; - } - - public: - boost::signal<void (const ComponentError&)> onError; - boost::signal<void ()> onConnected; - boost::signal<void (const SafeByteArray&)> onDataRead; - boost::signal<void (const SafeByteArray&)> onDataWritten; - - boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived; - boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived; - - private: - void handleConnectorFinished(boost::shared_ptr<Connection>); - void handleStanzaChannelAvailableChanged(bool available); - void handleSessionFinished(boost::shared_ptr<Error>); - void handleDataRead(const SafeByteArray&); - void handleDataWritten(const SafeByteArray&); - - private: - NetworkFactories* networkFactories; - JID jid_; - std::string secret_; - ComponentSessionStanzaChannel* stanzaChannel_; - IQRouter* iqRouter_; - ComponentConnector::ref connector_; - boost::shared_ptr<Connection> connection_; - boost::shared_ptr<BasicSessionStream> sessionStream_; - boost::shared_ptr<ComponentSession> session_; - bool disconnectRequested_; - }; + class BasicSessionStream; + class ComponentSession; + class IQRouter; + class NetworkFactories; + + /** + * The central class for communicating with an XMPP server as a component. + * + * This class is responsible for setting up the connection with the XMPP + * server and authenticating the component. + * + * This class can be used directly in your application, although the Component + * subclass provides more functionality and interfaces, and is better suited + * for most needs. + */ + class SWIFTEN_API CoreComponent : public Entity { + public: + CoreComponent(const JID& jid, const std::string& secret, NetworkFactories* networkFactories); + virtual ~CoreComponent(); + + void connect(const std::string& host, unsigned short port); + void disconnect(); + + void sendMessage(std::shared_ptr<Message>); + void sendPresence(std::shared_ptr<Presence>); + void sendData(const std::string& data); + + IQRouter* getIQRouter() const { + return iqRouter_; + } + + StanzaChannel* getStanzaChannel() const { + return stanzaChannel_; + } + + /** + * Checks whether the component is connected to the server, + * and stanzas can be sent. + */ + bool isAvailable() const; + + /** + * Checks whether the component is active. + * + * A component is active when it is connected or connecting to the server. + */ + bool isActive() const; + + /** + * Returns the JID of the component + */ + const JID& getJID() const { + return jid_; + } + + public: + boost::signals2::signal<void (const ComponentError&)> onError; + boost::signals2::signal<void ()> onConnected; + boost::signals2::signal<void (const SafeByteArray&)> onDataRead; + boost::signals2::signal<void (const SafeByteArray&)> onDataWritten; + + boost::signals2::signal<void (std::shared_ptr<Message>)> onMessageReceived; + boost::signals2::signal<void (std::shared_ptr<Presence>) > onPresenceReceived; + + private: + void handleConnectorFinished(std::shared_ptr<Connection>); + void handleStanzaChannelAvailableChanged(bool available); + void handleSessionFinished(std::shared_ptr<Error>); + void handleDataRead(const SafeByteArray&); + void handleDataWritten(const SafeByteArray&); + + private: + NetworkFactories* networkFactories; + JID jid_; + std::string secret_; + ComponentSessionStanzaChannel* stanzaChannel_; + IQRouter* iqRouter_; + ComponentConnector::ref connector_; + std::shared_ptr<Connection> connection_; + std::shared_ptr<BasicSessionStream> sessionStream_; + std::shared_ptr<ComponentSession> session_; + bool disconnectRequested_; + }; } diff --git a/Swiften/Component/SConscript b/Swiften/Component/SConscript index ef5700c..2553ac6 100644 --- a/Swiften/Component/SConscript +++ b/Swiften/Component/SConscript @@ -1,13 +1,13 @@ Import("swiften_env") sources = [ - "ComponentHandshakeGenerator.cpp", - "ComponentConnector.cpp", - "ComponentSession.cpp", - "ComponentSessionStanzaChannel.cpp", - "CoreComponent.cpp", - "Component.cpp", - "ComponentXMLTracer.cpp", - ] + "ComponentHandshakeGenerator.cpp", + "ComponentConnector.cpp", + "ComponentSession.cpp", + "ComponentSessionStanzaChannel.cpp", + "CoreComponent.cpp", + "Component.cpp", + "ComponentXMLTracer.cpp", + ] swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources)) diff --git a/Swiften/Component/UnitTest/ComponentConnectorTest.cpp b/Swiften/Component/UnitTest/ComponentConnectorTest.cpp index 1b2a36b..bd26989 100644 --- a/Swiften/Component/UnitTest/ComponentConnectorTest.cpp +++ b/Swiften/Component/UnitTest/ComponentConnectorTest.cpp @@ -1,209 +1,210 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <boost/bind.hpp> +#include <boost/optional.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/optional.hpp> -#include <boost/bind.hpp> - #include <Swiften/Component/ComponentConnector.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/DummyTimerFactory.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/StaticDomainNameResolver.h> -#include <Swiften/Network/DummyTimerFactory.h> -#include <Swiften/EventLoop/DummyEventLoop.h> using namespace Swift; class ComponentConnectorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ComponentConnectorTest); - CPPUNIT_TEST(testConnect); - CPPUNIT_TEST(testConnect_FirstAddressHostFails); - CPPUNIT_TEST(testConnect_NoHosts); - CPPUNIT_TEST(testConnect_TimeoutDuringResolve); - CPPUNIT_TEST(testConnect_TimeoutDuringConnect); - CPPUNIT_TEST(testConnect_NoTimeout); - CPPUNIT_TEST(testStop_Timeout); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - host1 = HostAddress("1.1.1.1"); - host2 = HostAddress("2.2.2.2"); - eventLoop = new DummyEventLoop(); - resolver = new StaticDomainNameResolver(eventLoop); - connectionFactory = new MockConnectionFactory(eventLoop); - timerFactory = new DummyTimerFactory(); - } - - void tearDown() { - delete timerFactory; - delete connectionFactory; - delete resolver; - delete eventLoop; - } - - void testConnect() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - resolver->addAddress("foo.com", host1); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(HostAddressPort(host1, 1234) == *(connections[0]->hostAddressPort)); - } - - void testConnect_FirstAddressHostFails() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - resolver->addAddress("foo.com", host1); - resolver->addAddress("foo.com", host2); - connectionFactory->failingPorts.push_back(HostAddressPort(host1, 1234)); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(HostAddressPort(host2, 1234) == *(connections[0]->hostAddressPort)); - } - - void testConnect_NoHosts() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - } - - - void testConnect_TimeoutDuringResolve() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - - testling->setTimeoutMilliseconds(10); - resolver->setIsResponsive(false); - - testling->start(); - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - } - - void testConnect_TimeoutDuringConnect() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - testling->setTimeoutMilliseconds(10); - resolver->addAddress("foo.com", host1); - connectionFactory->isResponsive = false; - - testling->start(); - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - } - - void testConnect_NoTimeout() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - testling->setTimeoutMilliseconds(10); - resolver->addAddress("foo.com", host1); - - testling->start(); - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - } - - void testStop_Timeout() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - testling->setTimeoutMilliseconds(10); - resolver->addAddress("foo.com", host1); - - testling->start(); - testling->stop(); - - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - } - - private: - ComponentConnector::ref createConnector(const std::string& hostname, int port) { - ComponentConnector::ref connector = ComponentConnector::create(hostname, port, resolver, connectionFactory, timerFactory); - connector->onConnectFinished.connect(boost::bind(&ComponentConnectorTest::handleConnectorFinished, this, _1)); - return connector; - } - - void handleConnectorFinished(boost::shared_ptr<Connection> connection) { - boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection)); - if (connection) { - assert(c); - } - connections.push_back(c); - } - - struct MockConnection : public Connection { - public: - MockConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive) {} - - void listen() { assert(false); } - void connect(const HostAddressPort& address) { - hostAddressPort = address; - if (isResponsive) { - bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); - } - } - - void disconnect() { assert(false); } - void write(const SafeByteArray&) { assert(false); } - HostAddressPort getLocalAddress() const { return HostAddressPort(); } - - EventLoop* eventLoop; - boost::optional<HostAddressPort> hostAddressPort; - std::vector<HostAddressPort> failingPorts; - bool isResponsive; - }; - - struct MockConnectionFactory : public ConnectionFactory { - MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop), isResponsive(true) { - } - - boost::shared_ptr<Connection> createConnection() { - return boost::shared_ptr<Connection>(new MockConnection(failingPorts, isResponsive, eventLoop)); - } - - EventLoop* eventLoop; - bool isResponsive; - std::vector<HostAddressPort> failingPorts; - }; - - private: - HostAddress host1; - HostAddress host2; - DummyEventLoop* eventLoop; - StaticDomainNameResolver* resolver; - MockConnectionFactory* connectionFactory; - DummyTimerFactory* timerFactory; - std::vector< boost::shared_ptr<MockConnection> > connections; + CPPUNIT_TEST_SUITE(ComponentConnectorTest); + CPPUNIT_TEST(testConnect); + CPPUNIT_TEST(testConnect_FirstAddressHostFails); + CPPUNIT_TEST(testConnect_NoHosts); + CPPUNIT_TEST(testConnect_TimeoutDuringResolve); + CPPUNIT_TEST(testConnect_TimeoutDuringConnect); + CPPUNIT_TEST(testConnect_NoTimeout); + CPPUNIT_TEST(testStop_Timeout); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + host1 = HostAddress::fromString("1.1.1.1").get(); + host2 = HostAddress::fromString("2.2.2.2").get(); + eventLoop = new DummyEventLoop(); + resolver = new StaticDomainNameResolver(eventLoop); + connectionFactory = new MockConnectionFactory(eventLoop); + timerFactory = new DummyTimerFactory(); + } + + void tearDown() { + delete timerFactory; + delete connectionFactory; + delete resolver; + delete eventLoop; + } + + void testConnect() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + resolver->addAddress("foo.com", host1); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(HostAddressPort(host1, 1234) == *(connections[0]->hostAddressPort)); + } + + void testConnect_FirstAddressHostFails() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + resolver->addAddress("foo.com", host1); + resolver->addAddress("foo.com", host2); + connectionFactory->failingPorts.push_back(HostAddressPort(host1, 1234)); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(HostAddressPort(host2, 1234) == *(connections[0]->hostAddressPort)); + } + + void testConnect_NoHosts() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + + void testConnect_TimeoutDuringResolve() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + + testling->setTimeoutMilliseconds(10); + resolver->setIsResponsive(false); + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + void testConnect_TimeoutDuringConnect() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + testling->setTimeoutMilliseconds(10); + resolver->addAddress("foo.com", host1); + connectionFactory->isResponsive = false; + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + void testConnect_NoTimeout() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + testling->setTimeoutMilliseconds(10); + resolver->addAddress("foo.com", host1); + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + } + + void testStop_Timeout() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + testling->setTimeoutMilliseconds(10); + resolver->addAddress("foo.com", host1); + + testling->start(); + testling->stop(); + + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + private: + ComponentConnector::ref createConnector(const std::string& hostname, unsigned short port) { + ComponentConnector::ref connector = ComponentConnector::create(hostname, port, resolver, connectionFactory, timerFactory); + connector->onConnectFinished.connect(boost::bind(&ComponentConnectorTest::handleConnectorFinished, this, _1)); + return connector; + } + + void handleConnectorFinished(std::shared_ptr<Connection> connection) { + std::shared_ptr<MockConnection> c(std::dynamic_pointer_cast<MockConnection>(connection)); + if (connection) { + assert(c); + } + connections.push_back(c); + } + + struct MockConnection : public Connection { + public: + MockConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive) {} + + void listen() { assert(false); } + void connect(const HostAddressPort& address) { + hostAddressPort = address; + if (isResponsive) { + bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); + } + } + + void disconnect() { assert(false); } + void write(const SafeByteArray&) { assert(false); } + HostAddressPort getLocalAddress() const { return HostAddressPort(); } + HostAddressPort getRemoteAddress() const { return HostAddressPort(); } + + EventLoop* eventLoop; + boost::optional<HostAddressPort> hostAddressPort; + std::vector<HostAddressPort> failingPorts; + bool isResponsive; + }; + + struct MockConnectionFactory : public ConnectionFactory { + MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop), isResponsive(true) { + } + + std::shared_ptr<Connection> createConnection() { + return std::make_shared<MockConnection>(failingPorts, isResponsive, eventLoop); + } + + EventLoop* eventLoop; + bool isResponsive; + std::vector<HostAddressPort> failingPorts; + }; + + private: + HostAddress host1; + HostAddress host2; + DummyEventLoop* eventLoop; + StaticDomainNameResolver* resolver; + MockConnectionFactory* connectionFactory; + DummyTimerFactory* timerFactory; + std::vector< std::shared_ptr<MockConnection> > connections; }; CPPUNIT_TEST_SUITE_REGISTRATION(ComponentConnectorTest); diff --git a/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp b/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp index 280e46e..ce8eaa4 100644 --- a/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp +++ b/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,28 +14,28 @@ using namespace Swift; class ComponentHandshakeGeneratorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ComponentHandshakeGeneratorTest); - CPPUNIT_TEST(testGetHandshake); - CPPUNIT_TEST(testGetHandshake_SpecialChars); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - } - - void testGetHandshake() { - std::string result = ComponentHandshakeGenerator::getHandshake("myid", "mysecret", crypto.get()); - CPPUNIT_ASSERT_EQUAL(std::string("4011cd31f9b99ac089a0cd7ce297da7323fa2525"), result); - } - - void testGetHandshake_SpecialChars() { - std::string result = ComponentHandshakeGenerator::getHandshake("&<", ">'\"", crypto.get()); - CPPUNIT_ASSERT_EQUAL(std::string("33631b3e0aaeb2a11c4994c917919324028873fe"), result); - } - - private: - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(ComponentHandshakeGeneratorTest); + CPPUNIT_TEST(testGetHandshake); + CPPUNIT_TEST(testGetHandshake_SpecialChars); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } + + void testGetHandshake() { + std::string result = ComponentHandshakeGenerator::getHandshake("myid", "mysecret", crypto.get()); + CPPUNIT_ASSERT_EQUAL(std::string("4011cd31f9b99ac089a0cd7ce297da7323fa2525"), result); + } + + void testGetHandshake_SpecialChars() { + std::string result = ComponentHandshakeGenerator::getHandshake("&<", ">'\"", crypto.get()); + CPPUNIT_ASSERT_EQUAL(std::string("33631b3e0aaeb2a11c4994c917919324028873fe"), result); + } + + private: + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(ComponentHandshakeGeneratorTest); diff --git a/Swiften/Component/UnitTest/ComponentSessionTest.cpp b/Swiften/Component/UnitTest/ComponentSessionTest.cpp index 0533645..48c6d8d 100644 --- a/Swiften/Component/UnitTest/ComponentSessionTest.cpp +++ b/Swiften/Component/UnitTest/ComponentSessionTest.cpp @@ -1,220 +1,222 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> #include <deque> + #include <boost/bind.hpp> #include <boost/optional.hpp> -#include <Swiften/Session/SessionStream.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + #include <Swiften/Component/ComponentSession.h> -#include <Swiften/Elements/ComponentHandshake.h> -#include <Swiften/Elements/AuthFailure.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Elements/AuthFailure.h> +#include <Swiften/Elements/ComponentHandshake.h> +#include <Swiften/Session/SessionStream.h> using namespace Swift; class ComponentSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ComponentSessionTest); - CPPUNIT_TEST(testStart); - CPPUNIT_TEST(testStart_Error); - CPPUNIT_TEST(testStart_Unauthorized); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - server = boost::make_shared<MockSessionStream>(); - sessionFinishedReceived = false; - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - } - - void testStart() { - boost::shared_ptr<ComponentSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->receiveHandshake(); - server->sendHandshakeResponse(); - - CPPUNIT_ASSERT(server->whitespacePingEnabled); - - session->finish(); - CPPUNIT_ASSERT(!server->whitespacePingEnabled); - - } - - void testStart_Error() { - boost::shared_ptr<ComponentSession> session(createSession()); - session->start(); - server->breakConnection(); - - CPPUNIT_ASSERT_EQUAL(ComponentSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStart_Unauthorized() { - boost::shared_ptr<ComponentSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->receiveHandshake(); - server->sendHandshakeError(); - - CPPUNIT_ASSERT_EQUAL(ComponentSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - private: - boost::shared_ptr<ComponentSession> createSession() { - boost::shared_ptr<ComponentSession> session = ComponentSession::create(JID("service.foo.com"), "servicesecret", server, crypto.get()); - session->onFinished.connect(boost::bind(&ComponentSessionTest::handleSessionFinished, this, _1)); - return session; - } - - void handleSessionFinished(boost::shared_ptr<Error> error) { - sessionFinishedReceived = true; - sessionFinishedError = error; - } - - class MockSessionStream : public SessionStream { - public: - struct Event { - Event(boost::shared_ptr<Element> element) : element(element), footer(false) {} - Event(const ProtocolHeader& header) : header(header), footer(false) {} - Event() : footer(true) {} - - boost::shared_ptr<Element> element; - boost::optional<ProtocolHeader> header; - bool footer; - }; - - MockSessionStream() : available(true), whitespacePingEnabled(false), resetCount(0) { - } - - virtual void close() { - onClosed(boost::shared_ptr<Error>()); - } - - virtual bool isOpen() { - return available; - } - - virtual void writeHeader(const ProtocolHeader& header) { - receivedEvents.push_back(Event(header)); - } - - virtual void writeFooter() { - receivedEvents.push_back(Event()); - } - - virtual void writeElement(boost::shared_ptr<Element> element) { - receivedEvents.push_back(Event(element)); - } - - virtual void writeData(const std::string&) { - } - - virtual bool supportsTLSEncryption() { - return false; - } - - virtual void addTLSEncryption() { - assert(false); - } - - virtual bool isTLSEncrypted() { - return false; - } - - virtual ByteArray getTLSFinishMessage() const { - return ByteArray(); - } - - virtual Certificate::ref getPeerCertificate() const { - return Certificate::ref(); - } - - virtual std::vector<Certificate::ref> getPeerCertificateChain() const { - return std::vector<Certificate::ref>(); - } - - virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const { - return boost::shared_ptr<CertificateVerificationError>(); - } - - virtual bool supportsZLibCompression() { - return true; - } - - virtual void addZLibCompression() { - assert(false); - } - - virtual void setWhitespacePingEnabled(bool enabled) { - whitespacePingEnabled = enabled; - } - - virtual void resetXMPPParser() { - resetCount++; - } - - void breakConnection() { - onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::ConnectionReadError)); - } - - void sendStreamStart() { - ProtocolHeader header; - header.setFrom("service.foo.com"); - return onStreamStartReceived(header); - } - - void sendHandshakeResponse() { - onElementReceived(ComponentHandshake::ref(new ComponentHandshake())); - } - - void sendHandshakeError() { - // FIXME: This isn't the correct element - onElementReceived(AuthFailure::ref(new AuthFailure())); - } - - void receiveStreamStart() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.header); - } - - void receiveHandshake() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - ComponentHandshake::ref handshake(boost::dynamic_pointer_cast<ComponentHandshake>(event.element)); - CPPUNIT_ASSERT(handshake); - CPPUNIT_ASSERT_EQUAL(std::string("4c4f8a41141722c8bbfbdd92d827f7b2fc0a542b"), handshake->getData()); - } - - Event popEvent() { - CPPUNIT_ASSERT(!receivedEvents.empty()); - Event event = receivedEvents.front(); - receivedEvents.pop_front(); - return event; - } - - bool available; - bool whitespacePingEnabled; - std::string bindID; - int resetCount; - std::deque<Event> receivedEvents; - }; - - boost::shared_ptr<MockSessionStream> server; - bool sessionFinishedReceived; - boost::shared_ptr<Error> sessionFinishedError; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(ComponentSessionTest); + CPPUNIT_TEST(testStart); + CPPUNIT_TEST(testStart_Error); + CPPUNIT_TEST(testStart_Unauthorized); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + server = std::make_shared<MockSessionStream>(); + sessionFinishedReceived = false; + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } + + void testStart() { + std::shared_ptr<ComponentSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->receiveHandshake(); + server->sendHandshakeResponse(); + + CPPUNIT_ASSERT(server->whitespacePingEnabled); + + session->finish(); + CPPUNIT_ASSERT(!server->whitespacePingEnabled); + + } + + void testStart_Error() { + std::shared_ptr<ComponentSession> session(createSession()); + session->start(); + server->breakConnection(); + + CPPUNIT_ASSERT_EQUAL(ComponentSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStart_Unauthorized() { + std::shared_ptr<ComponentSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->receiveHandshake(); + server->sendHandshakeError(); + + CPPUNIT_ASSERT_EQUAL(ComponentSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + private: + std::shared_ptr<ComponentSession> createSession() { + std::shared_ptr<ComponentSession> session = ComponentSession::create(JID("service.foo.com"), "servicesecret", server, crypto.get()); + session->onFinished.connect(boost::bind(&ComponentSessionTest::handleSessionFinished, this, _1)); + return session; + } + + void handleSessionFinished(std::shared_ptr<Error> error) { + sessionFinishedReceived = true; + sessionFinishedError = error; + } + + class MockSessionStream : public SessionStream { + public: + struct Event { + Event(std::shared_ptr<ToplevelElement> element) : element(element), footer(false) {} + Event(const ProtocolHeader& header) : header(header), footer(false) {} + Event() : footer(true) {} + + std::shared_ptr<ToplevelElement> element; + boost::optional<ProtocolHeader> header; + bool footer; + }; + + MockSessionStream() : available(true), whitespacePingEnabled(false), resetCount(0) { + } + + virtual void close() { + onClosed(std::shared_ptr<Error>()); + } + + virtual bool isOpen() { + return available; + } + + virtual void writeHeader(const ProtocolHeader& header) { + receivedEvents.push_back(Event(header)); + } + + virtual void writeFooter() { + receivedEvents.push_back(Event()); + } + + virtual void writeElement(std::shared_ptr<ToplevelElement> element) { + receivedEvents.push_back(Event(element)); + } + + virtual void writeData(const std::string&) { + } + + virtual bool supportsTLSEncryption() { + return false; + } + + virtual void addTLSEncryption() { + assert(false); + } + + virtual bool isTLSEncrypted() { + return false; + } + + virtual ByteArray getTLSFinishMessage() const { + return ByteArray(); + } + + virtual Certificate::ref getPeerCertificate() const { + return Certificate::ref(); + } + + virtual std::vector<Certificate::ref> getPeerCertificateChain() const { + return std::vector<Certificate::ref>(); + } + + virtual std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const { + return std::shared_ptr<CertificateVerificationError>(); + } + + virtual bool supportsZLibCompression() { + return true; + } + + virtual void addZLibCompression() { + assert(false); + } + + virtual void setWhitespacePingEnabled(bool enabled) { + whitespacePingEnabled = enabled; + } + + virtual void resetXMPPParser() { + resetCount++; + } + + void breakConnection() { + onClosed(std::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::ConnectionReadError)); + } + + void sendStreamStart() { + ProtocolHeader header; + header.setFrom("service.foo.com"); + return onStreamStartReceived(header); + } + + void sendHandshakeResponse() { + onElementReceived(ComponentHandshake::ref(new ComponentHandshake())); + } + + void sendHandshakeError() { + // FIXME: This isn't the correct element + onElementReceived(AuthFailure::ref(new AuthFailure())); + } + + void receiveStreamStart() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.header); + } + + void receiveHandshake() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + ComponentHandshake::ref handshake(std::dynamic_pointer_cast<ComponentHandshake>(event.element)); + CPPUNIT_ASSERT(handshake); + CPPUNIT_ASSERT_EQUAL(std::string("4c4f8a41141722c8bbfbdd92d827f7b2fc0a542b"), handshake->getData()); + } + + Event popEvent() { + CPPUNIT_ASSERT(!receivedEvents.empty()); + Event event = receivedEvents.front(); + receivedEvents.pop_front(); + return event; + } + + bool available; + bool whitespacePingEnabled; + std::string bindID; + int resetCount; + std::deque<Event> receivedEvents; + }; + + std::shared_ptr<MockSessionStream> server; + bool sessionFinishedReceived = false; + std::shared_ptr<Error> sessionFinishedError; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(ComponentSessionTest); diff --git a/Swiften/Compress/UnitTest/ZLibCompressorTest.cpp b/Swiften/Compress/UnitTest/ZLibCompressorTest.cpp index 1de9322..ca99201 100644 --- a/Swiften/Compress/UnitTest/ZLibCompressorTest.cpp +++ b/Swiften/Compress/UnitTest/ZLibCompressorTest.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/SafeByteArray.h> #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/Compress/ZLibCompressor.h> using namespace Swift; @@ -17,28 +17,28 @@ using namespace Swift; class ZLibCompressorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ZLibCompressorTest); - CPPUNIT_TEST(testProcess); - CPPUNIT_TEST(testProcess_Twice); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(ZLibCompressorTest); + CPPUNIT_TEST(testProcess); + CPPUNIT_TEST(testProcess_Twice); + CPPUNIT_TEST_SUITE_END(); - public: - ZLibCompressorTest() {} + public: + ZLibCompressorTest() {} - void testProcess() { - ZLibCompressor testling; - SafeByteArray result = testling.process(createSafeByteArray("foo")); + void testProcess() { + ZLibCompressor testling; + SafeByteArray result = testling.process(createSafeByteArray("foo")); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("\x78\xda\x4a\xcb\xcf\x07\x00\x00\x00\xff\xff", 11), result); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("\x78\xda\x4a\xcb\xcf\x07\x00\x00\x00\xff\xff", 11), result); + } - void testProcess_Twice() { - ZLibCompressor testling; - testling.process(createSafeByteArray("foo")); - SafeByteArray result = testling.process(createSafeByteArray("bar")); + void testProcess_Twice() { + ZLibCompressor testling; + testling.process(createSafeByteArray("foo")); + SafeByteArray result = testling.process(createSafeByteArray("bar")); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("\x4a\x4a\x2c\x02\x00\x00\x00\xff\xff",9), result); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("\x4a\x4a\x2c\x02\x00\x00\x00\xff\xff",9), result); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(ZLibCompressorTest); diff --git a/Swiften/Compress/UnitTest/ZLibDecompressorTest.cpp b/Swiften/Compress/UnitTest/ZLibDecompressorTest.cpp index 906c2dd..5873c0e 100644 --- a/Swiften/Compress/UnitTest/ZLibDecompressorTest.cpp +++ b/Swiften/Compress/UnitTest/ZLibDecompressorTest.cpp @@ -1,17 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Compress/ZLibDecompressor.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Compress/ZLibCompressor.h> +#include <Swiften/Compress/ZLibDecompressor.h> #include <Swiften/Compress/ZLibException.h> using namespace Swift; @@ -19,62 +19,62 @@ using namespace Swift; class ZLibDecompressorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ZLibDecompressorTest); - CPPUNIT_TEST(testProcess); - CPPUNIT_TEST(testProcess_Twice); - CPPUNIT_TEST(testProcess_Invalid); - CPPUNIT_TEST(testProcess_Huge); - CPPUNIT_TEST(testProcess_ChunkSize); - CPPUNIT_TEST_SUITE_END(); - - public: - ZLibDecompressorTest() {} - - void testProcess() { - ZLibDecompressor testling; - SafeByteArray result = testling.process(createSafeByteArray("\x78\xda\x4a\xcb\xcf\x07\x00\x00\x00\xff\xff", 11)); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("foo"), result); - } - - void testProcess_Twice() { - ZLibDecompressor testling; - testling.process(createSafeByteArray("\x78\xda\x4a\xcb\xcf\x07\x00\x00\x00\xff\xff", 11)); - SafeByteArray result = testling.process(createSafeByteArray("\x4a\x4a\x2c\x02\x00\x00\x00\xff\xff", 9)); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("bar"), result); - } - - void testProcess_Invalid() { - ZLibDecompressor testling; - CPPUNIT_ASSERT_THROW(testling.process(createSafeByteArray("invalid")), ZLibException); - } - - void testProcess_Huge() { - std::vector<char> data; - data.reserve(2048); - for (unsigned int i = 0; i < 2048; ++i) { - data.push_back(static_cast<char>(i)); - } - SafeByteArray original(createSafeByteArray(&data[0], data.size())); - SafeByteArray compressed = ZLibCompressor().process(original); - SafeByteArray decompressed = ZLibDecompressor().process(compressed); - - CPPUNIT_ASSERT_EQUAL(original, decompressed); - } - - void testProcess_ChunkSize() { - std::vector<char> data; - data.reserve(1024); - for (unsigned int i = 0; i < 1024; ++i) { - data.push_back(static_cast<char>(i)); - } - SafeByteArray original(createSafeByteArray(&data[0], data.size())); - SafeByteArray compressed = ZLibCompressor().process(original); - SafeByteArray decompressed = ZLibDecompressor().process(compressed); - - CPPUNIT_ASSERT_EQUAL(original, decompressed); - } + CPPUNIT_TEST_SUITE(ZLibDecompressorTest); + CPPUNIT_TEST(testProcess); + CPPUNIT_TEST(testProcess_Twice); + CPPUNIT_TEST(testProcess_Invalid); + CPPUNIT_TEST(testProcess_Huge); + CPPUNIT_TEST(testProcess_ChunkSize); + CPPUNIT_TEST_SUITE_END(); + + public: + ZLibDecompressorTest() {} + + void testProcess() { + ZLibDecompressor testling; + SafeByteArray result = testling.process(createSafeByteArray("\x78\xda\x4a\xcb\xcf\x07\x00\x00\x00\xff\xff", 11)); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("foo"), result); + } + + void testProcess_Twice() { + ZLibDecompressor testling; + testling.process(createSafeByteArray("\x78\xda\x4a\xcb\xcf\x07\x00\x00\x00\xff\xff", 11)); + SafeByteArray result = testling.process(createSafeByteArray("\x4a\x4a\x2c\x02\x00\x00\x00\xff\xff", 9)); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("bar"), result); + } + + void testProcess_Invalid() { + ZLibDecompressor testling; + CPPUNIT_ASSERT_THROW(testling.process(createSafeByteArray("invalid")), ZLibException); + } + + void testProcess_Huge() { + std::vector<char> data; + data.reserve(2048); + for (unsigned int i = 0; i < 2048; ++i) { + data.push_back(static_cast<char>(i)); + } + SafeByteArray original(createSafeByteArray(&data[0], data.size())); + SafeByteArray compressed = ZLibCompressor().process(original); + SafeByteArray decompressed = ZLibDecompressor().process(compressed); + + CPPUNIT_ASSERT_EQUAL(original, decompressed); + } + + void testProcess_ChunkSize() { + std::vector<char> data; + data.reserve(1024); + for (unsigned int i = 0; i < 1024; ++i) { + data.push_back(static_cast<char>(i)); + } + SafeByteArray original(createSafeByteArray(&data[0], data.size())); + SafeByteArray compressed = ZLibCompressor().process(original); + SafeByteArray decompressed = ZLibDecompressor().process(compressed); + + CPPUNIT_ASSERT_EQUAL(original, decompressed); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(ZLibDecompressorTest); diff --git a/Swiften/Compress/ZLibCodecompressor.cpp b/Swiften/Compress/ZLibCodecompressor.cpp index 85d0174..344e6b7 100644 --- a/Swiften/Compress/ZLibCodecompressor.cpp +++ b/Swiften/Compress/ZLibCodecompressor.cpp @@ -1,55 +1,58 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Compress/ZLibCodecompressor.h> -#include <cassert> #include <string.h> -#include <zlib.h> + +#include <cassert> + #include <boost/numeric/conversion/cast.hpp> -#include <Swiften/Compress/ZLibException.h> +#include <zlib.h> + #include <Swiften/Compress/ZLibCodecompressor_Private.h> +#include <Swiften/Compress/ZLibException.h> namespace Swift { static const size_t CHUNK_SIZE = 1024; // If you change this, also change the unittest -ZLibCodecompressor::ZLibCodecompressor() : p(boost::make_shared<Private>()) { - memset(&p->stream, 0, sizeof(z_stream)); - p->stream.zalloc = Z_NULL; - p->stream.zfree = Z_NULL; - p->stream.opaque = Z_NULL; +ZLibCodecompressor::ZLibCodecompressor() : p(new Private()) { + memset(&p->stream, 0, sizeof(z_stream)); + p->stream.zalloc = Z_NULL; + p->stream.zfree = Z_NULL; + p->stream.opaque = Z_NULL; } ZLibCodecompressor::~ZLibCodecompressor() { } SafeByteArray ZLibCodecompressor::process(const SafeByteArray& input) { - SafeByteArray output; - p->stream.avail_in = static_cast<unsigned int>(input.size()); - p->stream.next_in = reinterpret_cast<Bytef*>(const_cast<unsigned char*>(vecptr(input))); - size_t outputPosition = 0; - do { - output.resize(outputPosition + CHUNK_SIZE); - p->stream.avail_out = CHUNK_SIZE; - p->stream.next_out = reinterpret_cast<Bytef*>(vecptr(output) + outputPosition); - int result = processZStream(); - if (result != Z_OK && result != Z_BUF_ERROR) { - throw ZLibException(/* p->stream.msg */); - } - outputPosition += CHUNK_SIZE; - } - while (p->stream.avail_out == 0); - if (p->stream.avail_in != 0) { - throw ZLibException(); - } - output.resize(outputPosition - p->stream.avail_out); - return output; + SafeByteArray output; + p->stream.avail_in = static_cast<unsigned int>(input.size()); + p->stream.next_in = reinterpret_cast<Bytef*>(const_cast<unsigned char*>(vecptr(input))); + size_t outputPosition = 0; + do { + output.resize(outputPosition + CHUNK_SIZE); + p->stream.avail_out = CHUNK_SIZE; + p->stream.next_out = reinterpret_cast<Bytef*>(vecptr(output) + outputPosition); + int result = processZStream(); + if (result != Z_OK && result != Z_BUF_ERROR) { + throw ZLibException(/* p->stream.msg */); + } + outputPosition += CHUNK_SIZE; + } + while (p->stream.avail_out == 0); + if (p->stream.avail_in != 0) { + throw ZLibException(); + } + output.resize(outputPosition - p->stream.avail_out); + return output; } } diff --git a/Swiften/Compress/ZLibCodecompressor.h b/Swiften/Compress/ZLibCodecompressor.h index 6ff64df..8bc5d88 100644 --- a/Swiften/Compress/ZLibCodecompressor.h +++ b/Swiften/Compress/ZLibCodecompressor.h @@ -1,25 +1,27 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class SWIFTEN_API ZLibCodecompressor { - public: - ZLibCodecompressor(); - virtual ~ZLibCodecompressor(); + class SWIFTEN_API ZLibCodecompressor { + public: + ZLibCodecompressor(); + virtual ~ZLibCodecompressor(); - SafeByteArray process(const SafeByteArray& data); - virtual int processZStream() = 0; + SafeByteArray process(const SafeByteArray& data); + virtual int processZStream() = 0; - protected: - struct Private; - boost::shared_ptr<Private> p; - }; + protected: + struct Private; + const std::unique_ptr<Private> p; + }; } diff --git a/Swiften/Compress/ZLibCodecompressor_Private.h b/Swiften/Compress/ZLibCodecompressor_Private.h index 1f24b83..2adc4b6 100644 --- a/Swiften/Compress/ZLibCodecompressor_Private.h +++ b/Swiften/Compress/ZLibCodecompressor_Private.h @@ -1,17 +1,17 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Compress/ZLibCodecompressor.h> - #include <zlib.h> +#include <Swiften/Compress/ZLibCodecompressor.h> + namespace Swift { - struct ZLibCodecompressor::Private { - z_stream stream; - }; + struct ZLibCodecompressor::Private { + z_stream stream; + }; } diff --git a/Swiften/Compress/ZLibCompressor.cpp b/Swiften/Compress/ZLibCompressor.cpp index 6af8d83..a2fef15 100644 --- a/Swiften/Compress/ZLibCompressor.cpp +++ b/Swiften/Compress/ZLibCompressor.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Compress/ZLibCompressor.h> @@ -16,17 +16,17 @@ namespace Swift { ZLibCompressor::ZLibCompressor() { - int result = deflateInit(&p->stream, COMPRESSION_LEVEL); - assert(result == Z_OK); - (void) result; + int result = deflateInit(&p->stream, COMPRESSION_LEVEL); + assert(result == Z_OK); + (void) result; } ZLibCompressor::~ZLibCompressor() { - deflateEnd(&p->stream); + deflateEnd(&p->stream); } int ZLibCompressor::processZStream() { - return deflate(&p->stream, Z_SYNC_FLUSH); + return deflate(&p->stream, Z_SYNC_FLUSH); } } diff --git a/Swiften/Compress/ZLibCompressor.h b/Swiften/Compress/ZLibCompressor.h index 3ba1955..59ebbb9 100644 --- a/Swiften/Compress/ZLibCompressor.h +++ b/Swiften/Compress/ZLibCompressor.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,14 +10,14 @@ #include <Swiften/Compress/ZLibCodecompressor.h> namespace Swift { - class SWIFTEN_API ZLibCompressor : public ZLibCodecompressor { - public: - ZLibCompressor(); - ~ZLibCompressor(); + class SWIFTEN_API ZLibCompressor : public ZLibCodecompressor { + public: + ZLibCompressor(); + virtual ~ZLibCompressor(); - virtual int processZStream(); + virtual int processZStream(); - private: - static const int COMPRESSION_LEVEL = 9; - }; + private: + static const int COMPRESSION_LEVEL = 9; + }; } diff --git a/Swiften/Compress/ZLibDecompressor.cpp b/Swiften/Compress/ZLibDecompressor.cpp index f5df9fe..adc40c5 100644 --- a/Swiften/Compress/ZLibDecompressor.cpp +++ b/Swiften/Compress/ZLibDecompressor.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Compress/ZLibDecompressor.h> @@ -16,17 +16,17 @@ namespace Swift { ZLibDecompressor::ZLibDecompressor() { - int result = inflateInit(&p->stream); - assert(result == Z_OK); - (void) result; + int result = inflateInit(&p->stream); + assert(result == Z_OK); + (void) result; } ZLibDecompressor::~ZLibDecompressor() { - inflateEnd(&p->stream); + inflateEnd(&p->stream); } int ZLibDecompressor::processZStream() { - return inflate(&p->stream, Z_SYNC_FLUSH); + return inflate(&p->stream, Z_SYNC_FLUSH); } } diff --git a/Swiften/Compress/ZLibDecompressor.h b/Swiften/Compress/ZLibDecompressor.h index e3122f1..9c2dd4f 100644 --- a/Swiften/Compress/ZLibDecompressor.h +++ b/Swiften/Compress/ZLibDecompressor.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Compress/ZLibCodecompressor.h> #include <Swiften/Base/API.h> +#include <Swiften/Compress/ZLibCodecompressor.h> namespace Swift { - class SWIFTEN_API ZLibDecompressor : public ZLibCodecompressor { - public: - ZLibDecompressor(); - ~ZLibDecompressor(); + class SWIFTEN_API ZLibDecompressor : public ZLibCodecompressor { + public: + ZLibDecompressor(); + virtual ~ZLibDecompressor(); - virtual int processZStream(); - }; + virtual int processZStream(); + }; } diff --git a/Swiften/Compress/ZLibException.h b/Swiften/Compress/ZLibException.h index 8e60aa3..2201e62 100644 --- a/Swiften/Compress/ZLibException.h +++ b/Swiften/Compress/ZLibException.h @@ -1,15 +1,14 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once - namespace Swift { - class ZLibException { - public: - ZLibException() {} - }; + class ZLibException { + public: + ZLibException() {} + }; } diff --git a/Swiften/Config/SConscript b/Swiften/Config/SConscript index 837884b..ae0d37a 100644 --- a/Swiften/Config/SConscript +++ b/Swiften/Config/SConscript @@ -3,16 +3,16 @@ import os.path Import("env") def replaceSwiftenPath(input) : - return input.replace(env.Dir("#").abspath, "#") + return input.replace(env.Dir("#").abspath, "#") def cStringVariable(env, cVar, sconsVar) : - result = "static const char* " + cVar + "[] = {\n" - # FIXME: Probably not very robust - for var in sconsVar.split(" ") : - result += "\t\"" + env.subst(var).replace("\\", "\\\\") + "\",\n" - result += "\t0\n" - result += "};\n" - return result + result = "static const char* " + cVar + "[] = {\n" + # FIXME: Probably not very robust + for var in sconsVar.split(" ") : + result += "\t\"" + env.subst(var).replace("\\", "\\\\") + "\",\n" + result += "\tnullptr\n" + result += "};\n" + return result config_flags = "" @@ -21,36 +21,38 @@ swiften_env.UseFlags(swiften_env["SWIFTEN_FLAGS"]) swiften_env.UseFlags(swiften_env["SWIFTEN_DEP_FLAGS"]) cppflags = replaceSwiftenPath(" ".join([ - swiften_env.subst("$CPPFLAGS").replace("-isystem ","-I"), - swiften_env.subst("$_CPPDEFFLAGS"), - swiften_env.subst("$_CPPINCFLAGS")])) + swiften_env.subst("$CPPFLAGS").replace("-isystem ","-I"), + swiften_env.subst("$_CPPDEFFLAGS"), + swiften_env.subst("$_CPPINCFLAGS")])) config_flags += cStringVariable(swiften_env, "CPPFLAGS", cppflags) libflags = replaceSwiftenPath(" ".join([ - swiften_env.subst("$_LIBDIRFLAGS"), - swiften_env.subst("$_LIBFLAGS"), - swiften_env.subst("$_FRAMEWORKPATH"), - swiften_env.subst("$_FRAMEWORKS"), - swiften_env.subst("$_FRAMEWORKSFLAGS") - ])) + swiften_env.subst("$_LIBDIRFLAGS"), + swiften_env.subst("$_LIBFLAGS"), + swiften_env.subst("$_FRAMEWORKPATH"), + swiften_env.subst("$_FRAMEWORKS"), + swiften_env.subst("$_FRAMEWORKSFLAGS") + ])) config_flags += cStringVariable(swiften_env, "LIBFLAGS", libflags) config_env = env.Clone() +config_env.Append(CPPDEFINES = ["SWIFTEN_STATIC"]) + # Create a local copy of Paths.cpp to avoid a Swiften dependency config_env.Install(".", [ - "#/Swiften/Base/Paths.cpp", - "#/Swiften/Base/Path.cpp", - "#/Swiften/Base/String.cpp", + "#/Swiften/Base/Paths.cpp", + "#/Swiften/Base/Path.cpp", + "#/Swiften/Base/String.cpp", ]) config_env.UseFlags(config_env["BOOST_FLAGS"]) config_env.UseFlags(config_env["PLATFORM_FLAGS"]) config_env.WriteVal("swiften-config.h", config_env.Value(config_flags)) swiften_config = config_env.Program("swiften-config", [ - "Paths.cpp", - "Path.cpp", - "String.cpp", - "swiften-config.cpp" - ]) + "Paths.cpp", + "Path.cpp", + "String.cpp", + "swiften-config.cpp" + ]) if swiften_env.get("SWIFTEN_INSTALLDIR", "") : - swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "bin"), swiften_config) + swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "bin"), swiften_config) diff --git a/Swiften/Config/swiften-config.cpp b/Swiften/Config/swiften-config.cpp index 778134d..2b66989 100644 --- a/Swiften/Config/swiften-config.cpp +++ b/Swiften/Config/swiften-config.cpp @@ -1,126 +1,126 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <Swiften/Config/swiften-config.h> + #include <iostream> +#include <string> #include <boost/algorithm/string.hpp> +#include <boost/filesystem.hpp> +#include <boost/program_options.hpp> #include <boost/program_options/options_description.hpp> #include <boost/program_options/variables_map.hpp> -#include <boost/program_options.hpp> #include <boost/version.hpp> -#include <boost/filesystem.hpp> -#include <string> -#include <Swiften/Base/Platform.h> -#include <Swiften/Base/Paths.h> #include <Swiften/Base/Path.h> +#include <Swiften/Base/Paths.h> +#include <Swiften/Base/Platform.h> #include <Swiften/Version.h> -#include "swiften-config.h" - using namespace Swift; static void printFlags(const std::vector<std::string>& flags) { - for (size_t i = 0; i < flags.size(); ++i) { - if (i > 0) { - std::cout << " "; - } - std::cout << flags[i]; - } - std::cout << std::endl; + for (size_t i = 0; i < flags.size(); ++i) { + if (i > 0) { + std::cout << " "; + } + std::cout << flags[i]; + } + std::cout << std::endl; } int main(int argc, char* argv[]) { - boost::program_options::options_description desc; - desc.add_options() - ("help", "Show this help message") - ("version", "Show version information") - ("libs", "List the library flags") - ("cflags", "List the compiler & preprocessor flags") - ; - boost::program_options::variables_map vm; - try { - boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); - boost::program_options::notify(vm); - } - catch (const boost::program_options::unknown_option& option) { + boost::program_options::options_description desc; + desc.add_options() + ("help", "Show this help message") + ("version", "Show version information") + ("libs", "List the library flags") + ("cflags", "List the compiler & preprocessor flags") + ; + boost::program_options::variables_map vm; + try { + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + boost::program_options::notify(vm); + } + catch (const boost::program_options::unknown_option& option) { #if BOOST_VERSION >= 104200 - std::cout << "Ignoring unknown option " << option.get_option_name() << std::endl; + std::cout << "Ignoring unknown option " << option.get_option_name() << std::endl; #else - std::cout << "Error: " << option.what() << std::endl; + std::cout << "Error: " << option.what() << std::endl; #endif - } - catch (const boost::program_options::error& e) { - std::cout << "Error: " << e.what() << std::endl; - return -1; - } + } + catch (const boost::program_options::error& e) { + std::cout << "Error: " << e.what() << std::endl; + return -1; + } - if (vm.count("help") > 0) { - std::cout << "swiften-config outputs the Swiften build options." << std::endl; - std::cout << std::endl; - std::cout << "Usage: swiften-config [OPTIONS]..." << std::endl; - std::cout << std::endl; - std::cout << desc << "\n"; - return 0; - } - if (vm.count("version") > 0) { - std::cout << "swiften-config " << SWIFTEN_VERSION_STRING << std::endl; - return 0; - } + if (vm.count("help") > 0) { + std::cout << "swiften-config outputs the Swiften build options." << std::endl; + std::cout << std::endl; + std::cout << "Usage: swiften-config [OPTIONS]..." << std::endl; + std::cout << std::endl; + std::cout << desc << "\n"; + return 0; + } + if (vm.count("version") > 0) { + std::cout << "swiften-config " << SWIFTEN_VERSION_STRING << std::endl; + return 0; + } - // Read in all variables - std::vector<std::string> libs; - for (size_t i = 0; LIBFLAGS[i]; ++i) { - libs.push_back(LIBFLAGS[i]); - } - std::vector<std::string> cflags; - for (size_t i = 0; CPPFLAGS[i]; ++i) { - cflags.push_back(CPPFLAGS[i]); - } + // Read in all variables + std::vector<std::string> libs; + for (size_t i = 0; LIBFLAGS[i]; ++i) { + libs.push_back(LIBFLAGS[i]); + } + std::vector<std::string> cflags; + for (size_t i = 0; CPPFLAGS[i]; ++i) { + cflags.push_back(CPPFLAGS[i]); + } - // Detect whether we're running in-place or not - boost::filesystem::path executablePath = Paths::getExecutablePath(); - boost::filesystem::path topSourcePath = executablePath / ".." / ".."; - boost::filesystem::path topInstallPath = executablePath / ".."; - bool inPlace = !boost::filesystem::exists(topInstallPath / "include" / "Swiften" / "Swiften.h"); + // Detect whether we're running in-place or not + boost::filesystem::path executablePath = Paths::getExecutablePath(); + boost::filesystem::path topSourcePath = executablePath / ".." / ".."; + boost::filesystem::path topInstallPath = executablePath / ".."; + bool inPlace = !boost::filesystem::exists(topInstallPath / "include" / "Swiften" / "Swiften.h"); - // Replace "#" variables with the correct path - for(size_t i = 0; i < libs.size(); ++i) { - if (inPlace) { - std::string lib = libs[i]; - boost::replace_all(lib, "#", pathToString(topSourcePath)); - libs[i] = lib; - } - else { - std::string lib = libs[i]; - boost::replace_all(lib, "#", pathToString(topInstallPath / "lib")); - boost::erase_all(lib, "/Swiften"); - libs[i] = lib; - } - } - for(size_t i = 0; i < cflags.size(); ++i) { - if (inPlace) { - std::string cflag = cflags[i]; - boost::replace_all(cflag, "#", pathToString(topSourcePath)); - cflags[i] = cflag; - } - else { - std::string cflag = cflags[i]; - boost::replace_all(cflag, "#", pathToString(topInstallPath / "include")); - cflags[i] = cflag; - } - } + // Replace "#" variables with the correct path + for(auto & i : libs) { + if (inPlace) { + std::string lib = i; + boost::replace_all(lib, "#", pathToString(topSourcePath)); + i = lib; + } + else { + std::string lib = i; + boost::replace_all(lib, "#", pathToString(topInstallPath / "lib")); + boost::erase_all(lib, "/Swiften"); + i = lib; + } + } + for(auto & i : cflags) { + if (inPlace) { + std::string cflag = i; + boost::replace_all(cflag, "#", pathToString(topSourcePath)); + i = cflag; + } + else { + std::string cflag = i; + boost::replace_all(cflag, "#", pathToString(topInstallPath / "include")); + i = cflag; + } + } - // Print the requested variable - if (vm.count("libs") > 0) { - printFlags(libs); - } - if (vm.count("cflags") > 0) { - printFlags(cflags); - } - return 0; + // Print the requested variable + if (vm.count("libs") > 0) { + printFlags(libs); + } + if (vm.count("cflags") > 0) { + printFlags(cflags); + } + return 0; } diff --git a/Swiften/Crypto/CommonCryptoCryptoProvider.cpp b/Swiften/Crypto/CommonCryptoCryptoProvider.cpp index 14f9284..3cc69b0 100644 --- a/Swiften/Crypto/CommonCryptoCryptoProvider.cpp +++ b/Swiften/Crypto/CommonCryptoCryptoProvider.cpp @@ -1,110 +1,127 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2018 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/Crypto/CommonCryptoCryptoProvider.h> +#include <cassert> + +#include <boost/numeric/conversion/cast.hpp> + #include <CommonCrypto/CommonDigest.h> #include <CommonCrypto/CommonHMAC.h> -#include <cassert> -#include <Swiften/Crypto/Hash.h> #include <Swiften/Base/ByteArray.h> -#include <boost/numeric/conversion/cast.hpp> +#include <Swiften/Crypto/Hash.h> using namespace Swift; namespace { - class SHA1Hash : public Hash { - public: - SHA1Hash() : finalized(false) { - if (!CC_SHA1_Init(&context)) { - assert(false); - } - } - - ~SHA1Hash() { - } - - virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual std::vector<unsigned char> getHash() { - assert(!finalized); - std::vector<unsigned char> result(CC_SHA1_DIGEST_LENGTH); - CC_SHA1_Final(vecptr(result), &context); - return result; - } - - private: - template<typename ContainerType> - Hash& updateInternal(const ContainerType& data) { - assert(!finalized); - if (!CC_SHA1_Update(&context, vecptr(data), boost::numeric_cast<CC_LONG>(data.size()))) { - assert(false); - } - return *this; - } - - private: - CC_SHA1_CTX context; - bool finalized; - }; - - class MD5Hash : public Hash { - public: - MD5Hash() : finalized(false) { - if (!CC_MD5_Init(&context)) { - assert(false); - } - } - - ~MD5Hash() { - } - - virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual std::vector<unsigned char> getHash() { - assert(!finalized); - std::vector<unsigned char> result(CC_MD5_DIGEST_LENGTH); - CC_MD5_Final(vecptr(result), &context); - return result; - } - - private: - template<typename ContainerType> - Hash& updateInternal(const ContainerType& data) { - assert(!finalized); - if (!CC_MD5_Update(&context, vecptr(data), boost::numeric_cast<CC_LONG>(data.size()))) { - assert(false); - } - return *this; - } - - private: - CC_MD5_CTX context; - bool finalized; - }; - - template<typename T> - ByteArray getHMACSHA1Internal(const T& key, const ByteArray& data) { - std::vector<unsigned char> result(CC_SHA1_DIGEST_LENGTH); - CCHmac(kCCHmacAlgSHA1, vecptr(key), key.size(), vecptr(data), boost::numeric_cast<CC_LONG>(data.size()), vecptr(result)); - return result; - } + class SHA1Hash : public Hash { + public: + SHA1Hash() : finalized(false) { + if (!CC_SHA1_Init(&context)) { + assert(false); + } + } + + virtual ~SHA1Hash() override { + } + + virtual Hash& update(const ByteArray& data) override { + return updateInternal(data); + } + + virtual Hash& update(const SafeByteArray& data) override { + return updateInternal(data); + } + + virtual std::vector<unsigned char> getHash() override { + assert(!finalized); + std::vector<unsigned char> result(CC_SHA1_DIGEST_LENGTH); + CC_SHA1_Final(vecptr(result), &context); + return result; + } + + private: + template<typename ContainerType> + Hash& updateInternal(const ContainerType& data) { + assert(!finalized); + try { + if (!CC_SHA1_Update(&context, vecptr(data), boost::numeric_cast<CC_LONG>(data.size()))) { + assert(false); + } + } + catch (const boost::numeric::bad_numeric_cast&) { + assert(false); + } + return *this; + } + + private: + CC_SHA1_CTX context; + bool finalized; + }; + + class MD5Hash : public Hash { + public: + MD5Hash() : finalized(false) { + if (!CC_MD5_Init(&context)) { + assert(false); + } + } + + virtual ~MD5Hash() override { + } + + virtual Hash& update(const ByteArray& data) override { + return updateInternal(data); + } + + virtual Hash& update(const SafeByteArray& data) override { + return updateInternal(data); + } + + virtual std::vector<unsigned char> getHash() override { + assert(!finalized); + std::vector<unsigned char> result(CC_MD5_DIGEST_LENGTH); + CC_MD5_Final(vecptr(result), &context); + return result; + } + + private: + template<typename ContainerType> + Hash& updateInternal(const ContainerType& data) { + assert(!finalized); + try { + if (!CC_MD5_Update(&context, vecptr(data), boost::numeric_cast<CC_LONG>(data.size()))) { + assert(false); + } + } + catch (const boost::numeric::bad_numeric_cast&) { + assert(false); + } + return *this; + } + + private: + CC_MD5_CTX context; + bool finalized; + }; + + template<typename T> + ByteArray getHMACSHA1Internal(const T& key, const ByteArray& data) { + std::vector<unsigned char> result(CC_SHA1_DIGEST_LENGTH); + try { + CCHmac(kCCHmacAlgSHA1, vecptr(key), key.size(), vecptr(data), boost::numeric_cast<CC_LONG>(data.size()), vecptr(result)); + } + catch (const boost::numeric::bad_numeric_cast&) { + assert(false); + } + return result; + } } CommonCryptoCryptoProvider::CommonCryptoCryptoProvider() { @@ -114,22 +131,22 @@ CommonCryptoCryptoProvider::~CommonCryptoCryptoProvider() { } Hash* CommonCryptoCryptoProvider::createSHA1() { - return new SHA1Hash(); + return new SHA1Hash(); } Hash* CommonCryptoCryptoProvider::createMD5() { - return new MD5Hash(); + return new MD5Hash(); } ByteArray CommonCryptoCryptoProvider::getHMACSHA1(const SafeByteArray& key, const ByteArray& data) { - return getHMACSHA1Internal(key, data); + return getHMACSHA1Internal(key, data); } ByteArray CommonCryptoCryptoProvider::getHMACSHA1(const ByteArray& key, const ByteArray& data) { - return getHMACSHA1Internal(key, data); + return getHMACSHA1Internal(key, data); } bool CommonCryptoCryptoProvider::isMD5AllowedForCrypto() const { - return true; + return true; } diff --git a/Swiften/Crypto/CommonCryptoCryptoProvider.h b/Swiften/Crypto/CommonCryptoCryptoProvider.h index f921e17..7d1675f 100644 --- a/Swiften/Crypto/CommonCryptoCryptoProvider.h +++ b/Swiften/Crypto/CommonCryptoCryptoProvider.h @@ -1,24 +1,24 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Base/Override.h> namespace Swift { - class CommonCryptoCryptoProvider : public CryptoProvider { - public: - CommonCryptoCryptoProvider(); - ~CommonCryptoCryptoProvider(); + class SWIFTEN_API CommonCryptoCryptoProvider : public CryptoProvider { + public: + CommonCryptoCryptoProvider(); + virtual ~CommonCryptoCryptoProvider() override; - virtual Hash* createSHA1() SWIFTEN_OVERRIDE; - virtual Hash* createMD5() SWIFTEN_OVERRIDE; - virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE; - virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE; - virtual bool isMD5AllowedForCrypto() const SWIFTEN_OVERRIDE; - }; + virtual Hash* createSHA1() override; + virtual Hash* createMD5() override; + virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) override; + virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) override; + virtual bool isMD5AllowedForCrypto() const override; + }; } diff --git a/Swiften/Crypto/CryptoProvider.cpp b/Swiften/Crypto/CryptoProvider.cpp index 0189de4..9c7c637 100644 --- a/Swiften/Crypto/CryptoProvider.cpp +++ b/Swiften/Crypto/CryptoProvider.cpp @@ -1,14 +1,14 @@ -/*
- * Copyright (c) 2013 Remko Tronçon
- * Licensed under the GNU General Public License.
- * See the COPYING file for more information.
- */
-
-#include <Swiften/Crypto/CryptoProvider.h>
-
-#include <boost/shared_ptr.hpp>
-
-using namespace Swift;
-
-CryptoProvider::~CryptoProvider() {
-}
+/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Crypto/CryptoProvider.h> + +#include <memory> + +using namespace Swift; + +CryptoProvider::~CryptoProvider() { +} diff --git a/Swiften/Crypto/CryptoProvider.h b/Swiften/Crypto/CryptoProvider.h index c1e1eb9..3eaeeb3 100644 --- a/Swiften/Crypto/CryptoProvider.h +++ b/Swiften/Crypto/CryptoProvider.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -12,25 +12,25 @@ #include <Swiften/Crypto/Hash.h> namespace Swift { - class Hash; + class Hash; - class SWIFTEN_API CryptoProvider { - public: - virtual ~CryptoProvider(); + class SWIFTEN_API CryptoProvider { + public: + virtual ~CryptoProvider(); - virtual Hash* createSHA1() = 0; - virtual Hash* createMD5() = 0; - virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) = 0; - virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) = 0; - virtual bool isMD5AllowedForCrypto() const = 0; + virtual Hash* createSHA1() = 0; + virtual Hash* createMD5() = 0; + virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) = 0; + virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) = 0; + virtual bool isMD5AllowedForCrypto() const = 0; - // Convenience - template<typename T> ByteArray getSHA1Hash(const T& data) { - return boost::shared_ptr<Hash>(createSHA1())->update(data).getHash(); - } + // Convenience + template<typename T> ByteArray getSHA1Hash(const T& data) { + return std::shared_ptr<Hash>(createSHA1())->update(data).getHash(); + } - template<typename T> ByteArray getMD5Hash(const T& data) { - return boost::shared_ptr<Hash>(createMD5())->update(data).getHash(); - } - }; + template<typename T> ByteArray getMD5Hash(const T& data) { + return std::shared_ptr<Hash>(createMD5())->update(data).getHash(); + } + }; } diff --git a/Swiften/Crypto/Hash.cpp b/Swiften/Crypto/Hash.cpp index 35c7e70..b945301 100644 --- a/Swiften/Crypto/Hash.cpp +++ b/Swiften/Crypto/Hash.cpp @@ -1,12 +1,12 @@ -/*
- * Copyright (c) 2013 Remko Tronçon
- * Licensed under the GNU General Public License.
- * See the COPYING file for more information.
- */
-
-#include <Swiften/Crypto/Hash.h>
-
-using namespace Swift;
-
-Hash::~Hash() {
-}
+/* + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Crypto/Hash.h> + +using namespace Swift; + +Hash::~Hash() { +} diff --git a/Swiften/Crypto/Hash.h b/Swiften/Crypto/Hash.h index 37c6ec8..a9ed323 100644 --- a/Swiften/Crypto/Hash.h +++ b/Swiften/Crypto/Hash.h @@ -1,24 +1,25 @@ -/*
- * Copyright (c) 2013 Remko Tronçon
- * Licensed under the GNU General Public License.
- * See the COPYING file for more information.
- */
-
-#pragma once
-
-#include <vector>
-
-#include <Swiften/Base/ByteArray.h>
-#include <Swiften/Base/SafeByteArray.h>
-
-namespace Swift {
- class Hash {
- public:
- virtual ~Hash();
-
- virtual Hash& update(const ByteArray& data) = 0;
- virtual Hash& update(const SafeByteArray& data) = 0;
-
- virtual std::vector<unsigned char> getHash() = 0;
- };
-}
+/* + * Copyright (c) 2013-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <vector> + +#include <Swiften/Base/API.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/SafeByteArray.h> + +namespace Swift { + class SWIFTEN_API Hash { + public: + virtual ~Hash(); + + virtual Hash& update(const ByteArray& data) = 0; + virtual Hash& update(const SafeByteArray& data) = 0; + + virtual std::vector<unsigned char> getHash() = 0; + }; +} diff --git a/Swiften/Crypto/OpenSSLCryptoProvider.cpp b/Swiften/Crypto/OpenSSLCryptoProvider.cpp index 9b1d544..5245bd8 100644 --- a/Swiften/Crypto/OpenSSLCryptoProvider.cpp +++ b/Swiften/Crypto/OpenSSLCryptoProvider.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2018 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -20,96 +20,101 @@ using namespace Swift; namespace { - class SHA1Hash : public Hash { - public: - SHA1Hash() : finalized(false) { - if (!SHA1_Init(&context)) { - assert(false); - } - } - - ~SHA1Hash() { - } - - virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual std::vector<unsigned char> getHash() { - assert(!finalized); - std::vector<unsigned char> result(SHA_DIGEST_LENGTH); - SHA1_Final(vecptr(result), &context); - return result; - } - - private: - template<typename ContainerType> - Hash& updateInternal(const ContainerType& data) { - assert(!finalized); - if (!SHA1_Update(&context, vecptr(data), data.size())) { - assert(false); - } - return *this; - } - - private: - SHA_CTX context; - bool finalized; - }; - - class MD5Hash : public Hash { - public: - MD5Hash() : finalized(false) { - if (!MD5_Init(&context)) { - assert(false); - } - } - - ~MD5Hash() { - } - - virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual std::vector<unsigned char> getHash() { - assert(!finalized); - std::vector<unsigned char> result(MD5_DIGEST_LENGTH); - MD5_Final(vecptr(result), &context); - return result; - } - - private: - template<typename ContainerType> - Hash& updateInternal(const ContainerType& data) { - assert(!finalized); - if (!MD5_Update(&context, vecptr(data), data.size())) { - assert(false); - } - return *this; - } - - private: - MD5_CTX context; - bool finalized; - }; - - - template<typename T> - ByteArray getHMACSHA1Internal(const T& key, const ByteArray& data) { - unsigned int len = SHA_DIGEST_LENGTH; - std::vector<unsigned char> result(len); - HMAC(EVP_sha1(), vecptr(key), boost::numeric_cast<int>(key.size()), vecptr(data), data.size(), vecptr(result), &len); - return result; - } + class SHA1Hash : public Hash { + public: + SHA1Hash() : finalized(false) { + if (!SHA1_Init(&context)) { + assert(false); + } + } + + ~SHA1Hash() override { + } + + virtual Hash& update(const ByteArray& data) override { + return updateInternal(data); + } + + virtual Hash& update(const SafeByteArray& data) override { + return updateInternal(data); + } + + virtual std::vector<unsigned char> getHash() override { + assert(!finalized); + std::vector<unsigned char> result(SHA_DIGEST_LENGTH); + SHA1_Final(vecptr(result), &context); + return result; + } + + private: + template<typename ContainerType> + Hash& updateInternal(const ContainerType& data) { + assert(!finalized); + if (!SHA1_Update(&context, vecptr(data), data.size())) { + assert(false); + } + return *this; + } + + private: + SHA_CTX context; + bool finalized; + }; + + class MD5Hash : public Hash { + public: + MD5Hash() : finalized(false) { + if (!MD5_Init(&context)) { + assert(false); + } + } + + ~MD5Hash() override { + } + + virtual Hash& update(const ByteArray& data) override { + return updateInternal(data); + } + + virtual Hash& update(const SafeByteArray& data) override { + return updateInternal(data); + } + + virtual std::vector<unsigned char> getHash() override { + assert(!finalized); + std::vector<unsigned char> result(MD5_DIGEST_LENGTH); + MD5_Final(vecptr(result), &context); + return result; + } + + private: + template<typename ContainerType> + Hash& updateInternal(const ContainerType& data) { + assert(!finalized); + if (!MD5_Update(&context, vecptr(data), data.size())) { + assert(false); + } + return *this; + } + + private: + MD5_CTX context; + bool finalized; + }; + + + template<typename T> + ByteArray getHMACSHA1Internal(const T& key, const ByteArray& data) { + unsigned int len = SHA_DIGEST_LENGTH; + std::vector<unsigned char> result(len); + try { + HMAC(EVP_sha1(), vecptr(key), boost::numeric_cast<int>(key.size()), vecptr(data), data.size(), vecptr(result), &len); + } + catch (const boost::numeric::bad_numeric_cast&) { + assert(false); + } + return result; + } } OpenSSLCryptoProvider::OpenSSLCryptoProvider() { @@ -119,22 +124,22 @@ OpenSSLCryptoProvider::~OpenSSLCryptoProvider() { } Hash* OpenSSLCryptoProvider::createSHA1() { - return new SHA1Hash(); + return new SHA1Hash(); } Hash* OpenSSLCryptoProvider::createMD5() { - return new MD5Hash(); + return new MD5Hash(); } ByteArray OpenSSLCryptoProvider::getHMACSHA1(const SafeByteArray& key, const ByteArray& data) { - return getHMACSHA1Internal(key, data); + return getHMACSHA1Internal(key, data); } ByteArray OpenSSLCryptoProvider::getHMACSHA1(const ByteArray& key, const ByteArray& data) { - return getHMACSHA1Internal(key, data); + return getHMACSHA1Internal(key, data); } bool OpenSSLCryptoProvider::isMD5AllowedForCrypto() const { - return true; + return true; } diff --git a/Swiften/Crypto/OpenSSLCryptoProvider.h b/Swiften/Crypto/OpenSSLCryptoProvider.h index 9440aee..e4ee97d 100644 --- a/Swiften/Crypto/OpenSSLCryptoProvider.h +++ b/Swiften/Crypto/OpenSSLCryptoProvider.h @@ -1,24 +1,23 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Base/Override.h> namespace Swift { - class OpenSSLCryptoProvider : public CryptoProvider { - public: - OpenSSLCryptoProvider(); - ~OpenSSLCryptoProvider(); + class OpenSSLCryptoProvider : public CryptoProvider { + public: + OpenSSLCryptoProvider(); + virtual ~OpenSSLCryptoProvider() override; - virtual Hash* createSHA1() SWIFTEN_OVERRIDE; - virtual Hash* createMD5() SWIFTEN_OVERRIDE; - virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE; - virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE; - virtual bool isMD5AllowedForCrypto() const SWIFTEN_OVERRIDE; - }; + virtual Hash* createSHA1() override; + virtual Hash* createMD5() override; + virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) override; + virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) override; + virtual bool isMD5AllowedForCrypto() const override; + }; } diff --git a/Swiften/Crypto/PlatformCryptoProvider.cpp b/Swiften/Crypto/PlatformCryptoProvider.cpp index ab0fa7b..a72bf8e 100644 --- a/Swiften/Crypto/PlatformCryptoProvider.cpp +++ b/Swiften/Crypto/PlatformCryptoProvider.cpp @@ -1,32 +1,32 @@ -/*
- * Copyright (c) 2013 Remko Tronçon
- * Licensed under the GNU General Public License.
- * See the COPYING file for more information.
- */
-
-#include <Swiften/Crypto/PlatformCryptoProvider.h>
-
-#include <cassert>
-
-#include <Swiften/Base/Platform.h>
-#if defined(SWIFTEN_PLATFORM_WIN32)
-#include <Swiften/Crypto/WindowsCryptoProvider.h>
-#elif defined(HAVE_COMMONCRYPTO_CRYPTO_PROVIDER)
-#include <Swiften/Crypto/CommonCryptoCryptoProvider.h>
-#elif defined(HAVE_OPENSSL_CRYPTO_PROVIDER)
-#include <Swiften/Crypto/OpenSSLCryptoProvider.h>
-#endif
-
-using namespace Swift;
-
-CryptoProvider* PlatformCryptoProvider::create() {
-#if defined(SWIFTEN_PLATFORM_WIN32)
- return new WindowsCryptoProvider();
-#elif defined(HAVE_COMMONCRYPTO_CRYPTO_PROVIDER)
- return new CommonCryptoCryptoProvider();
-#elif defined(HAVE_OPENSSL_CRYPTO_PROVIDER)
- return new OpenSSLCryptoProvider();
-#endif
- assert(false);
- return NULL;
-}
+/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Crypto/PlatformCryptoProvider.h> + +#include <cassert> + +#include <Swiften/Base/Platform.h> +#if defined(SWIFTEN_PLATFORM_WIN32) +#include <Swiften/Crypto/WindowsCryptoProvider.h> +#elif defined(HAVE_COMMONCRYPTO_CRYPTO_PROVIDER) +#include <Swiften/Crypto/CommonCryptoCryptoProvider.h> +#elif defined(HAVE_OPENSSL_CRYPTO_PROVIDER) +#include <Swiften/Crypto/OpenSSLCryptoProvider.h> +#endif + +using namespace Swift; + +CryptoProvider* PlatformCryptoProvider::create() { +#if defined(SWIFTEN_PLATFORM_WIN32) + return new WindowsCryptoProvider(); +#elif defined(HAVE_COMMONCRYPTO_CRYPTO_PROVIDER) + return new CommonCryptoCryptoProvider(); +#elif defined(HAVE_OPENSSL_CRYPTO_PROVIDER) + return new OpenSSLCryptoProvider(); +#endif + assert(false); + return nullptr; +} diff --git a/Swiften/Crypto/PlatformCryptoProvider.h b/Swiften/Crypto/PlatformCryptoProvider.h index 0721887..1133ae5 100644 --- a/Swiften/Crypto/PlatformCryptoProvider.h +++ b/Swiften/Crypto/PlatformCryptoProvider.h @@ -1,17 +1,17 @@ -/*
- * Copyright (c) 2013 Remko Tronçon
- * Licensed under the GNU General Public License.
- * See the COPYING file for more information.
- */
-
-#pragma once
-
-#include <Swiften/Base/API.h>
-
-namespace Swift {
- class CryptoProvider;
-
- namespace PlatformCryptoProvider {
- SWIFTEN_API CryptoProvider* create();
- }
-}
+/* + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> + +namespace Swift { + class CryptoProvider; + + namespace PlatformCryptoProvider { + SWIFTEN_API CryptoProvider* create(); + } +} diff --git a/Swiften/Crypto/SConscript b/Swiften/Crypto/SConscript index ce4bdae..d5532fd 100644 --- a/Swiften/Crypto/SConscript +++ b/Swiften/Crypto/SConscript @@ -2,27 +2,27 @@ Import("swiften_env", "env") objects = swiften_env.SwiftenObject([
- "CryptoProvider.cpp",
- "Hash.cpp"
+ "CryptoProvider.cpp",
+ "Hash.cpp"
])
myenv = swiften_env.Clone()
if myenv["PLATFORM"] == "win32" :
- objects += myenv.SwiftenObject(["WindowsCryptoProvider.cpp"])
+ objects += myenv.SwiftenObject(["WindowsCryptoProvider.cpp"])
if myenv.get("HAVE_OPENSSL", False) :
- myenv.Append(CPPDEFINES = ["HAVE_OPENSSL_CRYPTO_PROVIDER"])
- objects += myenv.SwiftenObject(["OpenSSLCryptoProvider.cpp"])
+ myenv.Append(CPPDEFINES = ["HAVE_OPENSSL_CRYPTO_PROVIDER"])
+ objects += myenv.SwiftenObject(["OpenSSLCryptoProvider.cpp"])
if myenv["PLATFORM"] == "darwin" and myenv["target"] == "native" :
- myenv.Append(CPPDEFINES = ["HAVE_COMMONCRYPTO_CRYPTO_PROVIDER"])
- objects += myenv.SwiftenObject(["CommonCryptoCryptoProvider.cpp"])
+ myenv.Append(CPPDEFINES = ["HAVE_COMMONCRYPTO_CRYPTO_PROVIDER"])
+ objects += myenv.SwiftenObject(["CommonCryptoCryptoProvider.cpp"])
objects += myenv.SwiftenObject(["PlatformCryptoProvider.cpp"])
swiften_env.Append(SWIFTEN_OBJECTS = [objects])
if env["TEST"] :
- test_env = myenv.Clone()
- test_env.UseFlags(swiften_env["CPPUNIT_FLAGS"])
- env.Append(UNITTEST_OBJECTS = test_env.SwiftenObject([
- File("UnitTest/CryptoProviderTest.cpp"),
- ]))
+ test_env = myenv.Clone()
+ test_env.UseFlags(swiften_env["CPPUNIT_FLAGS"])
+ env.Append(UNITTEST_OBJECTS = test_env.SwiftenObject([
+ File("UnitTest/CryptoProviderTest.cpp"),
+ ]))
diff --git a/Swiften/Crypto/UnitTest/CryptoProviderTest.cpp b/Swiften/Crypto/UnitTest/CryptoProviderTest.cpp index 1e2275a..72eb81d 100644 --- a/Swiften/Crypto/UnitTest/CryptoProviderTest.cpp +++ b/Swiften/Crypto/UnitTest/CryptoProviderTest.cpp @@ -1,156 +1,156 @@ -/*
- * Copyright (c) 2010-2013 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <Swiften/Base/ByteArray.h>
-#include <Swiften/Base/Platform.h>
-#include <QA/Checker/IO.h>
-
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
-
-#ifdef SWIFTEN_PLATFORM_WIN32
-#include <Swiften/Crypto/WindowsCryptoProvider.h>
-#endif
-#ifdef HAVE_OPENSSL_CRYPTO_PROVIDER
-#include <Swiften/Crypto/OpenSSLCryptoProvider.h>
-#endif
-#ifdef HAVE_OPENSSL_CRYPTO_PROVIDER
-#include <Swiften/Crypto/CommonCryptoCryptoProvider.h>
-#endif
-#include <Swiften/Crypto/Hash.h>
-
-using namespace Swift;
-
-template <typename CryptoProviderType>
-class CryptoProviderTest : public CppUnit::TestFixture {
- CPPUNIT_TEST_SUITE(CryptoProviderTest);
-
- CPPUNIT_TEST(testGetSHA1Hash);
- CPPUNIT_TEST(testGetSHA1Hash_TwoUpdates);
- CPPUNIT_TEST(testGetSHA1Hash_NoData);
- CPPUNIT_TEST(testGetSHA1HashStatic);
- CPPUNIT_TEST(testGetSHA1HashStatic_Twice);
- CPPUNIT_TEST(testGetSHA1HashStatic_NoData);
-
- CPPUNIT_TEST(testGetMD5Hash_Empty);
- CPPUNIT_TEST(testGetMD5Hash_Alphabet);
- CPPUNIT_TEST(testMD5Incremental);
-
- CPPUNIT_TEST(testGetHMACSHA1);
- CPPUNIT_TEST(testGetHMACSHA1_KeyLongerThanBlockSize);
-
- CPPUNIT_TEST_SUITE_END();
-
- public:
- void setUp() {
- provider = new CryptoProviderType();
- }
-
- void tearDown() {
- delete provider;
- }
-
- ////////////////////////////////////////////////////////////
- // SHA-1
- ////////////////////////////////////////////////////////////
-
- void testGetSHA1Hash() {
- boost::shared_ptr<Hash> sha = boost::shared_ptr<Hash>(provider->createSHA1());
- sha->update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
-
- CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha->getHash());
- }
-
- void testGetSHA1Hash_TwoUpdates() {
- boost::shared_ptr<Hash> sha = boost::shared_ptr<Hash>(provider->createSHA1());
- sha->update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<"));
- sha->update(createByteArray("http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
-
- CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha->getHash());
- }
-
- void testGetSHA1Hash_NoData() {
- boost::shared_ptr<Hash> sha = boost::shared_ptr<Hash>(provider->createSHA1());
- sha->update(std::vector<unsigned char>());
-
- CPPUNIT_ASSERT_EQUAL(createByteArray("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09"), sha->getHash());
- }
-
- void testGetSHA1HashStatic() {
- ByteArray result(provider->getSHA1Hash(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<")));
- CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), result);
- }
-
-
- void testGetSHA1HashStatic_Twice() {
- ByteArray input(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
- provider->getSHA1Hash(input);
- ByteArray result(provider->getSHA1Hash(input));
-
- CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), result);
- }
-
- void testGetSHA1HashStatic_NoData() {
- ByteArray result(provider->getSHA1Hash(ByteArray()));
-
- CPPUNIT_ASSERT_EQUAL(createByteArray("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09"), result);
- }
-
-
- ////////////////////////////////////////////////////////////
- // MD5
- ////////////////////////////////////////////////////////////
-
- void testGetMD5Hash_Empty() {
- ByteArray result(provider->getMD5Hash(createByteArray("")));
-
- CPPUNIT_ASSERT_EQUAL(createByteArray("\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e", 16), result);
- }
-
- void testGetMD5Hash_Alphabet() {
- ByteArray result(provider->getMD5Hash(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")));
-
- CPPUNIT_ASSERT_EQUAL(createByteArray("\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f", 16), result);
- }
-
- void testMD5Incremental() {
- boost::shared_ptr<Hash> testling = boost::shared_ptr<Hash>(provider->createMD5());
- testling->update(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
- testling->update(createByteArray("abcdefghijklmnopqrstuvwxyz0123456789"));
-
- ByteArray result = testling->getHash();
-
- CPPUNIT_ASSERT_EQUAL(createByteArray("\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f", 16), result);
- }
-
-
- ////////////////////////////////////////////////////////////
- // HMAC-SHA1
- ////////////////////////////////////////////////////////////
-
- void testGetHMACSHA1() {
- ByteArray result(provider->getHMACSHA1(createSafeByteArray("foo"), createByteArray("foobar")));
- CPPUNIT_ASSERT_EQUAL(createByteArray("\xa4\xee\xba\x8e\x63\x3d\x77\x88\x69\xf5\x68\xd0\x5a\x1b\x3d\xc7\x2b\xfd\x4\xdd"), result);
- }
-
- void testGetHMACSHA1_KeyLongerThanBlockSize() {
- ByteArray result(provider->getHMACSHA1(createSafeByteArray("---------|---------|---------|---------|---------|----------|---------|"), createByteArray("foobar")));
- CPPUNIT_ASSERT_EQUAL(createByteArray("\xd6""n""\x8f""P|1""\xd3"",""\x6"" ""\xb9\xe3""gg""\x8e\xcf"" ]+""\xa"), result);
- }
-
- private:
- CryptoProviderType* provider;
-};
-
-#ifdef SWIFTEN_PLATFORM_WIN32
-CPPUNIT_TEST_SUITE_REGISTRATION(CryptoProviderTest<WindowsCryptoProvider>);
-#endif
-#ifdef HAVE_OPENSSL_CRYPTO_PROVIDER
-CPPUNIT_TEST_SUITE_REGISTRATION(CryptoProviderTest<OpenSSLCryptoProvider>);
-#endif
-#ifdef HAVE_COMMONCRYPTO_CRYPTO_PROVIDER
-CPPUNIT_TEST_SUITE_REGISTRATION(CryptoProviderTest<CommonCryptoCryptoProvider>);
-#endif
+/* + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Platform.h> +#include <QA/Checker/IO.h> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#ifdef SWIFTEN_PLATFORM_WIN32 +#include <Swiften/Crypto/WindowsCryptoProvider.h> +#endif +#ifdef HAVE_OPENSSL_CRYPTO_PROVIDER +#include <Swiften/Crypto/OpenSSLCryptoProvider.h> +#endif +#ifdef HAVE_COMMONCRYPTO_CRYPTO_PROVIDER +#include <Swiften/Crypto/CommonCryptoCryptoProvider.h> +#endif +#include <Swiften/Crypto/Hash.h> + +using namespace Swift; + +template <typename CryptoProviderType> +class CryptoProviderTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(CryptoProviderTest); + + CPPUNIT_TEST(testGetSHA1Hash); + CPPUNIT_TEST(testGetSHA1Hash_TwoUpdates); + CPPUNIT_TEST(testGetSHA1Hash_NoData); + CPPUNIT_TEST(testGetSHA1HashStatic); + CPPUNIT_TEST(testGetSHA1HashStatic_Twice); + CPPUNIT_TEST(testGetSHA1HashStatic_NoData); + + CPPUNIT_TEST(testGetMD5Hash_Empty); + CPPUNIT_TEST(testGetMD5Hash_Alphabet); + CPPUNIT_TEST(testMD5Incremental); + + CPPUNIT_TEST(testGetHMACSHA1); + CPPUNIT_TEST(testGetHMACSHA1_KeyLongerThanBlockSize); + + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + provider = new CryptoProviderType(); + } + + void tearDown() { + delete provider; + } + + //////////////////////////////////////////////////////////// + // SHA-1 + //////////////////////////////////////////////////////////// + + void testGetSHA1Hash() { + std::shared_ptr<Hash> sha = std::shared_ptr<Hash>(provider->createSHA1()); + sha->update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<")); + + CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha->getHash()); + } + + void testGetSHA1Hash_TwoUpdates() { + std::shared_ptr<Hash> sha = std::shared_ptr<Hash>(provider->createSHA1()); + sha->update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<")); + sha->update(createByteArray("http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<")); + + CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha->getHash()); + } + + void testGetSHA1Hash_NoData() { + std::shared_ptr<Hash> sha = std::shared_ptr<Hash>(provider->createSHA1()); + sha->update(std::vector<unsigned char>()); + + CPPUNIT_ASSERT_EQUAL(createByteArray("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09"), sha->getHash()); + } + + void testGetSHA1HashStatic() { + ByteArray result(provider->getSHA1Hash(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"))); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), result); + } + + + void testGetSHA1HashStatic_Twice() { + ByteArray input(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<")); + provider->getSHA1Hash(input); + ByteArray result(provider->getSHA1Hash(input)); + + CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), result); + } + + void testGetSHA1HashStatic_NoData() { + ByteArray result(provider->getSHA1Hash(ByteArray())); + + CPPUNIT_ASSERT_EQUAL(createByteArray("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09"), result); + } + + + //////////////////////////////////////////////////////////// + // MD5 + //////////////////////////////////////////////////////////// + + void testGetMD5Hash_Empty() { + ByteArray result(provider->getMD5Hash(createByteArray(""))); + + CPPUNIT_ASSERT_EQUAL(createByteArray("\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e", 16), result); + } + + void testGetMD5Hash_Alphabet() { + ByteArray result(provider->getMD5Hash(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"))); + + CPPUNIT_ASSERT_EQUAL(createByteArray("\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f", 16), result); + } + + void testMD5Incremental() { + std::shared_ptr<Hash> testling = std::shared_ptr<Hash>(provider->createMD5()); + testling->update(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); + testling->update(createByteArray("abcdefghijklmnopqrstuvwxyz0123456789")); + + ByteArray result = testling->getHash(); + + CPPUNIT_ASSERT_EQUAL(createByteArray("\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f", 16), result); + } + + + //////////////////////////////////////////////////////////// + // HMAC-SHA1 + //////////////////////////////////////////////////////////// + + void testGetHMACSHA1() { + ByteArray result(provider->getHMACSHA1(createSafeByteArray("foo"), createByteArray("foobar"))); + CPPUNIT_ASSERT_EQUAL(createByteArray("\xa4\xee\xba\x8e\x63\x3d\x77\x88\x69\xf5\x68\xd0\x5a\x1b\x3d\xc7\x2b\xfd\x4\xdd"), result); + } + + void testGetHMACSHA1_KeyLongerThanBlockSize() { + ByteArray result(provider->getHMACSHA1(createSafeByteArray("---------|---------|---------|---------|---------|----------|---------|"), createByteArray("foobar"))); + CPPUNIT_ASSERT_EQUAL(createByteArray("\xd6""n""\x8f""P|1""\xd3"",""\x6"" ""\xb9\xe3""gg""\x8e\xcf"" ]+""\xa"), result); + } + + private: + CryptoProviderType* provider; +}; + +#ifdef SWIFTEN_PLATFORM_WIN32 +CPPUNIT_TEST_SUITE_REGISTRATION(CryptoProviderTest<WindowsCryptoProvider>); +#endif +#ifdef HAVE_OPENSSL_CRYPTO_PROVIDER +CPPUNIT_TEST_SUITE_REGISTRATION(CryptoProviderTest<OpenSSLCryptoProvider>); +#endif +#ifdef HAVE_COMMONCRYPTO_CRYPTO_PROVIDER +CPPUNIT_TEST_SUITE_REGISTRATION(CryptoProviderTest<CommonCryptoCryptoProvider>); +#endif diff --git a/Swiften/Crypto/WindowsCryptoProvider.cpp b/Swiften/Crypto/WindowsCryptoProvider.cpp index 9ca4c14..c784283 100644 --- a/Swiften/Crypto/WindowsCryptoProvider.cpp +++ b/Swiften/Crypto/WindowsCryptoProvider.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License. + * Copyright (c) 2012-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -17,7 +17,7 @@ #include <security.h> #include <Wincrypt.h> #include <cassert> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Crypto/Hash.h> #include <Swiften/Base/ByteArray.h> @@ -27,196 +27,195 @@ using namespace Swift; struct WindowsCryptoProvider::Private { - HCRYPTPROV context; + HCRYPTPROV context; }; namespace { - class WindowsHash : public Hash { - public: - WindowsHash(HCRYPTPROV context, ALG_ID algorithm) : hash(NULL) { - if (!CryptCreateHash(context, algorithm, 0, 0, &hash)) { - assert(false); - } - } - - ~WindowsHash() { - CryptDestroyHash(hash); - } - - virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual std::vector<unsigned char> getHash() { - std::vector<unsigned char> result; - DWORD hashLength = sizeof(DWORD); - DWORD hashSize; - CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0); - result.resize(static_cast<size_t>(hashSize)); - if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) { - assert(false); - } - result.resize(static_cast<size_t>(hashSize)); - return result; - } - - private: - template<typename ContainerType> - Hash& updateInternal(const ContainerType& data) { - if (!CryptHashData(hash, const_cast<BYTE*>(vecptr(data)), data.size(), 0)) { - assert(false); - } - return *this; - } - - private: - HCRYPTHASH hash; - }; + class WindowsHash : public Hash { + public: + WindowsHash(HCRYPTPROV context, ALG_ID algorithm) : hash(NULL) { + if (!CryptCreateHash(context, algorithm, 0, 0, &hash)) { + assert(false); + } + } + + virtual ~WindowsHash() { + CryptDestroyHash(hash); + } + + virtual Hash& update(const ByteArray& data) override { + return updateInternal(data); + } + + virtual Hash& update(const SafeByteArray& data) override { + return updateInternal(data); + } + + virtual std::vector<unsigned char> getHash() { + std::vector<unsigned char> result; + DWORD hashLength = sizeof(DWORD); + DWORD hashSize; + CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0); + result.resize(static_cast<size_t>(hashSize)); + if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) { + assert(false); + } + result.resize(static_cast<size_t>(hashSize)); + return result; + } + + private: + template<typename ContainerType> + Hash& updateInternal(const ContainerType& data) { + if (!CryptHashData(hash, const_cast<BYTE*>(vecptr(data)), data.size(), 0)) { + assert(false); + } + return *this; + } + + private: + HCRYPTHASH hash; + }; #if 0 // NOT YET DONE - // Haven't tested the code below properly yet, but figured out after writing - // it that PLAINTEXTKEYBLOB doesn't work on XP or 2k, and the workaround is a - // bit too ugly to try this now. So, using our own algorithm for now. See - // http://support.microsoft.com/kb/228786/en-us - - // MSDN describes this as PLAINTEXTKEYBLOB, but this struct doesn't exist, - // and seems to even conflict with the PLAINTEXTKEYBLOB constant. Redefining - // here. - struct PlainTextKeyBlob { - BLOBHEADER hdr; - DWORD dwKeySize; - }; - - class HMACHash : public Hash { - public: - template<typename T> - HMACHash(HCRYPTPROV context, const T& rawKey) : hash(NULL) { - // Import raw key - T blobData(sizeof(PlainTextKeyBlob) + rawKey.size()); - PlainTextKeyBlob* blob = reinterpret_cast<PlainTextKeyBlob*>(vecptr(blobData)); - blob->hdr.bType = PLAINTEXTKEYBLOB; - blob->hdr.bVersion = CUR_BLOB_VERSION; - blob->hdr.reserved = 0; - blob->hdr.aiKeyAlg = CALG_RC2; - blob->dwKeySize = rawKey.size(); - std::copy(rawKey.begin(), rawKey.end(), blobData.begin() + sizeof(PlainTextKeyBlob)); - HCRYPTKEY key; - if (!CryptImportKey(context, vecptr(blobData), blobData.size(), 0, CRYPT_IPSEC_HMAC_KEY, &key)) { - assert(false); - return; - } - - // Create hash - if (!CryptCreateHash(context, CALG_HMAC, key, 0, &hash)) { - assert(false); - return; - } - ZeroMemory(&info, sizeof(info)); - info.HashAlgid = CALG_SHA1; - } - - ~HMACHash() { - CryptDestroyHash(hash); - } - - virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE { - return updateInternal(data); - } - - virtual std::vector<unsigned char> getHash() { - std::vector<unsigned char> result; - DWORD hashLength = sizeof(DWORD); - DWORD hashSize; - CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0); - result.resize(static_cast<size_t>(hashSize)); - if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) { - assert(false); - } - result.resize(static_cast<size_t>(hashSize)); - return result; - } - - private: - template<typename ContainerType> - Hash& updateInternal(const ContainerType& data) { - if (!CryptHashData(hash, const_cast<BYTE*>(vecptr(data)), data.size(), 0)) { - assert(false); - } - return *this; - } - - private: - HCRYPTHASH hash; - HMAC_INFO info; - }; + // Haven't tested the code below properly yet, but figured out after writing + // it that PLAINTEXTKEYBLOB doesn't work on XP or 2k, and the workaround is a + // bit too ugly to try this now. So, using our own algorithm for now. See + // http://support.microsoft.com/kb/228786/en-us + + // MSDN describes this as PLAINTEXTKEYBLOB, but this struct doesn't exist, + // and seems to even conflict with the PLAINTEXTKEYBLOB constant. Redefining + // here. + struct PlainTextKeyBlob { + BLOBHEADER hdr; + DWORD dwKeySize; + }; + + class HMACHash : public Hash { + public: + template<typename T> + HMACHash(HCRYPTPROV context, const T& rawKey) : hash(NULL) { + // Import raw key + T blobData(sizeof(PlainTextKeyBlob) + rawKey.size()); + PlainTextKeyBlob* blob = reinterpret_cast<PlainTextKeyBlob*>(vecptr(blobData)); + blob->hdr.bType = PLAINTEXTKEYBLOB; + blob->hdr.bVersion = CUR_BLOB_VERSION; + blob->hdr.reserved = 0; + blob->hdr.aiKeyAlg = CALG_RC2; + blob->dwKeySize = rawKey.size(); + std::copy(rawKey.begin(), rawKey.end(), blobData.begin() + sizeof(PlainTextKeyBlob)); + HCRYPTKEY key; + if (!CryptImportKey(context, vecptr(blobData), blobData.size(), 0, CRYPT_IPSEC_HMAC_KEY, &key)) { + assert(false); + return; + } + + // Create hash + if (!CryptCreateHash(context, CALG_HMAC, key, 0, &hash)) { + assert(false); + return; + } + ZeroMemory(&info, sizeof(info)); + info.HashAlgid = CALG_SHA1; + } + + ~HMACHash() { + CryptDestroyHash(hash); + } + + virtual Hash& update(const ByteArray& data) override { + return updateInternal(data); + } + + virtual Hash& update(const SafeByteArray& data) override { + return updateInternal(data); + } + + virtual std::vector<unsigned char> getHash() { + std::vector<unsigned char> result; + DWORD hashLength = sizeof(DWORD); + DWORD hashSize; + CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0); + result.resize(static_cast<size_t>(hashSize)); + if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) { + assert(false); + } + result.resize(static_cast<size_t>(hashSize)); + return result; + } + + private: + template<typename ContainerType> + Hash& updateInternal(const ContainerType& data) { + if (!CryptHashData(hash, const_cast<BYTE*>(vecptr(data)), data.size(), 0)) { + assert(false); + } + return *this; + } + + private: + HCRYPTHASH hash; + HMAC_INFO info; + }; #endif - // Simple implementation. - template<typename T> - ByteArray getHMACSHA1Internal(const T& key, const ByteArray& data, CryptoProvider* crypto) { - static const int BLOCK_SIZE = 64; - - T paddedKey; - if (key.size() <= BLOCK_SIZE) { - paddedKey = key; - } - else { - assign(paddedKey, crypto->getSHA1Hash(key)); - } - paddedKey.resize(BLOCK_SIZE, 0x0); - - // Create the first value - T x(paddedKey); - for (unsigned int i = 0; i < x.size(); ++i) { - x[i] ^= 0x36; - } - append(x, data); - - // Create the second value - T y(paddedKey); - for (unsigned int i = 0; i < y.size(); ++i) { - y[i] ^= 0x5c; - } - append(y, crypto->getSHA1Hash(x)); - return crypto->getSHA1Hash(y); - } + // Simple implementation. + template<typename T> + ByteArray getHMACSHA1Internal(const T& key, const ByteArray& data, CryptoProvider* crypto) { + static const int BLOCK_SIZE = 64; + + T paddedKey; + if (key.size() <= BLOCK_SIZE) { + paddedKey = key; + } + else { + assign(paddedKey, crypto->getSHA1Hash(key)); + } + paddedKey.resize(BLOCK_SIZE, 0x0); + + // Create the first value + T x(paddedKey); + for (unsigned int i = 0; i < x.size(); ++i) { + x[i] ^= 0x36; + } + append(x, data); + + // Create the second value + T y(paddedKey); + for (unsigned int i = 0; i < y.size(); ++i) { + y[i] ^= 0x5c; + } + append(y, crypto->getSHA1Hash(x)); + return crypto->getSHA1Hash(y); + } } -WindowsCryptoProvider::WindowsCryptoProvider() { - p = boost::make_shared<Private>(); - if (!CryptAcquireContext(&p->context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - assert(false); - } +WindowsCryptoProvider::WindowsCryptoProvider() : p(new Private()){ + if (!CryptAcquireContext(&p->context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + assert(false); + } } WindowsCryptoProvider::~WindowsCryptoProvider() { - CryptReleaseContext(p->context, 0); + CryptReleaseContext(p->context, 0); } Hash* WindowsCryptoProvider::createSHA1() { - return new WindowsHash(p->context, CALG_SHA1); + return new WindowsHash(p->context, CALG_SHA1); } Hash* WindowsCryptoProvider::createMD5() { - return new WindowsHash(p->context, CALG_MD5); + return new WindowsHash(p->context, CALG_MD5); } bool WindowsCryptoProvider::isMD5AllowedForCrypto() const { - return !WindowsRegistry::isFIPSEnabled(); + return !WindowsRegistry::isFIPSEnabled(); } ByteArray WindowsCryptoProvider::getHMACSHA1(const SafeByteArray& key, const ByteArray& data) { - return getHMACSHA1Internal(key, data, this); + return getHMACSHA1Internal(key, data, this); } ByteArray WindowsCryptoProvider::getHMACSHA1(const ByteArray& key, const ByteArray& data) { - return getHMACSHA1Internal(key, data, this); + return getHMACSHA1Internal(key, data, this); } diff --git a/Swiften/Crypto/WindowsCryptoProvider.h b/Swiften/Crypto/WindowsCryptoProvider.h index 9418fc0..d0c982e 100644 --- a/Swiften/Crypto/WindowsCryptoProvider.h +++ b/Swiften/Crypto/WindowsCryptoProvider.h @@ -1,30 +1,31 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Base/Override.h> +#include <memory> + #include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> + +#include <Swiften/Crypto/CryptoProvider.h> namespace Swift { - class WindowsCryptoProvider : public CryptoProvider, public boost::noncopyable { - public: - WindowsCryptoProvider(); - ~WindowsCryptoProvider(); + class WindowsCryptoProvider : public CryptoProvider, public boost::noncopyable { + public: + WindowsCryptoProvider(); + virtual ~WindowsCryptoProvider(); - virtual Hash* createSHA1() SWIFTEN_OVERRIDE; - virtual Hash* createMD5() SWIFTEN_OVERRIDE; - virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE; - virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE; - virtual bool isMD5AllowedForCrypto() const SWIFTEN_OVERRIDE; + virtual Hash* createSHA1() override; + virtual Hash* createMD5() override; + virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) override; + virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) override; + virtual bool isMD5AllowedForCrypto() const override; - private: - struct Private; - boost::shared_ptr<Private> p; - }; + private: + struct Private; + const std::unique_ptr<Private> p; + }; } diff --git a/Swiften/Disco/CapsInfoGenerator.cpp b/Swiften/Disco/CapsInfoGenerator.cpp index 4332f76..961ef43 100644 --- a/Swiften/Disco/CapsInfoGenerator.cpp +++ b/Swiften/Disco/CapsInfoGenerator.cpp @@ -1,23 +1,22 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Disco/CapsInfoGenerator.h> #include <algorithm> -#include <Swiften/Base/foreach.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Elements/DiscoInfo.h> #include <Swiften/Elements/FormField.h> -#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/StringCodecs/Base64.h> namespace { - bool compareFields(Swift::FormField::ref f1, Swift::FormField::ref f2) { - return f1->getName() < f2->getName(); - } + bool compareFields(Swift::FormField::ref f1, Swift::FormField::ref f2) { + return f1->getName() < f2->getName(); + } } namespace Swift { @@ -26,39 +25,39 @@ CapsInfoGenerator::CapsInfoGenerator(const std::string& node, CryptoProvider* cr } CapsInfo CapsInfoGenerator::generateCapsInfo(const DiscoInfo& discoInfo) const { - std::string serializedCaps; - - std::vector<DiscoInfo::Identity> identities(discoInfo.getIdentities()); - std::sort(identities.begin(), identities.end()); - foreach (const DiscoInfo::Identity& identity, identities) { - serializedCaps += identity.getCategory() + "/" + identity.getType() + "/" + identity.getLanguage() + "/" + identity.getName() + "<"; - } - - std::vector<std::string> features(discoInfo.getFeatures()); - std::sort(features.begin(), features.end()); - foreach (const std::string& feature, features) { - serializedCaps += feature + "<"; - } - - foreach(Form::ref extension, discoInfo.getExtensions()) { - serializedCaps += extension->getFormType() + "<"; - std::vector<FormField::ref> fields(extension->getFields()); - std::sort(fields.begin(), fields.end(), &compareFields); - foreach(FormField::ref field, fields) { - if (field->getName() == "FORM_TYPE") { - continue; - } - serializedCaps += field->getName() + "<"; - std::vector<std::string> values(field->getValues()); - std::sort(values.begin(), values.end()); - foreach(const std::string& value, values) { - serializedCaps += value + "<"; - } - } - } - - std::string version(Base64::encode(crypto_->getSHA1Hash(createByteArray(serializedCaps)))); - return CapsInfo(node_, version, "sha-1"); + std::string serializedCaps; + + std::vector<DiscoInfo::Identity> identities(discoInfo.getIdentities()); + std::sort(identities.begin(), identities.end()); + for (const auto& identity : identities) { + serializedCaps += identity.getCategory() + "/" + identity.getType() + "/" + identity.getLanguage() + "/" + identity.getName() + "<"; + } + + std::vector<std::string> features(discoInfo.getFeatures()); + std::sort(features.begin(), features.end()); + for (const auto& feature : features) { + serializedCaps += feature + "<"; + } + + for (const auto& extension : discoInfo.getExtensions()) { + serializedCaps += extension->getFormType() + "<"; + std::vector<FormField::ref> fields(extension->getFields()); + std::sort(fields.begin(), fields.end(), &compareFields); + for (const auto& field : fields) { + if (field->getName() == "FORM_TYPE") { + continue; + } + serializedCaps += field->getName() + "<"; + std::vector<std::string> values(field->getValues()); + std::sort(values.begin(), values.end()); + for (const auto& value : values) { + serializedCaps += value + "<"; + } + } + } + + std::string version(Base64::encode(crypto_->getSHA1Hash(createByteArray(serializedCaps)))); + return CapsInfo(node_, version, "sha-1"); } } diff --git a/Swiften/Disco/CapsInfoGenerator.h b/Swiften/Disco/CapsInfoGenerator.h index 17a01dd..ed1b1bd 100644 --- a/Swiften/Disco/CapsInfoGenerator.h +++ b/Swiften/Disco/CapsInfoGenerator.h @@ -1,27 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + #include <Swiften/Base/API.h> #include <Swiften/Elements/CapsInfo.h> namespace Swift { - class DiscoInfo; - class CryptoProvider; + class DiscoInfo; + class CryptoProvider; - class SWIFTEN_API CapsInfoGenerator { - public: - CapsInfoGenerator(const std::string& node, CryptoProvider* crypto); + class SWIFTEN_API CapsInfoGenerator { + public: + CapsInfoGenerator(const std::string& node, CryptoProvider* crypto); - CapsInfo generateCapsInfo(const DiscoInfo& discoInfo) const; + CapsInfo generateCapsInfo(const DiscoInfo& discoInfo) const; - private: - std::string node_; - CryptoProvider* crypto_; - }; + private: + std::string node_; + CryptoProvider* crypto_; + }; } diff --git a/Swiften/Disco/CapsManager.cpp b/Swiften/Disco/CapsManager.cpp index 18f8745..2b8fb7d 100644 --- a/Swiften/Disco/CapsManager.cpp +++ b/Swiften/Disco/CapsManager.cpp @@ -1,83 +1,83 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Disco/CapsManager.h> #include <boost/bind.hpp> -#include <iostream> +#include <Swiften/Base/Log.h> #include <Swiften/Client/StanzaChannel.h> -#include <Swiften/Disco/CapsStorage.h> #include <Swiften/Disco/CapsInfoGenerator.h> -#include <Swiften/Elements/CapsInfo.h> +#include <Swiften/Disco/CapsStorage.h> #include <Swiften/Disco/GetDiscoInfoRequest.h> +#include <Swiften/Elements/CapsInfo.h> namespace Swift { CapsManager::CapsManager(CapsStorage* capsStorage, StanzaChannel* stanzaChannel, IQRouter* iqRouter, CryptoProvider* crypto) : iqRouter(iqRouter), crypto(crypto), capsStorage(capsStorage), warnOnInvalidHash(true) { - stanzaChannel->onPresenceReceived.connect(boost::bind(&CapsManager::handlePresenceReceived, this, _1)); - stanzaChannel->onAvailableChanged.connect(boost::bind(&CapsManager::handleStanzaChannelAvailableChanged, this, _1)); + stanzaChannel->onPresenceReceived.connect(boost::bind(&CapsManager::handlePresenceReceived, this, _1)); + stanzaChannel->onAvailableChanged.connect(boost::bind(&CapsManager::handleStanzaChannelAvailableChanged, this, _1)); } -void CapsManager::handlePresenceReceived(boost::shared_ptr<Presence> presence) { - boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>(); - if (!capsInfo || capsInfo->getHash() != "sha-1" || presence->getPayload<ErrorPayload>()) { - return; - } - std::string hash = capsInfo->getVersion(); - if (capsStorage->getDiscoInfo(hash)) { - return; - } - if (failingCaps.find(std::make_pair(presence->getFrom(), hash)) != failingCaps.end()) { - return; - } - if (requestedDiscoInfos.find(hash) != requestedDiscoInfos.end()) { - fallbacks[hash].insert(std::make_pair(presence->getFrom(), capsInfo->getNode())); - return; - } - requestDiscoInfo(presence->getFrom(), capsInfo->getNode(), hash); +void CapsManager::handlePresenceReceived(std::shared_ptr<Presence> presence) { + std::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>(); + if (!capsInfo || capsInfo->getHash() != "sha-1" || presence->getPayload<ErrorPayload>()) { + return; + } + std::string hash = capsInfo->getVersion(); + if (capsStorage->getDiscoInfo(hash)) { + return; + } + if (failingCaps.find(std::make_pair(presence->getFrom(), hash)) != failingCaps.end()) { + return; + } + if (requestedDiscoInfos.find(hash) != requestedDiscoInfos.end()) { + fallbacks[hash].insert(std::make_pair(presence->getFrom(), capsInfo->getNode())); + return; + } + requestDiscoInfo(presence->getFrom(), capsInfo->getNode(), hash); } void CapsManager::handleStanzaChannelAvailableChanged(bool available) { - if (available) { - failingCaps.clear(); - fallbacks.clear(); - requestedDiscoInfos.clear(); - } + if (available) { + failingCaps.clear(); + fallbacks.clear(); + requestedDiscoInfos.clear(); + } } void CapsManager::handleDiscoInfoReceived(const JID& from, const std::string& hash, DiscoInfo::ref discoInfo, ErrorPayload::ref error) { - requestedDiscoInfos.erase(hash); - if (error || !discoInfo || CapsInfoGenerator("", crypto).generateCapsInfo(*discoInfo.get()).getVersion() != hash) { - if (warnOnInvalidHash && !error && discoInfo) { - std::cerr << "Warning: Caps from " << from.toString() << " do not verify" << std::endl; - } - failingCaps.insert(std::make_pair(from, hash)); - std::map<std::string, std::set< std::pair<JID, std::string> > >::iterator i = fallbacks.find(hash); - if (i != fallbacks.end() && !i->second.empty()) { - std::pair<JID,std::string> fallbackAndNode = *i->second.begin(); - i->second.erase(i->second.begin()); - requestDiscoInfo(fallbackAndNode.first, fallbackAndNode.second, hash); - } - return; - } - fallbacks.erase(hash); - capsStorage->setDiscoInfo(hash, discoInfo); - onCapsAvailable(hash); + requestedDiscoInfos.erase(hash); + if (error || !discoInfo || CapsInfoGenerator("", crypto).generateCapsInfo(*discoInfo.get()).getVersion() != hash) { + if (warnOnInvalidHash && !error && discoInfo) { + SWIFT_LOG(warning) << "Caps from " << from.toString() << " do not verify"; + } + failingCaps.insert(std::make_pair(from, hash)); + std::map<std::string, std::set< std::pair<JID, std::string> > >::iterator i = fallbacks.find(hash); + if (i != fallbacks.end() && !i->second.empty()) { + std::pair<JID,std::string> fallbackAndNode = *i->second.begin(); + i->second.erase(i->second.begin()); + requestDiscoInfo(fallbackAndNode.first, fallbackAndNode.second, hash); + } + return; + } + fallbacks.erase(hash); + capsStorage->setDiscoInfo(hash, discoInfo); + onCapsAvailable(hash); } void CapsManager::requestDiscoInfo(const JID& jid, const std::string& node, const std::string& hash) { - GetDiscoInfoRequest::ref request = GetDiscoInfoRequest::create(jid, node + "#" + hash, iqRouter); - request->onResponse.connect(boost::bind(&CapsManager::handleDiscoInfoReceived, this, jid, hash, _1, _2)); - requestedDiscoInfos.insert(hash); - request->send(); + GetDiscoInfoRequest::ref request = GetDiscoInfoRequest::create(jid, node + "#" + hash, iqRouter); + request->onResponse.connect(boost::bind(&CapsManager::handleDiscoInfoReceived, this, jid, hash, _1, _2)); + requestedDiscoInfos.insert(hash); + request->send(); } DiscoInfo::ref CapsManager::getCaps(const std::string& hash) const { - return capsStorage->getDiscoInfo(hash); + return capsStorage->getDiscoInfo(hash); } diff --git a/Swiften/Disco/CapsManager.h b/Swiften/Disco/CapsManager.h index 3529812..e57730e 100644 --- a/Swiften/Disco/CapsManager.h +++ b/Swiften/Disco/CapsManager.h @@ -1,53 +1,54 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <set> #include <map> +#include <set> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Elements/Presence.h> -#include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/Disco/CapsProvider.h> #include <Swiften/Elements/CapsInfo.h> +#include <Swiften/Elements/DiscoInfo.h> #include <Swiften/Elements/ErrorPayload.h> -#include <Swiften/Disco/CapsProvider.h> +#include <Swiften/Elements/Presence.h> namespace Swift { - class StanzaChannel; - class IQRouter; - class JID; - class CapsStorage; - class CryptoProvider; - - class SWIFTEN_API CapsManager : public CapsProvider, public boost::bsignals::trackable { - public: - CapsManager(CapsStorage*, StanzaChannel*, IQRouter*, CryptoProvider*); - - DiscoInfo::ref getCaps(const std::string&) const; - - // Mainly for testing purposes - void setWarnOnInvalidHash(bool b) { - warnOnInvalidHash = b; - } - - private: - void handlePresenceReceived(boost::shared_ptr<Presence>); - void handleStanzaChannelAvailableChanged(bool); - void handleDiscoInfoReceived(const JID&, const std::string& hash, DiscoInfo::ref, ErrorPayload::ref); - void requestDiscoInfo(const JID& jid, const std::string& node, const std::string& hash); - - private: - IQRouter* iqRouter; - CryptoProvider* crypto; - CapsStorage* capsStorage; - bool warnOnInvalidHash; - std::set<std::string> requestedDiscoInfos; - std::set< std::pair<JID, std::string> > failingCaps; - std::map<std::string, std::set< std::pair<JID, std::string> > > fallbacks; - }; + class StanzaChannel; + class IQRouter; + class JID; + class CapsStorage; + class CryptoProvider; + + class SWIFTEN_API CapsManager : public CapsProvider, public boost::signals2::trackable { + public: + CapsManager(CapsStorage*, StanzaChannel*, IQRouter*, CryptoProvider*); + + DiscoInfo::ref getCaps(const std::string&) const; + + // Mainly for testing purposes + void setWarnOnInvalidHash(bool b) { + warnOnInvalidHash = b; + } + + private: + void handlePresenceReceived(std::shared_ptr<Presence>); + void handleStanzaChannelAvailableChanged(bool); + void handleDiscoInfoReceived(const JID&, const std::string& hash, DiscoInfo::ref, ErrorPayload::ref); + void requestDiscoInfo(const JID& jid, const std::string& node, const std::string& hash); + + private: + IQRouter* iqRouter; + CryptoProvider* crypto; + CapsStorage* capsStorage; + bool warnOnInvalidHash; + std::set<std::string> requestedDiscoInfos; + std::set< std::pair<JID, std::string> > failingCaps; + std::map<std::string, std::set< std::pair<JID, std::string> > > fallbacks; + }; } diff --git a/Swiften/Disco/CapsMemoryStorage.h b/Swiften/Disco/CapsMemoryStorage.h index 2503d7d..15a1fd3 100644 --- a/Swiften/Disco/CapsMemoryStorage.h +++ b/Swiften/Disco/CapsMemoryStorage.h @@ -1,38 +1,39 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> #include <map> - +#include <memory> #include <string> + +#include <Swiften/Base/API.h> #include <Swiften/Disco/CapsStorage.h> namespace Swift { - class CapsMemoryStorage : public CapsStorage { - public: - CapsMemoryStorage() {} + class SWIFTEN_API CapsMemoryStorage : public CapsStorage { + public: + CapsMemoryStorage() {} - virtual DiscoInfo::ref getDiscoInfo(const std::string& hash) const { - CapsMap::const_iterator i = caps.find(hash); - if (i != caps.end()) { - return i->second; - } - else { - return DiscoInfo::ref(); - } - } + virtual DiscoInfo::ref getDiscoInfo(const std::string& hash) const { + CapsMap::const_iterator i = caps.find(hash); + if (i != caps.end()) { + return i->second; + } + else { + return DiscoInfo::ref(); + } + } - virtual void setDiscoInfo(const std::string& hash, DiscoInfo::ref discoInfo) { - caps[hash] = discoInfo; - } + virtual void setDiscoInfo(const std::string& hash, DiscoInfo::ref discoInfo) { + caps[hash] = discoInfo; + } - private: - typedef std::map<std::string, DiscoInfo::ref> CapsMap; - CapsMap caps; - }; + private: + typedef std::map<std::string, DiscoInfo::ref> CapsMap; + CapsMap caps; + }; } diff --git a/Swiften/Disco/CapsProvider.h b/Swiften/Disco/CapsProvider.h index 8bb3767..b9e2d21 100644 --- a/Swiften/Disco/CapsProvider.h +++ b/Swiften/Disco/CapsProvider.h @@ -1,24 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Elements/DiscoInfo.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/CapsInfo.h> +#include <Swiften/Elements/DiscoInfo.h> namespace Swift { - - class CapsProvider { - public: - virtual ~CapsProvider() {} - virtual DiscoInfo::ref getCaps(const std::string&) const = 0; + class SWIFTEN_API CapsProvider { + public: + virtual ~CapsProvider() {} + + virtual DiscoInfo::ref getCaps(const std::string&) const = 0; - boost::signal<void (const std::string&)> onCapsAvailable; - }; + boost::signals2::signal<void (const std::string&)> onCapsAvailable; + }; } diff --git a/Swiften/Disco/CapsStorage.cpp b/Swiften/Disco/CapsStorage.cpp index fe4a6ac..4282aa2 100644 --- a/Swiften/Disco/CapsStorage.cpp +++ b/Swiften/Disco/CapsStorage.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Disco/CapsStorage.h> diff --git a/Swiften/Disco/CapsStorage.h b/Swiften/Disco/CapsStorage.h index 7420c28..ebfd3f3 100644 --- a/Swiften/Disco/CapsStorage.h +++ b/Swiften/Disco/CapsStorage.h @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Elements/DiscoInfo.h> #include <Swiften/Base/API.h> +#include <Swiften/Elements/DiscoInfo.h> namespace Swift { - class SWIFTEN_API CapsStorage { - public: - virtual ~CapsStorage(); + class SWIFTEN_API CapsStorage { + public: + virtual ~CapsStorage(); - virtual DiscoInfo::ref getDiscoInfo(const std::string&) const = 0; - virtual void setDiscoInfo(const std::string&, DiscoInfo::ref) = 0; - }; + virtual DiscoInfo::ref getDiscoInfo(const std::string&) const = 0; + virtual void setDiscoInfo(const std::string&, DiscoInfo::ref) = 0; + }; } diff --git a/Swiften/Disco/ClientDiscoManager.cpp b/Swiften/Disco/ClientDiscoManager.cpp index f6683a8..8c90d2d 100644 --- a/Swiften/Disco/ClientDiscoManager.cpp +++ b/Swiften/Disco/ClientDiscoManager.cpp @@ -1,43 +1,43 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Disco/ClientDiscoManager.h> -#include <Swiften/Disco/DiscoInfoResponder.h> #include <Swiften/Disco/CapsInfoGenerator.h> +#include <Swiften/Disco/DiscoInfoResponder.h> #include <Swiften/Presence/PayloadAddingPresenceSender.h> namespace Swift { ClientDiscoManager::ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender, CryptoProvider* crypto) : crypto(crypto) { - discoInfoResponder = new DiscoInfoResponder(iqRouter); - discoInfoResponder->start(); - this->presenceSender = new PayloadAddingPresenceSender(presenceSender); + discoInfoResponder = new DiscoInfoResponder(iqRouter); + discoInfoResponder->start(); + this->presenceSender = new PayloadAddingPresenceSender(presenceSender); } ClientDiscoManager::~ClientDiscoManager() { - delete presenceSender; - discoInfoResponder->stop(); - delete discoInfoResponder; + delete presenceSender; + discoInfoResponder->stop(); + delete discoInfoResponder; } void ClientDiscoManager::setCapsNode(const std::string& node) { - capsNode = node; + capsNode = node; } void ClientDiscoManager::setDiscoInfo(const DiscoInfo& discoInfo) { - capsInfo = CapsInfo::ref(new CapsInfo(CapsInfoGenerator(capsNode, crypto).generateCapsInfo(discoInfo))); - discoInfoResponder->clearDiscoInfo(); - discoInfoResponder->setDiscoInfo(discoInfo); - discoInfoResponder->setDiscoInfo(capsInfo->getNode() + "#" + capsInfo->getVersion(), discoInfo); - presenceSender->setPayload(capsInfo); + capsInfo = CapsInfo::ref(new CapsInfo(CapsInfoGenerator(capsNode, crypto).generateCapsInfo(discoInfo))); + discoInfoResponder->clearDiscoInfo(); + discoInfoResponder->setDiscoInfo(discoInfo); + discoInfoResponder->setDiscoInfo(capsInfo->getNode() + "#" + capsInfo->getVersion(), discoInfo); + presenceSender->setPayload(capsInfo); } void ClientDiscoManager::handleConnected() { - presenceSender->reset(); + presenceSender->reset(); } } diff --git a/Swiften/Disco/ClientDiscoManager.h b/Swiften/Disco/ClientDiscoManager.h index a9ed10a..595beeb 100644 --- a/Swiften/Disco/ClientDiscoManager.h +++ b/Swiften/Disco/ClientDiscoManager.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -12,66 +12,67 @@ #include <Swiften/Presence/PayloadAddingPresenceSender.h> namespace Swift { - class IQRouter; - class DiscoInfoResponder; - class PayloadAddingPresenceSender; - class PresenceSender; - class CryptoProvider; + class IQRouter; + class DiscoInfoResponder; + class PayloadAddingPresenceSender; + class PresenceSender; + class CryptoProvider; - /** - * Class responsible for managing outgoing disco information for a client. - * - * The manager will respond to disco#info requests, and add entity capabilities information - * to outgoing presence. - * - * To use this class, call setCapsNode() once with the caps URI of the client. After this, - * call setDiscoInfo() with the capabilities for the client. This can be - * called whenever the capabilities change. - */ - class SWIFTEN_API ClientDiscoManager { - public: - /** - * Constructs the manager - * - * \param iqRouter the router on which requests will be answered - * \param presenceSender the presence sender to which all outgoing presence - * (with caps information) will be sent. - */ - ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender, CryptoProvider* crypto); - ~ClientDiscoManager(); + /** + * Class responsible for managing outgoing disco information for a client. + * + * The manager will respond to disco#info requests, and add entity capabilities information + * to outgoing presence. + * + * To use this class, call setCapsNode() once with the caps URI of the client. After this, + * call setDiscoInfo() with the capabilities for the client. This can be + * called whenever the capabilities change. + */ + class SWIFTEN_API ClientDiscoManager { + public: + /** + * Constructs the manager + * + * \param iqRouter the router on which requests will be answered + * \param presenceSender the presence sender to which all outgoing presence + * (with caps information) will be sent. + * \param crypto the crypto provider used for cryptographic hash computations. + */ + ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender, CryptoProvider* crypto); + ~ClientDiscoManager(); - /** - * Needs to be called before calling setDiscoInfo(). - */ - void setCapsNode(const std::string& node); + /** + * Needs to be called before calling setDiscoInfo(). + */ + void setCapsNode(const std::string& node); - /** - * Sets the capabilities of the client. - */ - void setDiscoInfo(const DiscoInfo& info); + /** + * Sets the capabilities of the client. + */ + void setDiscoInfo(const DiscoInfo& info); - /** - * Returns the presence sender through which all outgoing presence - * should be sent. - * The manager will add the necessary caps information, and forward it to - * the presence sender passed at construction time. - */ - PresenceSender* getPresenceSender() const { - return presenceSender; - } + /** + * Returns the presence sender through which all outgoing presence + * should be sent. + * The manager will add the necessary caps information, and forward it to + * the presence sender passed at construction time. + */ + PresenceSender* getPresenceSender() const { + return presenceSender; + } - /** - * Called when the client is connected. - * This resets the presence sender, such that it assumes initial presence - * hasn't been sent yet. - */ - void handleConnected(); + /** + * Called when the client is connected. + * This resets the presence sender, such that it assumes initial presence + * hasn't been sent yet. + */ + void handleConnected(); - private: - PayloadAddingPresenceSender* presenceSender; - CryptoProvider* crypto; - DiscoInfoResponder* discoInfoResponder; - std::string capsNode; - CapsInfo::ref capsInfo; - }; + private: + PayloadAddingPresenceSender* presenceSender; + CryptoProvider* crypto; + DiscoInfoResponder* discoInfoResponder; + std::string capsNode; + CapsInfo::ref capsInfo; + }; } diff --git a/Swiften/Disco/DiscoInfoResponder.cpp b/Swiften/Disco/DiscoInfoResponder.cpp index 9e58bff..c94d299 100644 --- a/Swiften/Disco/DiscoInfoResponder.cpp +++ b/Swiften/Disco/DiscoInfoResponder.cpp @@ -1,14 +1,15 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Disco/DiscoInfoResponder.h> -#include <Swiften/Queries/IQRouter.h> + +#include <memory> + #include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/Queries/IQRouter.h> namespace Swift { @@ -16,34 +17,34 @@ DiscoInfoResponder::DiscoInfoResponder(IQRouter* router) : GetResponder<DiscoInf } void DiscoInfoResponder::clearDiscoInfo() { - info_ = DiscoInfo(); - nodeInfo_.clear(); + info_ = DiscoInfo(); + nodeInfo_.clear(); } void DiscoInfoResponder::setDiscoInfo(const DiscoInfo& info) { - info_ = info; + info_ = info; } void DiscoInfoResponder::setDiscoInfo(const std::string& node, const DiscoInfo& info) { - DiscoInfo newInfo(info); - newInfo.setNode(node); - nodeInfo_[node] = newInfo; + DiscoInfo newInfo(info); + newInfo.setNode(node); + nodeInfo_[node] = newInfo; } -bool DiscoInfoResponder::handleGetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<DiscoInfo> info) { - if (info->getNode().empty()) { - sendResponse(from, id, boost::make_shared<DiscoInfo>(info_)); - } - else { - std::map<std::string,DiscoInfo>::const_iterator i = nodeInfo_.find(info->getNode()); - if (i != nodeInfo_.end()) { - sendResponse(from, id, boost::make_shared<DiscoInfo>((*i).second)); - } - else { - sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); - } - } - return true; +bool DiscoInfoResponder::handleGetRequest(const JID& from, const JID&, const std::string& id, std::shared_ptr<DiscoInfo> info) { + if (info->getNode().empty()) { + sendResponse(from, id, std::make_shared<DiscoInfo>(info_)); + } + else { + std::map<std::string,DiscoInfo>::const_iterator i = nodeInfo_.find(info->getNode()); + if (i != nodeInfo_.end()) { + sendResponse(from, id, std::make_shared<DiscoInfo>((*i).second)); + } + else { + sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); + } + } + return true; } } diff --git a/Swiften/Disco/DiscoInfoResponder.h b/Swiften/Disco/DiscoInfoResponder.h index cfe4d06..9995695 100644 --- a/Swiften/Disco/DiscoInfoResponder.h +++ b/Swiften/Disco/DiscoInfoResponder.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,25 +9,25 @@ #include <map> #include <Swiften/Base/API.h> -#include <Swiften/Queries/GetResponder.h> #include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/Queries/GetResponder.h> namespace Swift { - class IQRouter; + class IQRouter; - class SWIFTEN_API DiscoInfoResponder : public GetResponder<DiscoInfo> { - public: - DiscoInfoResponder(IQRouter* router); + class SWIFTEN_API DiscoInfoResponder : public GetResponder<DiscoInfo> { + public: + DiscoInfoResponder(IQRouter* router); - void clearDiscoInfo(); - void setDiscoInfo(const DiscoInfo& info); - void setDiscoInfo(const std::string& node, const DiscoInfo& info); + void clearDiscoInfo(); + void setDiscoInfo(const DiscoInfo& info); + void setDiscoInfo(const std::string& node, const DiscoInfo& info); - private: - virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<DiscoInfo> payload); + private: + virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, std::shared_ptr<DiscoInfo> payload); - private: - DiscoInfo info_; - std::map<std::string, DiscoInfo> nodeInfo_; - }; + private: + DiscoInfo info_; + std::map<std::string, DiscoInfo> nodeInfo_; + }; } diff --git a/Swiften/Disco/DiscoServiceWalker.cpp b/Swiften/Disco/DiscoServiceWalker.cpp index 0f27111..7332e63 100644 --- a/Swiften/Disco/DiscoServiceWalker.cpp +++ b/Swiften/Disco/DiscoServiceWalker.cpp @@ -1,16 +1,15 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Disco/DiscoServiceWalker.h> -#include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> - #include <boost/bind.hpp> +#include <Swiften/Base/Log.h> + namespace Swift { DiscoServiceWalker::DiscoServiceWalker(const JID& service, IQRouter* iqRouter, size_t maxSteps) : service_(service), iqRouter_(iqRouter), maxSteps_(maxSteps), active_(false) { @@ -18,116 +17,118 @@ DiscoServiceWalker::DiscoServiceWalker(const JID& service, IQRouter* iqRouter, s } void DiscoServiceWalker::beginWalk() { - SWIFT_LOG(debug) << "Starting walk to " << service_ << std::endl; - assert(!active_); - assert(servicesBeingSearched_.empty()); - active_ = true; - walkNode(service_); + SWIFT_LOG(debug) << "Starting walk to " << service_; + assert(!active_); + assert(servicesBeingSearched_.empty()); + active_ = true; + walkNode(service_); } void DiscoServiceWalker::endWalk() { - if (active_) { - SWIFT_LOG(debug) << "Ending walk to " << service_ << std::endl; - foreach (GetDiscoInfoRequest::ref request, pendingDiscoInfoRequests_) { - request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, request)); - } - foreach (GetDiscoItemsRequest::ref request, pendingDiscoItemsRequests_) { - request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, request)); - } - active_ = false; - onWalkAborted(); - } + if (active_) { + SWIFT_LOG(debug) << "Ending walk to " << service_; + for (auto&& request : pendingDiscoInfoRequests_) { + request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, request)); + } + for (auto&& request : pendingDiscoItemsRequests_) { + request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, request)); + } + active_ = false; + onWalkAborted(); + } } void DiscoServiceWalker::walkNode(const JID& jid) { - SWIFT_LOG(debug) << "Walking node " << jid << std::endl; - servicesBeingSearched_.insert(jid); - searchedServices_.insert(jid); - GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(jid, iqRouter_); - discoInfoRequest->onResponse.connect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, discoInfoRequest)); - pendingDiscoInfoRequests_.insert(discoInfoRequest); - discoInfoRequest->send(); + SWIFT_LOG(debug) << "Walking node " << jid; + servicesBeingSearched_.insert(jid); + searchedServices_.insert(jid); + GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(jid, iqRouter_); + discoInfoRequest->onResponse.connect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, discoInfoRequest)); + pendingDiscoInfoRequests_.insert(discoInfoRequest); + discoInfoRequest->send(); } -void DiscoServiceWalker::handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> info, ErrorPayload::ref error, GetDiscoInfoRequest::ref request) { - /* If we got canceled, don't do anything */ - if (!active_) { - return; - } - - SWIFT_LOG(debug) << "Disco info response from " << request->getReceiver() << std::endl; - - pendingDiscoInfoRequests_.erase(request); - if (error) { - handleDiscoError(request->getReceiver(), error); - return; - } - - bool couldContainServices = false; - foreach (DiscoInfo::Identity identity, info->getIdentities()) { - if (identity.getCategory() == "server") { - couldContainServices = true; - } - } - bool completed = false; - if (couldContainServices) { - GetDiscoItemsRequest::ref discoItemsRequest = GetDiscoItemsRequest::create(request->getReceiver(), iqRouter_); - discoItemsRequest->onResponse.connect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, discoItemsRequest)); - pendingDiscoItemsRequests_.insert(discoItemsRequest); - discoItemsRequest->send(); - } else { - completed = true; - } - onServiceFound(request->getReceiver(), info); - if (completed) { - markNodeCompleted(request->getReceiver()); - } +void DiscoServiceWalker::handleDiscoInfoResponse(std::shared_ptr<DiscoInfo> info, ErrorPayload::ref error, GetDiscoInfoRequest::ref request) { + /* If we got canceled, don't do anything */ + if (!active_) { + return; + } + + SWIFT_LOG(debug) << "Disco info response from " << request->getReceiver(); + + request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, request)); + pendingDiscoInfoRequests_.erase(request); + if (error) { + handleDiscoError(request->getReceiver(), error); + return; + } + + bool couldContainServices = false; + for (const auto& identity : info->getIdentities()) { + if (identity.getCategory() == "server") { + couldContainServices = true; + } + } + bool completed = false; + if (couldContainServices) { + GetDiscoItemsRequest::ref discoItemsRequest = GetDiscoItemsRequest::create(request->getReceiver(), iqRouter_); + discoItemsRequest->onResponse.connect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, discoItemsRequest)); + pendingDiscoItemsRequests_.insert(discoItemsRequest); + discoItemsRequest->send(); + } else { + completed = true; + } + onServiceFound(request->getReceiver(), info); + if (completed) { + markNodeCompleted(request->getReceiver()); + } } -void DiscoServiceWalker::handleDiscoItemsResponse(boost::shared_ptr<DiscoItems> items, ErrorPayload::ref error, GetDiscoItemsRequest::ref request) { - /* If we got canceled, don't do anything */ - if (!active_) { - return; - } - - SWIFT_LOG(debug) << "Received disco items from " << request->getReceiver() << std::endl; - pendingDiscoItemsRequests_.erase(request); - if (error) { - handleDiscoError(request->getReceiver(), error); - return; - } - foreach (DiscoItems::Item item, items->getItems()) { - if (item.getNode().empty()) { - /* Don't look at noded items. It's possible that this will exclude some services, - * but I've never seen one in the wild, and it's an easy fix for not looping. - */ - if (std::find(searchedServices_.begin(), searchedServices_.end(), item.getJID()) == searchedServices_.end()) { /* Don't recurse infinitely */ - SWIFT_LOG(debug) << "Received disco item " << item.getJID() << std::endl; - walkNode(item.getJID()); - } - } - } - markNodeCompleted(request->getReceiver()); +void DiscoServiceWalker::handleDiscoItemsResponse(std::shared_ptr<DiscoItems> items, ErrorPayload::ref error, GetDiscoItemsRequest::ref request) { + /* If we got canceled, don't do anything */ + if (!active_) { + return; + } + + SWIFT_LOG(debug) << "Received disco items from " << request->getReceiver(); + request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, request)); + pendingDiscoItemsRequests_.erase(request); + if (error) { + handleDiscoError(request->getReceiver(), error); + return; + } + for (auto&& item : items->getItems()) { + if (item.getNode().empty()) { + /* Don't look at noded items. It's possible that this will exclude some services, + * but I've never seen one in the wild, and it's an easy fix for not looping. + */ + if (std::find(searchedServices_.begin(), searchedServices_.end(), item.getJID()) == searchedServices_.end()) { /* Don't recurse infinitely */ + SWIFT_LOG(debug) << "Received disco item " << item.getJID(); + walkNode(item.getJID()); + } + } + } + markNodeCompleted(request->getReceiver()); } void DiscoServiceWalker::handleDiscoError(const JID& jid, ErrorPayload::ref /*error*/) { - SWIFT_LOG(debug) << "Disco error from " << jid << std::endl; - markNodeCompleted(jid); + SWIFT_LOG(debug) << "Disco error from " << jid; + markNodeCompleted(jid); } void DiscoServiceWalker::markNodeCompleted(const JID& jid) { - SWIFT_LOG(debug) << "Node completed " << jid << std::endl; - servicesBeingSearched_.erase(jid); - /* All results are in */ - if (servicesBeingSearched_.empty()) { - active_ = false; - onWalkComplete(); - } - /* Check if we're on a rampage */ - else if (searchedServices_.size() >= maxSteps_) { - active_ = false; - onWalkComplete(); - } + SWIFT_LOG(debug) << "Node completed " << jid; + servicesBeingSearched_.erase(jid); + /* All results are in */ + if (servicesBeingSearched_.empty()) { + active_ = false; + onWalkComplete(); + } + /* Check if we're on a rampage */ + else if (searchedServices_.size() >= maxSteps_) { + active_ = false; + onWalkComplete(); + } } } diff --git a/Swiften/Disco/DiscoServiceWalker.h b/Swiften/Disco/DiscoServiceWalker.h index ea55a78..f7e1e6d 100644 --- a/Swiften/Disco/DiscoServiceWalker.h +++ b/Swiften/Disco/DiscoServiceWalker.h @@ -1,75 +1,76 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> +#include <memory> #include <set> +#include <string> +#include <vector> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> -#include <string> -#include <Swiften/JID/JID.h> +#include <Swiften/Disco/GetDiscoInfoRequest.h> +#include <Swiften/Disco/GetDiscoItemsRequest.h> #include <Swiften/Elements/DiscoInfo.h> #include <Swiften/Elements/DiscoItems.h> #include <Swiften/Elements/ErrorPayload.h> -#include <Swiften/Disco/GetDiscoInfoRequest.h> -#include <Swiften/Disco/GetDiscoItemsRequest.h> +#include <Swiften/JID/JID.h> namespace Swift { - class IQRouter; - /** - * Recursively walk service discovery trees to find all services offered. - * This stops on any disco item that's not reporting itself as a server. - */ - class SWIFTEN_API DiscoServiceWalker { - public: - DiscoServiceWalker(const JID& service, IQRouter* iqRouter, size_t maxSteps = 200); + class IQRouter; + /** + * Recursively walk service discovery trees to find all services offered. + * This stops on any disco item that's not reporting itself as a server. + */ + class SWIFTEN_API DiscoServiceWalker { + public: + DiscoServiceWalker(const JID& service, IQRouter* iqRouter, size_t maxSteps = 200); - /** - * Start the walk. - * - * Call this exactly once. - */ - void beginWalk(); + /** + * Start the walk. + * + * Call this exactly once. + */ + void beginWalk(); - /** - * End the walk. - */ - void endWalk(); + /** + * End the walk. + */ + void endWalk(); - bool isActive() const { - return active_; - } + bool isActive() const { + return active_; + } - /** Emitted for each service found. */ - boost::signal<void(const JID&, boost::shared_ptr<DiscoInfo>)> onServiceFound; + /** Emitted for each service found. */ + boost::signals2::signal<void(const JID&, std::shared_ptr<DiscoInfo>)> onServiceFound; - /** Emitted when walking is aborted. */ - boost::signal<void()> onWalkAborted; + /** Emitted when walking is aborted. */ + boost::signals2::signal<void()> onWalkAborted; - /** Emitted when walking is complete.*/ - boost::signal<void()> onWalkComplete; + /** Emitted when walking is complete.*/ + boost::signals2::signal<void()> onWalkComplete; - private: - void walkNode(const JID& jid); - void markNodeCompleted(const JID& jid); - void handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> info, ErrorPayload::ref error, GetDiscoInfoRequest::ref request); - void handleDiscoItemsResponse(boost::shared_ptr<DiscoItems> items, ErrorPayload::ref error, GetDiscoItemsRequest::ref request); - void handleDiscoError(const JID& jid, ErrorPayload::ref error); + private: + void walkNode(const JID& jid); + void markNodeCompleted(const JID& jid); + void handleDiscoInfoResponse(std::shared_ptr<DiscoInfo> info, ErrorPayload::ref error, GetDiscoInfoRequest::ref request); + void handleDiscoItemsResponse(std::shared_ptr<DiscoItems> items, ErrorPayload::ref error, GetDiscoItemsRequest::ref request); + void handleDiscoError(const JID& jid, ErrorPayload::ref error); - private: - JID service_; - IQRouter* iqRouter_; - size_t maxSteps_; - bool active_; - std::set<JID> servicesBeingSearched_; - std::set<JID> searchedServices_; - std::set<GetDiscoInfoRequest::ref> pendingDiscoInfoRequests_; - std::set<GetDiscoItemsRequest::ref> pendingDiscoItemsRequests_; - }; + private: + JID service_; + IQRouter* iqRouter_; + size_t maxSteps_; + bool active_; + std::set<JID> servicesBeingSearched_; + std::set<JID> searchedServices_; + std::set<GetDiscoInfoRequest::ref> pendingDiscoInfoRequests_; + std::set<GetDiscoItemsRequest::ref> pendingDiscoItemsRequests_; + }; } diff --git a/Swiften/Disco/DummyEntityCapsProvider.cpp b/Swiften/Disco/DummyEntityCapsProvider.cpp index a906652..eba58ac 100644 --- a/Swiften/Disco/DummyEntityCapsProvider.cpp +++ b/Swiften/Disco/DummyEntityCapsProvider.cpp @@ -1,21 +1,23 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Disco/DummyEntityCapsProvider.h> -#include <iostream> - namespace Swift { DiscoInfo::ref DummyEntityCapsProvider::getCaps(const JID& jid) const { - std::map<JID, DiscoInfo::ref>::const_iterator i = caps.find(jid); - if (i != caps.end()) { - return i->second; - } - return DiscoInfo::ref(); + std::map<JID, DiscoInfo::ref>::const_iterator i = caps.find(jid); + if (i != caps.end()) { + return i->second; + } + return DiscoInfo::ref(); +} + +DiscoInfo::ref DummyEntityCapsProvider::getCapsCached(const JID& jid) { + return getCaps(jid); } } diff --git a/Swiften/Disco/DummyEntityCapsProvider.h b/Swiften/Disco/DummyEntityCapsProvider.h index 713e21a..971e183 100644 --- a/Swiften/Disco/DummyEntityCapsProvider.h +++ b/Swiften/Disco/DummyEntityCapsProvider.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -12,13 +12,15 @@ #include <Swiften/Disco/EntityCapsProvider.h> namespace Swift { - class SWIFTEN_API DummyEntityCapsProvider : public EntityCapsProvider { - public: - DummyEntityCapsProvider() { - } + class SWIFTEN_API DummyEntityCapsProvider : public EntityCapsProvider { + public: + DummyEntityCapsProvider() { + } - DiscoInfo::ref getCaps(const JID& jid) const; + DiscoInfo::ref getCaps(const JID& jid) const; - std::map<JID, DiscoInfo::ref> caps; - }; + DiscoInfo::ref getCapsCached(const JID& jid); + + std::map<JID, DiscoInfo::ref> caps; + }; } diff --git a/Swiften/Disco/EntityCapsManager.cpp b/Swiften/Disco/EntityCapsManager.cpp index 1a9f5fb..28c525f 100644 --- a/Swiften/Disco/EntityCapsManager.cpp +++ b/Swiften/Disco/EntityCapsManager.cpp @@ -1,79 +1,95 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Disco/EntityCapsManager.h> #include <boost/bind.hpp> -#include <Swiften/Disco/CapsProvider.h> #include <Swiften/Client/StanzaChannel.h> +#include <Swiften/Disco/CapsProvider.h> namespace Swift { EntityCapsManager::EntityCapsManager(CapsProvider* capsProvider, StanzaChannel* stanzaChannel) : capsProvider(capsProvider) { - stanzaChannel->onPresenceReceived.connect(boost::bind(&EntityCapsManager::handlePresenceReceived, this, _1)); - stanzaChannel->onAvailableChanged.connect(boost::bind(&EntityCapsManager::handleStanzaChannelAvailableChanged, this, _1)); - capsProvider->onCapsAvailable.connect(boost::bind(&EntityCapsManager::handleCapsAvailable, this, _1)); + stanzaChannel->onPresenceReceived.connect(boost::bind(&EntityCapsManager::handlePresenceReceived, this, _1)); + stanzaChannel->onAvailableChanged.connect(boost::bind(&EntityCapsManager::handleStanzaChannelAvailableChanged, this, _1)); + capsProvider->onCapsAvailable.connect(boost::bind(&EntityCapsManager::handleCapsAvailable, this, _1)); } -void EntityCapsManager::handlePresenceReceived(boost::shared_ptr<Presence> presence) { - JID from = presence->getFrom(); - if (presence->isAvailable()) { - boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>(); - if (!capsInfo || capsInfo->getHash() != "sha-1" || presence->getPayload<ErrorPayload>()) { - return; - } - std::string hash = capsInfo->getVersion(); - std::map<JID, std::string>::iterator i = caps.find(from); - if (i == caps.end() || i->second != hash) { - caps.insert(std::make_pair(from, hash)); - DiscoInfo::ref disco = capsProvider->getCaps(hash); - if (disco) { - onCapsChanged(from); - } - else if (i != caps.end()) { - caps.erase(i); - onCapsChanged(from); - } - } - } - else { - std::map<JID, std::string>::iterator i = caps.find(from); - if (i != caps.end()) { - caps.erase(i); - onCapsChanged(from); - } - } +void EntityCapsManager::handlePresenceReceived(std::shared_ptr<Presence> presence) { + JID from = presence->getFrom(); + if (presence->isAvailable()) { + std::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>(); + if (!capsInfo || capsInfo->getHash() != "sha-1" || presence->getPayload<ErrorPayload>()) { + return; + } + std::string hash = capsInfo->getVersion(); + std::map<JID, std::string>::iterator i = caps.find(from); + if (i == caps.end() || i->second != hash) { + caps.insert(std::make_pair(from, hash)); + DiscoInfo::ref disco = capsProvider->getCaps(hash); + if (disco) { + onCapsChanged(from); + } + else if (i != caps.end()) { + caps.erase(i); + onCapsChanged(from); + } + } + } + else { + std::map<JID, std::string>::iterator i = caps.find(from); + if (i != caps.end()) { + caps.erase(i); + onCapsChanged(from); + } + } } void EntityCapsManager::handleStanzaChannelAvailableChanged(bool available) { - if (available) { - std::map<JID, std::string> capsCopy; - capsCopy.swap(caps); - for (std::map<JID,std::string>::const_iterator i = capsCopy.begin(); i != capsCopy.end(); ++i) { - onCapsChanged(i->first); - } - } + if (available) { + std::map<JID, std::string> capsCopy; + capsCopy.swap(caps); + for (std::map<JID,std::string>::const_iterator i = capsCopy.begin(); i != capsCopy.end(); ++i) { + onCapsChanged(i->first); + } + } } void EntityCapsManager::handleCapsAvailable(const std::string& hash) { - // TODO: Use Boost.Bimap ? - for (std::map<JID,std::string>::const_iterator i = caps.begin(); i != caps.end(); ++i) { - if (i->second == hash) { - onCapsChanged(i->first); - } - } + // TODO: Use Boost.Bimap ? + for (std::map<JID,std::string>::const_iterator i = caps.begin(); i != caps.end(); ++i) { + if (i->second == hash) { + onCapsChanged(i->first); + } + } } DiscoInfo::ref EntityCapsManager::getCaps(const JID& jid) const { - std::map<JID, std::string>::const_iterator i = caps.find(jid); - if (i != caps.end()) { - return capsProvider->getCaps(i->second); - } - return DiscoInfo::ref(); + std::map<JID, std::string>::const_iterator i = caps.find(jid); + if (i != caps.end()) { + return capsProvider->getCaps(i->second); + } + return DiscoInfo::ref(); +} + +DiscoInfo::ref EntityCapsManager::getCapsCached(const JID& jid) { + DiscoInfo::ref result; + auto capsHit = caps.find(jid); + if (capsHit != caps.end()) { + result = lruDiscoCache.get(capsHit->second, [&](const std::string& capsHash) { + boost::optional<DiscoInfo::ref> fileCacheResult; + auto fileCacheDiscoInfo = capsProvider->getCaps(capsHash); + if (fileCacheDiscoInfo) { + fileCacheResult = fileCacheDiscoInfo; + } + return fileCacheResult; + }).get_value_or(DiscoInfo::ref()); + } + return result; } } diff --git a/Swiften/Disco/EntityCapsManager.h b/Swiften/Disco/EntityCapsManager.h index 4472ba5..3934fc7 100644 --- a/Swiften/Disco/EntityCapsManager.h +++ b/Swiften/Disco/EntityCapsManager.h @@ -1,46 +1,51 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <map> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Elements/Presence.h> +#include <Swiften/Base/LRUCache.h> +#include <Swiften/Disco/EntityCapsProvider.h> #include <Swiften/Elements/DiscoInfo.h> #include <Swiften/Elements/ErrorPayload.h> -#include <Swiften/Disco/EntityCapsProvider.h> +#include <Swiften/Elements/Presence.h> namespace Swift { - class StanzaChannel; - class CapsProvider; - - /** - * This class is responsible for gathering and providing - * information about capabilities of entities on the network. - * This information is provided in the form of service discovery - * information. - */ - class SWIFTEN_API EntityCapsManager : public EntityCapsProvider, public boost::bsignals::trackable { - public: - EntityCapsManager(CapsProvider*, StanzaChannel*); - - /** - * Returns the service discovery information of the given JID. - */ - DiscoInfo::ref getCaps(const JID&) const; - - private: - void handlePresenceReceived(boost::shared_ptr<Presence>); - void handleStanzaChannelAvailableChanged(bool); - void handleCapsAvailable(const std::string&); - - private: - CapsProvider* capsProvider; - std::map<JID, std::string> caps; - }; + class StanzaChannel; + class CapsProvider; + + /** + * This class is responsible for gathering and providing + * information about capabilities of entities on the network. + * This information is provided in the form of service discovery + * information. + */ + class SWIFTEN_API EntityCapsManager : public EntityCapsProvider, public boost::signals2::trackable { + public: + EntityCapsManager(CapsProvider*, StanzaChannel*); + + /** + * Returns the service discovery information of the given JID. + */ + DiscoInfo::ref getCaps(const JID&) const; + + DiscoInfo::ref getCapsCached(const JID&); + + private: + void handlePresenceReceived(std::shared_ptr<Presence>); + void handleStanzaChannelAvailableChanged(bool); + void handleCapsAvailable(const std::string&); + + private: + CapsProvider* capsProvider; + std::map<JID, std::string> caps; + LRUCache<std::string, DiscoInfo::ref, 64> lruDiscoCache; + }; } diff --git a/Swiften/Disco/EntityCapsProvider.cpp b/Swiften/Disco/EntityCapsProvider.cpp index e3262b6..31ce24c 100644 --- a/Swiften/Disco/EntityCapsProvider.cpp +++ b/Swiften/Disco/EntityCapsProvider.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Disco/EntityCapsProvider.h> diff --git a/Swiften/Disco/EntityCapsProvider.h b/Swiften/Disco/EntityCapsProvider.h index 54b090b..e50a745 100644 --- a/Swiften/Disco/EntityCapsProvider.h +++ b/Swiften/Disco/EntityCapsProvider.h @@ -1,34 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/JID/JID.h> #include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/JID/JID.h> namespace Swift { - /** - * This class provides information about capabilities of entities on the network. - * This information is provided in the form of service discovery - * information. - */ - class SWIFTEN_API EntityCapsProvider { - public: - virtual ~EntityCapsProvider(); + /** + * This class provides information about capabilities of entities on the network. + * This information is provided in the form of service discovery + * information. + */ + class SWIFTEN_API EntityCapsProvider { + public: + virtual ~EntityCapsProvider(); + + /** + * Returns the service discovery information of the given JID. + */ + virtual DiscoInfo::ref getCaps(const JID&) const = 0; - /** - * Returns the service discovery information of the given JID. - */ - virtual DiscoInfo::ref getCaps(const JID&) const = 0; + virtual DiscoInfo::ref getCapsCached(const JID&) = 0; - /** - * Emitted when the capabilities of a JID changes. - */ - boost::signal<void (const JID&)> onCapsChanged; - }; + /** + * Emitted when the capabilities of a JID changes. + */ + boost::signals2::signal<void (const JID&)> onCapsChanged; + }; } diff --git a/Swiften/Disco/FeatureOracle.cpp b/Swiften/Disco/FeatureOracle.cpp new file mode 100644 index 0000000..63f7a4e --- /dev/null +++ b/Swiften/Disco/FeatureOracle.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Disco/FeatureOracle.h> + +#include <algorithm> +#include <iterator> +#include <unordered_set> +#include <vector> + +#include <Swiften/Base/Log.h> +#include <Swiften/Disco/EntityCapsProvider.h> +#include <Swiften/Elements/Idle.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/FileTransfer/FileTransferManager.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Presence/PresenceOracle.h> + +namespace Swift { + +FeatureOracle::FeatureOracle(EntityCapsProvider* capsProvider, PresenceOracle* presenceOracle) : capsProvider_(capsProvider), presenceOracle_(presenceOracle) { +} + +Tristate FeatureOracle::isFileTransferSupported(const JID& jid) { + Tristate fileTransferSupported = No; + + auto isYesOrMaybe = [](Tristate tristate) { return tristate == Yes || tristate == Maybe; }; + auto isYes = [](Tristate tristate) { return tristate == Yes; }; + + auto supportedFeatures = getFeaturesForJID(jid); + + auto jingleSupported = isFeatureSupported(supportedFeatures, DiscoInfo::JingleFeature); + auto jingleFTSupported = isFeatureSupported(supportedFeatures, DiscoInfo::JingleFTFeature); + auto jingleTransportIBBSupported = isFeatureSupported(supportedFeatures, DiscoInfo::JingleTransportsIBBFeature); + auto jingleTransportS5BSupported = isFeatureSupported(supportedFeatures, DiscoInfo::JingleTransportsS5BFeature); + + if (isYes(jingleSupported) && isYes(jingleFTSupported) && (isYes(jingleTransportIBBSupported) || isYes(jingleTransportS5BSupported))) { + fileTransferSupported = Yes; + } + else if (isYesOrMaybe(jingleSupported) && isYesOrMaybe(jingleFTSupported) && (isYesOrMaybe(jingleTransportIBBSupported) || isYesOrMaybe(jingleTransportS5BSupported))) { + fileTransferSupported = Maybe; + } + + return fileTransferSupported; +} + +Tristate FeatureOracle::isMessageReceiptsSupported(const JID& jid) { + return isFeatureSupported(getFeaturesForJID(jid), DiscoInfo::MessageDeliveryReceiptsFeature); +} + +Tristate FeatureOracle::isMessageCorrectionSupported(const JID& jid) { + return isFeatureSupported(getFeaturesForJID(jid), DiscoInfo::MessageCorrectionFeature); +} + +Tristate FeatureOracle::isWhiteboardSupported(const JID& jid) { + return isFeatureSupported(getFeaturesForJID(jid), DiscoInfo::WhiteboardFeature); +} + +class PresenceFeatureAvailablityComparator { + public: + static int preferenceFromStatusShow(StatusShow::Type showType) { + switch (showType) { + case StatusShow::FFC: + return 5; + case StatusShow::Online: + return 4; + case StatusShow::DND: + return 3; + case StatusShow::Away: + return 2; + case StatusShow::XA: + return 1; + case StatusShow::None: + return 0; + } + assert(false); + return -1; + } + + static int compareWithoutResource(const Presence::ref& a, const Presence::ref& b) { + int aPreference = preferenceFromStatusShow(a->getShow()); + int bPreference = preferenceFromStatusShow(b->getShow()); + + if (aPreference != bPreference) { + return aPreference < bPreference ? 1 : -1; + } + + Idle::ref aIdle = a->getPayload<Idle>(); + Idle::ref bIdle = b->getPayload<Idle>(); + + if (aIdle && !bIdle) { + return -1; + } + else if (!aIdle && bIdle) { + return 1; + } + + if (a->getPriority() != b->getPriority()) { + return a->getPriority() < b->getPriority() ? 1 : -1; + } + + return 0; + } + + /* + * This method returns true, if \ref Presence \p b is more available than + * \ref Presence \p a. + * Going by \ref StatusShow::Type first, then by idle state, then by + * presence priority and finally by resource name. + */ + bool operator()(const Presence::ref& a, const Presence::ref& b) { + int aMoreAvailableThanB = compareWithoutResource(a, b); + if (aMoreAvailableThanB < 0) { + return true; + } + else if (aMoreAvailableThanB > 0) { + return false; + } + + return a->getFrom().getResource() < b->getFrom().getResource(); + } +}; + +JID FeatureOracle::getMostAvailableClientForFileTrasfer(const JID& bareJID) { + JID fullJID; + assert(bareJID.isBare()); + + std::vector<Presence::ref> allPresences = presenceOracle_->getAllPresence(bareJID); + std::sort(allPresences.begin(), allPresences.end(), PresenceFeatureAvailablityComparator()); + + for (const auto& presence : allPresences) { + if (presence->isAvailable()) { + if (isFileTransferSupported(presence->getFrom()) == Yes) { + fullJID = presence->getFrom(); + break; + } + } + } + + SWIFT_LOG_ASSERT(!fullJID.isBare(), error); + return fullJID; +} + +std::unordered_map<std::string, Tristate> FeatureOracle::getFeaturesForJID(const JID& jid) { + std::unordered_map<std::string, Tristate> supportedFeatures; + if (jid.isBare()) { + // Calculate the union of disco features of all most available results and return that. + std::vector<DiscoInfo::ref> onlineDiscoInfos; + std::unordered_set<std::string> features; + + // Collect relevant disco info results and the set of features. + for (auto&& presence : presenceOracle_->getAllPresence(jid)) { + if (presence->getType() == Presence::Available) { + DiscoInfo::ref presenceDiscoInfo = capsProvider_->getCapsCached(presence->getFrom()); + if (presenceDiscoInfo) { + onlineDiscoInfos.push_back(presenceDiscoInfo); + features.insert(presenceDiscoInfo->getFeatures().begin(), presenceDiscoInfo->getFeatures().end()); + } + } + } + + // Calculate supportedFeaturesMap. + for (auto&& feature : features) { + Tristate supported = Yes; + for (auto&& discoInfo : onlineDiscoInfos) { + if (!discoInfo->hasFeature(feature)) { + supported = Maybe; + break; + } + } + supportedFeatures[feature] = supported; + } + } + else { + // Return the disco result of the full JID. + auto discoInfo = capsProvider_->getCapsCached(jid); + if (discoInfo) { + for (auto&& feature : discoInfo->getFeatures()) { + supportedFeatures[feature] = Yes; + } + } + } + + return supportedFeatures; +} + +Tristate FeatureOracle::isFeatureSupported(const std::unordered_map<std::string, Tristate>& supportedFeatures, const std::string& feature) { + Tristate supported = No; + auto lookupResult = supportedFeatures.find(feature); + if (lookupResult != supportedFeatures.end()) { + supported = lookupResult->second; + } + return supported; +} + +} + + diff --git a/Swiften/Disco/FeatureOracle.h b/Swiften/Disco/FeatureOracle.h new file mode 100644 index 0000000..be0cd6f --- /dev/null +++ b/Swiften/Disco/FeatureOracle.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <unordered_map> +#include <unordered_set> + +#include <Swiften/Base/API.h> +#include <Swiften/Base/Tristate.h> +#include <Swiften/Elements/DiscoInfo.h> + +namespace Swift { + +class EntityCapsProvider; +class JID; +class PresenceOracle; + +/** + * @brief The FeatureOracle class enables direct feature support lookup for client features supported by Swiften. + */ +class SWIFTEN_API FeatureOracle { + public: + FeatureOracle(EntityCapsProvider* capsProvider, PresenceOracle* presenceOracle); + + public: + Tristate isFileTransferSupported(const JID& jid); + Tristate isMessageReceiptsSupported(const JID& jid); + Tristate isMessageCorrectionSupported(const JID& jid); + Tristate isWhiteboardSupported(const JID& jid); + + JID getMostAvailableClientForFileTrasfer(const JID& bareJID); + + private: + /** + * @brief getDiscoResultForJID returns a shared reference to a DiscoInfo representing features supported by the jid. + * @param jid The JID to return an std::unordered_map<std::string, Tristate> for. + * @return std::unordered_map<std::string, Tristate> + */ + std::unordered_map<std::string, Tristate> getFeaturesForJID(const JID& jid); + + Tristate isFeatureSupported(const std::unordered_map<std::string, Tristate>& supportedFeatures, const std::string& feature); + + private: + EntityCapsProvider* capsProvider_; + PresenceOracle* presenceOracle_; +}; + +} + diff --git a/Swiften/Disco/GetDiscoInfoRequest.h b/Swiften/Disco/GetDiscoInfoRequest.h index c9a4c97..1d86c14 100644 --- a/Swiften/Disco/GetDiscoInfoRequest.h +++ b/Swiften/Disco/GetDiscoInfoRequest.h @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class GetDiscoInfoRequest : public GenericRequest<DiscoInfo> { - public: - typedef boost::shared_ptr<GetDiscoInfoRequest> ref; - - static ref create(const JID& jid, IQRouter* router) { - return ref(new GetDiscoInfoRequest(jid, router)); - } - - static ref create(const JID& jid, const std::string& node, IQRouter* router) { - return ref(new GetDiscoInfoRequest(jid, node, router)); - } - - private: - GetDiscoInfoRequest(const JID& jid, IQRouter* router) : - GenericRequest<DiscoInfo>(IQ::Get, jid, boost::make_shared<DiscoInfo>(), router) { - } - - GetDiscoInfoRequest(const JID& jid, const std::string& node, IQRouter* router) : - GenericRequest<DiscoInfo>(IQ::Get, jid, boost::make_shared<DiscoInfo>(), router) { - getPayloadGeneric()->setNode(node); - } - }; + class SWIFTEN_API GetDiscoInfoRequest : public GenericRequest<DiscoInfo> { + public: + typedef std::shared_ptr<GetDiscoInfoRequest> ref; + + static ref create(const JID& jid, IQRouter* router) { + return ref(new GetDiscoInfoRequest(jid, router)); + } + + static ref create(const JID& jid, const std::string& node, IQRouter* router) { + return ref(new GetDiscoInfoRequest(jid, node, router)); + } + + private: + GetDiscoInfoRequest(const JID& jid, IQRouter* router) : + GenericRequest<DiscoInfo>(IQ::Get, jid, std::make_shared<DiscoInfo>(), router) { + } + + GetDiscoInfoRequest(const JID& jid, const std::string& node, IQRouter* router) : + GenericRequest<DiscoInfo>(IQ::Get, jid, std::make_shared<DiscoInfo>(), router) { + getPayloadGeneric()->setNode(node); + } + }; } diff --git a/Swiften/Disco/GetDiscoItemsRequest.h b/Swiften/Disco/GetDiscoItemsRequest.h index c4ed579..5b1ccf2 100644 --- a/Swiften/Disco/GetDiscoItemsRequest.h +++ b/Swiften/Disco/GetDiscoItemsRequest.h @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/DiscoItems.h> +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class GetDiscoItemsRequest : public GenericRequest<DiscoItems> { - public: - typedef boost::shared_ptr<GetDiscoItemsRequest> ref; - - static ref create(const JID& jid, IQRouter* router) { - return ref(new GetDiscoItemsRequest(jid, router)); - } - - static ref create(const JID& jid, const std::string& node, IQRouter* router) { - return ref(new GetDiscoItemsRequest(jid, node, router)); - } - - private: - GetDiscoItemsRequest(const JID& jid, IQRouter* router) : - GenericRequest<DiscoItems>(IQ::Get, jid, boost::make_shared<DiscoItems>(), router) { - } - - GetDiscoItemsRequest(const JID& jid, const std::string& node, IQRouter* router) : - GenericRequest<DiscoItems>(IQ::Get, jid, boost::make_shared<DiscoItems>(), router) { - getPayloadGeneric()->setNode(node); - } - }; + class SWIFTEN_API GetDiscoItemsRequest : public GenericRequest<DiscoItems> { + public: + typedef std::shared_ptr<GetDiscoItemsRequest> ref; + + static ref create(const JID& jid, IQRouter* router) { + return ref(new GetDiscoItemsRequest(jid, router)); + } + + static ref create(const JID& jid, const std::string& node, IQRouter* router) { + return ref(new GetDiscoItemsRequest(jid, node, router)); + } + + private: + GetDiscoItemsRequest(const JID& jid, IQRouter* router) : + GenericRequest<DiscoItems>(IQ::Get, jid, std::make_shared<DiscoItems>(), router) { + } + + GetDiscoItemsRequest(const JID& jid, const std::string& node, IQRouter* router) : + GenericRequest<DiscoItems>(IQ::Get, jid, std::make_shared<DiscoItems>(), router) { + getPayloadGeneric()->setNode(node); + } + }; } diff --git a/Swiften/Disco/JIDDiscoInfoResponder.cpp b/Swiften/Disco/JIDDiscoInfoResponder.cpp index 4aed254..8802bce 100644 --- a/Swiften/Disco/JIDDiscoInfoResponder.cpp +++ b/Swiften/Disco/JIDDiscoInfoResponder.cpp @@ -1,14 +1,15 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Disco/JIDDiscoInfoResponder.h> -#include <Swiften/Queries/IQRouter.h> + +#include <memory> + #include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/Queries/IQRouter.h> namespace Swift { @@ -16,41 +17,41 @@ JIDDiscoInfoResponder::JIDDiscoInfoResponder(IQRouter* router) : GetResponder<Di } void JIDDiscoInfoResponder::clearDiscoInfo(const JID& jid) { - info.erase(jid); + info.erase(jid); } void JIDDiscoInfoResponder::setDiscoInfo(const JID& jid, const DiscoInfo& discoInfo) { - JIDDiscoInfoMap::iterator i = info.insert(std::make_pair(jid, JIDDiscoInfo())).first; - i->second.discoInfo = discoInfo; + JIDDiscoInfoMap::iterator i = info.insert(std::make_pair(jid, JIDDiscoInfo())).first; + i->second.discoInfo = discoInfo; } void JIDDiscoInfoResponder::setDiscoInfo(const JID& jid, const std::string& node, const DiscoInfo& discoInfo) { - JIDDiscoInfoMap::iterator i = info.insert(std::make_pair(jid, JIDDiscoInfo())).first; - DiscoInfo newInfo(discoInfo); - newInfo.setNode(node); - i->second.nodeDiscoInfo[node] = newInfo; + JIDDiscoInfoMap::iterator i = info.insert(std::make_pair(jid, JIDDiscoInfo())).first; + DiscoInfo newInfo(discoInfo); + newInfo.setNode(node); + i->second.nodeDiscoInfo[node] = newInfo; } -bool JIDDiscoInfoResponder::handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<DiscoInfo> discoInfo) { - JIDDiscoInfoMap::const_iterator i = info.find(to); - if (i != info.end()) { - if (discoInfo->getNode().empty()) { - sendResponse(from, to, id, boost::make_shared<DiscoInfo>(i->second.discoInfo)); - } - else { - std::map<std::string,DiscoInfo>::const_iterator j = i->second.nodeDiscoInfo.find(discoInfo->getNode()); - if (j != i->second.nodeDiscoInfo.end()) { - sendResponse(from, to, id, boost::make_shared<DiscoInfo>(j->second)); - } - else { - sendError(from, to, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); - } - } - } - else { - sendError(from, to, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); - } - return true; +bool JIDDiscoInfoResponder::handleGetRequest(const JID& from, const JID& to, const std::string& id, std::shared_ptr<DiscoInfo> discoInfo) { + JIDDiscoInfoMap::const_iterator i = info.find(to); + if (i != info.end()) { + if (discoInfo->getNode().empty()) { + sendResponse(from, to, id, std::make_shared<DiscoInfo>(i->second.discoInfo)); + } + else { + std::map<std::string,DiscoInfo>::const_iterator j = i->second.nodeDiscoInfo.find(discoInfo->getNode()); + if (j != i->second.nodeDiscoInfo.end()) { + sendResponse(from, to, id, std::make_shared<DiscoInfo>(j->second)); + } + else { + sendError(from, to, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); + } + } + } + else { + sendError(from, to, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); + } + return true; } } diff --git a/Swiften/Disco/JIDDiscoInfoResponder.h b/Swiften/Disco/JIDDiscoInfoResponder.h index df529c6..1eb6228 100644 --- a/Swiften/Disco/JIDDiscoInfoResponder.h +++ b/Swiften/Disco/JIDDiscoInfoResponder.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,30 +9,30 @@ #include <map> #include <Swiften/Base/API.h> -#include <Swiften/Queries/GetResponder.h> #include <Swiften/Elements/DiscoInfo.h> #include <Swiften/JID/JID.h> +#include <Swiften/Queries/GetResponder.h> namespace Swift { - class IQRouter; - - class SWIFTEN_API JIDDiscoInfoResponder : public GetResponder<DiscoInfo> { - public: - JIDDiscoInfoResponder(IQRouter* router); - - void clearDiscoInfo(const JID& jid); - void setDiscoInfo(const JID& jid, const DiscoInfo& info); - void setDiscoInfo(const JID& jid, const std::string& node, const DiscoInfo& info); - - private: - virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<DiscoInfo> payload); - - private: - struct JIDDiscoInfo { - DiscoInfo discoInfo; - std::map<std::string, DiscoInfo> nodeDiscoInfo; - }; - typedef std::map<JID, JIDDiscoInfo> JIDDiscoInfoMap; - JIDDiscoInfoMap info; - }; + class IQRouter; + + class SWIFTEN_API JIDDiscoInfoResponder : public GetResponder<DiscoInfo> { + public: + JIDDiscoInfoResponder(IQRouter* router); + + void clearDiscoInfo(const JID& jid); + void setDiscoInfo(const JID& jid, const DiscoInfo& info); + void setDiscoInfo(const JID& jid, const std::string& node, const DiscoInfo& info); + + private: + virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, std::shared_ptr<DiscoInfo> payload); + + private: + struct JIDDiscoInfo { + DiscoInfo discoInfo; + std::map<std::string, DiscoInfo> nodeDiscoInfo; + }; + typedef std::map<JID, JIDDiscoInfo> JIDDiscoInfoMap; + JIDDiscoInfoMap info; + }; } diff --git a/Swiften/Disco/SConscript b/Swiften/Disco/SConscript index c821b42..15137ae 100644 --- a/Swiften/Disco/SConscript +++ b/Swiften/Disco/SConscript @@ -1,15 +1,16 @@ Import("swiften_env") objects = swiften_env.SwiftenObject([ - "CapsInfoGenerator.cpp", - "CapsManager.cpp", - "EntityCapsManager.cpp", - "EntityCapsProvider.cpp", - "DummyEntityCapsProvider.cpp", - "CapsStorage.cpp", - "ClientDiscoManager.cpp", - "DiscoInfoResponder.cpp", - "JIDDiscoInfoResponder.cpp", - "DiscoServiceWalker.cpp", - ]) + "CapsInfoGenerator.cpp", + "CapsManager.cpp", + "EntityCapsManager.cpp", + "EntityCapsProvider.cpp", + "DummyEntityCapsProvider.cpp", + "CapsStorage.cpp", + "ClientDiscoManager.cpp", + "DiscoInfoResponder.cpp", + "JIDDiscoInfoResponder.cpp", + "DiscoServiceWalker.cpp", + "FeatureOracle.cpp", + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp index 67d27c0..8d27ec5 100644 --- a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp +++ b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp @@ -1,86 +1,86 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Elements/DiscoInfo.h> -#include <Swiften/Disco/CapsInfoGenerator.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Disco/CapsInfoGenerator.h> +#include <Swiften/Elements/DiscoInfo.h> using namespace Swift; class CapsInfoGeneratorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(CapsInfoGeneratorTest); - CPPUNIT_TEST(testGenerate_XEP0115SimpleExample); - CPPUNIT_TEST(testGenerate_XEP0115ComplexExample); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(CapsInfoGeneratorTest); + CPPUNIT_TEST(testGenerate_XEP0115SimpleExample); + CPPUNIT_TEST(testGenerate_XEP0115ComplexExample); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - } + void testGenerate_XEP0115SimpleExample() { + DiscoInfo discoInfo; + discoInfo.addIdentity(DiscoInfo::Identity("Exodus 0.9.1", "client", "pc")); + discoInfo.addFeature("http://jabber.org/protocol/disco#items"); + discoInfo.addFeature("http://jabber.org/protocol/caps"); + discoInfo.addFeature("http://jabber.org/protocol/disco#info"); + discoInfo.addFeature("http://jabber.org/protocol/muc"); - void testGenerate_XEP0115SimpleExample() { - DiscoInfo discoInfo; - discoInfo.addIdentity(DiscoInfo::Identity("Exodus 0.9.1", "client", "pc")); - discoInfo.addFeature("http://jabber.org/protocol/disco#items"); - discoInfo.addFeature("http://jabber.org/protocol/caps"); - discoInfo.addFeature("http://jabber.org/protocol/disco#info"); - discoInfo.addFeature("http://jabber.org/protocol/muc"); + CapsInfoGenerator testling("http://code.google.com/p/exodus", crypto.get()); + CapsInfo result = testling.generateCapsInfo(discoInfo); - CapsInfoGenerator testling("http://code.google.com/p/exodus", crypto.get()); - CapsInfo result = testling.generateCapsInfo(discoInfo); + CPPUNIT_ASSERT_EQUAL(std::string("http://code.google.com/p/exodus"), result.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), result.getHash()); + CPPUNIT_ASSERT_EQUAL(std::string("QgayPKawpkPSDYmwT/WM94uAlu0="), result.getVersion()); + } - CPPUNIT_ASSERT_EQUAL(std::string("http://code.google.com/p/exodus"), result.getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), result.getHash()); - CPPUNIT_ASSERT_EQUAL(std::string("QgayPKawpkPSDYmwT/WM94uAlu0="), result.getVersion()); - } + void testGenerate_XEP0115ComplexExample() { + DiscoInfo discoInfo; + discoInfo.addIdentity(DiscoInfo::Identity("Psi 0.11", "client", "pc", "en")); + discoInfo.addIdentity(DiscoInfo::Identity("\xce\xa8 0.11", "client", "pc", "el")); + discoInfo.addFeature("http://jabber.org/protocol/disco#items"); + discoInfo.addFeature("http://jabber.org/protocol/caps"); + discoInfo.addFeature("http://jabber.org/protocol/disco#info"); + discoInfo.addFeature("http://jabber.org/protocol/muc"); - void testGenerate_XEP0115ComplexExample() { - DiscoInfo discoInfo; - discoInfo.addIdentity(DiscoInfo::Identity("Psi 0.11", "client", "pc", "en")); - discoInfo.addIdentity(DiscoInfo::Identity("\xce\xa8 0.11", "client", "pc", "el")); - discoInfo.addFeature("http://jabber.org/protocol/disco#items"); - discoInfo.addFeature("http://jabber.org/protocol/caps"); - discoInfo.addFeature("http://jabber.org/protocol/disco#info"); - discoInfo.addFeature("http://jabber.org/protocol/muc"); + Form::ref extension(new Form(Form::ResultType)); + FormField::ref field = std::make_shared<FormField>(FormField::HiddenType, "urn:xmpp:dataforms:softwareinfo"); + field->setName("FORM_TYPE"); + extension->addField(field); + field = std::make_shared<FormField>(FormField::ListMultiType); + field->addValue("ipv6"); + field->addValue("ipv4"); + field->setName("ip_version"); + extension->addField(field); + field = std::make_shared<FormField>(FormField::TextSingleType, "Psi"); + field->setName("software"); + extension->addField(field); + field = std::make_shared<FormField>(FormField::TextSingleType, "0.11"); + field->setName("software_version"); + extension->addField(field); + field = std::make_shared<FormField>(FormField::TextSingleType, "Mac"); + field->setName("os"); + extension->addField(field); + field = std::make_shared<FormField>(FormField::TextSingleType, "10.5.1"); + field->setName("os_version"); + extension->addField(field); + discoInfo.addExtension(extension); - Form::ref extension(new Form(Form::ResultType)); - FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "urn:xmpp:dataforms:softwareinfo"); - field->setName("FORM_TYPE"); - extension->addField(field); - field = boost::make_shared<FormField>(FormField::ListMultiType); - field->addValue("ipv6"); - field->addValue("ipv4"); - field->setName("ip_version"); - extension->addField(field); - field = boost::make_shared<FormField>(FormField::TextSingleType, "Psi"); - field->setName("software"); - extension->addField(field); - field = boost::make_shared<FormField>(FormField::TextSingleType, "0.11"); - field->setName("software_version"); - extension->addField(field); - field = boost::make_shared<FormField>(FormField::TextSingleType, "Mac"); - field->setName("os"); - extension->addField(field); - field = boost::make_shared<FormField>(FormField::TextSingleType, "10.5.1"); - field->setName("os_version"); - extension->addField(field); - discoInfo.addExtension(extension); + CapsInfoGenerator testling("http://psi-im.org", crypto.get()); + CapsInfo result = testling.generateCapsInfo(discoInfo); - CapsInfoGenerator testling("http://psi-im.org", crypto.get()); - CapsInfo result = testling.generateCapsInfo(discoInfo); + CPPUNIT_ASSERT_EQUAL(std::string("q07IKJEyjvHSyhy//CH0CxmKi8w="), result.getVersion()); + } - CPPUNIT_ASSERT_EQUAL(std::string("q07IKJEyjvHSyhy//CH0CxmKi8w="), result.getVersion()); - } - - private: - boost::shared_ptr<CryptoProvider> crypto; + private: + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(CapsInfoGeneratorTest); diff --git a/Swiften/Disco/UnitTest/CapsManagerTest.cpp b/Swiften/Disco/UnitTest/CapsManagerTest.cpp index 303fd78..5f1aaf4 100644 --- a/Swiften/Disco/UnitTest/CapsManagerTest.cpp +++ b/Swiften/Disco/UnitTest/CapsManagerTest.cpp @@ -1,290 +1,291 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <memory> #include <vector> + #include <boost/bind.hpp> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Disco/CapsInfoGenerator.h> #include <Swiften/Disco/CapsManager.h> #include <Swiften/Disco/CapsMemoryStorage.h> -#include <Swiften/Disco/CapsInfoGenerator.h> -#include <Swiften/Queries/IQRouter.h> #include <Swiften/Elements/CapsInfo.h> #include <Swiften/Elements/DiscoInfo.h> -#include <Swiften/Client/DummyStanzaChannel.h> -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Queries/IQRouter.h> using namespace Swift; class CapsManagerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(CapsManagerTest); - CPPUNIT_TEST(testReceiveNewHashRequestsDisco); - CPPUNIT_TEST(testReceiveSameHashDoesNotRequestDisco); - CPPUNIT_TEST(testReceiveLegacyCapsDoesNotRequestDisco); - CPPUNIT_TEST(testReceiveSameHashFromSameUserAfterFailedDiscoDoesNotRequestDisco); - CPPUNIT_TEST(testReceiveSameHashFromDifferentUserAfterFailedDiscoRequestsDisco); - CPPUNIT_TEST(testReceiveSameHashFromDifferentUserAfterIncorrectVerificationRequestsDisco); - CPPUNIT_TEST(testReceiveDifferentHashFromSameUserAfterFailedDiscoDoesNotRequestDisco); - CPPUNIT_TEST(testReceiveSameHashAfterSuccesfulDiscoDoesNotRequestDisco); - CPPUNIT_TEST(testReceiveSuccesfulDiscoStoresCaps); - CPPUNIT_TEST(testReceiveIncorrectVerificationDiscoDoesNotStoreCaps); - CPPUNIT_TEST(testReceiveFailingDiscoFallsBack); - CPPUNIT_TEST(testReceiveNoDiscoFallsBack); - CPPUNIT_TEST(testReceiveFailingFallbackDiscoFallsBack); - CPPUNIT_TEST(testReceiveSameHashFromFailingUserAfterReconnectRequestsDisco); - CPPUNIT_TEST(testReconnectResetsFallback); - CPPUNIT_TEST(testReconnectResetsRequests); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - storage = new CapsMemoryStorage(); - user1 = JID("user1@bar.com/bla"); - discoInfo1 = boost::make_shared<DiscoInfo>(); - discoInfo1->addFeature("http://swift.im/feature1"); - capsInfo1 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); - capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); - user2 = JID("user2@foo.com/baz"); - discoInfo2 = boost::make_shared<DiscoInfo>(); - discoInfo2->addFeature("http://swift.im/feature2"); - capsInfo2 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get())); - user3 = JID("user3@foo.com/baz"); - legacyCapsInfo = boost::make_shared<CapsInfo>("http://swift.im", "ver1", ""); - } - - void tearDown() { - delete storage; - delete iqRouter; - delete stanzaChannel; - } - - void testReceiveNewHashRequestsDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); - boost::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[0]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(discoInfo); - CPPUNIT_ASSERT_EQUAL("http://node1.im#" + capsInfo1->getVersion(), discoInfo->getNode()); - } - - void testReceiveSameHashDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReceiveLegacyCapsDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, legacyCapsInfo); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReceiveSameHashAfterSuccesfulDiscoDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendDiscoInfoResult(discoInfo1); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReceiveSameHashFromSameUserAfterFailedDiscoDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReceiveSameHashFromSameUserAfterIncorrectVerificationDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendDiscoInfoResult(discoInfo2); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReceiveSameHashFromDifferentUserAfterFailedDiscoRequestsDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user2, capsInfo1); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user2, IQ::Get)); - } - - void testReceiveSameHashFromDifferentUserAfterIncorrectVerificationRequestsDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendDiscoInfoResult(discoInfo2); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user2, capsInfo1); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user2, IQ::Get)); - } - - void testReceiveDifferentHashFromSameUserAfterFailedDiscoDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo2); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); - } - - void testReceiveSuccesfulDiscoStoresCaps() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendDiscoInfoResult(discoInfo1); - - boost::shared_ptr<DiscoInfo> discoInfo(storage->getDiscoInfo(capsInfo1->getVersion())); - CPPUNIT_ASSERT(discoInfo); - CPPUNIT_ASSERT(discoInfo->hasFeature("http://swift.im/feature1")); - } - - void testReceiveIncorrectVerificationDiscoDoesNotStoreCaps() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendDiscoInfoResult(discoInfo2); - - boost::shared_ptr<DiscoInfo> discoInfo(storage->getDiscoInfo(capsInfo1->getVersion())); - CPPUNIT_ASSERT(!discoInfo); - } - - void testReceiveFailingDiscoFallsBack() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendPresenceWithCaps(user2, capsInfo1alt); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(1, user2, IQ::Get)); - boost::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[1]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(discoInfo); - CPPUNIT_ASSERT_EQUAL("http://node2.im#" + capsInfo1alt->getVersion(), discoInfo->getNode()); - } - - void testReceiveNoDiscoFallsBack() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendPresenceWithCaps(user2, capsInfo1alt); - stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), boost::shared_ptr<DiscoInfo>())); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(1, user2, IQ::Get)); - boost::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[1]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(discoInfo); - CPPUNIT_ASSERT_EQUAL("http://node2.im#" + capsInfo1alt->getVersion(), discoInfo->getNode()); - } - - void testReceiveFailingFallbackDiscoFallsBack() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendPresenceWithCaps(user2, capsInfo1alt); - sendPresenceWithCaps(user3, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[1]->getTo(), stanzaChannel->sentStanzas[1]->getID())); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(2, user3, IQ::Get)); - } - - void testReceiveSameHashFromFailingUserAfterReconnectRequestsDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - stanzaChannel->setAvailable(false); - stanzaChannel->setAvailable(true); - stanzaChannel->sentStanzas.clear(); - - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); - } - - void testReconnectResetsFallback() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendPresenceWithCaps(user2, capsInfo1alt); - stanzaChannel->setAvailable(false); - stanzaChannel->setAvailable(true); - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReconnectResetsRequests() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->sentStanzas.clear(); - stanzaChannel->setAvailable(false); - stanzaChannel->setAvailable(true); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); - } - - private: - boost::shared_ptr<CapsManager> createManager() { - boost::shared_ptr<CapsManager> manager(new CapsManager(storage, stanzaChannel, iqRouter, crypto.get())); - manager->setWarnOnInvalidHash(false); - //manager->onCapsChanged.connect(boost::bind(&CapsManagerTest::handleCapsChanged, this, _1)); - return manager; - } - - void handleCapsChanged(const JID& jid) { - changes.push_back(jid); - } - - void sendPresenceWithCaps(const JID& jid, boost::shared_ptr<CapsInfo> caps) { - boost::shared_ptr<Presence> presence(new Presence()); - presence->setFrom(jid); - presence->addPayload(caps); - stanzaChannel->onPresenceReceived(presence); - } - - void sendDiscoInfoResult(boost::shared_ptr<DiscoInfo> discoInfo) { - stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), discoInfo)); - } - - private: - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - CapsStorage* storage; - std::vector<JID> changes; - JID user1; - boost::shared_ptr<DiscoInfo> discoInfo1; - boost::shared_ptr<CapsInfo> capsInfo1; - boost::shared_ptr<CapsInfo> capsInfo1alt; - JID user2; - boost::shared_ptr<DiscoInfo> discoInfo2; - boost::shared_ptr<CapsInfo> capsInfo2; - boost::shared_ptr<CapsInfo> legacyCapsInfo; - JID user3; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(CapsManagerTest); + CPPUNIT_TEST(testReceiveNewHashRequestsDisco); + CPPUNIT_TEST(testReceiveSameHashDoesNotRequestDisco); + CPPUNIT_TEST(testReceiveLegacyCapsDoesNotRequestDisco); + CPPUNIT_TEST(testReceiveSameHashFromSameUserAfterFailedDiscoDoesNotRequestDisco); + CPPUNIT_TEST(testReceiveSameHashFromDifferentUserAfterFailedDiscoRequestsDisco); + CPPUNIT_TEST(testReceiveSameHashFromDifferentUserAfterIncorrectVerificationRequestsDisco); + CPPUNIT_TEST(testReceiveDifferentHashFromSameUserAfterFailedDiscoDoesNotRequestDisco); + CPPUNIT_TEST(testReceiveSameHashAfterSuccesfulDiscoDoesNotRequestDisco); + CPPUNIT_TEST(testReceiveSuccesfulDiscoStoresCaps); + CPPUNIT_TEST(testReceiveIncorrectVerificationDiscoDoesNotStoreCaps); + CPPUNIT_TEST(testReceiveFailingDiscoFallsBack); + CPPUNIT_TEST(testReceiveNoDiscoFallsBack); + CPPUNIT_TEST(testReceiveFailingFallbackDiscoFallsBack); + CPPUNIT_TEST(testReceiveSameHashFromFailingUserAfterReconnectRequestsDisco); + CPPUNIT_TEST(testReconnectResetsFallback); + CPPUNIT_TEST(testReconnectResetsRequests); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + stanzaChannel = std::make_unique<DummyStanzaChannel>(); + iqRouter = std::make_unique<IQRouter>(stanzaChannel.get()); + storage = std::make_unique<CapsMemoryStorage>(); + user1 = JID("user1@bar.com/bla"); + discoInfo1 = std::make_shared<DiscoInfo>(); + discoInfo1->addFeature("http://swift.im/feature1"); + capsInfo1 = std::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); + capsInfo1alt = std::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); + user2 = JID("user2@foo.com/baz"); + discoInfo2 = std::make_shared<DiscoInfo>(); + discoInfo2->addFeature("http://swift.im/feature2"); + capsInfo2 = std::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get())); + user3 = JID("user3@foo.com/baz"); + legacyCapsInfo = std::make_shared<CapsInfo>("http://swift.im", "ver1", ""); + } + + void tearDown() { + iqRouter.reset(); + } + + void testReceiveNewHashRequestsDisco() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); + std::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[0]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(discoInfo); + CPPUNIT_ASSERT_EQUAL("http://node1.im#" + capsInfo1->getVersion(), discoInfo->getNode()); + } + + void testReceiveSameHashDoesNotRequestDisco() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReceiveLegacyCapsDoesNotRequestDisco() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, legacyCapsInfo); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReceiveSameHashAfterSuccesfulDiscoDoesNotRequestDisco() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendDiscoInfoResult(discoInfo1); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReceiveSameHashFromSameUserAfterFailedDiscoDoesNotRequestDisco() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReceiveSameHashFromSameUserAfterIncorrectVerificationDoesNotRequestDisco() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendDiscoInfoResult(discoInfo2); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReceiveSameHashFromDifferentUserAfterFailedDiscoRequestsDisco() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user2, capsInfo1); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user2, IQ::Get)); + } + + void testReceiveSameHashFromDifferentUserAfterIncorrectVerificationRequestsDisco() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendDiscoInfoResult(discoInfo2); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user2, capsInfo1); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user2, IQ::Get)); + } + + void testReceiveDifferentHashFromSameUserAfterFailedDiscoDoesNotRequestDisco() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo2); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); + } + + void testReceiveSuccesfulDiscoStoresCaps() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendDiscoInfoResult(discoInfo1); + + std::shared_ptr<DiscoInfo> discoInfo(storage->getDiscoInfo(capsInfo1->getVersion())); + CPPUNIT_ASSERT(discoInfo); + CPPUNIT_ASSERT(discoInfo->hasFeature("http://swift.im/feature1")); + } + + void testReceiveIncorrectVerificationDiscoDoesNotStoreCaps() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendDiscoInfoResult(discoInfo2); + + std::shared_ptr<DiscoInfo> discoInfo(storage->getDiscoInfo(capsInfo1->getVersion())); + CPPUNIT_ASSERT(!discoInfo); + } + + void testReceiveFailingDiscoFallsBack() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendPresenceWithCaps(user2, capsInfo1alt); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(1, user2, IQ::Get)); + std::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[1]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(discoInfo); + CPPUNIT_ASSERT_EQUAL("http://node2.im#" + capsInfo1alt->getVersion(), discoInfo->getNode()); + } + + void testReceiveNoDiscoFallsBack() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendPresenceWithCaps(user2, capsInfo1alt); + stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), std::shared_ptr<DiscoInfo>())); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(1, user2, IQ::Get)); + std::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[1]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(discoInfo); + CPPUNIT_ASSERT_EQUAL("http://node2.im#" + capsInfo1alt->getVersion(), discoInfo->getNode()); + } + + void testReceiveFailingFallbackDiscoFallsBack() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendPresenceWithCaps(user2, capsInfo1alt); + sendPresenceWithCaps(user3, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[1]->getTo(), stanzaChannel->sentStanzas[1]->getID())); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(2, user3, IQ::Get)); + } + + void testReceiveSameHashFromFailingUserAfterReconnectRequestsDisco() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + stanzaChannel->setAvailable(false); + stanzaChannel->setAvailable(true); + stanzaChannel->sentStanzas.clear(); + + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); + } + + void testReconnectResetsFallback() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendPresenceWithCaps(user2, capsInfo1alt); + stanzaChannel->setAvailable(false); + stanzaChannel->setAvailable(true); + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReconnectResetsRequests() { + std::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->sentStanzas.clear(); + stanzaChannel->setAvailable(false); + stanzaChannel->setAvailable(true); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); + } + + private: + std::shared_ptr<CapsManager> createManager() { + std::shared_ptr<CapsManager> manager(new CapsManager(storage.get(), stanzaChannel.get(), iqRouter.get(), crypto.get())); + manager->setWarnOnInvalidHash(false); + //manager->onCapsChanged.connect(boost::bind(&CapsManagerTest::handleCapsChanged, this, _1)); + return manager; + } + + void handleCapsChanged(const JID& jid) { + changes.push_back(jid); + } + + void sendPresenceWithCaps(const JID& jid, std::shared_ptr<CapsInfo> caps) { + std::shared_ptr<Presence> presence(new Presence()); + presence->setFrom(jid); + presence->addPayload(caps); + stanzaChannel->onPresenceReceived(presence); + } + + void sendDiscoInfoResult(std::shared_ptr<DiscoInfo> discoInfo) { + stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), discoInfo)); + } + + private: + std::unique_ptr<DummyStanzaChannel> stanzaChannel; + std::unique_ptr<IQRouter> iqRouter; + std::unique_ptr<CapsStorage> storage; + std::vector<JID> changes; + JID user1; + std::shared_ptr<DiscoInfo> discoInfo1; + std::shared_ptr<CapsInfo> capsInfo1; + std::shared_ptr<CapsInfo> capsInfo1alt; + JID user2; + std::shared_ptr<DiscoInfo> discoInfo2; + std::shared_ptr<CapsInfo> capsInfo2; + std::shared_ptr<CapsInfo> legacyCapsInfo; + JID user3; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(CapsManagerTest); diff --git a/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp b/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp index 1477e23..45dc959 100644 --- a/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp +++ b/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp @@ -1,96 +1,97 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <typeinfo> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <typeinfo> #include <Swiften/Disco/DiscoInfoResponder.h> -#include <Swiften/Queries/IQRouter.h> #include <Swiften/Queries/DummyIQChannel.h> +#include <Swiften/Queries/IQRouter.h> using namespace Swift; class DiscoInfoResponderTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DiscoInfoResponderTest); - CPPUNIT_TEST(testHandleRequest_GetToplevelInfo); - CPPUNIT_TEST(testHandleRequest_GetNodeInfo); - CPPUNIT_TEST(testHandleRequest_GetInvalidNodeInfo); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - channel_ = new DummyIQChannel(); - router_ = new IQRouter(channel_); - } - - void tearDown() { - delete router_; - delete channel_; - } - - void testHandleRequest_GetToplevelInfo() { - DiscoInfoResponder testling(router_); - testling.start(); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(discoInfo); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT_EQUAL(std::string(""), payload->getNode()); - CPPUNIT_ASSERT(payload->hasFeature("foo")); - - testling.stop(); - } - - void testHandleRequest_GetNodeInfo() { - DiscoInfoResponder testling(router_); - testling.start(); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(discoInfo); - DiscoInfo discoInfoBar; - discoInfoBar.addFeature("bar"); - testling.setDiscoInfo("bar-node", discoInfoBar); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - query->setNode("bar-node"); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT_EQUAL(std::string("bar-node"), payload->getNode()); - CPPUNIT_ASSERT(payload->hasFeature("bar")); - - testling.stop(); - } - - void testHandleRequest_GetInvalidNodeInfo() { - DiscoInfoResponder testling(router_); - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - query->setNode("bar-node"); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); - testling.start(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); - CPPUNIT_ASSERT(payload); - - testling.stop(); - } - - private: - IQRouter* router_; - DummyIQChannel* channel_; + CPPUNIT_TEST_SUITE(DiscoInfoResponderTest); + CPPUNIT_TEST(testHandleRequest_GetToplevelInfo); + CPPUNIT_TEST(testHandleRequest_GetNodeInfo); + CPPUNIT_TEST(testHandleRequest_GetInvalidNodeInfo); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + channel_ = new DummyIQChannel(); + router_ = new IQRouter(channel_); + } + + void tearDown() { + delete router_; + delete channel_; + } + + void testHandleRequest_GetToplevelInfo() { + DiscoInfoResponder testling(router_); + testling.start(); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(discoInfo); + + std::shared_ptr<DiscoInfo> query(new DiscoInfo()); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + std::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string(""), payload->getNode()); + CPPUNIT_ASSERT(payload->hasFeature("foo")); + + testling.stop(); + } + + void testHandleRequest_GetNodeInfo() { + DiscoInfoResponder testling(router_); + testling.start(); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(discoInfo); + DiscoInfo discoInfoBar; + discoInfoBar.addFeature("bar"); + testling.setDiscoInfo("bar-node", discoInfoBar); + + std::shared_ptr<DiscoInfo> query(new DiscoInfo()); + query->setNode("bar-node"); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + std::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string("bar-node"), payload->getNode()); + CPPUNIT_ASSERT(payload->hasFeature("bar")); + + testling.stop(); + } + + void testHandleRequest_GetInvalidNodeInfo() { + DiscoInfoResponder testling(router_); + std::shared_ptr<DiscoInfo> query(new DiscoInfo()); + query->setNode("bar-node"); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); + testling.start(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + std::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); + CPPUNIT_ASSERT(payload); + + testling.stop(); + } + + private: + IQRouter* router_; + DummyIQChannel* channel_; }; CPPUNIT_TEST_SUITE_REGISTRATION(DiscoInfoResponderTest); diff --git a/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp b/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp index 940f043..6548485 100644 --- a/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp +++ b/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp @@ -1,193 +1,191 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <memory> #include <vector> + #include <boost/bind.hpp> -#include <Swiften/Disco/EntityCapsManager.h> -#include <Swiften/Disco/CapsProvider.h> -#include <Swiften/Elements/CapsInfo.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + #include <Swiften/Client/DummyStanzaChannel.h> -#include <Swiften/Disco/CapsInfoGenerator.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Disco/CapsInfoGenerator.h> +#include <Swiften/Disco/CapsProvider.h> +#include <Swiften/Disco/EntityCapsManager.h> +#include <Swiften/Elements/CapsInfo.h> using namespace Swift; class EntityCapsManagerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(EntityCapsManagerTest); - CPPUNIT_TEST(testReceiveKnownHash); - CPPUNIT_TEST(testReceiveKnownHashTwiceDoesNotTriggerChange); - CPPUNIT_TEST(testReceiveUnknownHashDoesNotTriggerChange); - CPPUNIT_TEST(testReceiveUnknownHashAfterKnownHashTriggersChangeAndClearsCaps); - CPPUNIT_TEST(testReceiveUnavailablePresenceAfterKnownHashTriggersChangeAndClearsCaps); - CPPUNIT_TEST(testReconnectTriggersChangeAndClearsCaps); - CPPUNIT_TEST(testHashAvailable); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - - stanzaChannel = new DummyStanzaChannel(); - capsProvider = new DummyCapsProvider(); - - user1 = JID("user1@bar.com/bla"); - discoInfo1 = boost::make_shared<DiscoInfo>(); - discoInfo1->addFeature("http://swift.im/feature1"); - capsInfo1 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); - capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); - user2 = JID("user2@foo.com/baz"); - discoInfo2 = boost::make_shared<DiscoInfo>(); - discoInfo2->addFeature("http://swift.im/feature2"); - capsInfo2 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get())); - user3 = JID("user3@foo.com/baz"); - legacyCapsInfo = boost::make_shared<CapsInfo>("http://swift.im", "ver1", ""); - } - - void tearDown() { - delete capsProvider; - delete stanzaChannel; - } - - void testReceiveKnownHash() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - CPPUNIT_ASSERT_EQUAL(discoInfo1, testling->getCaps(user1)); - } - - void testReceiveKnownHashTwiceDoesNotTriggerChange() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - sendPresenceWithCaps(user1, capsInfo1); - changes.clear(); - - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); - } - - void testReceiveUnknownHashDoesNotTriggerChange() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); - } - - void testHashAvailable() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - capsProvider->onCapsAvailable(capsInfo1->getVersion()); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - CPPUNIT_ASSERT_EQUAL(discoInfo1, testling->getCaps(user1)); - } - - void testReceiveUnknownHashAfterKnownHashTriggersChangeAndClearsCaps() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - sendPresenceWithCaps(user1, capsInfo1); - changes.clear(); - sendPresenceWithCaps(user1, capsInfo2); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - CPPUNIT_ASSERT(!testling->getCaps(user1)); - } - - void testReceiveUnavailablePresenceAfterKnownHashTriggersChangeAndClearsCaps() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - sendPresenceWithCaps(user1, capsInfo1); - changes.clear(); - sendUnavailablePresence(user1); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - CPPUNIT_ASSERT(!testling->getCaps(user1)); - } - - void testReconnectTriggersChangeAndClearsCaps() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - capsProvider->caps[capsInfo2->getVersion()] = discoInfo2; - sendPresenceWithCaps(user1, capsInfo1); - sendPresenceWithCaps(user2, capsInfo2); - changes.clear(); - stanzaChannel->setAvailable(false); - stanzaChannel->setAvailable(true); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - CPPUNIT_ASSERT(!testling->getCaps(user1)); - CPPUNIT_ASSERT_EQUAL(user2, changes[1]); - CPPUNIT_ASSERT(!testling->getCaps(user2)); - } - - private: - boost::shared_ptr<EntityCapsManager> createManager() { - boost::shared_ptr<EntityCapsManager> manager(new EntityCapsManager(capsProvider, stanzaChannel)); - manager->onCapsChanged.connect(boost::bind(&EntityCapsManagerTest::handleCapsChanged, this, _1)); - return manager; - } - - void handleCapsChanged(const JID& jid) { - changes.push_back(jid); - } - - void sendPresenceWithCaps(const JID& jid, boost::shared_ptr<CapsInfo> caps) { - boost::shared_ptr<Presence> presence(new Presence()); - presence->setFrom(jid); - presence->addPayload(caps); - stanzaChannel->onPresenceReceived(presence); - } - - void sendUnavailablePresence(const JID& jid) { - boost::shared_ptr<Presence> presence(new Presence()); - presence->setFrom(jid); - presence->setType(Presence::Unavailable); - stanzaChannel->onPresenceReceived(presence); - } - - private: - struct DummyCapsProvider : public CapsProvider { - virtual DiscoInfo::ref getCaps(const std::string& hash) const { - std::map<std::string, DiscoInfo::ref>::const_iterator i = caps.find(hash); - if (i != caps.end()) { - return i->second; - } - return DiscoInfo::ref(); - } - - std::map<std::string, DiscoInfo::ref> caps; - }; - - private: - DummyStanzaChannel* stanzaChannel; - DummyCapsProvider* capsProvider; - JID user1; - boost::shared_ptr<DiscoInfo> discoInfo1; - boost::shared_ptr<CapsInfo> capsInfo1; - boost::shared_ptr<CapsInfo> capsInfo1alt; - JID user2; - boost::shared_ptr<DiscoInfo> discoInfo2; - boost::shared_ptr<CapsInfo> capsInfo2; - boost::shared_ptr<CapsInfo> legacyCapsInfo; - JID user3; - std::vector<JID> changes; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(EntityCapsManagerTest); + CPPUNIT_TEST(testReceiveKnownHash); + CPPUNIT_TEST(testReceiveKnownHashTwiceDoesNotTriggerChange); + CPPUNIT_TEST(testReceiveUnknownHashDoesNotTriggerChange); + CPPUNIT_TEST(testReceiveUnknownHashAfterKnownHashTriggersChangeAndClearsCaps); + CPPUNIT_TEST(testReceiveUnavailablePresenceAfterKnownHashTriggersChangeAndClearsCaps); + CPPUNIT_TEST(testReconnectTriggersChangeAndClearsCaps); + CPPUNIT_TEST(testHashAvailable); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + + stanzaChannel = std::make_unique<DummyStanzaChannel>(); + capsProvider = std::make_unique<DummyCapsProvider>(); + + user1 = JID("user1@bar.com/bla"); + discoInfo1 = std::make_shared<DiscoInfo>(); + discoInfo1->addFeature("http://swift.im/feature1"); + capsInfo1 = std::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); + capsInfo1alt = std::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); + user2 = JID("user2@foo.com/baz"); + discoInfo2 = std::make_shared<DiscoInfo>(); + discoInfo2->addFeature("http://swift.im/feature2"); + capsInfo2 = std::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get())); + user3 = JID("user3@foo.com/baz"); + legacyCapsInfo = std::make_shared<CapsInfo>("http://swift.im", "ver1", ""); + } + + void testReceiveKnownHash() { + std::shared_ptr<EntityCapsManager> testling = createManager(); + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + CPPUNIT_ASSERT_EQUAL(discoInfo1, testling->getCaps(user1)); + } + + void testReceiveKnownHashTwiceDoesNotTriggerChange() { + std::shared_ptr<EntityCapsManager> testling = createManager(); + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + sendPresenceWithCaps(user1, capsInfo1); + changes.clear(); + + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testReceiveUnknownHashDoesNotTriggerChange() { + std::shared_ptr<EntityCapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testHashAvailable() { + std::shared_ptr<EntityCapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + capsProvider->onCapsAvailable(capsInfo1->getVersion()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + CPPUNIT_ASSERT_EQUAL(discoInfo1, testling->getCaps(user1)); + } + + void testReceiveUnknownHashAfterKnownHashTriggersChangeAndClearsCaps() { + std::shared_ptr<EntityCapsManager> testling = createManager(); + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + sendPresenceWithCaps(user1, capsInfo1); + changes.clear(); + sendPresenceWithCaps(user1, capsInfo2); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + CPPUNIT_ASSERT(!testling->getCaps(user1)); + } + + void testReceiveUnavailablePresenceAfterKnownHashTriggersChangeAndClearsCaps() { + std::shared_ptr<EntityCapsManager> testling = createManager(); + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + sendPresenceWithCaps(user1, capsInfo1); + changes.clear(); + sendUnavailablePresence(user1); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + CPPUNIT_ASSERT(!testling->getCaps(user1)); + } + + void testReconnectTriggersChangeAndClearsCaps() { + std::shared_ptr<EntityCapsManager> testling = createManager(); + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + capsProvider->caps[capsInfo2->getVersion()] = discoInfo2; + sendPresenceWithCaps(user1, capsInfo1); + sendPresenceWithCaps(user2, capsInfo2); + changes.clear(); + stanzaChannel->setAvailable(false); + stanzaChannel->setAvailable(true); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + CPPUNIT_ASSERT(!testling->getCaps(user1)); + CPPUNIT_ASSERT_EQUAL(user2, changes[1]); + CPPUNIT_ASSERT(!testling->getCaps(user2)); + } + + private: + std::shared_ptr<EntityCapsManager> createManager() { + std::shared_ptr<EntityCapsManager> manager(new EntityCapsManager(capsProvider.get(), stanzaChannel.get())); + manager->onCapsChanged.connect(boost::bind(&EntityCapsManagerTest::handleCapsChanged, this, _1)); + return manager; + } + + void handleCapsChanged(const JID& jid) { + changes.push_back(jid); + } + + void sendPresenceWithCaps(const JID& jid, std::shared_ptr<CapsInfo> caps) { + std::shared_ptr<Presence> presence(new Presence()); + presence->setFrom(jid); + presence->addPayload(caps); + stanzaChannel->onPresenceReceived(presence); + } + + void sendUnavailablePresence(const JID& jid) { + std::shared_ptr<Presence> presence(new Presence()); + presence->setFrom(jid); + presence->setType(Presence::Unavailable); + stanzaChannel->onPresenceReceived(presence); + } + + private: + struct DummyCapsProvider : public CapsProvider { + virtual DiscoInfo::ref getCaps(const std::string& hash) const { + std::map<std::string, DiscoInfo::ref>::const_iterator i = caps.find(hash); + if (i != caps.end()) { + return i->second; + } + return DiscoInfo::ref(); + } + + std::map<std::string, DiscoInfo::ref> caps; + }; + + private: + std::unique_ptr<DummyStanzaChannel> stanzaChannel; + std::unique_ptr<DummyCapsProvider> capsProvider; + JID user1; + std::shared_ptr<DiscoInfo> discoInfo1; + std::shared_ptr<CapsInfo> capsInfo1; + std::shared_ptr<CapsInfo> capsInfo1alt; + JID user2; + std::shared_ptr<DiscoInfo> discoInfo2; + std::shared_ptr<CapsInfo> capsInfo2; + std::shared_ptr<CapsInfo> legacyCapsInfo; + JID user3; + std::vector<JID> changes; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(EntityCapsManagerTest); diff --git a/Swiften/Disco/UnitTest/FeatureOracleTest.cpp b/Swiften/Disco/UnitTest/FeatureOracleTest.cpp new file mode 100644 index 0000000..e5ff09b --- /dev/null +++ b/Swiften/Disco/UnitTest/FeatureOracleTest.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <vector> + +#include <boost/bind.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/Tristate.h> +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Disco/CapsInfoGenerator.h> +#include <Swiften/Disco/CapsProvider.h> +#include <Swiften/Disco/EntityCapsManager.h> +#include <Swiften/Disco/FeatureOracle.h> +#include <Swiften/Elements/CapsInfo.h> +#include <Swiften/Presence/PresenceOracle.h> +#include <Swiften/Roster/XMPPRosterImpl.h> + +using namespace Swift; + +class FeatureOracleTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(FeatureOracleTest); + CPPUNIT_TEST(testMergeAvailableResourcesForFeatures); + CPPUNIT_TEST(testMostAvailableFileTransferClient); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto_ = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + dummyStanzaChannel_ = new DummyStanzaChannel(); + xmppRosterImpl_ = new XMPPRosterImpl(); + dummyCapsProvider_ = new DummyCapsProvider(); + entityCapsManager_ = new EntityCapsManager(dummyCapsProvider_, dummyStanzaChannel_); + presenceOracle_ = new PresenceOracle(dummyStanzaChannel_, xmppRosterImpl_); + featureOracle_ = new FeatureOracle(entityCapsManager_, presenceOracle_); + } + + void tearDown() { + delete featureOracle_; + delete presenceOracle_; + delete entityCapsManager_; + delete dummyCapsProvider_; + delete xmppRosterImpl_; + delete dummyStanzaChannel_; + } + + void simulateIncomingPresence(const JID& from, Presence::Type type, StatusShow::Type status, const DiscoInfo::ref& disco, const std::vector<Payload::ref>& additionalPayloads = {}) { + auto capsInfo = std::make_shared<CapsInfo>(CapsInfoGenerator("http://example.com", crypto_.get()).generateCapsInfo(*disco.get())); + dummyCapsProvider_->caps[capsInfo->getVersion()] = disco; + + Presence::ref capsNotifyPresence = std::make_shared<Presence>(); + capsNotifyPresence->setType(type); + capsNotifyPresence->setFrom(from); + capsNotifyPresence->setShow(status); + capsNotifyPresence->addPayload(capsInfo); + + capsNotifyPresence->addPayloads(additionalPayloads); + + xmppRosterImpl_->addContact(from, "Foo", {}, RosterItemPayload::Both); + dummyStanzaChannel_->onPresenceReceived(capsNotifyPresence); + } + + DiscoInfo::ref fileTransferSupportingDisco() { + DiscoInfo::ref discoInfo = std::make_shared<DiscoInfo>(); + discoInfo->addFeature(DiscoInfo::JingleFeature); + discoInfo->addFeature(DiscoInfo::JingleFTFeature); + discoInfo->addFeature(DiscoInfo::JingleTransportsS5BFeature); + discoInfo->addFeature(DiscoInfo::JingleTransportsIBBFeature); + return discoInfo; + } + + DiscoInfo::ref noFileTransferSupportingDisco() { + DiscoInfo::ref discoInfo = std::make_shared<DiscoInfo>(); + discoInfo->addFeature(DiscoInfo::JingleFeature); + return discoInfo; + } + + void testMergeAvailableResourcesForFeatures() { + CPPUNIT_ASSERT_EQUAL(No, featureOracle_->isFileTransferSupported(baseJID)); + + simulateIncomingPresence(noFileTransferJID, Presence::Available, StatusShow::Online, noFileTransferSupportingDisco()); + + CPPUNIT_ASSERT_EQUAL(size_t(1), presenceOracle_->getAllPresence(baseJID).size()); + CPPUNIT_ASSERT_EQUAL(No, featureOracle_->isFileTransferSupported(baseJID)); + + simulateIncomingPresence(fileTransferJID, Presence::Available, StatusShow::Online, fileTransferSupportingDisco()); + + CPPUNIT_ASSERT_EQUAL(size_t(2), presenceOracle_->getAllPresence(baseJID).size()); + CPPUNIT_ASSERT_EQUAL(Maybe, featureOracle_->isFileTransferSupported(baseJID)); + + simulateIncomingPresence(noFileTransferJID, Presence::Unavailable, StatusShow::None, noFileTransferSupportingDisco()); + + CPPUNIT_ASSERT_EQUAL(size_t(1), presenceOracle_->getAllPresence(baseJID).size()); + CPPUNIT_ASSERT_EQUAL(Yes, featureOracle_->isFileTransferSupported(baseJID)); + + simulateIncomingPresence(fileTransferJID, Presence::Unavailable, StatusShow::None, fileTransferSupportingDisco()); + + CPPUNIT_ASSERT_EQUAL(size_t(1), presenceOracle_->getAllPresence(baseJID).size()); + CPPUNIT_ASSERT_EQUAL(No, featureOracle_->isFileTransferSupported(baseJID)); + } + + void testMostAvailableFileTransferClient() { + simulateIncomingPresence(fileTransferJID, Presence::Available, StatusShow::DND, fileTransferSupportingDisco()); + + CPPUNIT_ASSERT_EQUAL(fileTransferJID, featureOracle_->getMostAvailableClientForFileTrasfer(baseJID)); + + simulateIncomingPresence(noFileTransferJID, Presence::Available, StatusShow::Online, noFileTransferSupportingDisco()); + + CPPUNIT_ASSERT_EQUAL(fileTransferJID, featureOracle_->getMostAvailableClientForFileTrasfer(baseJID)); + + auto moreAvailableJID = baseJID.withResource("moreAvailableFt"); + simulateIncomingPresence(moreAvailableJID, Presence::Available, StatusShow::Online, fileTransferSupportingDisco()); + + CPPUNIT_ASSERT_EQUAL(moreAvailableJID, featureOracle_->getMostAvailableClientForFileTrasfer(baseJID)); + } + + private: + struct DummyCapsProvider : public CapsProvider { + virtual DiscoInfo::ref getCaps(const std::string& hash) const { + std::map<std::string, DiscoInfo::ref>::const_iterator i = caps.find(hash); + if (i != caps.end()) { + return i->second; + } + return DiscoInfo::ref(); + } + + std::map<std::string, DiscoInfo::ref> caps; + }; + + private: + JID baseJID = "test@example.com"; + JID fileTransferJID = baseJID.withResource("fileTransfer"); + JID noFileTransferJID = baseJID.withResource("noFileTransfer"); + + std::shared_ptr<CryptoProvider> crypto_; + DummyCapsProvider* dummyCapsProvider_; + DummyStanzaChannel* dummyStanzaChannel_; + EntityCapsManager* entityCapsManager_; + FeatureOracle* featureOracle_; + PresenceOracle* presenceOracle_; + XMPPRosterImpl* xmppRosterImpl_; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(FeatureOracleTest); diff --git a/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp b/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp index 7e2e3dd..9369a04 100644 --- a/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp +++ b/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp @@ -1,118 +1,119 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <typeinfo> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <typeinfo> #include <Swiften/Disco/JIDDiscoInfoResponder.h> -#include <Swiften/Queries/IQRouter.h> #include <Swiften/Queries/DummyIQChannel.h> +#include <Swiften/Queries/IQRouter.h> using namespace Swift; class JIDDiscoInfoResponderTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(JIDDiscoInfoResponderTest); - CPPUNIT_TEST(testHandleRequest_GetToplevelInfo); - CPPUNIT_TEST(testHandleRequest_GetNodeInfo); - CPPUNIT_TEST(testHandleRequest_GetInvalidNodeInfo); - CPPUNIT_TEST(testHandleRequest_GetUnknownJID); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - channel_ = new DummyIQChannel(); - router_ = new IQRouter(channel_); - } - - void tearDown() { - delete router_; - delete channel_; - } - - void testHandleRequest_GetToplevelInfo() { - JIDDiscoInfoResponder testling(router_); - testling.start(); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT_EQUAL(std::string(""), payload->getNode()); - CPPUNIT_ASSERT(payload->hasFeature("foo")); - - testling.stop(); - } - - void testHandleRequest_GetNodeInfo() { - JIDDiscoInfoResponder testling(router_); - testling.start(); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); - DiscoInfo discoInfoBar; - discoInfoBar.addFeature("bar"); - testling.setDiscoInfo(JID("foo@bar.com/baz"), "bar-node", discoInfoBar); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - query->setNode("bar-node"); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT_EQUAL(std::string("bar-node"), payload->getNode()); - CPPUNIT_ASSERT(payload->hasFeature("bar")); - - testling.stop(); - } - - void testHandleRequest_GetInvalidNodeInfo() { - JIDDiscoInfoResponder testling(router_); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); - testling.start(); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - query->setNode("bar-node"); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); - CPPUNIT_ASSERT(payload); - - testling.stop(); - } - - void testHandleRequest_GetUnknownJID() { - JIDDiscoInfoResponder testling(router_); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); - testling.start(); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/fum"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); - CPPUNIT_ASSERT(payload); - - testling.stop(); - } - - private: - IQRouter* router_; - DummyIQChannel* channel_; + CPPUNIT_TEST_SUITE(JIDDiscoInfoResponderTest); + CPPUNIT_TEST(testHandleRequest_GetToplevelInfo); + CPPUNIT_TEST(testHandleRequest_GetNodeInfo); + CPPUNIT_TEST(testHandleRequest_GetInvalidNodeInfo); + CPPUNIT_TEST(testHandleRequest_GetUnknownJID); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + channel_ = new DummyIQChannel(); + router_ = new IQRouter(channel_); + } + + void tearDown() { + delete router_; + delete channel_; + } + + void testHandleRequest_GetToplevelInfo() { + JIDDiscoInfoResponder testling(router_); + testling.start(); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + + std::shared_ptr<DiscoInfo> query(new DiscoInfo()); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + std::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string(""), payload->getNode()); + CPPUNIT_ASSERT(payload->hasFeature("foo")); + + testling.stop(); + } + + void testHandleRequest_GetNodeInfo() { + JIDDiscoInfoResponder testling(router_); + testling.start(); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + DiscoInfo discoInfoBar; + discoInfoBar.addFeature("bar"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), "bar-node", discoInfoBar); + + std::shared_ptr<DiscoInfo> query(new DiscoInfo()); + query->setNode("bar-node"); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + std::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string("bar-node"), payload->getNode()); + CPPUNIT_ASSERT(payload->hasFeature("bar")); + + testling.stop(); + } + + void testHandleRequest_GetInvalidNodeInfo() { + JIDDiscoInfoResponder testling(router_); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + testling.start(); + + std::shared_ptr<DiscoInfo> query(new DiscoInfo()); + query->setNode("bar-node"); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + std::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); + CPPUNIT_ASSERT(payload); + + testling.stop(); + } + + void testHandleRequest_GetUnknownJID() { + JIDDiscoInfoResponder testling(router_); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + testling.start(); + + std::shared_ptr<DiscoInfo> query(new DiscoInfo()); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/fum"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + std::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); + CPPUNIT_ASSERT(payload); + + testling.stop(); + } + + private: + IQRouter* router_; + DummyIQChannel* channel_; }; CPPUNIT_TEST_SUITE_REGISTRATION(JIDDiscoInfoResponderTest); diff --git a/Swiften/Elements/AuthChallenge.h b/Swiften/Elements/AuthChallenge.h index f7f2796..0c43980 100644 --- a/Swiften/Elements/AuthChallenge.h +++ b/Swiften/Elements/AuthChallenge.h @@ -1,34 +1,36 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/optional.hpp> #include <vector> -#include <Swiften/Elements/Element.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class AuthChallenge : public Element { - public: - AuthChallenge() { - } + class SWIFTEN_API AuthChallenge : public ToplevelElement { + public: + AuthChallenge() { + } - AuthChallenge(const std::vector<unsigned char>& value) : value(value) { - } + AuthChallenge(const std::vector<unsigned char>& value) : value(value) { + } - const boost::optional< std::vector<unsigned char> >& getValue() const { - return value; - } + const boost::optional< std::vector<unsigned char> >& getValue() const { + return value; + } - void setValue(const std::vector<unsigned char>& value) { - this->value = boost::optional<std::vector<unsigned char> >(value); - } + void setValue(const std::vector<unsigned char>& value) { + this->value = boost::optional<std::vector<unsigned char> >(value); + } - private: - boost::optional< std::vector<unsigned char> > value; - }; + private: + boost::optional< std::vector<unsigned char> > value; + }; } diff --git a/Swiften/Elements/AuthFailure.h b/Swiften/Elements/AuthFailure.h index ac40956..9546b0d 100644 --- a/Swiften/Elements/AuthFailure.h +++ b/Swiften/Elements/AuthFailure.h @@ -1,20 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class AuthFailure : public Element { - public: - typedef boost::shared_ptr<AuthFailure> ref; + class SWIFTEN_API AuthFailure : public ToplevelElement { + public: + typedef std::shared_ptr<AuthFailure> ref; - AuthFailure() {} - }; + AuthFailure() {} + }; } diff --git a/Swiften/Elements/AuthRequest.h b/Swiften/Elements/AuthRequest.h index bfc86c2..33b25b4 100644 --- a/Swiften/Elements/AuthRequest.h +++ b/Swiften/Elements/AuthRequest.h @@ -1,50 +1,52 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <string> +#include <vector> + #include <boost/optional.hpp> -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class AuthRequest : public Element { - public: - AuthRequest(const std::string& mechanism = "") : mechanism_(mechanism) { - } - - AuthRequest(const std::string& mechanism, const SafeByteArray& message) : - mechanism_(mechanism), message_(message) { - } - - AuthRequest(const std::string& mechanism, const boost::optional<SafeByteArray>& message) : - mechanism_(mechanism), message_(message) { - } - - const boost::optional<SafeByteArray>& getMessage() const { - return message_; - } - - void setMessage(const SafeByteArray& message) { - message_ = boost::optional<SafeByteArray>(message); - } - - const std::string& getMechanism() const { - return mechanism_; - } - - void setMechanism(const std::string& mechanism) { - mechanism_ = mechanism; - } - - private: - std::string mechanism_; - boost::optional<SafeByteArray> message_; - }; + class SWIFTEN_API AuthRequest : public ToplevelElement { + public: + AuthRequest(const std::string& mechanism = "") : mechanism_(mechanism) { + } + + AuthRequest(const std::string& mechanism, const SafeByteArray& message) : + mechanism_(mechanism), message_(message) { + } + + AuthRequest(const std::string& mechanism, const boost::optional<SafeByteArray>& message) : + mechanism_(mechanism), message_(message) { + } + + const boost::optional<SafeByteArray>& getMessage() const { + return message_; + } + + void setMessage(const SafeByteArray& message) { + message_ = boost::optional<SafeByteArray>(message); + } + + const std::string& getMechanism() const { + return mechanism_; + } + + void setMechanism(const std::string& mechanism) { + mechanism_ = mechanism; + } + + private: + std::string mechanism_; + boost::optional<SafeByteArray> message_; + }; } diff --git a/Swiften/Elements/AuthResponse.h b/Swiften/Elements/AuthResponse.h index db2dcea..a88e8d0 100644 --- a/Swiften/Elements/AuthResponse.h +++ b/Swiften/Elements/AuthResponse.h @@ -1,38 +1,40 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <vector> + #include <boost/optional.hpp> -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class AuthResponse : public Element { - public: - AuthResponse() { - } + class SWIFTEN_API AuthResponse : public ToplevelElement { + public: + AuthResponse() { + } - AuthResponse(const SafeByteArray& value) : value(value) { - } + AuthResponse(const SafeByteArray& value) : value(value) { + } - AuthResponse(const boost::optional<SafeByteArray>& value) : value(value) { - } + AuthResponse(const boost::optional<SafeByteArray>& value) : value(value) { + } - const boost::optional<SafeByteArray>& getValue() const { - return value; - } + const boost::optional<SafeByteArray>& getValue() const { + return value; + } - void setValue(const SafeByteArray& value) { - this->value = boost::optional<SafeByteArray>(value); - } + void setValue(const SafeByteArray& value) { + this->value = boost::optional<SafeByteArray>(value); + } - private: - boost::optional<SafeByteArray> value; - }; + private: + boost::optional<SafeByteArray> value; + }; } diff --git a/Swiften/Elements/AuthSuccess.h b/Swiften/Elements/AuthSuccess.h index 3c0f329..860702c 100644 --- a/Swiften/Elements/AuthSuccess.h +++ b/Swiften/Elements/AuthSuccess.h @@ -1,30 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <vector> + #include <boost/optional.hpp> -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class AuthSuccess : public Element { - public: - AuthSuccess() {} + class SWIFTEN_API AuthSuccess : public ToplevelElement { + public: + AuthSuccess() {} - const boost::optional<std::vector<unsigned char> >& getValue() const { - return value; - } + const boost::optional<std::vector<unsigned char> >& getValue() const { + return value; + } - void setValue(const std::vector<unsigned char>& value) { - this->value = boost::optional<std::vector<unsigned char> >(value); - } + void setValue(const std::vector<unsigned char>& value) { + this->value = boost::optional<std::vector<unsigned char> >(value); + } - private: - boost::optional<std::vector<unsigned char> > value; - }; + private: + boost::optional<std::vector<unsigned char> > value; + }; } diff --git a/Swiften/Elements/BlockListPayload.h b/Swiften/Elements/BlockListPayload.h index 49df75f..acc9df4 100644 --- a/Swiften/Elements/BlockListPayload.h +++ b/Swiften/Elements/BlockListPayload.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <vector> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class BlockListPayload : public Payload { - public: - BlockListPayload(const std::vector<JID>& items = std::vector<JID>()) : items(items) { - } + class SWIFTEN_API BlockListPayload : public Payload { + public: + BlockListPayload(const std::vector<JID>& items = std::vector<JID>()) : items(items) { + } - void addItem(const JID& item) { - items.push_back(item); - } + void addItem(const JID& item) { + items.push_back(item); + } - const std::vector<JID>& getItems() const { - return items; - } + const std::vector<JID>& getItems() const { + return items; + } - private: - std::vector<JID> items; - }; + private: + std::vector<JID> items; + }; } diff --git a/Swiften/Elements/BlockPayload.h b/Swiften/Elements/BlockPayload.h index 49a0463..df8d150 100644 --- a/Swiften/Elements/BlockPayload.h +++ b/Swiften/Elements/BlockPayload.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <vector> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class BlockPayload : public Payload { - public: - BlockPayload(const std::vector<JID>& jids = std::vector<JID>()) : items(jids) { - } + class SWIFTEN_API BlockPayload : public Payload { + public: + BlockPayload(const std::vector<JID>& jids = std::vector<JID>()) : items(jids) { + } - void addItem(const JID& jid) { - items.push_back(jid); - } + void addItem(const JID& jid) { + items.push_back(jid); + } - const std::vector<JID>& getItems() const { - return items; - } + const std::vector<JID>& getItems() const { + return items; + } - private: - std::vector<JID> items; - }; + private: + std::vector<JID> items; + }; } diff --git a/Swiften/Elements/Body.h b/Swiften/Elements/Body.h index a2497f7..8761d5a 100644 --- a/Swiften/Elements/Body.h +++ b/Swiften/Elements/Body.h @@ -1,30 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class Body : public Payload { - public: - Body(const std::string& text = "") : text_(text) { - } + class SWIFTEN_API Body : public Payload { + public: + Body(const std::string& text = "") : text_(text) { + } - void setText(const std::string& text) { - text_ = text; - } + void setText(const std::string& text) { + text_ = text; + } - const std::string& getText() const { - return text_; - } + const std::string& getText() const { + return text_; + } - private: - std::string text_; - }; + private: + std::string text_; + }; } diff --git a/Swiften/Elements/Bytestreams.h b/Swiften/Elements/Bytestreams.h index 9724a54..599ed46 100644 --- a/Swiften/Elements/Bytestreams.h +++ b/Swiften/Elements/Bytestreams.h @@ -1,61 +1,63 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> +#include <string> #include <vector> + #include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> -#include <string> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class Bytestreams : public Payload { - public: - typedef boost::shared_ptr<Bytestreams> ref; + class SWIFTEN_API Bytestreams : public Payload { + public: + typedef std::shared_ptr<Bytestreams> ref; - struct StreamHost { - StreamHost(const std::string& host = "", const JID& jid = JID(), int port = -1) : host(host), jid(jid), port(port) {} + struct StreamHost { + StreamHost(const std::string& host = "", const JID& jid = JID(), unsigned short port = 0) : host(host), jid(jid), port(port) {} - std::string host; - JID jid; - int port; - }; + std::string host; + JID jid; + unsigned short port; + }; - Bytestreams() {} + Bytestreams() {} - const std::string& getStreamID() const { - return id; - } + const std::string& getStreamID() const { + return id; + } - void setStreamID(const std::string& id) { - this->id = id; - } + void setStreamID(const std::string& id) { + this->id = id; + } - const boost::optional<JID>& getUsedStreamHost() const { - return usedStreamHost; - } + const boost::optional<JID>& getUsedStreamHost() const { + return usedStreamHost; + } - void setUsedStreamHost(const JID& host) { - usedStreamHost = host; - } + void setUsedStreamHost(const JID& host) { + usedStreamHost = host; + } - const std::vector<StreamHost>& getStreamHosts() const { - return streamHosts; - } + const std::vector<StreamHost>& getStreamHosts() const { + return streamHosts; + } - void addStreamHost(const StreamHost& streamHost) { - streamHosts.push_back(streamHost); - } + void addStreamHost(const StreamHost& streamHost) { + streamHosts.push_back(streamHost); + } - private: - std::string id; - boost::optional<JID> usedStreamHost; - std::vector<StreamHost> streamHosts; - }; + private: + std::string id; + boost::optional<JID> usedStreamHost; + std::vector<StreamHost> streamHosts; + }; } diff --git a/Swiften/Elements/CapsInfo.h b/Swiften/Elements/CapsInfo.h index c6d3b64..d1e5103 100644 --- a/Swiften/Elements/CapsInfo.h +++ b/Swiften/Elements/CapsInfo.h @@ -1,59 +1,60 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class CapsInfo : public Payload { - public: - typedef boost::shared_ptr<CapsInfo> ref; - - CapsInfo(const std::string& node = "", const std::string& version = "", const std::string& hash = "sha-1") : node_(node), version_(version), hash_(hash) {} - - bool operator==(const CapsInfo& o) const { - return o.node_ == node_ && o.version_ == version_ && o.hash_ == hash_; - } - - bool operator<(const CapsInfo& o) const { - if (o.node_ == node_) { - if (o.version_ == version_) { - return hash_ < o.hash_; - } - else { - return version_ < o.version_; - } - } - else { - return node_ < o.node_; - } - } - - const std::string& getNode() const { return node_; } - void setNode(const std::string& node) { - node_ = node; - } - - const std::string& getVersion() const { return version_; } - void setVersion(const std::string& version) { - version_ = version; - } - - const std::string& getHash() const { return hash_; } - void setHash(const std::string& hash) { - hash_ = hash; - } - - private: - std::string node_; - std::string version_; - std::string hash_; - }; + class SWIFTEN_API CapsInfo : public Payload { + public: + typedef std::shared_ptr<CapsInfo> ref; + + CapsInfo(const std::string& node = "", const std::string& version = "", const std::string& hash = "sha-1") : node_(node), version_(version), hash_(hash) {} + + bool operator==(const CapsInfo& o) const { + return o.node_ == node_ && o.version_ == version_ && o.hash_ == hash_; + } + + bool operator<(const CapsInfo& o) const { + if (o.node_ == node_) { + if (o.version_ == version_) { + return hash_ < o.hash_; + } + else { + return version_ < o.version_; + } + } + else { + return node_ < o.node_; + } + } + + const std::string& getNode() const { return node_; } + void setNode(const std::string& node) { + node_ = node; + } + + const std::string& getVersion() const { return version_; } + void setVersion(const std::string& version) { + version_ = version; + } + + const std::string& getHash() const { return hash_; } + void setHash(const std::string& hash) { + hash_ = hash; + } + + private: + std::string node_; + std::string version_; + std::string hash_; + }; } diff --git a/Swiften/Elements/CarbonsDisable.cpp b/Swiften/Elements/CarbonsDisable.cpp new file mode 100644 index 0000000..848fa92 --- /dev/null +++ b/Swiften/Elements/CarbonsDisable.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/CarbonsDisable.h> + +namespace Swift { + CarbonsDisable::~CarbonsDisable() { + } +} diff --git a/Swiften/Elements/CarbonsDisable.h b/Swiften/Elements/CarbonsDisable.h new file mode 100644 index 0000000..9526061 --- /dev/null +++ b/Swiften/Elements/CarbonsDisable.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API CarbonsDisable : public Payload { + public: + typedef std::shared_ptr<CarbonsDisable> ref; + + public: + virtual ~CarbonsDisable(); + }; +} diff --git a/Swiften/Elements/CarbonsEnable.cpp b/Swiften/Elements/CarbonsEnable.cpp new file mode 100644 index 0000000..c927cfb --- /dev/null +++ b/Swiften/Elements/CarbonsEnable.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/CarbonsEnable.h> + +namespace Swift { + CarbonsEnable::~CarbonsEnable() { + } +} diff --git a/Swiften/Elements/CarbonsEnable.h b/Swiften/Elements/CarbonsEnable.h new file mode 100644 index 0000000..bcb27a2 --- /dev/null +++ b/Swiften/Elements/CarbonsEnable.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API CarbonsEnable : public Payload { + public: + typedef std::shared_ptr<CarbonsEnable> ref; + + public: + virtual ~CarbonsEnable(); + }; +} diff --git a/Swiften/Elements/CarbonsPrivate.cpp b/Swiften/Elements/CarbonsPrivate.cpp new file mode 100644 index 0000000..4ebcd31 --- /dev/null +++ b/Swiften/Elements/CarbonsPrivate.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/CarbonsPrivate.h> + +namespace Swift { + CarbonsPrivate::~CarbonsPrivate() { + } +} diff --git a/Swiften/Elements/CarbonsPrivate.h b/Swiften/Elements/CarbonsPrivate.h new file mode 100644 index 0000000..5cc25ff --- /dev/null +++ b/Swiften/Elements/CarbonsPrivate.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API CarbonsPrivate : public Payload { + public: + typedef std::shared_ptr<CarbonsPrivate> ref; + + public: + virtual ~CarbonsPrivate(); + }; +} diff --git a/Swiften/Elements/CarbonsReceived.cpp b/Swiften/Elements/CarbonsReceived.cpp new file mode 100644 index 0000000..7c233a3 --- /dev/null +++ b/Swiften/Elements/CarbonsReceived.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/CarbonsReceived.h> + +namespace Swift { + CarbonsReceived::~CarbonsReceived() { + + } + + void CarbonsReceived::setForwarded(std::shared_ptr<Forwarded> forwarded) { + forwarded_ = forwarded; + } + + std::shared_ptr<Forwarded> CarbonsReceived::getForwarded() const { + return forwarded_; + } +} diff --git a/Swiften/Elements/CarbonsReceived.h b/Swiften/Elements/CarbonsReceived.h new file mode 100644 index 0000000..c33b600 --- /dev/null +++ b/Swiften/Elements/CarbonsReceived.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API CarbonsReceived : public Payload { + public: + typedef std::shared_ptr<CarbonsReceived> ref; + + public: + virtual ~CarbonsReceived(); + void setForwarded(std::shared_ptr<Forwarded> forwarded); + std::shared_ptr<Forwarded> getForwarded() const; + + private: + std::shared_ptr<Forwarded> forwarded_; + }; +} diff --git a/Swiften/Elements/CarbonsSent.cpp b/Swiften/Elements/CarbonsSent.cpp new file mode 100644 index 0000000..a026871 --- /dev/null +++ b/Swiften/Elements/CarbonsSent.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/CarbonsSent.h> + +namespace Swift { + CarbonsSent::~CarbonsSent() { + + } + + void CarbonsSent::setForwarded(std::shared_ptr<Forwarded> forwarded) { + forwarded_ = forwarded; + } + + std::shared_ptr<Forwarded> CarbonsSent::getForwarded() const { + return forwarded_; + } +} diff --git a/Swiften/Elements/CarbonsSent.h b/Swiften/Elements/CarbonsSent.h new file mode 100644 index 0000000..89739de --- /dev/null +++ b/Swiften/Elements/CarbonsSent.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API CarbonsSent : public Payload { + public: + typedef std::shared_ptr<CarbonsSent> ref; + + public: + virtual ~CarbonsSent(); + void setForwarded(std::shared_ptr<Forwarded> forwarded); + std::shared_ptr<Forwarded> getForwarded() const; + + private: + std::shared_ptr<Forwarded> forwarded_; + }; +} diff --git a/Swiften/Elements/ChatState.h b/Swiften/Elements/ChatState.h index 477fd27..4288398 100644 --- a/Swiften/Elements/ChatState.h +++ b/Swiften/Elements/ChatState.h @@ -1,27 +1,31 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class ChatState : public Payload { - public: - enum ChatStateType {Active, Composing, Paused, Inactive, Gone}; - ChatState(ChatStateType state = Active) { - state_ = state; - } + class SWIFTEN_API ChatState : public Payload { + public: + typedef std::shared_ptr<ChatState> ref; - ChatStateType getChatState() const { return state_; } - void setChatState(ChatStateType state) {state_ = state;} + public: + enum ChatStateType {Active, Composing, Paused, Inactive, Gone}; + ChatState(ChatStateType state = Active) { + state_ = state; + } - private: - ChatStateType state_; - }; + ChatStateType getChatState() const { return state_; } + void setChatState(ChatStateType state) {state_ = state;} + + private: + ChatStateType state_; + }; } diff --git a/Swiften/Elements/ClientState.h b/Swiften/Elements/ClientState.h new file mode 100644 index 0000000..868d352 --- /dev/null +++ b/Swiften/Elements/ClientState.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API ClientState : public Payload { + public: + typedef std::shared_ptr<ClientState> ref; + + public: + enum class ClientStateType {Active, Inactive}; + ClientState(ClientStateType state = ClientStateType::Active) : state_(state) { + + } + + ClientStateType getClientState() const { return state_; } + void setClientState(ClientStateType state) {state_ = state;} + + private: + ClientStateType state_; + }; +} diff --git a/Swiften/Elements/Command.h b/Swiften/Elements/Command.h index 5454d8d..33aadd5 100644 --- a/Swiften/Elements/Command.h +++ b/Swiften/Elements/Command.h @@ -1,81 +1,82 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> -#include <Swiften/Elements/Payload.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Payload.h> namespace Swift { - /** - * Ad-Hoc Command (XEP-0050). - */ - class Command : public Payload { - public: - typedef boost::shared_ptr<Command> ref; - - enum Status {Executing, Completed, Canceled, NoStatus}; - enum Action {Cancel, Execute, Complete, Prev, Next, NoAction}; - - struct Note { - enum Type {Info, Warn, Error}; - - Note(std::string note, Type type) : note(note), type(type) {} - - std::string note; - Type type; - }; - - public: - Command(const std::string& node, const std::string& sessionID, Status status) { constructor(node, sessionID, NoAction, status);} - Command(const std::string& node = "", const std::string& sessionID = "", Action action = Execute) { constructor(node, sessionID, action, NoStatus); } - - const std::string& getNode() const { return node_; } - void setNode(const std::string& node) { node_ = node; } - - const std::string& getSessionID() const { return sessionID_; } - void setSessionID(const std::string& id) { sessionID_ = id; } - - Action getAction() const { return action_; } - void setAction(Action action) { action_ = action; } - - void setExecuteAction(Action action) { executeAction_ = action; } - Action getExecuteAction() const { return executeAction_; } - - Status getStatus() const { return status_; } - void setStatus(Status status) { status_ = status; } - - void addAvailableAction(Action action) { availableActions_.push_back(action); } - const std::vector<Action>& getAvailableActions() const { return availableActions_; } - void addNote(const Note& note) { notes_.push_back(note); } - const std::vector<Note>& getNotes() const { return notes_; } - - Form::ref getForm() const { return form_; } - void setForm(Form::ref payload) { form_ = payload; } - - private: - void constructor(const std::string& node, const std::string& sessionID, Action action, Status status) { - node_ = node; - sessionID_ = sessionID; - action_ = action; - status_ = status; - executeAction_ = NoAction; - } - - private: - std::string node_; - std::string sessionID_; - Action action_; - Status status_; - Action executeAction_; - std::vector<Action> availableActions_; - std::vector<Note> notes_; - Form::ref form_; - }; + /** + * Ad-Hoc Command (XEP-0050). + */ + class SWIFTEN_API Command : public Payload { + public: + typedef std::shared_ptr<Command> ref; + + enum Status {Executing, Completed, Canceled, NoStatus}; + enum Action {Cancel, Execute, Complete, Prev, Next, NoAction}; + + struct Note { + enum Type {Info, Warn, Error}; + + Note(std::string note, Type type) : note(note), type(type) {} + + std::string note; + Type type; + }; + + public: + Command(const std::string& node, const std::string& sessionID, Status status) { constructor(node, sessionID, NoAction, status);} + Command(const std::string& node = "", const std::string& sessionID = "", Action action = Execute) { constructor(node, sessionID, action, NoStatus); } + + const std::string& getNode() const { return node_; } + void setNode(const std::string& node) { node_ = node; } + + const std::string& getSessionID() const { return sessionID_; } + void setSessionID(const std::string& id) { sessionID_ = id; } + + Action getAction() const { return action_; } + void setAction(Action action) { action_ = action; } + + void setExecuteAction(Action action) { executeAction_ = action; } + Action getExecuteAction() const { return executeAction_; } + + Status getStatus() const { return status_; } + void setStatus(Status status) { status_ = status; } + + void addAvailableAction(Action action) { availableActions_.push_back(action); } + const std::vector<Action>& getAvailableActions() const { return availableActions_; } + void addNote(const Note& note) { notes_.push_back(note); } + const std::vector<Note>& getNotes() const { return notes_; } + + Form::ref getForm() const { return form_; } + void setForm(Form::ref payload) { form_ = payload; } + + private: + void constructor(const std::string& node, const std::string& sessionID, Action action, Status status) { + node_ = node; + sessionID_ = sessionID; + action_ = action; + status_ = status; + executeAction_ = NoAction; + } + + private: + std::string node_; + std::string sessionID_; + Action action_; + Status status_; + Action executeAction_; + std::vector<Action> availableActions_; + std::vector<Note> notes_; + Form::ref form_; + }; } diff --git a/Swiften/Elements/ComponentHandshake.h b/Swiften/Elements/ComponentHandshake.h index 5992b8c..4d6d059 100644 --- a/Swiften/Elements/ComponentHandshake.h +++ b/Swiften/Elements/ComponentHandshake.h @@ -1,33 +1,34 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class ComponentHandshake : public Element { - public: - typedef boost::shared_ptr<ComponentHandshake> ref; + class SWIFTEN_API ComponentHandshake : public ToplevelElement { + public: + typedef std::shared_ptr<ComponentHandshake> ref; - ComponentHandshake(const std::string& data = "") : data(data) { - } + ComponentHandshake(const std::string& data = "") : data(data) { + } - void setData(const std::string& d) { - data = d; - } + void setData(const std::string& d) { + data = d; + } - const std::string& getData() const { - return data; - } + const std::string& getData() const { + return data; + } - private: - std::string data; - }; + private: + std::string data; + }; } diff --git a/Swiften/Elements/CompressFailure.h b/Swiften/Elements/CompressFailure.h index 7dd8867..8cdd268 100644 --- a/Swiften/Elements/CompressFailure.h +++ b/Swiften/Elements/CompressFailure.h @@ -1,17 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once - -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class CompressFailure : public Element { - public: - CompressFailure() {} - }; + class SWIFTEN_API CompressFailure : public ToplevelElement { + public: + CompressFailure() {} + }; } diff --git a/Swiften/Elements/CompressRequest.h b/Swiften/Elements/CompressRequest.h index b6fcc64..7e813b9 100644 --- a/Swiften/Elements/CompressRequest.h +++ b/Swiften/Elements/CompressRequest.h @@ -1,28 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Element.h> +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class CompressRequest : public Element - { - public: - CompressRequest(const std::string& method = "") : method_(method) {} + class SWIFTEN_API CompressRequest : public ToplevelElement + { + public: + CompressRequest(const std::string& method = "") : method_(method) {} - const std::string& getMethod() const { - return method_; - } + const std::string& getMethod() const { + return method_; + } - void setMethod(const std::string& method) { - method_ = method; - } + void setMethod(const std::string& method) { + method_ = method; + } - private: - std::string method_; - }; + private: + std::string method_; + }; } diff --git a/Swiften/Elements/Compressed.h b/Swiften/Elements/Compressed.h index 2affec5..a2e236f 100644 --- a/Swiften/Elements/Compressed.h +++ b/Swiften/Elements/Compressed.h @@ -1,16 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class Compressed : public Element { - public: - Compressed() {} - }; + class SWIFTEN_API Compressed : public ToplevelElement { + public: + Compressed() {} + }; } diff --git a/Swiften/Elements/ContainerPayload.h b/Swiften/Elements/ContainerPayload.h index e2a4682..033575a 100644 --- a/Swiften/Elements/ContainerPayload.h +++ b/Swiften/Elements/ContainerPayload.h @@ -1,33 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> +#include <vector> + #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> -#include <vector> namespace Swift { - template<typename T> - class SWIFTEN_API ContainerPayload : public Payload { - public: - ContainerPayload() {} - ContainerPayload(boost::shared_ptr<T> payload) : payload(payload) {} + template<typename T> + class SWIFTEN_API ContainerPayload : public Payload { + public: + ContainerPayload() {} + ContainerPayload(std::shared_ptr<T> payload) : payload(payload) {} + + void setPayload(std::shared_ptr<T> payload) { + this->payload = payload; + } - void setPayload(boost::shared_ptr<T> payload) { - this->payload = payload; - } - - boost::shared_ptr<T> getPayload() const { - return payload; - } + std::shared_ptr<T> getPayload() const { + return payload; + } - private: - boost::shared_ptr<T> payload; - }; + private: + std::shared_ptr<T> payload; + }; } diff --git a/Swiften/Elements/Delay.h b/Swiften/Elements/Delay.h index f4376dc..b154dea 100644 --- a/Swiften/Elements/Delay.h +++ b/Swiften/Elements/Delay.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,23 +9,24 @@ #include <boost/date_time/posix_time/posix_time_types.hpp> #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> #include <Swiften/JID/JID.h> namespace Swift { - class Delay : public Payload { - public: - Delay() {} - Delay(const boost::posix_time::ptime& time, const JID& from = JID()) : time_(time), from_(from) {} + class SWIFTEN_API Delay : public Payload { + public: + Delay() {} + Delay(const boost::posix_time::ptime& time, const JID& from = JID()) : time_(time), from_(from) {} - const boost::posix_time::ptime& getStamp() const {return time_;} - void setStamp(const boost::posix_time::ptime& time) {time_ = time;} + const boost::posix_time::ptime& getStamp() const {return time_;} + void setStamp(const boost::posix_time::ptime& time) {time_ = time;} - const boost::optional<JID>& getFrom() const {return from_;} - void setFrom(const JID& from) {from_ = from;} + const boost::optional<JID>& getFrom() const {return from_;} + void setFrom(const JID& from) {from_ = from;} - private: - boost::posix_time::ptime time_; - boost::optional<JID> from_; - }; + private: + boost::posix_time::ptime time_; + boost::optional<JID> from_; + }; } diff --git a/Swiften/Elements/DeliveryReceipt.h b/Swiften/Elements/DeliveryReceipt.h index bd634db..238485d 100644 --- a/Swiften/Elements/DeliveryReceipt.h +++ b/Swiften/Elements/DeliveryReceipt.h @@ -4,35 +4,40 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ -#pragma once +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <string> +#pragma once #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { -class DeliveryReceipt : public Payload { - public: - typedef boost::shared_ptr<DeliveryReceipt> ref; +class SWIFTEN_API DeliveryReceipt : public Payload { + public: + typedef std::shared_ptr<DeliveryReceipt> ref; - public: - DeliveryReceipt() {} + public: + DeliveryReceipt() {} - DeliveryReceipt(const std::string& msgId) : receivedID_(msgId) {} + DeliveryReceipt(const std::string& msgId) : receivedID_(msgId) {} - void setReceivedID(const std::string& msgId) { - receivedID_ = msgId; - } + void setReceivedID(const std::string& msgId) { + receivedID_ = msgId; + } - std::string getReceivedID() const { - return receivedID_; - } + std::string getReceivedID() const { + return receivedID_; + } - private: - std::string receivedID_; + private: + std::string receivedID_; }; } diff --git a/Swiften/Elements/DeliveryReceiptRequest.h b/Swiften/Elements/DeliveryReceiptRequest.h index 3998785..9a7d478 100644 --- a/Swiften/Elements/DeliveryReceiptRequest.h +++ b/Swiften/Elements/DeliveryReceiptRequest.h @@ -4,18 +4,25 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { -class DeliveryReceiptRequest : public Payload { - public: - typedef boost::shared_ptr<DeliveryReceiptRequest> ref; +class SWIFTEN_API DeliveryReceiptRequest : public Payload { + public: + typedef std::shared_ptr<DeliveryReceiptRequest> ref; - public: - DeliveryReceiptRequest() {} + public: + DeliveryReceiptRequest() {} }; } diff --git a/Swiften/Elements/DiscoInfo.cpp b/Swiften/Elements/DiscoInfo.cpp index f353c42..701ed40 100644 --- a/Swiften/Elements/DiscoInfo.cpp +++ b/Swiften/Elements/DiscoInfo.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/DiscoInfo.h> @@ -11,41 +11,44 @@ namespace Swift { const std::string DiscoInfo::ChatStatesFeature = std::string("http://jabber.org/protocol/chatstates"); +const std::string DiscoInfo::ClientStatesFeature = std::string("urn:xmpp:csi:0"); const std::string DiscoInfo::SecurityLabelsFeature = std::string("urn:xmpp:sec-label:0"); const std::string DiscoInfo::SecurityLabelsCatalogFeature = std::string("urn:xmpp:sec-label:catalog:2"); const std::string DiscoInfo::JabberSearchFeature = std::string("jabber:iq:search"); const std::string DiscoInfo::CommandsFeature = std::string("http://jabber.org/protocol/commands"); const std::string DiscoInfo::MessageCorrectionFeature = std::string("urn:xmpp:message-correct:0"); const std::string DiscoInfo::JingleFeature = std::string("urn:xmpp:jingle:1"); -const std::string DiscoInfo::JingleFTFeature = std::string("urn:xmpp:jingle:apps:file-transfer:3"); +const std::string DiscoInfo::JingleFTFeature = std::string("urn:xmpp:jingle:apps:file-transfer:4"); const std::string DiscoInfo::JingleTransportsIBBFeature = std::string("urn:xmpp:jingle:transports:ibb:1"); const std::string DiscoInfo::JingleTransportsS5BFeature = std::string("urn:xmpp:jingle:transports:s5b:1"); const std::string DiscoInfo::Bytestream = std::string("http://jabber.org/protocol/bytestreams"); const std::string DiscoInfo::MessageDeliveryReceiptsFeature = std::string("urn:xmpp:receipts"); const std::string DiscoInfo::WhiteboardFeature = std::string("http://swift.im/whiteboard"); const std::string DiscoInfo::BlockingCommandFeature = std::string("urn:xmpp:blocking"); +const std::string DiscoInfo::MessageCarbonsFeature = std::string("urn:xmpp:carbons:2"); +const std::string DiscoInfo::ReferencesFeature = std::string("urn:xmpp:references:0"); bool DiscoInfo::Identity::operator<(const Identity& other) const { - if (category_ == other.category_) { - if (type_ == other.type_) { - if (lang_ == other.lang_) { - return name_ < other.name_; - } - else { - return lang_ < other.lang_; - } - } - else { - return type_ < other.type_; - } - } - else { - return category_ < other.category_; - } + if (category_ == other.category_) { + if (type_ == other.type_) { + if (lang_ == other.lang_) { + return name_ < other.name_; + } + else { + return lang_ < other.lang_; + } + } + else { + return type_ < other.type_; + } + } + else { + return category_ < other.category_; + } } bool DiscoInfo::hasFeature(const std::string& feature) const { - return std::find(features_.begin(), features_.end(), feature) != features_.end(); + return std::find(features_.begin(), features_.end(), feature) != features_.end(); } } diff --git a/Swiften/Elements/DiscoInfo.h b/Swiften/Elements/DiscoInfo.h index 3701096..713eaba 100644 --- a/Swiften/Elements/DiscoInfo.h +++ b/Swiften/Elements/DiscoInfo.h @@ -1,113 +1,116 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <string> +#include <vector> #include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Payload.h> namespace Swift { - /** - * disco#info from XEP-0030 - */ - class SWIFTEN_API DiscoInfo : public Payload { - public: - typedef boost::shared_ptr<DiscoInfo> ref; - - static const std::string ChatStatesFeature; - static const std::string SecurityLabelsFeature; - static const std::string SecurityLabelsCatalogFeature; - static const std::string JabberSearchFeature; - static const std::string CommandsFeature; - static const std::string MessageCorrectionFeature; - static const std::string JingleFeature; - static const std::string JingleFTFeature; - static const std::string JingleTransportsIBBFeature; - static const std::string JingleTransportsS5BFeature; - static const std::string Bytestream; - static const std::string MessageDeliveryReceiptsFeature; - static const std::string WhiteboardFeature; - static const std::string BlockingCommandFeature; - - class Identity { - public: - Identity(const std::string& name, const std::string& category = "client", const std::string& type = "pc", const std::string& lang = "") : name_(name), category_(category), type_(type), lang_(lang) { - } - - const std::string& getCategory() const { - return category_; - } - - const std::string& getType() const { - return type_; - } - - const std::string& getLanguage() const { - return lang_; - } - - const std::string& getName() const { - return name_; - } - - // Sorted according to XEP-115 rules - bool operator<(const Identity& other) const; - - private: - std::string name_; - std::string category_; - std::string type_; - std::string lang_; - }; - - DiscoInfo() { - } - - const std::string& getNode() const { - return node_; - } - - void setNode(const std::string& node) { - node_ = node; - } - - const std::vector<Identity>& getIdentities() const { - return identities_; - } - - void addIdentity(const Identity& identity) { - identities_.push_back(identity); - } - - const std::vector<std::string>& getFeatures() const { - return features_; - } - - void addFeature(const std::string& feature) { - features_.push_back(feature); - } - - bool hasFeature(const std::string& feature) const; - - void addExtension(Form::ref form) { - extensions_.push_back(form); - } - - const std::vector<Form::ref>& getExtensions() const { - return extensions_; - } - - private: - std::string node_; - std::vector<Identity> identities_; - std::vector<std::string> features_; - std::vector<Form::ref> extensions_; - }; + /** + * disco#info from XEP-0030 + */ + class SWIFTEN_API DiscoInfo : public Payload { + public: + typedef std::shared_ptr<DiscoInfo> ref; + + static const std::string ChatStatesFeature; + static const std::string ClientStatesFeature; + static const std::string SecurityLabelsFeature; + static const std::string SecurityLabelsCatalogFeature; + static const std::string JabberSearchFeature; + static const std::string CommandsFeature; + static const std::string MessageCorrectionFeature; + static const std::string JingleFeature; + static const std::string JingleFTFeature; + static const std::string JingleTransportsIBBFeature; + static const std::string JingleTransportsS5BFeature; + static const std::string Bytestream; + static const std::string MessageDeliveryReceiptsFeature; + static const std::string WhiteboardFeature; + static const std::string BlockingCommandFeature; + static const std::string MessageCarbonsFeature; + static const std::string ReferencesFeature; + + class Identity { + public: + Identity(const std::string& name, const std::string& category = "client", const std::string& type = "pc", const std::string& lang = "") : name_(name), category_(category), type_(type), lang_(lang) { + } + + const std::string& getCategory() const { + return category_; + } + + const std::string& getType() const { + return type_; + } + + const std::string& getLanguage() const { + return lang_; + } + + const std::string& getName() const { + return name_; + } + + // Sorted according to XEP-115 rules + bool operator<(const Identity& other) const; + + private: + std::string name_; + std::string category_; + std::string type_; + std::string lang_; + }; + + DiscoInfo() { + } + + const std::string& getNode() const { + return node_; + } + + void setNode(const std::string& node) { + node_ = node; + } + + const std::vector<Identity>& getIdentities() const { + return identities_; + } + + void addIdentity(const Identity& identity) { + identities_.push_back(identity); + } + + const std::vector<std::string>& getFeatures() const { + return features_; + } + + void addFeature(const std::string& feature) { + features_.push_back(feature); + } + + bool hasFeature(const std::string& feature) const; + + void addExtension(Form::ref form) { + extensions_.push_back(form); + } + + const std::vector<Form::ref>& getExtensions() const { + return extensions_; + } + + private: + std::string node_; + std::vector<Identity> identities_; + std::vector<std::string> features_; + std::vector<Form::ref> extensions_; + }; } diff --git a/Swiften/Elements/DiscoItems.h b/Swiften/Elements/DiscoItems.h index cbca399..9c06b8d 100644 --- a/Swiften/Elements/DiscoItems.h +++ b/Swiften/Elements/DiscoItems.h @@ -1,70 +1,71 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <string> +#include <vector> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> #include <Swiften/JID/JID.h> namespace Swift { - /** - * Service discovery disco#items from XEP-0030. - */ - class DiscoItems : public Payload { - public: - /** - * A single result item. - */ - class Item { - public: - Item(const std::string& name, const JID& jid, const std::string& node="") : name_(name), jid_(jid), node_(node) { - } + /** + * Service discovery disco#items from XEP-0030. + */ + class SWIFTEN_API DiscoItems : public Payload { + public: + /** + * A single result item. + */ + class Item { + public: + Item(const std::string& name, const JID& jid, const std::string& node="") : name_(name), jid_(jid), node_(node) { + } - const std::string& getName() const { - return name_; - } + const std::string& getName() const { + return name_; + } - const std::string& getNode() const { - return node_; - } + const std::string& getNode() const { + return node_; + } - const JID& getJID() const { - return jid_; - } + const JID& getJID() const { + return jid_; + } - private: - std::string name_; - JID jid_; - std::string node_; - }; + private: + std::string name_; + JID jid_; + std::string node_; + }; - DiscoItems() { - } + DiscoItems() { + } - const std::string& getNode() const { - return node_; - } + const std::string& getNode() const { + return node_; + } - void setNode(const std::string& node) { - node_ = node; - } + void setNode(const std::string& node) { + node_ = node; + } - const std::vector<Item>& getItems() const { - return items_; - } + const std::vector<Item>& getItems() const { + return items_; + } - void addItem(const Item& item) { - items_.push_back(item); - } + void addItem(const Item& item) { + items_.push_back(item); + } - private: - std::string node_; - std::vector<Item> items_; - }; + private: + std::string node_; + std::vector<Item> items_; + }; } diff --git a/Swiften/Elements/Element.cpp b/Swiften/Elements/Element.cpp index 94829ba..7b176be 100644 --- a/Swiften/Elements/Element.cpp +++ b/Swiften/Elements/Element.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/Element.h> diff --git a/Swiften/Elements/Element.h b/Swiften/Elements/Element.h index 638418d..b036a29 100644 --- a/Swiften/Elements/Element.h +++ b/Swiften/Elements/Element.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,8 +9,12 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API Element { - public: - virtual ~Element(); - }; + class SWIFTEN_API Element { + public: + Element() {} + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(Element) + virtual ~Element(); + + SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(Element) + }; } diff --git a/Swiften/Elements/EnableStreamManagement.h b/Swiften/Elements/EnableStreamManagement.h index 15a091e..bf867e2 100644 --- a/Swiften/Elements/EnableStreamManagement.h +++ b/Swiften/Elements/EnableStreamManagement.h @@ -1,17 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Element.h> - +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class EnableStreamManagement : public Element { - public: - EnableStreamManagement() {} - }; + class SWIFTEN_API EnableStreamManagement : public ToplevelElement { + public: + EnableStreamManagement() {} + }; } diff --git a/Swiften/Elements/ErrorPayload.h b/Swiften/Elements/ErrorPayload.h index f21ba98..0269e4d 100644 --- a/Swiften/Elements/ErrorPayload.h +++ b/Swiften/Elements/ErrorPayload.h @@ -1,86 +1,87 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class ErrorPayload : public Payload { - public: - typedef boost::shared_ptr<ErrorPayload> ref; - - enum Type { Cancel, Continue, Modify, Auth, Wait }; - - enum Condition { - BadRequest, - Conflict, - FeatureNotImplemented, - Forbidden, - Gone, - InternalServerError, - ItemNotFound, - JIDMalformed, - NotAcceptable, - NotAllowed, - NotAuthorized, - PaymentRequired, - RecipientUnavailable, - Redirect, - RegistrationRequired, - RemoteServerNotFound, - RemoteServerTimeout, - ResourceConstraint, - ServiceUnavailable, - SubscriptionRequired, - UndefinedCondition, - UnexpectedRequest - }; - - ErrorPayload(Condition condition = UndefinedCondition, Type type = Cancel, const std::string& text = std::string()) : type_(type), condition_(condition), text_(text) { } - - Type getType() const { - return type_; - } - - void setType(Type type) { - type_ = type; - } - - Condition getCondition() const { - return condition_; - } - - void setCondition(Condition condition) { - condition_ = condition; - } - - void setText(const std::string& text) { - text_ = text; - } - - const std::string& getText() const { - return text_; - } - - void setPayload(boost::shared_ptr<Payload> payload) { - payload_ = payload; - } - - boost::shared_ptr<Payload> getPayload() const { - return payload_; - } - - private: - Type type_; - Condition condition_; - std::string text_; - boost::shared_ptr<Payload> payload_; - }; + class SWIFTEN_API ErrorPayload : public Payload { + public: + typedef std::shared_ptr<ErrorPayload> ref; + + enum Type { Cancel, Continue, Modify, Auth, Wait }; + + enum Condition { + BadRequest, + Conflict, + FeatureNotImplemented, + Forbidden, + Gone, + InternalServerError, + ItemNotFound, + JIDMalformed, + NotAcceptable, + NotAllowed, + NotAuthorized, + PaymentRequired, + RecipientUnavailable, + Redirect, + RegistrationRequired, + RemoteServerNotFound, + RemoteServerTimeout, + ResourceConstraint, + ServiceUnavailable, + SubscriptionRequired, + UndefinedCondition, + UnexpectedRequest + }; + + ErrorPayload(Condition condition = UndefinedCondition, Type type = Cancel, const std::string& text = std::string()) : type_(type), condition_(condition), text_(text) { } + + Type getType() const { + return type_; + } + + void setType(Type type) { + type_ = type; + } + + Condition getCondition() const { + return condition_; + } + + void setCondition(Condition condition) { + condition_ = condition; + } + + void setText(const std::string& text) { + text_ = text; + } + + const std::string& getText() const { + return text_; + } + + void setPayload(std::shared_ptr<Payload> payload) { + payload_ = payload; + } + + std::shared_ptr<Payload> getPayload() const { + return payload_; + } + + private: + Type type_; + Condition condition_; + std::string text_; + std::shared_ptr<Payload> payload_; + }; } diff --git a/Swiften/Elements/Form.cpp b/Swiften/Elements/Form.cpp index c4ae410..dc4bd72 100644 --- a/Swiften/Elements/Form.cpp +++ b/Swiften/Elements/Form.cpp @@ -1,45 +1,64 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/Form.h> -#include <Swiften/Base/foreach.h> namespace Swift { std::string Form::getFormType() const { - FormField::ref field = getField("FORM_TYPE"); - if (field && field->getType() == FormField::HiddenType) { - return field->getValues().empty() ? "" : field->getValues()[0]; - } - return ""; + FormField::ref field = getField("FORM_TYPE"); + if (field && field->getType() == FormField::HiddenType) { + return field->getValues().empty() ? "" : field->getValues()[0]; + } + return ""; } FormField::ref Form::getField(const std::string& name) const { - foreach(FormField::ref field, fields_) { - if (field->getName() == name) { - return field; - } - } - return FormField::ref(); + for (const auto& field : fields_) { + if (field->getName() == name) { + return field; + } + } + return FormField::ref(); } void Form::addReportedField(FormField::ref field) { - reportedFields_.push_back(field); + reportedFields_.push_back(field); } const std::vector<FormField::ref>& Form::getReportedFields() const { - return reportedFields_; + return reportedFields_; } void Form::addItem(const Form::FormItem& item) { - items_.push_back(item); + items_.push_back(item); } const std::vector<Form::FormItem>& Form::getItems() const { - return items_; + return items_; +} + +void Form::clearEmptyTextFields() { + std::vector<FormField::ref> populatedFields; + for (const auto& field : fields_) { + if (field->getType() == FormField::TextSingleType) { + if (!field->getTextSingleValue().empty()) { + populatedFields.push_back(field); + } + } + else if (field->getType() == FormField::TextMultiType) { + if (!field->getTextMultiValue().empty()) { + populatedFields.push_back(field); + } + } + else { + populatedFields.push_back(field); + } + } + fields_ = populatedFields; } } diff --git a/Swiften/Elements/Form.h b/Swiften/Elements/Form.h index 76ed674..827e497 100644 --- a/Swiften/Elements/Form.h +++ b/Swiften/Elements/Form.h @@ -1,68 +1,130 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> +#include <cassert> #include <string> +#include <vector> #include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/FormField.h> +#include <Swiften/Elements/FormPage.h> +#include <Swiften/Elements/FormSection.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/JID/JID.h> namespace Swift { - /** - * XEP-0004 Data form. - * For the relevant Fields, the parsers and serialisers protect the API user against - * the strange multi-value instead of newline thing by transforming them. - */ - class SWIFTEN_API Form : public Payload { - public: - typedef boost::shared_ptr<Form> ref; - typedef std::vector<FormField::ref> FormItem; - - enum Type { FormType, SubmitType, CancelType, ResultType }; - - public: - Form(Type type = FormType) : type_(type) {} - - /** Add a field to the form. - * @param field New field - must not be null. - */ - void addField(boost::shared_ptr<FormField> field) {assert(field); fields_.push_back(field); } - const std::vector<boost::shared_ptr<FormField> >& getFields() const { return fields_; } - void clearFields() { fields_.clear(); } - void setTitle(const std::string& title) { title_ = title; } - const std::string& getTitle() const { return title_; } - - void setInstructions(const std::string& instructions) { instructions_ = instructions; } - const std::string& getInstructions() const { return instructions_; } - - Type getType() const { return type_; } - void setType(Type type) { type_ = type; } - - std::string getFormType() const; - - FormField::ref getField(const std::string& name) const; - - void addReportedField(FormField::ref field); - const std::vector<FormField::ref>& getReportedFields() const; - void clearReportedFields() { reportedFields_.clear(); } - - void addItem(const FormItem& item); - const std::vector<FormItem>& getItems() const; - void clearItems() { items_.clear(); } - - private: - std::vector<boost::shared_ptr<FormField> > fields_; - std::vector<boost::shared_ptr<FormField> > reportedFields_; - std::vector<FormItem> items_; - std::string title_; - std::string instructions_; - Type type_; - }; + /** + * XEP-0004 Data form. + * For the relevant Fields, the parsers and serialisers protect the API user against + * the strange multi-value instead of newline thing by transforming them. + */ + class SWIFTEN_API Form : public Payload { + public: + typedef std::shared_ptr<Form> ref; + typedef std::vector<FormField::ref> FormItem; + + enum Type { FormType, SubmitType, CancelType, ResultType }; + + public: + Form(Type type = FormType) : type_(type) {} + + void addPage(std::shared_ptr<FormPage> page) { + assert(page); + pages_.push_back(page); + } + + const std::vector<std::shared_ptr<FormPage> >& getPages() const { + return pages_; + } + + void addField(std::shared_ptr<FormField> field) { + assert(field); + fields_.push_back(field); + } + + const std::vector<std::shared_ptr<FormField> >& getFields() const { + return fields_; + } + + void clearFields() { + fields_.clear(); + } + + void addTextElement(std::shared_ptr<FormText> text) { + assert(text); + textElements_.push_back(text); + } + + const std::vector<std::shared_ptr<FormText> >& getTextElements() const { + return textElements_; + } + + void addReportedRef(std::shared_ptr<FormReportedRef> reportedRef) { + assert(reportedRef); + reportedRefs_.push_back(reportedRef); + } + + const std::vector<std::shared_ptr<FormReportedRef> >& getReportedRefs() const { + return reportedRefs_; + } + + void setTitle(const std::string& title) { + title_ = title; + } + + const std::string& getTitle() const { + return title_; + } + + void setInstructions(const std::string& instructions) { + instructions_ = instructions; + } + + const std::string& getInstructions() const { + return instructions_; + } + + /** Returns the Form::Type enum (ie. ResultType, CancelType etc.). + * NOT to be confused with Form::getFormType(). + */ + Type getType() const { + return type_; + } + + void setType(Type type) { + type_ = type; + } + + /** Returns the value of the field FORM_TYPE + * NOT to be confused with Form::getType(). + */ + std::string getFormType() const; + FormField::ref getField(const std::string& name) const; + void addItem(const FormItem& item); + const std::vector<FormItem>& getItems() const; + void clearItems() { items_.clear(); } + + void clearEmptyTextFields(); + + void addReportedField(FormField::ref field); + const std::vector<FormField::ref> & getReportedFields() const; + void clearReportedFields() { reportedFields_.clear(); } + + private: + std::vector<std::shared_ptr<FormReportedRef> >reportedRefs_; + std::vector<std::shared_ptr<FormText> > textElements_; + std::vector<std::shared_ptr<FormPage> > pages_; + std::vector<std::shared_ptr<FormField> > fields_; + std::vector<std::shared_ptr<FormField> > reportedFields_; + std::vector<FormItem> items_; + std::shared_ptr<FormReportedRef> reportedRef_; + std::string title_; + std::string instructions_; + Type type_; + }; } diff --git a/Swiften/Elements/FormField.cpp b/Swiften/Elements/FormField.cpp index e9e4f77..d4bc9f4 100644 --- a/Swiften/Elements/FormField.cpp +++ b/Swiften/Elements/FormField.cpp @@ -1,14 +1,14 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/Elements/FormField.h> -#include <boost/algorithm/string/split.hpp> -#include <boost/algorithm/string/join.hpp> #include <boost/algorithm/string/classification.hpp> +#include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/split.hpp> using namespace Swift; @@ -16,17 +16,17 @@ FormField::~FormField() { } std::string FormField::getTextMultiValue() const { - assert(type == TextMultiType || type == UnknownType); - return boost::algorithm::join(values, "\n"); + assert(type == TextMultiType || type == UnknownType); + return boost::algorithm::join(values, "\n"); } void FormField::setTextMultiValue(const std::string& value) { - assert(type == TextMultiType || type == UnknownType); - values.clear(); - boost::split(values, value, boost::is_any_of("\n")); + assert(type == TextMultiType || type == UnknownType); + values.clear(); + boost::split(values, value, boost::is_any_of("\n")); } void FormField::setBoolValue(bool b) { - values.clear(); - values.push_back(b ? "1" : "0"); + values.clear(); + values.push_back(b ? "1" : "0"); } diff --git a/Swiften/Elements/FormField.h b/Swiften/Elements/FormField.h index f0bebd9..194589c 100644 --- a/Swiften/Elements/FormField.h +++ b/Swiften/Elements/FormField.h @@ -1,138 +1,140 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> -#include <boost/shared_ptr.hpp> +#include <cassert> +#include <memory> #include <string> +#include <vector> +#include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> namespace Swift { - class FormField { - public: - typedef boost::shared_ptr<FormField> ref; - - enum Type { - UnknownType, - BooleanType, - FixedType, - HiddenType, - ListSingleType, - TextMultiType, - TextPrivateType, - TextSingleType, - JIDSingleType, - JIDMultiType, - ListMultiType - }; - - FormField(Type type = UnknownType) : type(type), required(false) {} - FormField(Type type, const std::string& value) : type(type), required(false) { - addValue(value); - } - virtual ~FormField(); - - struct Option { - Option(const std::string& label, const std::string& value) : label(label), value(value) {} - std::string label; - std::string value; - }; - - void setName(const std::string& name) { this->name = name; } - const std::string& getName() const { return name; } - - void setLabel(const std::string& label) { this->label = label; } - const std::string& getLabel() const { return label; } - - void setDescription(const std::string& description) { this->description = description; } - const std::string& getDescription() const { return description; } - - void setRequired(bool required) { this->required = required; } - bool getRequired() const { return required; } - - void addOption(const Option& option) { - options.push_back(option); - } - - const std::vector<Option>& getOptions() const { - return options; - } - - void clearOptions() { - options.clear(); - } - - const std::vector<std::string>& getValues() const { - return values; - } - - void addValue(const std::string& value) { - values.push_back(value); - } - - Type getType() const { - return type; - } - - void setType(Type type) { - this->type = type; - } - - // Type specific - - bool getBoolValue() const { - assert(type == BooleanType || type == UnknownType); - if (values.empty()) { - return false; - } - return values[0] == "true" || values[0] == "1"; - } - - void setBoolValue(bool b); - - JID getJIDSingleValue() const { - assert(type == JIDSingleType || type == UnknownType); - return values.empty() ? JID() : JID(values[0]); - } - - JID getJIDMultiValue(size_t index) const { - assert(type == JIDMultiType || type == UnknownType); - return values.empty() ? JID() : JID(values[index]); - } - - std::string getTextPrivateValue() const { - assert(type == TextPrivateType || type == UnknownType); - return values.empty() ? "" : values[0]; - } - - std::string getFixedValue() const { - assert(type == FixedType || type == UnknownType); - return values.empty() ? "" : values[0]; - } - - std::string getTextSingleValue() const { - assert(type == TextSingleType || type == UnknownType); - return values.empty() ? "" : values[0]; - } - - std::string getTextMultiValue() const; - void setTextMultiValue(const std::string& value); - - protected: - - private: - Type type; - std::string name; - std::string label; - std::string description; - bool required; - std::vector<Option> options; - std::vector<std::string> values; - }; + class SWIFTEN_API FormField { + public: + typedef std::shared_ptr<FormField> ref; + + enum Type { + UnknownType, + BooleanType, + FixedType, + HiddenType, + ListSingleType, + TextMultiType, + TextPrivateType, + TextSingleType, + JIDSingleType, + JIDMultiType, + ListMultiType + }; + + FormField(Type type = UnknownType) : type(type), required(false) {} + FormField(Type type, const std::string& value) : type(type), required(false) { + addValue(value); + } + virtual ~FormField(); + + struct Option { + Option(const std::string& label, const std::string& value) : label(label), value(value) {} + std::string label; + std::string value; + }; + + void setName(const std::string& name) { this->name = name; } + const std::string& getName() const { return name; } + + void setLabel(const std::string& label) { this->label = label; } + const std::string& getLabel() const { return label; } + + void setDescription(const std::string& description) { this->description = description; } + const std::string& getDescription() const { return description; } + + void setRequired(bool required) { this->required = required; } + bool getRequired() const { return required; } + + void addOption(const Option& option) { + options.push_back(option); + } + + const std::vector<Option>& getOptions() const { + return options; + } + + void clearOptions() { + options.clear(); + } + + const std::vector<std::string>& getValues() const { + return values; + } + + void addValue(const std::string& value) { + values.push_back(value); + } + + Type getType() const { + return type; + } + + void setType(Type type) { + this->type = type; + } + + // Type specific + + bool getBoolValue() const { + assert(type == BooleanType || type == UnknownType); + if (values.empty()) { + return false; + } + return values[0] == "true" || values[0] == "1"; + } + + void setBoolValue(bool b); + + JID getJIDSingleValue() const { + assert(type == JIDSingleType || type == UnknownType); + return values.empty() ? JID() : JID(values[0]); + } + + JID getJIDMultiValue(size_t index) const { + assert(type == JIDMultiType || type == UnknownType); + return values.empty() ? JID() : JID(values[index]); + } + + std::string getTextPrivateValue() const { + assert(type == TextPrivateType || type == UnknownType); + return values.empty() ? "" : values[0]; + } + + std::string getFixedValue() const { + assert(type == FixedType || type == UnknownType); + return values.empty() ? "" : values[0]; + } + + std::string getTextSingleValue() const { + assert(type == TextSingleType || type == UnknownType); + return values.empty() ? "" : values[0]; + } + + std::string getTextMultiValue() const; + void setTextMultiValue(const std::string& value); + + protected: + + private: + Type type; + std::string name; + std::string label; + std::string description; + bool required; + std::vector<Option> options; + std::vector<std::string> values; + }; } diff --git a/Swiften/Elements/FormPage.cpp b/Swiften/Elements/FormPage.cpp new file mode 100644 index 0000000..0afa112 --- /dev/null +++ b/Swiften/Elements/FormPage.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +#include <Swiften/Elements/FormPage.h> + +namespace Swift { + +FormPage::FormPage() { +} + +FormPage::~FormPage() { +} + +void FormPage::setLabel(const std::string& label) { + label_ = label; +} + +const std::string& FormPage::getLabel() const { + return label_; +} + +void FormPage::addChildSection(std::shared_ptr<FormSection> section) { + childSections_.push_back(section); +} + +const std::vector<std::shared_ptr<FormSection> >& FormPage::getChildSections() const { + return childSections_; +} + +void FormPage::addTextElement(std::shared_ptr<FormText> textElement) { + textElements_.push_back(textElement); +} + +const std::vector<std::shared_ptr<FormText> >& FormPage::getTextElements() const { + return textElements_; +} + +void FormPage::addReportedRef(std::shared_ptr<FormReportedRef> reportedRef) { + reportedRefs_.push_back(reportedRef); +} + +const std::vector<std::shared_ptr<FormReportedRef> >& FormPage::getReportedRefs() const { + return reportedRefs_; +} + +void FormPage::addField(std::shared_ptr<FormField> field) { + fields_.push_back(field); +} + +const std::vector<std::shared_ptr<FormField> >& FormPage::getFields() const { + return fields_; +} + +void FormPage::addFieldRef(std::string ref) { + fieldRefs_.push_back(ref); +} + +const std::vector<std::string> FormPage::getFieldRefs() const { + return fieldRefs_; +} + +} diff --git a/Swiften/Elements/FormPage.h b/Swiften/Elements/FormPage.h new file mode 100644 index 0000000..8412d9e --- /dev/null +++ b/Swiften/Elements/FormPage.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +#pragma once + +#include <memory> +#include <string> +#include <vector> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/FormField.h> +#include <Swiften/Elements/FormReportedRef.h> +#include <Swiften/Elements/FormSection.h> +#include <Swiften/Elements/FormText.h> + +namespace Swift { + + class SWIFTEN_API FormPage { + public: + typedef std::shared_ptr<FormPage> page; + FormPage (); + ~FormPage(); + void setLabel(const std::string& label); + const std::string& getLabel() const; + void addChildSection(std::shared_ptr<FormSection> section); + const std::vector<std::shared_ptr<FormSection> >& getChildSections() const; + void addTextElement(std::shared_ptr<FormText> textElement); + const std::vector<std::shared_ptr<FormText> >& getTextElements() const; + void addReportedRef(std::shared_ptr<FormReportedRef> reportedRef); + const std::vector<std::shared_ptr<FormReportedRef> >& getReportedRefs() const; + void addField(std::shared_ptr<FormField> field); + const std::vector<std::shared_ptr<FormField> >& getFields() const; + void addFieldRef(std::string ref); + const std::vector<std::string> getFieldRefs() const; + + private: + std::string label_; + std::vector<std::shared_ptr<FormText> > textElements_; + std::vector<std::shared_ptr<FormSection> > childSections_; + std::vector<std::shared_ptr<FormReportedRef> > reportedRefs_; + std::vector<std::shared_ptr<FormField> > fields_; + std::vector<std::string> fieldRefs_; + }; +} diff --git a/Swiften/Elements/FormReportedRef.h b/Swiften/Elements/FormReportedRef.h new file mode 100644 index 0000000..d6dc718 --- /dev/null +++ b/Swiften/Elements/FormReportedRef.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> + +namespace Swift { + + class SWIFTEN_API FormReportedRef { + + public: + typedef std::shared_ptr<FormReportedRef> ref; + }; +} diff --git a/Swiften/Elements/FormSection.cpp b/Swiften/Elements/FormSection.cpp new file mode 100644 index 0000000..9ca3b4d --- /dev/null +++ b/Swiften/Elements/FormSection.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +#include <Swiften/Elements/FormSection.h> + +namespace Swift { + +FormSection::FormSection() { +} + +FormSection::~FormSection() { +} + +void FormSection::setLabel(const std::string& label) { + label_ = label; +} + +const std::string& FormSection::getLabel() const { + return label_; +} + +void FormSection::addTextElement(std::shared_ptr<FormText> textElement) { + textElements_.push_back(textElement); +} + +const std::vector<std::shared_ptr<FormText> >& FormSection::getTextElements() const { + return textElements_; +} + +void FormSection::addReportedRef(std::shared_ptr<FormReportedRef> reportedRef) { + reportedRefs_.push_back(reportedRef); +} + +const std::vector<std::shared_ptr<FormReportedRef> >& FormSection::getReportedRefs() const { + return reportedRefs_; +} + +void FormSection::addChildSection(std::shared_ptr<FormSection> childSection) { + childSections_.push_back(childSection); +} + +const std::vector<std::shared_ptr<FormSection> >& FormSection::getChildSections() const { + return childSections_; +} + +void FormSection::addField(std::shared_ptr<FormField> field) { + fields_.push_back(field); +} + +const std::vector<std::shared_ptr<FormField> >& FormSection::getFields() const { + return fields_; +} + +void FormSection::addFieldRef(std::string ref) { + fieldRefs_.push_back(ref); +} + +const std::vector<std::string> FormSection::getFieldRefs() const { + return fieldRefs_; +} + +} diff --git a/Swiften/Elements/FormSection.h b/Swiften/Elements/FormSection.h new file mode 100644 index 0000000..b1d60bc --- /dev/null +++ b/Swiften/Elements/FormSection.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +#pragma once + +#include <memory> +#include <string> +#include <vector> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/FormField.h> +#include <Swiften/Elements/FormReportedRef.h> +#include <Swiften/Elements/FormText.h> + +namespace Swift { + + class SWIFTEN_API FormSection { + public: + typedef std::shared_ptr<FormSection> section; + FormSection(); + ~FormSection(); + void setLabel(const std::string& label); + const std::string& getLabel() const; + void addTextElement(std::shared_ptr<FormText> textElement); + const std::vector<std::shared_ptr<FormText> >& getTextElements() const; + void addReportedRef(std::shared_ptr<FormReportedRef> reportedRef); + const std::vector<std::shared_ptr<FormReportedRef> >& getReportedRefs() const; + void addChildSection(std::shared_ptr<FormSection> childSection); + const std::vector<std::shared_ptr<FormSection> >& getChildSections() const; + void addField(std::shared_ptr<FormField> field); + const std::vector<std::shared_ptr<FormField> >& getFields() const; + void addFieldRef(std::string ref); + const std::vector<std::string> getFieldRefs() const; + + private: + std::string label_; + std::vector<std::shared_ptr<FormText> > textElements_; + std::vector<std::shared_ptr<FormReportedRef> > reportedRefs_; + std::vector<std::shared_ptr<FormSection> > childSections_; + std::vector<std::shared_ptr<FormField> > fields_; + std::vector<std::string> fieldRefs_; + }; +} diff --git a/Swiften/Elements/FormText.cpp b/Swiften/Elements/FormText.cpp new file mode 100644 index 0000000..2180e13 --- /dev/null +++ b/Swiften/Elements/FormText.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +#include <Swiften/Elements/FormText.h> + +namespace Swift { + +FormText::FormText() { +} + +FormText::~FormText() { +} + +void FormText::setTextString(const std::string& text) { + text_ = text; +} + +const std::string& FormText::getTextString() const { + return text_; +} + +} diff --git a/Swiften/Elements/FormText.h b/Swiften/Elements/FormText.h new file mode 100644 index 0000000..a0c8d56 --- /dev/null +++ b/Swiften/Elements/FormText.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +#pragma once + +#include <memory> +#include <string> + +#include <Swiften/Base/API.h> + +namespace Swift { + + class SWIFTEN_API FormText{ + + public: + typedef std::shared_ptr<FormText> text; + FormText(); + virtual ~FormText(); + void setTextString(const std::string& text); + const std::string& getTextString() const; + + private: + std::string text_; + }; +} diff --git a/Swiften/Elements/Forwarded.cpp b/Swiften/Elements/Forwarded.cpp new file mode 100644 index 0000000..0ba604c --- /dev/null +++ b/Swiften/Elements/Forwarded.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file 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..a7eb492 --- /dev/null +++ b/Swiften/Elements/Forwarded.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class Delay; + class Stanza; + + class SWIFTEN_API Forwarded : public Payload { + public: + typedef std::shared_ptr<Forwarded> ref; + + public: + virtual ~Forwarded(); + + void setDelay(std::shared_ptr<Delay> delay) { delay_ = delay; } + const std::shared_ptr<Delay>& getDelay() const { return delay_; } + + void setStanza(std::shared_ptr<Stanza> stanza) { stanza_ = stanza; } + const std::shared_ptr<Stanza>& getStanza() const { return stanza_; } + + private: + std::shared_ptr<Delay> delay_; + std::shared_ptr<Stanza> stanza_; + }; +} diff --git a/Swiften/Elements/HashElement.h b/Swiften/Elements/HashElement.h new file mode 100644 index 0000000..bbe4d1c --- /dev/null +++ b/Swiften/Elements/HashElement.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Base/ByteArray.h> + +namespace Swift { + /* + * @brief This class represents a XEP-0300 <hash/> element. + */ + class SWIFTEN_API HashElement { + public: + HashElement(const std::string& algorithm, const ByteArray& hash) : algorithm_(algorithm), hash_(hash) { + } + + void setHashValue(const std::string& algorithm, const ByteArray& hash) { + algorithm_ = algorithm; + hash_ = hash; + } + + const std::string& getAlgorithm() const { + return algorithm_; + } + + const ByteArray& getHashValue() const { + return hash_; + } + + bool operator==(const HashElement& rhs) const { + return (algorithm_ == rhs.algorithm_) && (hash_ == rhs.hash_); + } + + + private: + std::string algorithm_; + ByteArray hash_; + }; +} diff --git a/Swiften/Elements/IBB.h b/Swiften/Elements/IBB.h index fb33eaf..6ebe66e 100644 --- a/Swiften/Elements/IBB.h +++ b/Swiften/Elements/IBB.h @@ -1,107 +1,107 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <string> #include <vector> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class IBB : public Payload { - public: - typedef boost::shared_ptr<IBB> ref; - - enum Action { - Open, - Close, - Data - }; - enum StanzaType { - IQStanza, - MessageStanza - }; - - IBB(Action action = Open, const std::string& streamID = "") : action(action), streamID(streamID), stanzaType(IQStanza), blockSize(-1), sequenceNumber(-1) { - } - - static IBB::ref createIBBOpen(const std::string& streamID, int blockSize) { - IBB::ref result = boost::make_shared<IBB>(Open, streamID); - result->setBlockSize(blockSize); - return result; - } - - static IBB::ref createIBBData(const std::string& streamID, int sequenceNumber, const std::vector<unsigned char>& data) { - IBB::ref result = boost::make_shared<IBB>(Data, streamID); - result->setSequenceNumber(sequenceNumber); - result->setData(data); - return result; - } - - static IBB::ref createIBBClose(const std::string& streamID) { - return boost::make_shared<IBB>(Close, streamID); - } - - void setAction(Action action) { - this->action = action; - } - - Action getAction() const { - return action; - } - - void setStanzaType(StanzaType stanzaType) { - this->stanzaType = stanzaType; - } - - StanzaType getStanzaType() const { - return stanzaType; - } - - void setStreamID(const std::string& id) { - streamID = id; - } - - const std::string& getStreamID() const { - return streamID; - } - - const std::vector<unsigned char>& getData() const { - return data; - } - - void setData(const std::vector<unsigned char>& data) { - this->data = data; - } - - int getBlockSize() const { - return blockSize; - } - - void setBlockSize(int blockSize) { - this->blockSize = blockSize; - } - - int getSequenceNumber() const { - return sequenceNumber; - } - - void setSequenceNumber(int i) { - sequenceNumber = i; - } - - private: - Action action; - std::string streamID; - std::vector<unsigned char> data; - StanzaType stanzaType; - int blockSize; - int sequenceNumber; - }; + class SWIFTEN_API IBB : public Payload { + public: + typedef std::shared_ptr<IBB> ref; + + enum Action { + Open, + Close, + Data + }; + enum StanzaType { + IQStanza, + MessageStanza + }; + + IBB(Action action = Open, const std::string& streamID = "") : action(action), streamID(streamID), stanzaType(IQStanza), blockSize(0), sequenceNumber(-1) { + } + + static IBB::ref createIBBOpen(const std::string& streamID, unsigned int blockSize) { + IBB::ref result = std::make_shared<IBB>(Open, streamID); + result->setBlockSize(blockSize); + return result; + } + + static IBB::ref createIBBData(const std::string& streamID, int sequenceNumber, const std::vector<unsigned char>& data) { + IBB::ref result = std::make_shared<IBB>(Data, streamID); + result->setSequenceNumber(sequenceNumber); + result->setData(data); + return result; + } + + static IBB::ref createIBBClose(const std::string& streamID) { + return std::make_shared<IBB>(Close, streamID); + } + + void setAction(Action action) { + this->action = action; + } + + Action getAction() const { + return action; + } + + void setStanzaType(StanzaType stanzaType) { + this->stanzaType = stanzaType; + } + + StanzaType getStanzaType() const { + return stanzaType; + } + + void setStreamID(const std::string& id) { + streamID = id; + } + + const std::string& getStreamID() const { + return streamID; + } + + const std::vector<unsigned char>& getData() const { + return data; + } + + void setData(const std::vector<unsigned char>& data) { + this->data = data; + } + + unsigned int getBlockSize() const { + return blockSize; + } + + void setBlockSize(unsigned int blockSize) { + this->blockSize = blockSize; + } + + int getSequenceNumber() const { + return sequenceNumber; + } + + void setSequenceNumber(int i) { + sequenceNumber = i; + } + + private: + Action action; + std::string streamID; + std::vector<unsigned char> data; + StanzaType stanzaType; + unsigned int blockSize; + int sequenceNumber; + }; } diff --git a/Swiften/Elements/IQ.cpp b/Swiften/Elements/IQ.cpp index 8c0f692..31a654f 100644 --- a/Swiften/Elements/IQ.cpp +++ b/Swiften/Elements/IQ.cpp @@ -1,68 +1,68 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/IQ.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> namespace Swift { -boost::shared_ptr<IQ> IQ::createRequest( - Type type, const JID& to, const std::string& id, boost::shared_ptr<Payload> payload) { - boost::shared_ptr<IQ> iq = boost::make_shared<IQ>(type); - if (to.isValid()) { - iq->setTo(to); - } - iq->setID(id); - if (payload) { - iq->addPayload(payload); - } - return iq; +std::shared_ptr<IQ> IQ::createRequest( + Type type, const JID& to, const std::string& id, std::shared_ptr<Payload> payload) { + std::shared_ptr<IQ> iq = std::make_shared<IQ>(type); + if (to.isValid()) { + iq->setTo(to); + } + iq->setID(id); + if (payload) { + iq->addPayload(payload); + } + return iq; } -boost::shared_ptr<IQ> IQ::createResult(const JID& to, const std::string& id, boost::shared_ptr<Payload> payload) { - boost::shared_ptr<IQ> iq = boost::make_shared<IQ>(Result); - iq->setTo(to); - iq->setID(id); - if (payload) { - iq->addPayload(payload); - } - return iq; +std::shared_ptr<IQ> IQ::createResult(const JID& to, const std::string& id, std::shared_ptr<Payload> payload) { + std::shared_ptr<IQ> iq = std::make_shared<IQ>(Result); + iq->setTo(to); + iq->setID(id); + if (payload) { + iq->addPayload(payload); + } + return iq; } -boost::shared_ptr<IQ> IQ::createResult(const JID& to, const JID& from, const std::string& id, boost::shared_ptr<Payload> payload) { - boost::shared_ptr<IQ> iq = boost::make_shared<IQ>(Result); - iq->setTo(to); - iq->setFrom(from); - iq->setID(id); - if (payload) { - iq->addPayload(payload); - } - return iq; +std::shared_ptr<IQ> IQ::createResult(const JID& to, const JID& from, const std::string& id, std::shared_ptr<Payload> payload) { + std::shared_ptr<IQ> iq = std::make_shared<IQ>(Result); + iq->setTo(to); + iq->setFrom(from); + iq->setID(id); + if (payload) { + iq->addPayload(payload); + } + return iq; } -boost::shared_ptr<IQ> IQ::createError(const JID& to, const std::string& id, ErrorPayload::Condition condition, ErrorPayload::Type type, boost::shared_ptr<Payload> payload) { - boost::shared_ptr<IQ> iq = boost::make_shared<IQ>(IQ::Error); - iq->setTo(to); - iq->setID(id); - boost::shared_ptr<ErrorPayload> errorPayload = boost::make_shared<Swift::ErrorPayload>(condition, type); - errorPayload->setPayload(payload); - iq->addPayload(errorPayload); - return iq; +std::shared_ptr<IQ> IQ::createError(const JID& to, const std::string& id, ErrorPayload::Condition condition, ErrorPayload::Type type, std::shared_ptr<Payload> payload) { + std::shared_ptr<IQ> iq = std::make_shared<IQ>(IQ::Error); + iq->setTo(to); + iq->setID(id); + std::shared_ptr<ErrorPayload> errorPayload = std::make_shared<Swift::ErrorPayload>(condition, type); + errorPayload->setPayload(payload); + iq->addPayload(errorPayload); + return iq; } -boost::shared_ptr<IQ> IQ::createError(const JID& to, const JID& from, const std::string& id, ErrorPayload::Condition condition, ErrorPayload::Type type, boost::shared_ptr<Payload> payload) { - boost::shared_ptr<IQ> iq = boost::make_shared<IQ>(IQ::Error); - iq->setTo(to); - iq->setFrom(from); - iq->setID(id); - boost::shared_ptr<ErrorPayload> errorPayload = boost::make_shared<Swift::ErrorPayload>(condition, type); - errorPayload->setPayload(payload); - iq->addPayload(errorPayload); - return iq; +std::shared_ptr<IQ> IQ::createError(const JID& to, const JID& from, const std::string& id, ErrorPayload::Condition condition, ErrorPayload::Type type, std::shared_ptr<Payload> payload) { + std::shared_ptr<IQ> iq = std::make_shared<IQ>(IQ::Error); + iq->setTo(to); + iq->setFrom(from); + iq->setID(id); + std::shared_ptr<ErrorPayload> errorPayload = std::make_shared<Swift::ErrorPayload>(condition, type); + errorPayload->setPayload(payload); + iq->addPayload(errorPayload); + return iq; } } diff --git a/Swiften/Elements/IQ.h b/Swiften/Elements/IQ.h index ff978b3..00ed848 100644 --- a/Swiften/Elements/IQ.h +++ b/Swiften/Elements/IQ.h @@ -1,58 +1,58 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> -#include <Swiften/Elements/Stanza.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/Stanza.h> namespace Swift { - class SWIFTEN_API IQ : public Stanza { - public: - typedef boost::shared_ptr<IQ> ref; - - enum Type { Get, Set, Result, Error }; - - IQ(Type type = Get) : type_(type) { } - - Type getType() const { return type_; } - void setType(Type type) { type_ = type; } - - static boost::shared_ptr<IQ> createRequest( - Type type, - const JID& to, - const std::string& id, - boost::shared_ptr<Payload> payload); - static boost::shared_ptr<IQ> createResult( - const JID& to, - const std::string& id, - boost::shared_ptr<Payload> payload = boost::shared_ptr<Payload>()); - static boost::shared_ptr<IQ> createResult( - const JID& to, - const JID& from, - const std::string& id, - boost::shared_ptr<Payload> payload = boost::shared_ptr<Payload>()); - static boost::shared_ptr<IQ> createError( - const JID& to, - const std::string& id, - ErrorPayload::Condition condition = ErrorPayload::BadRequest, - ErrorPayload::Type type = ErrorPayload::Cancel, - boost::shared_ptr<Payload> payload = boost::shared_ptr<Payload>()); - static boost::shared_ptr<IQ> createError( - const JID& to, - const JID& from, - const std::string& id, - ErrorPayload::Condition condition = ErrorPayload::BadRequest, - ErrorPayload::Type type = ErrorPayload::Cancel, - boost::shared_ptr<Payload> payload = boost::shared_ptr<Payload>()); - - private: - Type type_; - }; + class SWIFTEN_API IQ : public Stanza { + public: + typedef std::shared_ptr<IQ> ref; + + enum Type { Get, Set, Result, Error }; + + IQ(Type type = Get) : type_(type) { } + + Type getType() const { return type_; } + void setType(Type type) { type_ = type; } + + static std::shared_ptr<IQ> createRequest( + Type type, + const JID& to, + const std::string& id, + std::shared_ptr<Payload> payload); + static std::shared_ptr<IQ> createResult( + const JID& to, + const std::string& id, + std::shared_ptr<Payload> payload = std::shared_ptr<Payload>()); + static std::shared_ptr<IQ> createResult( + const JID& to, + const JID& from, + const std::string& id, + std::shared_ptr<Payload> payload = std::shared_ptr<Payload>()); + static std::shared_ptr<IQ> createError( + const JID& to, + const std::string& id, + ErrorPayload::Condition condition = ErrorPayload::BadRequest, + ErrorPayload::Type type = ErrorPayload::Cancel, + std::shared_ptr<Payload> payload = std::shared_ptr<Payload>()); + static std::shared_ptr<IQ> createError( + const JID& to, + const JID& from, + const std::string& id, + ErrorPayload::Condition condition = ErrorPayload::BadRequest, + ErrorPayload::Type type = ErrorPayload::Cancel, + std::shared_ptr<Payload> payload = std::shared_ptr<Payload>()); + + private: + Type type_; + }; } diff --git a/Swiften/Elements/Idle.h b/Swiften/Elements/Idle.h index 572eba2..9f721aa 100644 --- a/Swiften/Elements/Idle.h +++ b/Swiften/Elements/Idle.h @@ -4,34 +4,42 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/date_time/posix_time/posix_time_types.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class Idle : public Payload { - public: - typedef boost::shared_ptr<Idle> ref; + class SWIFTEN_API Idle : public Payload { + public: + typedef std::shared_ptr<Idle> ref; - public: - Idle() {} - Idle(boost::posix_time::ptime since) : since_(since) { - } + public: + Idle() {} + Idle(boost::posix_time::ptime since) : since_(since) { + } - void setSince(boost::posix_time::ptime since) { - since_ = since; - } + void setSince(boost::posix_time::ptime since) { + since_ = since; + } - boost::posix_time::ptime getSince() const { - return since_; - } + boost::posix_time::ptime getSince() const { + return since_; + } - private: - boost::posix_time::ptime since_; - }; + private: + boost::posix_time::ptime since_; + }; } diff --git a/Swiften/Elements/InBandRegistrationPayload.h b/Swiften/Elements/InBandRegistrationPayload.h index 8f6a9f1..4fad248 100644 --- a/Swiften/Elements/InBandRegistrationPayload.h +++ b/Swiften/Elements/InBandRegistrationPayload.h @@ -1,209 +1,211 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/optional.hpp> +#include <memory> #include <string> -#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Payload.h> namespace Swift { - class InBandRegistrationPayload : public Payload { - public: - typedef boost::shared_ptr<InBandRegistrationPayload> ref; + class SWIFTEN_API InBandRegistrationPayload : public Payload { + public: + typedef std::shared_ptr<InBandRegistrationPayload> ref; - InBandRegistrationPayload() : registered(false), remove(false) {} + InBandRegistrationPayload() : registered(false), remove(false) {} - Form::ref getForm() const { return form; } - void setForm(Form::ref f) { form = f; } + Form::ref getForm() const { return form; } + void setForm(Form::ref f) { form = f; } - bool isRegistered() const { - return registered; - } + bool isRegistered() const { + return registered; + } - void setRegistered(bool b) { - registered = b; - } + void setRegistered(bool b) { + registered = b; + } - bool isRemove() const { - return remove; - } + bool isRemove() const { + return remove; + } - void setRemove(bool b) { - remove = b; - } + void setRemove(bool b) { + remove = b; + } - const boost::optional<std::string>& getInstructions() const { - return instructions; - } + const boost::optional<std::string>& getInstructions() const { + return instructions; + } - const boost::optional<std::string>& getUsername() const { - return username; - } + const boost::optional<std::string>& getUsername() const { + return username; + } - const boost::optional<std::string>& getNick() const { - return nick; - } + const boost::optional<std::string>& getNick() const { + return nick; + } - const boost::optional<std::string>& getPassword() const { - return password; - } + const boost::optional<std::string>& getPassword() const { + return password; + } - const boost::optional<std::string>& getName() const { - return name; - } + const boost::optional<std::string>& getName() const { + return name; + } - const boost::optional<std::string>& getFirst() const { - return first; - } + const boost::optional<std::string>& getFirst() const { + return first; + } - const boost::optional<std::string>& getLast() const { - return last; - } + const boost::optional<std::string>& getLast() const { + return last; + } - const boost::optional<std::string>& getEMail() const { - return email; - } + const boost::optional<std::string>& getEMail() const { + return email; + } - const boost::optional<std::string>& getAddress() const { - return address; - } + const boost::optional<std::string>& getAddress() const { + return address; + } - const boost::optional<std::string>& getCity() const { - return city; - } + const boost::optional<std::string>& getCity() const { + return city; + } - const boost::optional<std::string>& getState() const { - return state; - } + const boost::optional<std::string>& getState() const { + return state; + } - const boost::optional<std::string>& getZip() const { - return zip; - } + const boost::optional<std::string>& getZip() const { + return zip; + } - const boost::optional<std::string>& getPhone() const { - return phone; - } - - const boost::optional<std::string>& getURL() const { - return url; - } - - const boost::optional<std::string>& getDate() const { - return date; - } - - const boost::optional<std::string>& getMisc() const { - return misc; - } - - const boost::optional<std::string>& getText() const { - return text; - } - - const boost::optional<std::string>& getKey() const { - return key; - } - - void setInstructions(const std::string& v) { - this->instructions = v; - } - - void setUsername(const std::string& v) { - this->username = v; - } - - void setNick(const std::string& v) { - this->nick = v; - } - - void setPassword(const std::string& v) { - this->password = v; - } - - void setName(const std::string& v) { - this->name = v; - } - - void setFirst(const std::string& v) { - this->first = v; - } - - void setLast(const std::string& v) { - this->last = v; - } - - void setEMail(const std::string& v) { - this->email = v; - } - - void setAddress(const std::string& v) { - this->address = v; - } - - void setCity(const std::string& v) { - this->city = v; - } - - void setState(const std::string& v) { - this->state = v; - } - - void setZip(const std::string& v) { - this->zip = v; - } - - void setPhone(const std::string& v) { - this->phone = v; - } - - void setURL(const std::string& v) { - this->url = v; - } - - void setDate(const std::string& v) { - this->date = v; - } - - void setMisc(const std::string& v) { - this->misc = v; - } - - void setText(const std::string& v) { - this->text = v; - } - - void setKey(const std::string& v) { - this->key = v; - } - - private: - Form::ref form; - bool registered; - bool remove; - boost::optional<std::string> instructions; - boost::optional<std::string> username; - boost::optional<std::string> nick; - boost::optional<std::string> password; - boost::optional<std::string> name; - boost::optional<std::string> first; - boost::optional<std::string> last; - boost::optional<std::string> email; - boost::optional<std::string> address; - boost::optional<std::string> city; - boost::optional<std::string> state; - boost::optional<std::string> zip; - boost::optional<std::string> phone; - boost::optional<std::string> url; - boost::optional<std::string> date; - boost::optional<std::string> misc; - boost::optional<std::string> text; - boost::optional<std::string> key; - }; + const boost::optional<std::string>& getPhone() const { + return phone; + } + + const boost::optional<std::string>& getURL() const { + return url; + } + + const boost::optional<std::string>& getDate() const { + return date; + } + + const boost::optional<std::string>& getMisc() const { + return misc; + } + + const boost::optional<std::string>& getText() const { + return text; + } + + const boost::optional<std::string>& getKey() const { + return key; + } + + void setInstructions(const std::string& v) { + this->instructions = v; + } + + void setUsername(const std::string& v) { + this->username = v; + } + + void setNick(const std::string& v) { + this->nick = v; + } + + void setPassword(const std::string& v) { + this->password = v; + } + + void setName(const std::string& v) { + this->name = v; + } + + void setFirst(const std::string& v) { + this->first = v; + } + + void setLast(const std::string& v) { + this->last = v; + } + + void setEMail(const std::string& v) { + this->email = v; + } + + void setAddress(const std::string& v) { + this->address = v; + } + + void setCity(const std::string& v) { + this->city = v; + } + + void setState(const std::string& v) { + this->state = v; + } + + void setZip(const std::string& v) { + this->zip = v; + } + + void setPhone(const std::string& v) { + this->phone = v; + } + + void setURL(const std::string& v) { + this->url = v; + } + + void setDate(const std::string& v) { + this->date = v; + } + + void setMisc(const std::string& v) { + this->misc = v; + } + + void setText(const std::string& v) { + this->text = v; + } + + void setKey(const std::string& v) { + this->key = v; + } + + private: + Form::ref form; + bool registered; + bool remove; + boost::optional<std::string> instructions; + boost::optional<std::string> username; + boost::optional<std::string> nick; + boost::optional<std::string> password; + boost::optional<std::string> name; + boost::optional<std::string> first; + boost::optional<std::string> last; + boost::optional<std::string> email; + boost::optional<std::string> address; + boost::optional<std::string> city; + boost::optional<std::string> state; + boost::optional<std::string> zip; + boost::optional<std::string> phone; + boost::optional<std::string> url; + boost::optional<std::string> date; + boost::optional<std::string> misc; + boost::optional<std::string> text; + boost::optional<std::string> key; + }; } diff --git a/Swiften/Elements/IsodeIQDelegation.cpp b/Swiften/Elements/IsodeIQDelegation.cpp new file mode 100644 index 0000000..e84b4ed --- /dev/null +++ b/Swiften/Elements/IsodeIQDelegation.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/IsodeIQDelegation.h> + +using namespace Swift; + +IsodeIQDelegation::IsodeIQDelegation() { +} + +IsodeIQDelegation::~IsodeIQDelegation() { +} diff --git a/Swiften/Elements/IsodeIQDelegation.h b/Swiften/Elements/IsodeIQDelegation.h new file mode 100644 index 0000000..074a06d --- /dev/null +++ b/Swiften/Elements/IsodeIQDelegation.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API IsodeIQDelegation : public Payload { + public: + + IsodeIQDelegation(); + + virtual ~IsodeIQDelegation(); + + std::shared_ptr<Forwarded> getForward() const { + return forward; + } + + void setForward(std::shared_ptr<Forwarded> value) { + this->forward = value ; + } + + + private: + std::shared_ptr<Forwarded> forward; + }; +} diff --git a/Swiften/Elements/JingleContentPayload.h b/Swiften/Elements/JingleContentPayload.h index 547fc70..744ac09 100644 --- a/Swiften/Elements/JingleContentPayload.h +++ b/Swiften/Elements/JingleContentPayload.h @@ -1,97 +1,102 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <string> #include <vector> + #include <boost/optional.hpp> -#include <string> -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/Payload.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleDescription.h> #include <Swiften/Elements/JingleTransportPayload.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class JingleContentPayload : public Payload { - public: - typedef boost::shared_ptr<JingleContentPayload> ref; - - enum Creator { - UnknownCreator, - InitiatorCreator, - ResponderCreator - }; - - /*enum Senders { - NoSenders, - InitiatorSender, - ResponderSender, - BothSenders, - };*/ - - Creator getCreator() const { - return creator; - } - - void setCreator(Creator creator) { - this->creator = creator; - } - - const std::string& getName() const { - return name; - } - - void setName(const std::string& name) { - this->name = name; - } - - const std::vector<JingleDescription::ref>& getDescriptions() const { - return descriptions; - } - - void addDescription(JingleDescription::ref description) { - descriptions.push_back(description); - } - - const std::vector<boost::shared_ptr<JingleTransportPayload> >& getTransports() const { - return transports; - } - - void addTransport(boost::shared_ptr<JingleTransportPayload> transport) { - transports.push_back(transport); - } - - template<typename T> - boost::shared_ptr<T> getDescription() const { - for (size_t i = 0; i < descriptions.size(); ++i) { - boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(descriptions[i])); - if (result) { - return result; - } - } - return boost::shared_ptr<T>(); - } - - template<typename T> - boost::shared_ptr<T> getTransport() const { - for (size_t i = 0; i < transports.size(); ++i) { - boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(transports[i])); - if (result) { - return result; - } - } - return boost::shared_ptr<T>(); - } - - private: - Creator creator; - std::string name; - //Senders senders; - std::vector<JingleDescription::ref> descriptions; - std::vector<boost::shared_ptr<JingleTransportPayload> > transports; - }; + class SWIFTEN_API JingleContentPayload : public Payload { + public: + typedef std::shared_ptr<JingleContentPayload> ref; + + enum Creator { + UnknownCreator, + InitiatorCreator, + ResponderCreator + }; + + JingleContentPayload() : creator(UnknownCreator) { + } + + /*enum Senders { + NoSenders, + InitiatorSender, + ResponderSender, + BothSenders, + };*/ + + Creator getCreator() const { + return creator; + } + + void setCreator(Creator creator) { + this->creator = creator; + } + + const std::string& getName() const { + return name; + } + + void setName(const std::string& name) { + this->name = name; + } + + const std::vector<JingleDescription::ref>& getDescriptions() const { + return descriptions; + } + + void addDescription(JingleDescription::ref description) { + descriptions.push_back(description); + } + + const std::vector<std::shared_ptr<JingleTransportPayload> >& getTransports() const { + return transports; + } + + void addTransport(std::shared_ptr<JingleTransportPayload> transport) { + transports.push_back(transport); + } + + template<typename T> + std::shared_ptr<T> getDescription() const { + for (const auto& description : descriptions) { + std::shared_ptr<T> result(std::dynamic_pointer_cast<T>(description)); + if (result) { + return result; + } + } + return std::shared_ptr<T>(); + } + + template<typename T> + std::shared_ptr<T> getTransport() const { + for (const auto& transport : transports) { + std::shared_ptr<T> result(std::dynamic_pointer_cast<T>(transport)); + if (result) { + return result; + } + } + return std::shared_ptr<T>(); + } + + private: + Creator creator; + std::string name; + //Senders senders; + std::vector<JingleDescription::ref> descriptions; + std::vector<std::shared_ptr<JingleTransportPayload> > transports; + }; } diff --git a/Swiften/Elements/JingleDescription.h b/Swiften/Elements/JingleDescription.h index 775c0f7..ee3dcae 100644 --- a/Swiften/Elements/JingleDescription.h +++ b/Swiften/Elements/JingleDescription.h @@ -1,18 +1,19 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class JingleDescription : public Payload { - public: - typedef boost::shared_ptr<JingleDescription> ref; - }; + class SWIFTEN_API JingleDescription : public Payload { + public: + typedef std::shared_ptr<JingleDescription> ref; + }; } diff --git a/Swiften/Elements/JingleFileTransferDescription.h b/Swiften/Elements/JingleFileTransferDescription.h index 04f3f1f..2418f3b 100644 --- a/Swiften/Elements/JingleFileTransferDescription.h +++ b/Swiften/Elements/JingleFileTransferDescription.h @@ -1,41 +1,32 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <vector> +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleDescription.h> -#include <Swiften/Elements/StreamInitiationFileInfo.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h> namespace Swift { - class JingleFileTransferDescription : public JingleDescription { - public: - typedef boost::shared_ptr<JingleFileTransferDescription> ref; + class SWIFTEN_API JingleFileTransferDescription : public JingleDescription { + public: + typedef std::shared_ptr<JingleFileTransferDescription> ref; - void addOffer(const StreamInitiationFileInfo& offer) { - offers.push_back(offer); - } - + void setFileInfo(const JingleFileTransferFileInfo& fileInfo) { + fileInfo_ = fileInfo; + } - const std::vector<StreamInitiationFileInfo>& getOffers() const { - return offers; - } - - void addRequest(const StreamInitiationFileInfo& request) { - reqeusts.push_back(request); - } - - const std::vector<StreamInitiationFileInfo>& getRequests() const { - return reqeusts; - } + const JingleFileTransferFileInfo& getFileInfo() { + return fileInfo_; + } - private: - std::vector<StreamInitiationFileInfo> offers; - std::vector<StreamInitiationFileInfo> reqeusts; - }; + private: + JingleFileTransferFileInfo fileInfo_; + }; } diff --git a/Swiften/Elements/JingleFileTransferFileInfo.h b/Swiften/Elements/JingleFileTransferFileInfo.h new file mode 100644 index 0000000..0e8ccd4 --- /dev/null +++ b/Swiften/Elements/JingleFileTransferFileInfo.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/HashElement.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + + /** + * @brief This class represents the file info used in XEP-0234. + */ + class SWIFTEN_API JingleFileTransferFileInfo : public Payload { + typedef std::shared_ptr<JingleFileTransferFileInfo> ref; + + public: + JingleFileTransferFileInfo(const std::string& name = "", const std::string& description = "", unsigned long long size = 0, const boost::posix_time::ptime &date = boost::posix_time::ptime()) : + name_(name), description_(description), size_(size), date_(date), supportsRangeRequests_(false), rangeOffset_(0) { + } + + public: + typedef std::map<std::string, ByteArray> HashElementMap; + + public: + void setName(const std::string& name) { + name_ = name; + } + + const std::string& getName() const { + return name_; + } + + void setDescription(const std::string& description) { + description_ = description; + } + + const std::string& getDescription() const { + return description_; + } + + void setMediaType(const std::string& mediaType) { + mediaType_ = mediaType; + } + + const std::string& getMediaType() const { + return mediaType_; + } + + void setSize(const boost::uintmax_t size) { + size_ = size; + } + + boost::uintmax_t getSize() const { + return size_; + } + + void setDate(const boost::posix_time::ptime& date) { + date_ = date; + } + + const boost::posix_time::ptime& getDate() const { + return date_; + } + + void setSupportsRangeRequests(const bool supportsIt) { + supportsRangeRequests_ = supportsIt; + } + + bool getSupportsRangeRequests() const { + return supportsRangeRequests_; + } + + void setRangeOffset(const boost::uintmax_t offset) { + supportsRangeRequests_ = true; + rangeOffset_ = offset; + } + + boost::uintmax_t getRangeOffset() const { + return rangeOffset_; + } + + void addHash(const HashElement& hash) { + hashes_[hash.getAlgorithm()] = hash.getHashValue(); + } + + const std::map<std::string, ByteArray>& getHashes() const { + return hashes_; + } + + boost::optional<ByteArray> getHash(const std::string& algorithm) const { + boost::optional<ByteArray> ret; + if (hashes_.find(algorithm) != hashes_.end()) { + ret = boost::optional<ByteArray>(hashes_.find(algorithm)->second); + } + return ret; + } + + private: + std::string name_; + std::string description_; + std::string mediaType_; + boost::uintmax_t size_; + boost::posix_time::ptime date_; + bool supportsRangeRequests_; + boost::uintmax_t rangeOffset_; + HashElementMap hashes_; + }; +} diff --git a/Swiften/Elements/JingleFileTransferHash.h b/Swiften/Elements/JingleFileTransferHash.h index 5603531..4669e1c 100644 --- a/Swiften/Elements/JingleFileTransferHash.h +++ b/Swiften/Elements/JingleFileTransferHash.h @@ -4,32 +4,38 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/shared_ptr.hpp> #include <map> +#include <memory> #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleDescription.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h> namespace Swift { -class JingleFileTransferHash : public Payload { +class SWIFTEN_API JingleFileTransferHash : public Payload { public: - typedef std::map<std::string, std::string> HashesMap; -public: - typedef boost::shared_ptr<JingleFileTransferHash> ref; + typedef std::shared_ptr<JingleFileTransferHash> ref; - void setHash(const std::string& algo, const std::string& hash) { - hashes[algo] = hash; - } + void setFileInfo(const JingleFileTransferFileInfo& fileInfo) { + fileInfo_ = fileInfo; + } - const HashesMap& getHashes() const { - return hashes; - } + JingleFileTransferFileInfo& getFileInfo() { + return fileInfo_; + } private: - HashesMap hashes; + JingleFileTransferFileInfo fileInfo_; }; - + } diff --git a/Swiften/Elements/JingleFileTransferReceived.h b/Swiften/Elements/JingleFileTransferReceived.h deleted file mode 100644 index 75c95d9..0000000 --- a/Swiften/Elements/JingleFileTransferReceived.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2011 Tobias Markmann - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. - */ - -#pragma once - -#include <boost/shared_ptr.hpp> -#include <vector> - -#include <Swiften/Elements/StreamInitiationFileInfo.h> -#include <Swiften/Elements/Payload.h> - -namespace Swift { - -class JingleFileTransferReceived : public Payload { - public: - typedef boost::shared_ptr<JingleFileTransferReceived> ref; - - void setFileInfo(const StreamInitiationFileInfo& fileInfo) { - this->fileInfo = fileInfo; - } - - const StreamInitiationFileInfo& getFileInfo() const { - return this->fileInfo; - } - private: - StreamInitiationFileInfo fileInfo; - -}; - -} diff --git a/Swiften/Elements/JingleIBBTransportPayload.h b/Swiften/Elements/JingleIBBTransportPayload.h index a329ff0..8f0a369 100644 --- a/Swiften/Elements/JingleIBBTransportPayload.h +++ b/Swiften/Elements/JingleIBBTransportPayload.h @@ -1,45 +1,50 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/optional.hpp> +#include <memory> #include <string> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleTransportPayload.h> namespace Swift { - class JingleIBBTransportPayload : public JingleTransportPayload { - public: - typedef boost::shared_ptr<JingleIBBTransportPayload> ref; - - enum StanzaType { - IQStanza, - MessageStanza - }; - - void setStanzaType(StanzaType stanzaType) { - this->stanzaType = stanzaType; - } - - StanzaType getStanzaType() const { - return stanzaType; - } - - boost::optional<unsigned int> getBlockSize() const { - return blockSize; - } - - void setBlockSize(unsigned int blockSize) { - this->blockSize = blockSize; - } - - private: - boost::optional<unsigned int> blockSize; - StanzaType stanzaType; - }; + class SWIFTEN_API JingleIBBTransportPayload : public JingleTransportPayload { + public: + typedef std::shared_ptr<JingleIBBTransportPayload> ref; + + enum StanzaType { + IQStanza, + MessageStanza + }; + + JingleIBBTransportPayload() : stanzaType(IQStanza) { + } + + void setStanzaType(StanzaType stanzaType) { + this->stanzaType = stanzaType; + } + + StanzaType getStanzaType() const { + return stanzaType; + } + + boost::optional<unsigned int> getBlockSize() const { + return blockSize; + } + + void setBlockSize(unsigned int blockSize) { + this->blockSize = blockSize; + } + + private: + boost::optional<unsigned int> blockSize; + StanzaType stanzaType; + }; } diff --git a/Swiften/Elements/JinglePayload.h b/Swiften/Elements/JinglePayload.h index 5f12e90..a1e8500 100644 --- a/Swiften/Elements/JinglePayload.h +++ b/Swiften/Elements/JinglePayload.h @@ -1,166 +1,167 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> +#include <string> #include <vector> -#include <boost/shared_ptr.hpp> + #include <boost/optional.hpp> -#include <string> -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/Payload.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleContentPayload.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class JinglePayload : public Payload { - public: - typedef boost::shared_ptr<JinglePayload> ref; - struct Reason : public Payload { - enum Type { - UnknownType, - AlternativeSession, - Busy, - Cancel, - ConnectivityError, - Decline, - Expired, - FailedApplication, - FailedTransport, - GeneralError, - Gone, - IncompatibleParameters, - MediaError, - SecurityError, - Success, - Timeout, - UnsupportedApplications, - UnsupportedTransports - }; - Reason() : type(UnknownType), text("") {} - Reason(Type type, const std::string& text = "") : type(type), text(text) {} - ~Reason() {} - Type type; - std::string text; - }; - - enum Action { - UnknownAction, - ContentAccept, - ContentAdd, - ContentModify, - ContentReject, - ContentRemove, - DescriptionInfo, - SecurityInfo, - SessionAccept, - SessionInfo, - SessionInitiate, - SessionTerminate, - TransportAccept, - TransportInfo, - TransportReject, - TransportReplace - }; - JinglePayload() : action(SessionTerminate), sessionID("") { - } - - JinglePayload(Action action, const std::string& sessionID) : action(action), sessionID(sessionID) { - - } - - void setAction(Action action) { - this->action = action; - } - - Action getAction() const { - return action; - } - - void setInitiator(const JID& initiator) { - this->initiator = initiator; - } - - const JID& getInitiator() const { - return initiator; - } - - void setResponder(const JID& responder) { - this->responder = responder; - } - - const JID& getResponder() const { - return responder; - } - - void setSessionID(const std::string& id) { - sessionID = id; - } - - const std::string& getSessionID() const { - return sessionID; - } - - void addContent(JingleContentPayload::ref content) { - this->payloads.push_back(content); - } - - void addPayload(boost::shared_ptr<Payload> payload) { - this->payloads.push_back(payload); - } - - const std::vector<JingleContentPayload::ref> getContents() const { - return getPayloads<JingleContentPayload>(); - } - - const std::vector<boost::shared_ptr<Payload> > getPayloads() const { - return payloads; - } - - template<typename T> - const std::vector<boost::shared_ptr<T> > getPayloads() const { - std::vector<boost::shared_ptr<T> > matched_payloads; - for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) { - boost::shared_ptr<T> result = boost::dynamic_pointer_cast<T>(*i); - if (result) { - matched_payloads.push_back(result); - } - } - - return matched_payloads; - - } - - template<typename T> - const boost::shared_ptr<T> getPayload() const { - boost::shared_ptr<T> result; - for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) { - result = boost::dynamic_pointer_cast<T>(*i); - if (result) { - return result; - } - } - - return result; - } - - void setReason(const Reason& reason) { - this->reason = reason; - } - - const boost::optional<Reason>& getReason() const { - return reason; - } - - private: - Action action; - JID initiator; - JID responder; - std::string sessionID; - std::vector<boost::shared_ptr<Payload> > payloads; - boost::optional<Reason> reason; - }; + class SWIFTEN_API JinglePayload : public Payload { + public: + typedef std::shared_ptr<JinglePayload> ref; + struct Reason : public Payload { + enum Type { + UnknownType, + AlternativeSession, + Busy, + Cancel, + ConnectivityError, + Decline, + Expired, + FailedApplication, + FailedTransport, + GeneralError, + Gone, + IncompatibleParameters, + MediaError, + SecurityError, + Success, + Timeout, + UnsupportedApplications, + UnsupportedTransports + }; + Reason() : type(UnknownType), text("") {} + Reason(Type type, const std::string& text = "") : type(type), text(text) {} + Type type; + std::string text; + }; + + enum Action { + UnknownAction, + ContentAccept, + ContentAdd, + ContentModify, + ContentReject, + ContentRemove, + DescriptionInfo, + SecurityInfo, + SessionAccept, + SessionInfo, + SessionInitiate, + SessionTerminate, + TransportAccept, + TransportInfo, + TransportReject, + TransportReplace + }; + JinglePayload() : action(SessionTerminate), sessionID("") { + } + + JinglePayload(Action action, const std::string& sessionID) : action(action), sessionID(sessionID) { + + } + + void setAction(Action action) { + this->action = action; + } + + Action getAction() const { + return action; + } + + void setInitiator(const JID& initiator) { + this->initiator = initiator; + } + + const JID& getInitiator() const { + return initiator; + } + + void setResponder(const JID& responder) { + this->responder = responder; + } + + const JID& getResponder() const { + return responder; + } + + void setSessionID(const std::string& id) { + sessionID = id; + } + + const std::string& getSessionID() const { + return sessionID; + } + + void addContent(JingleContentPayload::ref content) { + this->payloads.push_back(content); + } + + void addPayload(std::shared_ptr<Payload> payload) { + this->payloads.push_back(payload); + } + + const std::vector<JingleContentPayload::ref> getContents() const { + return getPayloads<JingleContentPayload>(); + } + + const std::vector<std::shared_ptr<Payload> > getPayloads() const { + return payloads; + } + + template<typename T> + const std::vector<std::shared_ptr<T> > getPayloads() const { + std::vector<std::shared_ptr<T> > matched_payloads; + for (const auto& payload : payloads) { + std::shared_ptr<T> result = std::dynamic_pointer_cast<T>(payload); + if (result) { + matched_payloads.push_back(result); + } + } + + return matched_payloads; + + } + + template<typename T> + const std::shared_ptr<T> getPayload() const { + std::shared_ptr<T> result; + for (const auto& payload : payloads) { + result = std::dynamic_pointer_cast<T>(payload); + if (result) { + return result; + } + } + + return result; + } + + void setReason(const Reason& reason) { + this->reason = reason; + } + + const boost::optional<Reason>& getReason() const { + return reason; + } + + private: + Action action; + JID initiator; + JID responder; + std::string sessionID; + std::vector<std::shared_ptr<Payload> > payloads; + boost::optional<Reason> reason; + }; } diff --git a/Swiften/Elements/JingleS5BTransportPayload.h b/Swiften/Elements/JingleS5BTransportPayload.h index 41bf809..5e16243 100644 --- a/Swiften/Elements/JingleS5BTransportPayload.h +++ b/Swiften/Elements/JingleS5BTransportPayload.h @@ -1,112 +1,120 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <vector> -#include <boost/shared_ptr.hpp> - -#include <Swiften/Elements/JingleTransportPayload.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Bytestreams.h> +#include <Swiften/Elements/JingleTransportPayload.h> #include <Swiften/Network/HostAddressPort.h> - namespace Swift { - class JingleS5BTransportPayload : public JingleTransportPayload { - public: - enum Mode { - TCPMode, // default case - UDPMode - }; - - struct Candidate { - enum Type { - DirectType, // default case - AssistedType, - TunnelType, - ProxyType - }; - - Candidate() : priority(0), type(DirectType) {} - - std::string cid; - JID jid; - HostAddressPort hostPort; - int priority; - Type type; - }; - - struct CompareCandidate { - bool operator() (const JingleS5BTransportPayload::Candidate& c1, const JingleS5BTransportPayload::Candidate& c2) const { - if (c1.priority < c2.priority) return true; - return false; - } - }; - - public: - JingleS5BTransportPayload() : mode(TCPMode), candidateError(false), proxyError(false) {} - - Mode getMode() const { - return mode; - } - - void setMode(Mode mode) { - this->mode = mode; - } - - const std::vector<Candidate>& getCandidates() const { - return candidates; - } - - void addCandidate(const Candidate& candidate) { - candidates.push_back(candidate); - } - - void setCandidateUsed(const std::string& cid) { - candidateUsedCID = cid; - } - - const std::string& getCandidateUsed() const { - return candidateUsedCID; - } - - void setActivated(const std::string& cid) { - activatedCID = cid; - } - - const std::string& getActivated() const { - return activatedCID; - } - - void setCandidateError(bool hasError) { - candidateError = hasError; - } - - bool hasCandidateError() const { - return candidateError; - } - - void setProxyError(bool hasError) { - proxyError = hasError; - } - - bool hasProxyError() const { - return proxyError; - } - public: - typedef boost::shared_ptr<JingleS5BTransportPayload> ref; - - private: - Mode mode; - std::vector<Candidate> candidates; - - std::string candidateUsedCID; - std::string activatedCID; - bool candidateError; - bool proxyError; - }; + class SWIFTEN_API JingleS5BTransportPayload : public JingleTransportPayload { + public: + enum Mode { + TCPMode, // default case + UDPMode + }; + + struct Candidate { + enum Type { + DirectType, // default case + AssistedType, + TunnelType, + ProxyType + }; + + Candidate() : priority(0), type(DirectType) {} + + std::string cid; + JID jid; + HostAddressPort hostPort; + int priority; + Type type; + }; + + struct CompareCandidate { + bool operator() (const JingleS5BTransportPayload::Candidate& c1, const JingleS5BTransportPayload::Candidate& c2) const { + if (c1.priority < c2.priority) return true; + return false; + } + }; + + public: + JingleS5BTransportPayload() : mode(TCPMode), candidateError(false), proxyError(false) {} + + Mode getMode() const { + return mode; + } + + void setMode(Mode mode) { + this->mode = mode; + } + + const std::vector<Candidate>& getCandidates() const { + return candidates; + } + + void addCandidate(const Candidate& candidate) { + candidates.push_back(candidate); + } + + void setCandidateUsed(const std::string& cid) { + candidateUsedCID = cid; + } + + const std::string& getCandidateUsed() const { + return candidateUsedCID; + } + + void setActivated(const std::string& cid) { + activatedCID = cid; + } + + const std::string& getActivated() const { + return activatedCID; + } + + void setDstAddr(const std::string& addr) { + dstAddr = addr; + } + + const std::string& getDstAddr() const { + return dstAddr; + } + + void setCandidateError(bool hasError) { + candidateError = hasError; + } + + bool hasCandidateError() const { + return candidateError; + } + + void setProxyError(bool hasError) { + proxyError = hasError; + } + + bool hasProxyError() const { + return proxyError; + } + public: + typedef std::shared_ptr<JingleS5BTransportPayload> ref; + + private: + Mode mode; + std::vector<Candidate> candidates; + + std::string candidateUsedCID; + std::string activatedCID; + std::string dstAddr; + bool candidateError; + bool proxyError; + }; } diff --git a/Swiften/Elements/JingleTransportPayload.h b/Swiften/Elements/JingleTransportPayload.h index b870be9..dfd9d22 100644 --- a/Swiften/Elements/JingleTransportPayload.h +++ b/Swiften/Elements/JingleTransportPayload.h @@ -1,30 +1,32 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class JingleTransportPayload : public Payload { - public: - void setSessionID(const std::string& id) { - sessionID = id; - } + class SWIFTEN_API JingleTransportPayload : public Payload { + public: + void setSessionID(const std::string& id) { + sessionID = id; + } - const std::string& getSessionID() const { - return sessionID; - } + const std::string& getSessionID() const { + return sessionID; + } - public: - typedef boost::shared_ptr<JingleTransportPayload> ref; + public: + typedef std::shared_ptr<JingleTransportPayload> ref; - private: - std::string sessionID; - }; + private: + std::string sessionID; + }; } diff --git a/Swiften/Elements/Last.h b/Swiften/Elements/Last.h index cb7e0c6..869dab4 100644 --- a/Swiften/Elements/Last.h +++ b/Swiften/Elements/Last.h @@ -1,22 +1,23 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class Last : public Payload { - public: - Last(int seconds = 0) : seconds_(seconds) {} + class SWIFTEN_API Last : public Payload { + public: + Last(int seconds = 0) : seconds_(seconds) {} - int getSeconds() const {return seconds_;} - void setSeconds(int seconds) {seconds_ = seconds;} + int getSeconds() const {return seconds_;} + void setSeconds(int seconds) {seconds_ = seconds;} - private: - int seconds_; - }; + private: + int seconds_; + }; } diff --git a/Swiften/Elements/MAMFin.cpp b/Swiften/Elements/MAMFin.cpp new file mode 100644 index 0000000..24e7aa3 --- /dev/null +++ b/Swiften/Elements/MAMFin.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/MAMFin.h> + +namespace Swift { + +MAMFin::~MAMFin() { +} + +} diff --git a/Swiften/Elements/MAMFin.h b/Swiften/Elements/MAMFin.h new file mode 100644 index 0000000..e5e719b --- /dev/null +++ b/Swiften/Elements/MAMFin.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/Elements/ResultSet.h> + +namespace Swift { + class SWIFTEN_API MAMFin : public Payload { + public: + MAMFin() : isComplete_(false), isStable_(true) {} + virtual ~MAMFin(); + + void setComplete(const bool isComplete) { + isComplete_ = isComplete; + } + + bool isComplete() const { + return isComplete_; + } + + void setStable(const bool isStable) { + isStable_ = isStable; + } + + bool isStable() const { + return isStable_; + } + + void setResultSet(std::shared_ptr<ResultSet> resultSet) { + resultSet_ = resultSet; + } + + std::shared_ptr<ResultSet> getResultSet() const { + return resultSet_; + } + + void setQueryID(const std::string& queryID) { + queryID_ = queryID; + } + + const boost::optional<std::string>& getQueryID() const { + return queryID_; + } + + + private: + bool isComplete_; + bool isStable_; + std::shared_ptr<ResultSet> resultSet_; + boost::optional<std::string> queryID_; + }; +} diff --git a/Swiften/Elements/MAMQuery.cpp b/Swiften/Elements/MAMQuery.cpp new file mode 100644 index 0000000..abd4280 --- /dev/null +++ b/Swiften/Elements/MAMQuery.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file 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..764c238 --- /dev/null +++ b/Swiften/Elements/MAMQuery.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Form.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 setNode(const boost::optional<std::string>& node) { node_ = node; } + const boost::optional<std::string>& getNode() const { return node_; } + + void setForm(std::shared_ptr<Form> form) { form_ = form; } + const std::shared_ptr<Form>& getForm() const { return form_; } + + void setResultSet(std::shared_ptr<ResultSet> resultSet) { resultSet_ = resultSet; } + const std::shared_ptr<ResultSet>& getResultSet() const { return resultSet_; } + + private: + boost::optional<std::string> queryID_; + boost::optional<std::string> node_; + std::shared_ptr<Form> form_; + std::shared_ptr<ResultSet> resultSet_; + }; +} diff --git a/Swiften/Elements/MAMResult.cpp b/Swiften/Elements/MAMResult.cpp new file mode 100644 index 0000000..68048ac --- /dev/null +++ b/Swiften/Elements/MAMResult.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file 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..88ec8f0 --- /dev/null +++ b/Swiften/Elements/MAMResult.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#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/MIXCreate.h b/Swiften/Elements/MIXCreate.h new file mode 100644 index 0000000..0fab463 --- /dev/null +++ b/Swiften/Elements/MIXCreate.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API MIXCreate : public Payload { + public: + using ref = std::shared_ptr<MIXCreate>; + + public: + + MIXCreate() {} + + std::shared_ptr<Form> getData() const { + return data_; + } + + void setData(std::shared_ptr<Form> value) { + this->data_ = value ; + } + + const boost::optional<std::string>& getChannel() const { + return channel_; + } + + void setChannel(const std::string& channel) { + this->channel_ = channel; + } + + private: + boost::optional<std::string> channel_; + std::shared_ptr<Form> data_; + }; +} diff --git a/Swiften/Elements/MIXDestroy.h b/Swiften/Elements/MIXDestroy.h new file mode 100644 index 0000000..a674638 --- /dev/null +++ b/Swiften/Elements/MIXDestroy.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API MIXDestroy : public Payload { + public: + using ref = std::shared_ptr<MIXDestroy>; + + public: + MIXDestroy() {} + virtual ~MIXDestroy() {} + + const std::string& getChannel() const { + return channel_; + } + + void setChannel(const std::string& channel) { + this->channel_ = channel; + } + + private: + std::string channel_; + }; +} diff --git a/Swiften/Elements/MIXJoin.h b/Swiften/Elements/MIXJoin.h new file mode 100644 index 0000000..ecd7b12 --- /dev/null +++ b/Swiften/Elements/MIXJoin.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> +#include <string> +#include <unordered_set> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/Elements/Form.h> +#include <Swiften/JID/JID.h> + +namespace Swift { + class SWIFTEN_API MIXJoin : public Payload { + + public: + using ref = std::shared_ptr<MIXJoin>; + + public: + + MIXJoin() {} + + const boost::optional<JID>& getChannel() const { + return channel_; + } + + void setChannel(JID channel) { + channel_ = channel; + } + + const boost::optional<JID>& getJID() const { + return jid_; + } + + void setJID(JID jid) { + jid_ = jid; + } + + const std::unordered_set<std::string>& getSubscriptions() const { + return subscribeItems_; + } + + void setSubscriptions(std::unordered_set<std::string> values) { + subscribeItems_ = values ; + } + + void addSubscription(std::string value) { + subscribeItems_.insert(value); + } + + bool hasSubscription(const std::string& value) const { + return std::find(subscribeItems_.begin(), subscribeItems_.end(), value) != subscribeItems_.end(); + } + + void setForm(std::shared_ptr<Form> form) { + form_ = form; + } + + const std::shared_ptr<Form>& getForm() const { + return form_; + } + + private: + boost::optional<JID> jid_; + boost::optional<JID> channel_; + std::unordered_set<std::string> subscribeItems_; + std::shared_ptr<Form> form_; + // FIXME: MIXInvitation to be implemented. boost::optional<MIXInvitation> invitation_; + }; +} diff --git a/Swiften/Elements/MIXLeave.h b/Swiften/Elements/MIXLeave.h new file mode 100644 index 0000000..76ca09d --- /dev/null +++ b/Swiften/Elements/MIXLeave.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API MIXLeave : public Payload { + public: + using ref = std::shared_ptr<MIXLeave>; + + public: + + MIXLeave() {} + + const boost::optional<JID>& getChannel() const { + return channel_; + } + + void setChannel(const JID& channel) { + channel_ = channel; + } + + private: + boost::optional<JID> channel_; + }; +} diff --git a/Swiften/Elements/MIXParticipant.h b/Swiften/Elements/MIXParticipant.h new file mode 100644 index 0000000..22133b8 --- /dev/null +++ b/Swiften/Elements/MIXParticipant.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> + +namespace Swift { + class SWIFTEN_API MIXParticipant : public Payload { + public: + using ref = std::shared_ptr<MIXParticipant>; + + public: + + MIXParticipant() {} + + const boost::optional<std::string>& getNick() const { + return nick_; + } + + void setNick(const std::string& nick) { + nick_ = nick; + } + + const boost::optional<JID>& getJID() const { + return jid_; + } + + void setJID(const JID& jid) { + jid_ = jid; + } + + private: + boost::optional<JID> jid_; + boost::optional<std::string> nick_; + }; +} diff --git a/Swiften/Elements/MIXPayload.h b/Swiften/Elements/MIXPayload.h new file mode 100644 index 0000000..3989c18 --- /dev/null +++ b/Swiften/Elements/MIXPayload.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> + +namespace Swift { + class SWIFTEN_API MIXPayload : public Payload { + public: + using ref = std::shared_ptr<MIXPayload>; + + public: + + MIXPayload() {} + + const boost::optional<std::string>& getNick() const { + return nick_; + } + + void setNick(const std::string& nick) { + nick_ = nick; + } + + const boost::optional<JID>& getJID() const { + return jid_; + } + + void setJID(const JID& jid) { + jid_ = jid; + } + + const boost::optional<std::string>& getSubmissionID() const { + return submissionId_; + } + + void setSubmissionID(const std::string& submissionId) { + submissionId_ = submissionId; + } + + private: + boost::optional<JID> jid_; + boost::optional<std::string> nick_; + boost::optional<std::string> submissionId_; + }; +} diff --git a/Swiften/Elements/MIXRegisterNick.h b/Swiften/Elements/MIXRegisterNick.h new file mode 100644 index 0000000..3bd8c4a --- /dev/null +++ b/Swiften/Elements/MIXRegisterNick.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API MIXRegisterNick : public Payload { + public: + using ref = std::shared_ptr<MIXRegisterNick>; + + public: + + MIXRegisterNick() {} + + const std::string& getNick() const { + return nick_; + } + + void setNick(const std::string& nick) { + nick_ = nick; + } + + private: + std::string nick_; + }; +} diff --git a/Swiften/Elements/MIXSetNick.h b/Swiften/Elements/MIXSetNick.h new file mode 100644 index 0000000..94c5a3b --- /dev/null +++ b/Swiften/Elements/MIXSetNick.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API MIXSetNick : public Payload { + public: + using ref = std::shared_ptr<MIXSetNick>; + + public: + + MIXSetNick() {} + + const std::string& getNick() const { + return nick_; + } + + void setNick(const std::string& nick) { + nick_ = nick; + } + + private: + std::string nick_; + }; +} diff --git a/Swiften/Elements/MIXUpdateSubscription.h b/Swiften/Elements/MIXUpdateSubscription.h new file mode 100644 index 0000000..dc6ed27 --- /dev/null +++ b/Swiften/Elements/MIXUpdateSubscription.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> +#include <unordered_set> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> + +namespace Swift { + class SWIFTEN_API MIXUpdateSubscription : public Payload { + + public: + using ref = std::shared_ptr<MIXUpdateSubscription>; + + public: + + MIXUpdateSubscription() {} + + const boost::optional<JID>& getJID() const { + return jid_; + } + + void setJID(JID jid) { + jid_ = jid; + } + + const std::unordered_set<std::string>& getSubscriptions() const { + return subscribeItems_; + } + + void setSubscriptions(std::unordered_set<std::string> values) { + subscribeItems_ = values ; + } + + void addSubscription(std::string value) { + subscribeItems_.insert(value); + } + + bool hasSubscription(const std::string& value) const { + return std::find(subscribeItems_.begin(), subscribeItems_.end(), value) != subscribeItems_.end(); + } + + private: + boost::optional<JID> jid_; + std::unordered_set<std::string> subscribeItems_; + }; +} diff --git a/Swiften/Elements/MIXUserPreference.h b/Swiften/Elements/MIXUserPreference.h new file mode 100644 index 0000000..cd1311c --- /dev/null +++ b/Swiften/Elements/MIXUserPreference.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API MIXUserPreference : public Payload { + public: + using ref = std::shared_ptr<MIXUserPreference>; + + public: + + MIXUserPreference() {} + + std::shared_ptr<Form> getData() const { + return data_; + } + + void setData(std::shared_ptr<Form> value) { + this->data_ = value ; + } + + + private: + std::shared_ptr<Form> data_; + }; +} diff --git a/Swiften/Elements/MUCAdminPayload.h b/Swiften/Elements/MUCAdminPayload.h index dc09a24..3f78cc8 100644 --- a/Swiften/Elements/MUCAdminPayload.h +++ b/Swiften/Elements/MUCAdminPayload.h @@ -1,35 +1,37 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> #include <vector> -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/Payload.h> -#include <Swiften/Elements/MUCOccupant.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCItem.h> +#include <Swiften/Elements/MUCOccupant.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class MUCAdminPayload : public Payload { - public: - typedef boost::shared_ptr<MUCAdminPayload> ref; + class SWIFTEN_API MUCAdminPayload : public Payload { + public: + typedef std::shared_ptr<MUCAdminPayload> ref; - MUCAdminPayload() { - } + MUCAdminPayload() { + } - void addItem(const MUCItem& item) {items_.push_back(item);} + void addItem(const MUCItem& item) {items_.push_back(item);} - const std::vector<MUCItem>& getItems() const {return items_;} + const std::vector<MUCItem>& getItems() const {return items_;} - private: - std::vector<MUCItem> items_; - }; + private: + std::vector<MUCItem> items_; + }; } diff --git a/Swiften/Elements/MUCDestroyPayload.h b/Swiften/Elements/MUCDestroyPayload.h index f743ad0..ad1bda2 100644 --- a/Swiften/Elements/MUCDestroyPayload.h +++ b/Swiften/Elements/MUCDestroyPayload.h @@ -1,42 +1,43 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> #include <Swiften/JID/JID.h> namespace Swift { - class MUCDestroyPayload : public Payload { - public: - typedef boost::shared_ptr<MUCDestroyPayload> ref; + class SWIFTEN_API MUCDestroyPayload : public Payload { + public: + typedef std::shared_ptr<MUCDestroyPayload> ref; - MUCDestroyPayload() { - } + MUCDestroyPayload() { + } - void setNewVenue(const JID& jid) { - newVenue_ = jid; - } + void setNewVenue(const JID& jid) { + newVenue_ = jid; + } - const JID& getNewVenue() const { - return newVenue_; - } + const JID& getNewVenue() const { + return newVenue_; + } - void setReason(const std::string& reason) { - reason_ = reason; - } + void setReason(const std::string& reason) { + reason_ = reason; + } - const std::string& getReason() const { - return reason_; - } + const std::string& getReason() const { + return reason_; + } - private: - JID newVenue_; - std::string reason_; - }; + private: + JID newVenue_; + std::string reason_; + }; } diff --git a/Swiften/Elements/MUCInvitationPayload.h b/Swiften/Elements/MUCInvitationPayload.h index 290c585..545e60f 100644 --- a/Swiften/Elements/MUCInvitationPayload.h +++ b/Swiften/Elements/MUCInvitationPayload.h @@ -1,77 +1,78 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> #include <Swiften/JID/JID.h> namespace Swift { - class MUCInvitationPayload : public Payload { - public: - typedef boost::shared_ptr<MUCInvitationPayload> ref; - MUCInvitationPayload() : continuation_(false), impromptu_(false) { - } - - void setIsContinuation(bool b) { - continuation_ = b; - } - - bool getIsContinuation() const { - return continuation_; - } - - void setIsImpromptu(bool b) { - impromptu_ = b; - } - - bool getIsImpromptu() const { - return impromptu_; - } - - void setJID(const JID& jid) { - jid_ = jid; - } - - const JID& getJID() const { - return jid_; - } - - void setPassword(const std::string& password) { - password_ = password; - } - - const std::string& getPassword() const { - return password_; - } - - void setReason(const std::string& text) { - reason_ = text; - } - - const std::string& getReason() const { - return reason_; - } - - void setThread(const std::string& thread) { - thread_ = thread; - } - - const std::string& getThread() const { - return thread_; - } - - private: - bool continuation_; - bool impromptu_; - JID jid_; - std::string password_; - std::string reason_; - std::string thread_; - }; + class SWIFTEN_API MUCInvitationPayload : public Payload { + public: + typedef std::shared_ptr<MUCInvitationPayload> ref; + MUCInvitationPayload() : continuation_(false), impromptu_(false) { + } + + void setIsContinuation(bool b) { + continuation_ = b; + } + + bool getIsContinuation() const { + return continuation_; + } + + void setIsImpromptu(bool b) { + impromptu_ = b; + } + + bool getIsImpromptu() const { + return impromptu_; + } + + void setJID(const JID& jid) { + jid_ = jid; + } + + const JID& getJID() const { + return jid_; + } + + void setPassword(const std::string& password) { + password_ = password; + } + + const std::string& getPassword() const { + return password_; + } + + void setReason(const std::string& text) { + reason_ = text; + } + + const std::string& getReason() const { + return reason_; + } + + void setThread(const std::string& thread) { + thread_ = thread; + } + + const std::string& getThread() const { + return thread_; + } + + private: + bool continuation_; + bool impromptu_; + JID jid_; + std::string password_; + std::string reason_; + std::string thread_; + }; } diff --git a/Swiften/Elements/MUCItem.h b/Swiften/Elements/MUCItem.h index 86217ec..3c89e68 100644 --- a/Swiften/Elements/MUCItem.h +++ b/Swiften/Elements/MUCItem.h @@ -1,21 +1,24 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Elements/MUCOccupant.h> #include <Swiften/JID/JID.h> + namespace Swift { struct MUCItem { - MUCItem() {} - boost::optional<JID> realJID; - boost::optional<std::string> nick; - boost::optional<MUCOccupant::Affiliation> affiliation; - boost::optional<MUCOccupant::Role> role; - boost::optional<JID> actor; - boost::optional<std::string> reason; + MUCItem() {} + MUCItem(MUCOccupant::Affiliation affiliation, const JID& jid, MUCOccupant::Role role) : realJID(jid), affiliation(affiliation), role(role) {} + MUCItem(MUCOccupant::Affiliation affiliation, MUCOccupant::Role role) : affiliation(affiliation), role(role) {} + boost::optional<JID> realJID; + boost::optional<std::string> nick; + boost::optional<MUCOccupant::Affiliation> affiliation; + boost::optional<MUCOccupant::Role> role; + boost::optional<JID> actor; + boost::optional<std::string> reason; }; } diff --git a/Swiften/Elements/MUCOccupant.cpp b/Swiften/Elements/MUCOccupant.cpp index 57034ad..65fb8c2 100644 --- a/Swiften/Elements/MUCOccupant.cpp +++ b/Swiften/Elements/MUCOccupant.cpp @@ -1,11 +1,13 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/MUCOccupant.h> +#include <utility> + namespace Swift { MUCOccupant::MUCOccupant(const std::string &nick, Role role, Affiliation affiliation) : nick_(nick), role_(role), affiliation_(affiliation) { @@ -18,29 +20,37 @@ MUCOccupant::MUCOccupant(const MUCOccupant& other) : nick_(other.getNick()), rol } +MUCOccupant& MUCOccupant::operator=(MUCOccupant other) { + std::swap(nick_, other.nick_); + std::swap(role_, other.role_); + std::swap(affiliation_, other.affiliation_); + std::swap(realJID_, other.realJID_); + return *this; +} + std::string MUCOccupant::getNick() const { - return nick_; + return nick_; } MUCOccupant::Role MUCOccupant::getRole() const { - return role_; + return role_; } MUCOccupant::Affiliation MUCOccupant::getAffiliation() const { - return affiliation_; + return affiliation_; } void MUCOccupant::setRealJID(const JID& realJID) { - realJID_ = realJID; + realJID_ = realJID; } void MUCOccupant::setNick(const std::string& nick) { - nick_ = nick; + nick_ = nick; } boost::optional<JID> MUCOccupant::getRealJID() const { - return realJID_; + return realJID_; } } diff --git a/Swiften/Elements/MUCOccupant.h b/Swiften/Elements/MUCOccupant.h index 023643c..260502e 100644 --- a/Swiften/Elements/MUCOccupant.h +++ b/Swiften/Elements/MUCOccupant.h @@ -1,42 +1,43 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/optional.hpp> #include <string> +#include <boost/optional.hpp> + #include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> namespace Swift { - class Client; - - class SWIFTEN_API MUCOccupant { - public: - enum Role {Moderator, Participant, Visitor, NoRole}; - enum Affiliation {Owner, Admin, Member, Outcast, NoAffiliation}; - - MUCOccupant(const std::string &nick, Role role, Affiliation affiliation); - MUCOccupant(const MUCOccupant& other); - ~MUCOccupant(); - - std::string getNick() const; - Role getRole() const; - Affiliation getAffiliation() const; - boost::optional<JID> getRealJID() const; - void setRealJID(const JID& jid); - void setNick(const std::string& nick); - - private: - std::string nick_; - Role role_; - Affiliation affiliation_; - boost::optional<JID> realJID_; - /* If you add a field, remember to update the const copy constructor */ - }; + class SWIFTEN_API MUCOccupant { + public: + enum Role {Moderator, Participant, Visitor, NoRole}; + enum Affiliation {Owner, Admin, Member, Outcast, NoAffiliation}; + + MUCOccupant(const std::string &nick, Role role, Affiliation affiliation); + MUCOccupant(const MUCOccupant& other); + ~MUCOccupant(); + + MUCOccupant& operator=(MUCOccupant other); + + std::string getNick() const; + Role getRole() const; + Affiliation getAffiliation() const; + boost::optional<JID> getRealJID() const; + void setRealJID(const JID& jid); + void setNick(const std::string& nick); + + private: + std::string nick_; + Role role_; + Affiliation affiliation_; + boost::optional<JID> realJID_; + /* If you add a field, remember to update the const copy constructor */ + }; } diff --git a/Swiften/Elements/MUCOwnerPayload.h b/Swiften/Elements/MUCOwnerPayload.h index 5ccc755..5f3c633 100644 --- a/Swiften/Elements/MUCOwnerPayload.h +++ b/Swiften/Elements/MUCOwnerPayload.h @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> -#include <Swiften/Elements/Payload.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Payload.h> namespace Swift { - class MUCOwnerPayload : public Payload { - public: - typedef boost::shared_ptr<MUCOwnerPayload> ref; + class SWIFTEN_API MUCOwnerPayload : public Payload { + public: + typedef std::shared_ptr<MUCOwnerPayload> ref; - MUCOwnerPayload() { - } + MUCOwnerPayload() { + } - boost::shared_ptr<Payload> getPayload() const { - return payload; - } + std::shared_ptr<Payload> getPayload() const { + return payload; + } - void setPayload(boost::shared_ptr<Payload> p) { - payload = p; - } + void setPayload(std::shared_ptr<Payload> p) { + payload = p; + } - Form::ref getForm() { - return boost::dynamic_pointer_cast<Form>(payload); - } + Form::ref getForm() { + return std::dynamic_pointer_cast<Form>(payload); + } - private: - boost::shared_ptr<Payload> payload; - }; + private: + std::shared_ptr<Payload> payload; + }; } diff --git a/Swiften/Elements/MUCPayload.h b/Swiften/Elements/MUCPayload.h index 29cab8d..6e199e5 100644 --- a/Swiften/Elements/MUCPayload.h +++ b/Swiften/Elements/MUCPayload.h @@ -1,74 +1,76 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/optional.hpp> +#include <string> + #include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/optional.hpp> -#include <Swiften/JID/JID.h> -#include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class MUCPayload : public Payload { - public: - typedef boost::shared_ptr<MUCPayload> ref; - - MUCPayload() { - maxChars_ = -1; - maxStanzas_ = -1; - seconds_ = -1; - } - - void setMaxChars(int maxChars) { - maxChars_ = maxChars; - } - - void setMaxStanzas(int maxStanzas) { - maxStanzas_ = maxStanzas; - } - - void setSeconds(int seconds) { - seconds_ = seconds; - } - - void setSince(boost::posix_time::ptime since) { - since_ = since; - } - - void setPassword(const std::string& password) { - password_ = password; - } - - int getMaxChars() const{ - return maxChars_; - } - - int getMaxStanzas() const{ - return maxStanzas_; - } - - int getSeconds() const { - return seconds_; - } - - const boost::optional<std::string>& getPassword() const { - return password_; - } - - const boost::posix_time::ptime& getSince() const { - return since_; - } - - private: - int maxChars_; - int maxStanzas_; - int seconds_; - boost::posix_time::ptime since_; - boost::optional<std::string> password_; - }; + class SWIFTEN_API MUCPayload : public Payload { + public: + typedef std::shared_ptr<MUCPayload> ref; + + MUCPayload() { + maxChars_ = -1; + maxStanzas_ = -1; + seconds_ = -1; + } + + void setMaxChars(int maxChars) { + maxChars_ = maxChars; + } + + void setMaxStanzas(int maxStanzas) { + maxStanzas_ = maxStanzas; + } + + void setSeconds(int seconds) { + seconds_ = seconds; + } + + void setSince(boost::posix_time::ptime since) { + since_ = since; + } + + void setPassword(const std::string& password) { + password_ = password; + } + + int getMaxChars() const{ + return maxChars_; + } + + int getMaxStanzas() const{ + return maxStanzas_; + } + + int getSeconds() const { + return seconds_; + } + + const boost::optional<std::string>& getPassword() const { + return password_; + } + + const boost::posix_time::ptime& getSince() const { + return since_; + } + + private: + int maxChars_; + int maxStanzas_; + int seconds_; + boost::posix_time::ptime since_; + boost::optional<std::string> password_; + }; } diff --git a/Swiften/Elements/MUCUserPayload.h b/Swiften/Elements/MUCUserPayload.h index fcb585e..dd57376 100644 --- a/Swiften/Elements/MUCUserPayload.h +++ b/Swiften/Elements/MUCUserPayload.h @@ -1,95 +1,97 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> #include <vector> -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/Payload.h> -#include <Swiften/Elements/MUCOccupant.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCItem.h> +#include <Swiften/Elements/MUCOccupant.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class MUCUserPayload : public Payload { - public: - typedef boost::shared_ptr<MUCUserPayload> ref; + class SWIFTEN_API MUCUserPayload : public Payload { + public: + typedef std::shared_ptr<MUCUserPayload> ref; + + struct StatusCode { + StatusCode() : code(0) {} + StatusCode(int code) : code(code) {} + int code; + }; - struct StatusCode { - StatusCode() : code(0) {} - StatusCode(int code) : code(code) {} - int code; - }; + //struct Password { - //struct Password { + //} - //} + // struct History { - // struct History { + // } - // } + /** + * reason is optional. + * from and to are mutually exclusive. + * From is used for MUC sending to invited client. To is used sending to MUC from inviting client. + * from is the JID the MUC claims the invite is from. + * to is the JID to send the invite to. + */ + struct Invite { + std::string reason; + JID from; + JID to; + }; - /** - * reason is optional. - * from and to are mutually exclusive. - * From is used for MUC sending to invited client. To is used sending to MUC from inviting client. - * from is the JID the MUC claims the invite is from. - * to is the JID to send the invite to. - */ - struct Invite { - std::string reason; - JID from; - JID to; - }; + MUCUserPayload() { + } - MUCUserPayload() { - } + void addItem(const MUCItem& item) {items_.push_back(item);} - void addItem(const MUCItem& item) {items_.push_back(item);} - - void addStatusCode(StatusCode code) {statusCodes_.push_back(code);} + void addStatusCode(StatusCode code) {statusCodes_.push_back(code);} - const std::vector<MUCItem>& getItems() const {return items_;} + const std::vector<MUCItem>& getItems() const {return items_;} - const std::vector<StatusCode>& getStatusCodes() const {return statusCodes_;} + const std::vector<StatusCode>& getStatusCodes() const {return statusCodes_;} - boost::shared_ptr<Payload> getPayload() const { - return payload_; - } + std::shared_ptr<Payload> getPayload() const { + return payload_; + } - void setPayload(boost::shared_ptr<Payload> p) { - payload_ = p; - } + void setPayload(std::shared_ptr<Payload> p) { + payload_ = p; + } - const boost::optional<std::string>& getPassword() const { - return password_; - } + const boost::optional<std::string>& getPassword() const { + return password_; + } - void setPassword(const std::string& password) { - password_ = password; - } + void setPassword(const std::string& password) { + password_ = password; + } - const boost::optional<Invite>& getInvite() const { - return invite_; - } + const boost::optional<Invite>& getInvite() const { + return invite_; + } - void setInvite(const Invite& invite) { - invite_ = invite; - } + void setInvite(const Invite& invite) { + invite_ = invite; + } - private: - std::vector<MUCItem> items_; - std::vector<StatusCode> statusCodes_; - boost::shared_ptr<Payload> payload_; - boost::optional<std::string> password_; - boost::optional<Invite> invite_; - }; + private: + std::vector<MUCItem> items_; + std::vector<StatusCode> statusCodes_; + std::shared_ptr<Payload> payload_; + boost::optional<std::string> password_; + boost::optional<Invite> invite_; + }; } diff --git a/Swiften/Elements/Message.h b/Swiften/Elements/Message.h index ea99814..c357cd4 100644 --- a/Swiften/Elements/Message.h +++ b/Swiften/Elements/Message.h @@ -1,70 +1,79 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> +#include <string> + #include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Body.h> -#include <Swiften/Elements/Subject.h> #include <Swiften/Elements/ErrorPayload.h> -#include <Swiften/Elements/Stanza.h> #include <Swiften/Elements/Replace.h> +#include <Swiften/Elements/Stanza.h> +#include <Swiften/Elements/Subject.h> namespace Swift { - class Message : public Stanza { - public: - typedef boost::shared_ptr<Message> ref; - - enum Type { Normal, Chat, Error, Groupchat, Headline }; - - Message() : type_(Chat) { } - - std::string getSubject() const { - boost::shared_ptr<Subject> subject(getPayload<Subject>()); - if (subject) { - return subject->getText(); - } - return ""; - } - - void setSubject(const std::string& subject) { - updatePayload(boost::make_shared<Subject>(subject)); - } - - // Explicitly convert to bool. In C++11, it would be cleaner to - // compare to nullptr. - bool hasSubject() { - return static_cast<bool>(getPayload<Subject>()); - } - - std::string getBody() const { - boost::shared_ptr<Body> body(getPayload<Body>()); - if (body) { - return body->getText(); - } - return ""; - } - - void setBody(const std::string& body) { - updatePayload(boost::make_shared<Body>(body)); - } - - bool isError() { - boost::shared_ptr<Swift::ErrorPayload> error(getPayload<Swift::ErrorPayload>()); - return getType() == Message::Error || error; - } - - Type getType() const { return type_; } - void setType(Type type) { type_ = type; } - - private: - Type type_; - }; + class SWIFTEN_API Message : public Stanza { + public: + typedef std::shared_ptr<Message> ref; + + enum Type { Normal, Chat, Error, Groupchat, Headline }; + + Message() : type_(Chat) { } + + std::string getSubject() const { + std::shared_ptr<Subject> subject(getPayload<Subject>()); + if (subject) { + return subject->getText(); + } + return ""; + } + + void setSubject(const std::string& subject) { + updatePayload(std::make_shared<Subject>(subject)); + } + + bool hasSubject() { + return getPayload<Subject>() != nullptr; + } + + boost::optional<std::string> getBody() const { + std::shared_ptr<Body> body(getPayload<Body>()); + boost::optional<std::string> bodyData; + if (body) { + bodyData = body->getText(); + } + return bodyData; + } + + void setBody(const std::string& body) { + setBody(boost::optional<std::string>(body)); + } + + void setBody(const boost::optional<std::string>& body) { + if (body) { + updatePayload(std::make_shared<Body>(body.get())); + } + else { + removePayloadOfSameType(std::make_shared<Body>()); + } + } + + bool isError() { + std::shared_ptr<Swift::ErrorPayload> error(getPayload<Swift::ErrorPayload>()); + return getType() == Message::Error || error; + } + + Type getType() const { return type_; } + void setType(Type type) { type_ = type; } + + private: + Type type_; + }; } diff --git a/Swiften/Elements/Nickname.h b/Swiften/Elements/Nickname.h index a244ce3..123c156 100644 --- a/Swiften/Elements/Nickname.h +++ b/Swiften/Elements/Nickname.h @@ -1,29 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Payload.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + namespace Swift { - class Nickname : public Payload { - public: - Nickname(const std::string& nickname = "") : nickname(nickname) { - } + class SWIFTEN_API Nickname : public Payload { + public: + Nickname(const std::string& nickname = "") : nickname(nickname) { + } - void setNickname(const std::string& nickname) { - this->nickname = nickname; - } + void setNickname(const std::string& nickname) { + this->nickname = nickname; + } - const std::string& getNickname() const { - return nickname; - } + const std::string& getNickname() const { + return nickname; + } - private: - std::string nickname; - }; + private: + std::string nickname; + }; } diff --git a/Swiften/Elements/Payload.cpp b/Swiften/Elements/Payload.cpp index b7c3ffe..6d8a263 100644 --- a/Swiften/Elements/Payload.cpp +++ b/Swiften/Elements/Payload.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/Payload.h> diff --git a/Swiften/Elements/Payload.h b/Swiften/Elements/Payload.h index 15a72d5..9923f0b 100644 --- a/Swiften/Elements/Payload.h +++ b/Swiften/Elements/Payload.h @@ -1,20 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> +#include <Swiften/Elements/Element.h> namespace Swift { - class SWIFTEN_API Payload { - public: - typedef boost::shared_ptr<Payload> ref; - public: - virtual ~Payload(); - }; + class SWIFTEN_API Payload : public Element { + public: + typedef std::shared_ptr<Payload> ref; + public: + Payload() {} + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(Payload) + virtual ~Payload(); + + SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(Payload) + }; } diff --git a/Swiften/Elements/Presence.cpp b/Swiften/Elements/Presence.cpp index 38b8a4c..f75f3be 100644 --- a/Swiften/Elements/Presence.cpp +++ b/Swiften/Elements/Presence.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/Presence.h> @@ -15,32 +15,31 @@ Presence::Presence() : type_(Available) /*, showType_(Online)*/ { } Presence::Presence(const std::string& status) : type_(Available) { - setStatus(status); + setStatus(status); } Presence::~Presence() { } int Presence::getPriority() const { - boost::shared_ptr<Priority> priority(getPayload<Priority>()); - return (priority ? priority->getPriority() : 0); + std::shared_ptr<Priority> priority(getPayload<Priority>()); + return (priority ? priority->getPriority() : 0); } void Presence::setPriority(int priority) { - updatePayload(boost::make_shared<Priority>(priority)); + updatePayload(std::make_shared<Priority>(priority)); } -std::string Presence::getStatus() const { - boost::shared_ptr<Status> status(getPayload<Status>()); - if (status) { - return status->getText(); - } - return ""; +std::string Presence::getStatus() const { + std::shared_ptr<Status> status(getPayload<Status>()); + if (status) { + return status->getText(); + } + return ""; } -void Presence::setStatus(const std::string& status) { - updatePayload(boost::make_shared<Status>(status)); +void Presence::setStatus(const std::string& status) { + updatePayload(std::make_shared<Status>(status)); } - } diff --git a/Swiften/Elements/Presence.h b/Swiften/Elements/Presence.h index 2e9e224..e658606 100644 --- a/Swiften/Elements/Presence.h +++ b/Swiften/Elements/Presence.h @@ -1,70 +1,71 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Elements/Stanza.h> #include <Swiften/Elements/StatusShow.h> namespace Swift { - class SWIFTEN_API Presence : public Stanza { - public: - typedef boost::shared_ptr<Presence> ref; + class SWIFTEN_API Presence : public Stanza { + public: + typedef std::shared_ptr<Presence> ref; - enum Type { Available, Error, Probe, Subscribe, Subscribed, Unavailable, Unsubscribe, Unsubscribed }; + enum Type { Available, Error, Probe, Subscribe, Subscribed, Unavailable, Unsubscribe, Unsubscribed }; - Presence(); - Presence(const std::string& status); - virtual ~Presence(); + Presence(); + Presence(const std::string& status); + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(Presence) + virtual ~Presence(); - static ref create() { - return boost::make_shared<Presence>(); - } + static ref create() { + return std::make_shared<Presence>(); + } - static ref create(const std::string& status) { - return boost::make_shared<Presence>(status); - } + static ref create(const std::string& status) { + return std::make_shared<Presence>(status); + } - static ref create(Presence::ref presence) { - return boost::make_shared<Presence>(*presence); - } + static ref create(Presence::ref presence) { + return std::make_shared<Presence>(*presence); + } - Type getType() const { return type_; } - void setType(Type type) { type_ = type; } + Type getType() const { return type_; } + void setType(Type type) { type_ = type; } - StatusShow::Type getShow() const { - boost::shared_ptr<StatusShow> show(getPayload<StatusShow>()); - if (show) { - return show->getType(); - } - return type_ == Available ? StatusShow::Online : StatusShow::None; - } + StatusShow::Type getShow() const { + std::shared_ptr<StatusShow> show(getPayload<StatusShow>()); + if (show) { + return show->getType(); + } + return type_ == Available ? StatusShow::Online : StatusShow::None; + } - void setShow(const StatusShow::Type &show) { - updatePayload(boost::make_shared<StatusShow>(show)); - } + void setShow(const StatusShow::Type &show) { + updatePayload(std::make_shared<StatusShow>(show)); + } - std::string getStatus() const; - void setStatus(const std::string& status); + std::string getStatus() const; + void setStatus(const std::string& status); - int getPriority() const; - void setPriority(int priority); + int getPriority() const; + void setPriority(int priority); - boost::shared_ptr<Presence> clone() const { - return boost::make_shared<Presence>(*this); - } + std::shared_ptr<Presence> clone() const { + return std::make_shared<Presence>(*this); + } - bool isAvailable() const { - return type_ == Available; - } + bool isAvailable() const { + return type_ == Available; + } - private: - Presence::Type type_; - }; + private: + Presence::Type type_; + }; } diff --git a/Swiften/Elements/Priority.h b/Swiften/Elements/Priority.h index 2c0cb9b..56e493c 100644 --- a/Swiften/Elements/Priority.h +++ b/Swiften/Elements/Priority.h @@ -1,28 +1,29 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class Priority : public Payload { - public: - Priority(int priority = 0) : priority_(priority) { - } + class SWIFTEN_API Priority : public Payload { + public: + Priority(int priority = 0) : priority_(priority) { + } - void setPriority(int priority) { - priority_ = priority; - } + void setPriority(int priority) { + priority_ = priority; + } - int getPriority() const { - return priority_; - } + int getPriority() const { + return priority_; + } - private: - int priority_; - }; + private: + int priority_; + }; } diff --git a/Swiften/Elements/PrivateStorage.h b/Swiften/Elements/PrivateStorage.h index a8e1b74..dfae34c 100644 --- a/Swiften/Elements/PrivateStorage.h +++ b/Swiften/Elements/PrivateStorage.h @@ -1,30 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class PrivateStorage : public Payload { - public: - PrivateStorage(boost::shared_ptr<Payload> payload = boost::shared_ptr<Payload>()) : payload(payload) { - } + class SWIFTEN_API PrivateStorage : public Payload { + public: + PrivateStorage(std::shared_ptr<Payload> payload = std::shared_ptr<Payload>()) : payload(payload) { + } - boost::shared_ptr<Payload> getPayload() const { - return payload; - } + std::shared_ptr<Payload> getPayload() const { + return payload; + } - void setPayload(boost::shared_ptr<Payload> p) { - payload = p; - } + void setPayload(std::shared_ptr<Payload> p) { + payload = p; + } - private: - boost::shared_ptr<Payload> payload; - }; + private: + std::shared_ptr<Payload> payload; + }; } diff --git a/Swiften/Elements/ProtocolHeader.h b/Swiften/Elements/ProtocolHeader.h index 841f7a0..4ae545a 100644 --- a/Swiften/Elements/ProtocolHeader.h +++ b/Swiften/Elements/ProtocolHeader.h @@ -1,42 +1,44 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> +#include <Swiften/Base/API.h> + namespace Swift { - class ProtocolHeader { - public: - ProtocolHeader() : version("1.0") {} - - const std::string& getTo() const { return to; } - void setTo(const std::string& a) { - to = a; - } - - const std::string& getFrom() const { return from; } - void setFrom(const std::string& a) { - from = a; - } - - const std::string& getVersion() const { return version; } - void setVersion(const std::string& a) { - version = a; - } - - const std::string& getID() const { return id; } - void setID(const std::string& a) { - id = a; - } - - private: - std::string to; - std::string from; - std::string id; - std::string version; - }; + class SWIFTEN_API ProtocolHeader { + public: + ProtocolHeader() : version("1.0") {} + + const std::string& getTo() const { return to; } + void setTo(const std::string& a) { + to = a; + } + + const std::string& getFrom() const { return from; } + void setFrom(const std::string& a) { + from = a; + } + + const std::string& getVersion() const { return version; } + void setVersion(const std::string& a) { + version = a; + } + + const std::string& getID() const { return id; } + void setID(const std::string& a) { + id = a; + } + + private: + std::string to; + std::string from; + std::string id; + std::string version; + }; } diff --git a/Swiften/Elements/PubSub.cpp b/Swiften/Elements/PubSub.cpp index 30a6376..0e9b9e0 100644 --- a/Swiften/Elements/PubSub.cpp +++ b/Swiften/Elements/PubSub.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSub.h b/Swiften/Elements/PubSub.h index cd8bf43..47b8c3f 100644 --- a/Swiften/Elements/PubSub.h +++ b/Swiften/Elements/PubSub.h @@ -1,21 +1,19 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/ContainerPayload.h> - #include <Swiften/Elements/PubSubPayload.h> namespace Swift { - class SWIFTEN_API PubSub : public ContainerPayload<PubSubPayload> { - public: - PubSub(); - virtual ~PubSub(); - }; + class SWIFTEN_API PubSub : public ContainerPayload<PubSubPayload> { + public: + PubSub(); + virtual ~PubSub(); + }; } diff --git a/Swiften/Elements/PubSubAffiliation.cpp b/Swiften/Elements/PubSubAffiliation.cpp index 0b04494..4e2b06b 100644 --- a/Swiften/Elements/PubSubAffiliation.cpp +++ b/Swiften/Elements/PubSubAffiliation.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubAffiliation.h b/Swiften/Elements/PubSubAffiliation.h index 2ea9376..058ef88 100644 --- a/Swiften/Elements/PubSubAffiliation.h +++ b/Swiften/Elements/PubSubAffiliation.h @@ -1,53 +1,51 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> #include <string> - +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> namespace Swift { - class SWIFTEN_API PubSubAffiliation : public Payload { - public: - enum Type { - None, - Member, - Outcast, - Owner, - Publisher, - PublishOnly - }; - - PubSubAffiliation(); - PubSubAffiliation(const std::string& node) : node(node), type(None) {} - virtual ~PubSubAffiliation(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - Type getType() const { - return type; - } - - void setType(Type value) { - this->type = value ; - } - - - private: - std::string node; - Type type; - }; + class SWIFTEN_API PubSubAffiliation : public Payload { + public: + enum Type { + None, + Member, + Outcast, + Owner, + Publisher, + PublishOnly + }; + + PubSubAffiliation(); + PubSubAffiliation(const std::string& node) : node(node), type(None) {} + virtual ~PubSubAffiliation(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + Type getType() const { + return type; + } + + void setType(Type value) { + this->type = value ; + } + + + private: + std::string node; + Type type; + }; } diff --git a/Swiften/Elements/PubSubAffiliations.cpp b/Swiften/Elements/PubSubAffiliations.cpp index a53215d..49dea1b 100644 --- a/Swiften/Elements/PubSubAffiliations.cpp +++ b/Swiften/Elements/PubSubAffiliations.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubAffiliations.h b/Swiften/Elements/PubSubAffiliations.h index 6a413fe..f3a6dda 100644 --- a/Swiften/Elements/PubSubAffiliations.h +++ b/Swiften/Elements/PubSubAffiliations.h @@ -1,53 +1,53 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubAffiliation.h> #include <Swiften/Elements/PubSubPayload.h> namespace Swift { - class SWIFTEN_API PubSubAffiliations : public PubSubPayload { - public: - - PubSubAffiliations(); - - virtual ~PubSubAffiliations(); - - const boost::optional< std::string >& getNode() const { - return node; - } - - void setNode(const boost::optional< std::string >& value) { - this->node = value ; - } - - const std::vector< boost::shared_ptr<PubSubAffiliation> >& getAffiliations() const { - return affiliations; - } - - void setAffiliations(const std::vector< boost::shared_ptr<PubSubAffiliation> >& value) { - this->affiliations = value ; - } - - void addAffiliation(boost::shared_ptr<PubSubAffiliation> value) { - this->affiliations.push_back(value); - } - - - private: - boost::optional< std::string > node; - std::vector< boost::shared_ptr<PubSubAffiliation> > affiliations; - }; + class SWIFTEN_API PubSubAffiliations : public PubSubPayload { + public: + + PubSubAffiliations(); + + virtual ~PubSubAffiliations(); + + const boost::optional< std::string >& getNode() const { + return node; + } + + void setNode(const boost::optional< std::string >& value) { + this->node = value ; + } + + const std::vector< std::shared_ptr<PubSubAffiliation> >& getAffiliations() const { + return affiliations; + } + + void setAffiliations(const std::vector< std::shared_ptr<PubSubAffiliation> >& value) { + this->affiliations = value ; + } + + void addAffiliation(std::shared_ptr<PubSubAffiliation> value) { + this->affiliations.push_back(value); + } + + + private: + boost::optional< std::string > node; + std::vector< std::shared_ptr<PubSubAffiliation> > affiliations; + }; } diff --git a/Swiften/Elements/PubSubConfigure.cpp b/Swiften/Elements/PubSubConfigure.cpp index b1a6cb3..58c6bdc 100644 --- a/Swiften/Elements/PubSubConfigure.cpp +++ b/Swiften/Elements/PubSubConfigure.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubConfigure.h b/Swiften/Elements/PubSubConfigure.h index ed91832..88a1ea9 100644 --- a/Swiften/Elements/PubSubConfigure.h +++ b/Swiften/Elements/PubSubConfigure.h @@ -1,36 +1,35 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Payload.h> namespace Swift { - class SWIFTEN_API PubSubConfigure : public Payload { - public: - - PubSubConfigure(); - - virtual ~PubSubConfigure(); + class SWIFTEN_API PubSubConfigure : public Payload { + public: + + PubSubConfigure(); + + virtual ~PubSubConfigure(); - boost::shared_ptr<Form> getData() const { - return data; - } + std::shared_ptr<Form> getData() const { + return data; + } - void setData(boost::shared_ptr<Form> value) { - this->data = value ; - } + void setData(std::shared_ptr<Form> value) { + this->data = value ; + } - private: - boost::shared_ptr<Form> data; - }; + private: + std::shared_ptr<Form> data; + }; } diff --git a/Swiften/Elements/PubSubCreate.cpp b/Swiften/Elements/PubSubCreate.cpp index 9c60de3..f612f92 100644 --- a/Swiften/Elements/PubSubCreate.cpp +++ b/Swiften/Elements/PubSubCreate.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubCreate.h b/Swiften/Elements/PubSubCreate.h index 4e4eb92..ac6b987 100644 --- a/Swiften/Elements/PubSubCreate.h +++ b/Swiften/Elements/PubSubCreate.h @@ -1,47 +1,46 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubConfigure.h> #include <Swiften/Elements/PubSubPayload.h> namespace Swift { - class SWIFTEN_API PubSubCreate : public PubSubPayload { - public: - - PubSubCreate(); - PubSubCreate(const std::string& node) : node(node) {} - virtual ~PubSubCreate(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - boost::shared_ptr<PubSubConfigure> getConfigure() const { - return configure; - } - - void setConfigure(boost::shared_ptr<PubSubConfigure> value) { - this->configure = value ; - } - - - private: - std::string node; - boost::shared_ptr<PubSubConfigure> configure; - }; + class SWIFTEN_API PubSubCreate : public PubSubPayload { + public: + + PubSubCreate(); + PubSubCreate(const std::string& node) : node(node) {} + virtual ~PubSubCreate(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + std::shared_ptr<PubSubConfigure> getConfigure() const { + return configure; + } + + void setConfigure(std::shared_ptr<PubSubConfigure> value) { + this->configure = value ; + } + + + private: + std::string node; + std::shared_ptr<PubSubConfigure> configure; + }; } diff --git a/Swiften/Elements/PubSubDefault.cpp b/Swiften/Elements/PubSubDefault.cpp index 923d0ad..575b3c1 100644 --- a/Swiften/Elements/PubSubDefault.cpp +++ b/Swiften/Elements/PubSubDefault.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubDefault.h b/Swiften/Elements/PubSubDefault.h index 08326e7..aa058ac 100644 --- a/Swiften/Elements/PubSubDefault.h +++ b/Swiften/Elements/PubSubDefault.h @@ -1,51 +1,51 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> #include <string> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubPayload.h> namespace Swift { - class SWIFTEN_API PubSubDefault : public PubSubPayload { - public: - enum Type { - None, - Collection, - Leaf - }; - - PubSubDefault(); - - virtual ~PubSubDefault(); - - const boost::optional< std::string >& getNode() const { - return node; - } - - void setNode(const boost::optional< std::string >& value) { - this->node = value ; - } - - Type getType() const { - return type; - } - - void setType(Type value) { - this->type = value ; - } - - - private: - boost::optional< std::string > node; - Type type; - }; + class SWIFTEN_API PubSubDefault : public PubSubPayload { + public: + enum Type { + None, + Collection, + Leaf + }; + + PubSubDefault(); + + virtual ~PubSubDefault(); + + const boost::optional< std::string >& getNode() const { + return node; + } + + void setNode(const boost::optional< std::string >& value) { + this->node = value ; + } + + Type getType() const { + return type; + } + + void setType(Type value) { + this->type = value ; + } + + + private: + boost::optional< std::string > node; + Type type; + }; } diff --git a/Swiften/Elements/PubSubError.cpp b/Swiften/Elements/PubSubError.cpp index db07972..3bf7187 100644 --- a/Swiften/Elements/PubSubError.cpp +++ b/Swiften/Elements/PubSubError.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubError.h b/Swiften/Elements/PubSubError.h index 3748e44..2d4452a 100644 --- a/Swiften/Elements/PubSubError.h +++ b/Swiften/Elements/PubSubError.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -9,103 +9,103 @@ #include <Swiften/Elements/Payload.h> namespace Swift { - class SWIFTEN_API PubSubError : public Payload { - public: - enum Type { - UnknownType = 0, - ClosedNode, - ConfigurationRequired, - InvalidJID, - InvalidOptions, - InvalidPayload, - InvalidSubscriptionID, - ItemForbidden, - ItemRequired, - JIDRequired, - MaximumItemsExceeded, - MaximumNodesExceeded, - NodeIDRequired, - NotInRosterGroup, - NotSubscribed, - PayloadTooBig, - PayloadRequired, - PendingSubscription, - PresenceSubscriptionRequired, - SubscriptionIDRequired, - TooManySubscriptions, - Unsupported, - UnsupportedAccessModel - }; + class SWIFTEN_API PubSubError : public Payload { + public: + enum Type { + UnknownType = 0, + ClosedNode, + ConfigurationRequired, + InvalidJID, + InvalidOptions, + InvalidPayload, + InvalidSubscriptionID, + ItemForbidden, + ItemRequired, + JIDRequired, + MaximumItemsExceeded, + MaximumNodesExceeded, + NodeIDRequired, + NotInRosterGroup, + NotSubscribed, + PayloadTooBig, + PayloadRequired, + PendingSubscription, + PresenceSubscriptionRequired, + SubscriptionIDRequired, + TooManySubscriptions, + Unsupported, + UnsupportedAccessModel + }; - enum UnsupportedFeatureType { - UnknownUnsupportedFeatureType = 0, - AccessAuthorize, - AccessOpen, - AccessPresence, - AccessRoster, - AccessWhitelist, - AutoCreate, - AutoSubscribe, - Collections, - ConfigNode, - CreateAndConfigure, - CreateNodes, - DeleteItems, - DeleteNodes, - FilteredNotifications, - GetPending, - InstantNodes, - ItemIDs, - LastPublished, - LeasedSubscription, - ManageSubscriptions, - MemberAffiliation, - MetaData, - ModifyAffiliations, - MultiCollection, - MultiSubscribe, - OutcastAffiliation, - PersistentItems, - PresenceNotifications, - PresenceSubscribe, - Publish, - PublishOptions, - PublishOnlyAffiliation, - PublisherAffiliation, - PurgeNodes, - RetractItems, - RetrieveAffiliations, - RetrieveDefault, - RetrieveItems, - RetrieveSubscriptions, - Subscribe, - SubscriptionOptions, - SubscriptionNotifications - }; + enum UnsupportedFeatureType { + UnknownUnsupportedFeatureType = 0, + AccessAuthorize, + AccessOpen, + AccessPresence, + AccessRoster, + AccessWhitelist, + AutoCreate, + AutoSubscribe, + Collections, + ConfigNode, + CreateAndConfigure, + CreateNodes, + DeleteItems, + DeleteNodes, + FilteredNotifications, + GetPending, + InstantNodes, + ItemIDs, + LastPublished, + LeasedSubscription, + ManageSubscriptions, + MemberAffiliation, + MetaData, + ModifyAffiliations, + MultiCollection, + MultiSubscribe, + OutcastAffiliation, + PersistentItems, + PresenceNotifications, + PresenceSubscribe, + Publish, + PublishOptions, + PublishOnlyAffiliation, + PublisherAffiliation, + PurgeNodes, + RetractItems, + RetrieveAffiliations, + RetrieveDefault, + RetrieveItems, + RetrieveSubscriptions, + Subscribe, + SubscriptionOptions, + SubscriptionNotifications + }; - PubSubError(Type type = UnknownType) : type(type), unsupportedType(UnknownUnsupportedFeatureType) { - } + PubSubError(Type type = UnknownType) : type(type), unsupportedType(UnknownUnsupportedFeatureType) { + } - virtual ~PubSubError(); + virtual ~PubSubError(); - Type getType() const { - return type; - } + Type getType() const { + return type; + } - void setType(Type type) { - this->type = type; - } + void setType(Type type) { + this->type = type; + } - UnsupportedFeatureType getUnsupportedFeatureType() const { - return unsupportedType; - } + UnsupportedFeatureType getUnsupportedFeatureType() const { + return unsupportedType; + } - void setUnsupportedFeatureType(UnsupportedFeatureType unsupportedType) { - this->unsupportedType = unsupportedType; - } + void setUnsupportedFeatureType(UnsupportedFeatureType unsupportedType) { + this->unsupportedType = unsupportedType; + } - private: - Type type; - UnsupportedFeatureType unsupportedType; - }; + private: + Type type; + UnsupportedFeatureType unsupportedType; + }; } diff --git a/Swiften/Elements/PubSubEvent.cpp b/Swiften/Elements/PubSubEvent.cpp index 1b63134..3b3f59f 100644 --- a/Swiften/Elements/PubSubEvent.cpp +++ b/Swiften/Elements/PubSubEvent.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEvent.h b/Swiften/Elements/PubSubEvent.h index 9ef6d89..561f731 100644 --- a/Swiften/Elements/PubSubEvent.h +++ b/Swiften/Elements/PubSubEvent.h @@ -1,23 +1,22 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/ContainerPayload.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubEventPayload.h> namespace Swift { - class SWIFTEN_API PubSubEvent : public ContainerPayload<PubSubEventPayload> { - public: - PubSubEvent(); - virtual ~PubSubEvent(); - }; + class SWIFTEN_API PubSubEvent : public ContainerPayload<PubSubEventPayload> { + public: + PubSubEvent(); + virtual ~PubSubEvent(); + }; } diff --git a/Swiften/Elements/PubSubEventAssociate.cpp b/Swiften/Elements/PubSubEventAssociate.cpp index cb81b46..920a492 100644 --- a/Swiften/Elements/PubSubEventAssociate.cpp +++ b/Swiften/Elements/PubSubEventAssociate.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventAssociate.h b/Swiften/Elements/PubSubEventAssociate.h index a752345..b7bb839 100644 --- a/Swiften/Elements/PubSubEventAssociate.h +++ b/Swiften/Elements/PubSubEventAssociate.h @@ -1,36 +1,34 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <string> + #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> -#include <string> +namespace Swift { + class SWIFTEN_API PubSubEventAssociate : public Payload { + public: + PubSubEventAssociate(); -namespace Swift { - class SWIFTEN_API PubSubEventAssociate : public Payload { - public: - - PubSubEventAssociate(); - - virtual ~PubSubEventAssociate(); + virtual ~PubSubEventAssociate(); - const std::string& getNode() const { - return node; - } + const std::string& getNode() const { + return node; + } - void setNode(const std::string& value) { - this->node = value ; - } + void setNode(const std::string& value) { + this->node = value ; + } - private: - std::string node; - }; + private: + std::string node; + }; } diff --git a/Swiften/Elements/PubSubEventCollection.cpp b/Swiften/Elements/PubSubEventCollection.cpp index a8b2a56..657fba9 100644 --- a/Swiften/Elements/PubSubEventCollection.cpp +++ b/Swiften/Elements/PubSubEventCollection.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventCollection.h b/Swiften/Elements/PubSubEventCollection.h index e4498aa..367fe02 100644 --- a/Swiften/Elements/PubSubEventCollection.h +++ b/Swiften/Elements/PubSubEventCollection.h @@ -1,58 +1,58 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> -#include <Swiften/Elements/PubSubEventDisassociate.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubEventAssociate.h> +#include <Swiften/Elements/PubSubEventDisassociate.h> #include <Swiften/Elements/PubSubEventPayload.h> namespace Swift { - class SWIFTEN_API PubSubEventCollection : public PubSubEventPayload { - public: - - PubSubEventCollection(); - - virtual ~PubSubEventCollection(); - - const boost::optional< std::string >& getNode() const { - return node; - } - - void setNode(const boost::optional< std::string >& value) { - this->node = value ; - } - - boost::shared_ptr<PubSubEventDisassociate> getDisassociate() const { - return disassociate; - } - - void setDisassociate(boost::shared_ptr<PubSubEventDisassociate> value) { - this->disassociate = value ; - } - - boost::shared_ptr<PubSubEventAssociate> getAssociate() const { - return associate; - } - - void setAssociate(boost::shared_ptr<PubSubEventAssociate> value) { - this->associate = value ; - } - - - private: - boost::optional< std::string > node; - boost::shared_ptr<PubSubEventDisassociate> disassociate; - boost::shared_ptr<PubSubEventAssociate> associate; - }; + class SWIFTEN_API PubSubEventCollection : public PubSubEventPayload { + public: + + PubSubEventCollection(); + + virtual ~PubSubEventCollection(); + + const boost::optional< std::string >& getNode() const { + return node; + } + + void setNode(const boost::optional< std::string >& value) { + this->node = value ; + } + + std::shared_ptr<PubSubEventDisassociate> getDisassociate() const { + return disassociate; + } + + void setDisassociate(std::shared_ptr<PubSubEventDisassociate> value) { + this->disassociate = value ; + } + + std::shared_ptr<PubSubEventAssociate> getAssociate() const { + return associate; + } + + void setAssociate(std::shared_ptr<PubSubEventAssociate> value) { + this->associate = value ; + } + + + private: + boost::optional< std::string > node; + std::shared_ptr<PubSubEventDisassociate> disassociate; + std::shared_ptr<PubSubEventAssociate> associate; + }; } diff --git a/Swiften/Elements/PubSubEventConfiguration.cpp b/Swiften/Elements/PubSubEventConfiguration.cpp index 93ce6a3..64667d1 100644 --- a/Swiften/Elements/PubSubEventConfiguration.cpp +++ b/Swiften/Elements/PubSubEventConfiguration.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventConfiguration.h b/Swiften/Elements/PubSubEventConfiguration.h index 7ebfce1..e529014 100644 --- a/Swiften/Elements/PubSubEventConfiguration.h +++ b/Swiften/Elements/PubSubEventConfiguration.h @@ -1,47 +1,46 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubEventPayload.h> namespace Swift { - class SWIFTEN_API PubSubEventConfiguration : public PubSubEventPayload { - public: - - PubSubEventConfiguration(); - - virtual ~PubSubEventConfiguration(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - boost::shared_ptr<Form> getData() const { - return data; - } - - void setData(boost::shared_ptr<Form> value) { - this->data = value ; - } - - - private: - std::string node; - boost::shared_ptr<Form> data; - }; + class SWIFTEN_API PubSubEventConfiguration : public PubSubEventPayload { + public: + + PubSubEventConfiguration(); + + virtual ~PubSubEventConfiguration(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + std::shared_ptr<Form> getData() const { + return data; + } + + void setData(std::shared_ptr<Form> value) { + this->data = value ; + } + + + private: + std::string node; + std::shared_ptr<Form> data; + }; } diff --git a/Swiften/Elements/PubSubEventDelete.cpp b/Swiften/Elements/PubSubEventDelete.cpp index 85bbf2e..ecd6ddf 100644 --- a/Swiften/Elements/PubSubEventDelete.cpp +++ b/Swiften/Elements/PubSubEventDelete.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventDelete.h b/Swiften/Elements/PubSubEventDelete.h index fecfb0e..f899d4e 100644 --- a/Swiften/Elements/PubSubEventDelete.h +++ b/Swiften/Elements/PubSubEventDelete.h @@ -1,47 +1,46 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> -#include <Swiften/Elements/PubSubEventRedirect.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubEventPayload.h> +#include <Swiften/Elements/PubSubEventRedirect.h> namespace Swift { - class SWIFTEN_API PubSubEventDelete : public PubSubEventPayload { - public: - - PubSubEventDelete(); - - virtual ~PubSubEventDelete(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - boost::shared_ptr<PubSubEventRedirect> getRedirects() const { - return redirects; - } - - void setRedirects(boost::shared_ptr<PubSubEventRedirect> value) { - this->redirects = value ; - } - - - private: - std::string node; - boost::shared_ptr<PubSubEventRedirect> redirects; - }; + class SWIFTEN_API PubSubEventDelete : public PubSubEventPayload { + public: + + PubSubEventDelete(); + + virtual ~PubSubEventDelete(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + std::shared_ptr<PubSubEventRedirect> getRedirects() const { + return redirects; + } + + void setRedirects(std::shared_ptr<PubSubEventRedirect> value) { + this->redirects = value ; + } + + + private: + std::string node; + std::shared_ptr<PubSubEventRedirect> redirects; + }; } diff --git a/Swiften/Elements/PubSubEventDisassociate.cpp b/Swiften/Elements/PubSubEventDisassociate.cpp index 55e1c4e..3a94952 100644 --- a/Swiften/Elements/PubSubEventDisassociate.cpp +++ b/Swiften/Elements/PubSubEventDisassociate.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventDisassociate.h b/Swiften/Elements/PubSubEventDisassociate.h index cad9843..415ac29 100644 --- a/Swiften/Elements/PubSubEventDisassociate.h +++ b/Swiften/Elements/PubSubEventDisassociate.h @@ -1,36 +1,34 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <string> + #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> -#include <string> +namespace Swift { + class SWIFTEN_API PubSubEventDisassociate : public Payload { + public: + PubSubEventDisassociate(); -namespace Swift { - class SWIFTEN_API PubSubEventDisassociate : public Payload { - public: - - PubSubEventDisassociate(); - - virtual ~PubSubEventDisassociate(); + virtual ~PubSubEventDisassociate(); - const std::string& getNode() const { - return node; - } + const std::string& getNode() const { + return node; + } - void setNode(const std::string& value) { - this->node = value ; - } + void setNode(const std::string& value) { + this->node = value ; + } - private: - std::string node; - }; + private: + std::string node; + }; } diff --git a/Swiften/Elements/PubSubEventItem.cpp b/Swiften/Elements/PubSubEventItem.cpp index 6bb3823..53e5caa 100644 --- a/Swiften/Elements/PubSubEventItem.cpp +++ b/Swiften/Elements/PubSubEventItem.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventItem.h b/Swiften/Elements/PubSubEventItem.h index 25ebc82..defdbf4 100644 --- a/Swiften/Elements/PubSubEventItem.h +++ b/Swiften/Elements/PubSubEventItem.h @@ -1,70 +1,69 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class SWIFTEN_API PubSubEventItem : public Payload { - public: - - PubSubEventItem(); - - virtual ~PubSubEventItem(); - - const boost::optional< std::string >& getNode() const { - return node; - } - - void setNode(const boost::optional< std::string >& value) { - this->node = value ; - } - - const boost::optional< std::string >& getPublisher() const { - return publisher; - } - - void setPublisher(const boost::optional< std::string >& value) { - this->publisher = value ; - } - - const std::vector< boost::shared_ptr<Payload> >& getData() const { - return data; - } - - void setData(const std::vector< boost::shared_ptr<Payload> >& value) { - this->data = value ; - } - - void addData(boost::shared_ptr<Payload> value) { - this->data.push_back(value); - } - - const boost::optional< std::string >& getID() const { - return id; - } - - void setID(const boost::optional< std::string >& value) { - this->id = value ; - } - - - private: - boost::optional< std::string > node; - boost::optional< std::string > publisher; - std::vector< boost::shared_ptr<Payload> > data; - boost::optional< std::string > id; - }; + class SWIFTEN_API PubSubEventItem : public Payload { + public: + + PubSubEventItem(); + + virtual ~PubSubEventItem(); + + const boost::optional< std::string >& getNode() const { + return node; + } + + void setNode(const boost::optional< std::string >& value) { + this->node = value ; + } + + const boost::optional< std::string >& getPublisher() const { + return publisher; + } + + void setPublisher(const boost::optional< std::string >& value) { + this->publisher = value ; + } + + const std::vector< std::shared_ptr<Payload> >& getData() const { + return data; + } + + void setData(const std::vector< std::shared_ptr<Payload> >& value) { + this->data = value ; + } + + void addData(std::shared_ptr<Payload> value) { + this->data.push_back(value); + } + + const boost::optional< std::string >& getID() const { + return id; + } + + void setID(const boost::optional< std::string >& value) { + this->id = value ; + } + + + private: + boost::optional< std::string > node; + boost::optional< std::string > publisher; + std::vector< std::shared_ptr<Payload> > data; + boost::optional< std::string > id; + }; } diff --git a/Swiften/Elements/PubSubEventItems.cpp b/Swiften/Elements/PubSubEventItems.cpp index 01f3429..86257db 100644 --- a/Swiften/Elements/PubSubEventItems.cpp +++ b/Swiften/Elements/PubSubEventItems.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventItems.h b/Swiften/Elements/PubSubEventItems.h index a121728..aade826 100644 --- a/Swiften/Elements/PubSubEventItems.h +++ b/Swiften/Elements/PubSubEventItems.h @@ -1,66 +1,65 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubEventItem.h> -#include <Swiften/Elements/PubSubEventRetract.h> #include <Swiften/Elements/PubSubEventPayload.h> +#include <Swiften/Elements/PubSubEventRetract.h> namespace Swift { - class SWIFTEN_API PubSubEventItems : public PubSubEventPayload { - public: - - PubSubEventItems(); - - virtual ~PubSubEventItems(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - const std::vector< boost::shared_ptr<PubSubEventItem> >& getItems() const { - return items; - } - - void setItems(const std::vector< boost::shared_ptr<PubSubEventItem> >& value) { - this->items = value ; - } - - void addItem(boost::shared_ptr<PubSubEventItem> value) { - this->items.push_back(value); - } - - const std::vector< boost::shared_ptr<PubSubEventRetract> >& getRetracts() const { - return retracts; - } - - void setRetracts(const std::vector< boost::shared_ptr<PubSubEventRetract> >& value) { - this->retracts = value ; - } - - void addRetract(boost::shared_ptr<PubSubEventRetract> value) { - this->retracts.push_back(value); - } - - - private: - std::string node; - std::vector< boost::shared_ptr<PubSubEventItem> > items; - std::vector< boost::shared_ptr<PubSubEventRetract> > retracts; - }; + class SWIFTEN_API PubSubEventItems : public PubSubEventPayload { + public: + + PubSubEventItems(); + + virtual ~PubSubEventItems(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + const std::vector< std::shared_ptr<PubSubEventItem> >& getItems() const { + return items; + } + + void setItems(const std::vector< std::shared_ptr<PubSubEventItem> >& value) { + this->items = value ; + } + + void addItem(std::shared_ptr<PubSubEventItem> value) { + this->items.push_back(value); + } + + const std::vector< std::shared_ptr<PubSubEventRetract> >& getRetracts() const { + return retracts; + } + + void setRetracts(const std::vector< std::shared_ptr<PubSubEventRetract> >& value) { + this->retracts = value ; + } + + void addRetract(std::shared_ptr<PubSubEventRetract> value) { + this->retracts.push_back(value); + } + + + private: + std::string node; + std::vector< std::shared_ptr<PubSubEventItem> > items; + std::vector< std::shared_ptr<PubSubEventRetract> > retracts; + }; } diff --git a/Swiften/Elements/PubSubEventPayload.cpp b/Swiften/Elements/PubSubEventPayload.cpp index 0019942..90371f8 100644 --- a/Swiften/Elements/PubSubEventPayload.cpp +++ b/Swiften/Elements/PubSubEventPayload.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventPayload.h b/Swiften/Elements/PubSubEventPayload.h index 81fb9a8..f4abc06 100644 --- a/Swiften/Elements/PubSubEventPayload.h +++ b/Swiften/Elements/PubSubEventPayload.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -10,8 +10,8 @@ #include <Swiften/Elements/Payload.h> namespace Swift { - class SWIFTEN_API PubSubEventPayload : public Payload { - public: - virtual ~PubSubEventPayload(); - }; + class SWIFTEN_API PubSubEventPayload : public Payload { + public: + virtual ~PubSubEventPayload(); + }; } diff --git a/Swiften/Elements/PubSubEventPurge.cpp b/Swiften/Elements/PubSubEventPurge.cpp index 3fd77ed..2383566 100644 --- a/Swiften/Elements/PubSubEventPurge.cpp +++ b/Swiften/Elements/PubSubEventPurge.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventPurge.h b/Swiften/Elements/PubSubEventPurge.h index 5f04049..647598d 100644 --- a/Swiften/Elements/PubSubEventPurge.h +++ b/Swiften/Elements/PubSubEventPurge.h @@ -1,36 +1,35 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubEventPayload.h> namespace Swift { - class SWIFTEN_API PubSubEventPurge : public PubSubEventPayload { - public: - - PubSubEventPurge(); - - virtual ~PubSubEventPurge(); + class SWIFTEN_API PubSubEventPurge : public PubSubEventPayload { + public: + + PubSubEventPurge(); + + virtual ~PubSubEventPurge(); - const std::string& getNode() const { - return node; - } + const std::string& getNode() const { + return node; + } - void setNode(const std::string& value) { - this->node = value ; - } + void setNode(const std::string& value) { + this->node = value ; + } - private: - std::string node; - }; + private: + std::string node; + }; } diff --git a/Swiften/Elements/PubSubEventRedirect.cpp b/Swiften/Elements/PubSubEventRedirect.cpp index adde8bc..b8fd220 100644 --- a/Swiften/Elements/PubSubEventRedirect.cpp +++ b/Swiften/Elements/PubSubEventRedirect.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventRedirect.h b/Swiften/Elements/PubSubEventRedirect.h index 918c7f4..063cf8c 100644 --- a/Swiften/Elements/PubSubEventRedirect.h +++ b/Swiften/Elements/PubSubEventRedirect.h @@ -1,36 +1,34 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <string> + #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> -#include <string> +namespace Swift { + class SWIFTEN_API PubSubEventRedirect : public Payload { + public: + PubSubEventRedirect(); -namespace Swift { - class SWIFTEN_API PubSubEventRedirect : public Payload { - public: - - PubSubEventRedirect(); - - virtual ~PubSubEventRedirect(); + virtual ~PubSubEventRedirect(); - const std::string& getURI() const { - return uri; - } + const std::string& getURI() const { + return uri; + } - void setURI(const std::string& value) { - this->uri = value ; - } + void setURI(const std::string& value) { + this->uri = value ; + } - private: - std::string uri; - }; + private: + std::string uri; + }; } diff --git a/Swiften/Elements/PubSubEventRetract.cpp b/Swiften/Elements/PubSubEventRetract.cpp index bb3ebb1..cd0e4df 100644 --- a/Swiften/Elements/PubSubEventRetract.cpp +++ b/Swiften/Elements/PubSubEventRetract.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventRetract.h b/Swiften/Elements/PubSubEventRetract.h index 3c2d9c4..19e02c9 100644 --- a/Swiften/Elements/PubSubEventRetract.h +++ b/Swiften/Elements/PubSubEventRetract.h @@ -1,36 +1,34 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <string> + #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> -#include <string> +namespace Swift { + class SWIFTEN_API PubSubEventRetract : public Payload { + public: + PubSubEventRetract(); -namespace Swift { - class SWIFTEN_API PubSubEventRetract : public Payload { - public: - - PubSubEventRetract(); - - virtual ~PubSubEventRetract(); + virtual ~PubSubEventRetract(); - const std::string& getID() const { - return id; - } + const std::string& getID() const { + return id; + } - void setID(const std::string& value) { - this->id = value ; - } + void setID(const std::string& value) { + this->id = value ; + } - private: - std::string id; - }; + private: + std::string id; + }; } diff --git a/Swiften/Elements/PubSubEventSubscription.cpp b/Swiften/Elements/PubSubEventSubscription.cpp index fb069f9..ebffe3b 100644 --- a/Swiften/Elements/PubSubEventSubscription.cpp +++ b/Swiften/Elements/PubSubEventSubscription.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubEventSubscription.h b/Swiften/Elements/PubSubEventSubscription.h index b74d4f5..37e8b74 100644 --- a/Swiften/Elements/PubSubEventSubscription.h +++ b/Swiften/Elements/PubSubEventSubscription.h @@ -1,81 +1,81 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> #include <string> + #include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/optional.hpp> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubEventPayload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API PubSubEventSubscription : public PubSubEventPayload { - public: - enum SubscriptionType { - None, - Pending, - Subscribed, - Unconfigured - }; - - PubSubEventSubscription(); - - virtual ~PubSubEventSubscription(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - const JID& getJID() const { - return jid; - } - - void setJID(const JID& value) { - this->jid = value ; - } - - SubscriptionType getSubscription() const { - return subscription; - } - - void setSubscription(SubscriptionType value) { - this->subscription = value ; - } - - const boost::optional< std::string >& getSubscriptionID() const { - return subscriptionID; - } - - void setSubscriptionID(const boost::optional< std::string >& value) { - this->subscriptionID = value ; - } - - const boost::posix_time::ptime& getExpiry() const { - return expiry; - } - - void setExpiry(const boost::posix_time::ptime& value) { - this->expiry = value ; - } - - - private: - std::string node; - JID jid; - SubscriptionType subscription; - boost::optional< std::string > subscriptionID; - boost::posix_time::ptime expiry; - }; + class SWIFTEN_API PubSubEventSubscription : public PubSubEventPayload { + public: + enum SubscriptionType { + None, + Pending, + Subscribed, + Unconfigured + }; + + PubSubEventSubscription(); + + virtual ~PubSubEventSubscription(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + const JID& getJID() const { + return jid; + } + + void setJID(const JID& value) { + this->jid = value ; + } + + SubscriptionType getSubscription() const { + return subscription; + } + + void setSubscription(SubscriptionType value) { + this->subscription = value ; + } + + const boost::optional< std::string >& getSubscriptionID() const { + return subscriptionID; + } + + void setSubscriptionID(const boost::optional< std::string >& value) { + this->subscriptionID = value ; + } + + const boost::posix_time::ptime& getExpiry() const { + return expiry; + } + + void setExpiry(const boost::posix_time::ptime& value) { + this->expiry = value ; + } + + + private: + std::string node; + JID jid; + SubscriptionType subscription; + boost::optional< std::string > subscriptionID; + boost::posix_time::ptime expiry; + }; } diff --git a/Swiften/Elements/PubSubItem.cpp b/Swiften/Elements/PubSubItem.cpp index ae6206f..b5f17cc 100644 --- a/Swiften/Elements/PubSubItem.cpp +++ b/Swiften/Elements/PubSubItem.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2018 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -11,5 +11,8 @@ using namespace Swift; PubSubItem::PubSubItem() { } +PubSubItem::PubSubItem(const std::string& id) : id_(id) { +} + PubSubItem::~PubSubItem() { } diff --git a/Swiften/Elements/PubSubItem.h b/Swiften/Elements/PubSubItem.h index 93ff03a..161b733 100644 --- a/Swiften/Elements/PubSubItem.h +++ b/Swiften/Elements/PubSubItem.h @@ -1,51 +1,49 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2018 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class SWIFTEN_API PubSubItem : public Payload { - public: - - PubSubItem(); - - virtual ~PubSubItem(); - - const std::vector< boost::shared_ptr<Payload> >& getData() const { - return data; - } - - void setData(const std::vector< boost::shared_ptr<Payload> >& value) { - this->data = value ; - } - - void addData(boost::shared_ptr<Payload> value) { - this->data.push_back(value); - } - - const std::string& getID() const { - return id; - } - - void setID(const std::string& value) { - this->id = value ; - } - - - private: - std::vector< boost::shared_ptr<Payload> > data; - std::string id; - }; + class SWIFTEN_API PubSubItem : public Payload { + public: + + PubSubItem(); + PubSubItem(const std::string& id); + + virtual ~PubSubItem(); + + const std::vector< std::shared_ptr<Payload> >& getData() const { + return data_; + } + + void setData(const std::vector< std::shared_ptr<Payload> >& value) { + this->data_ = value ; + } + + void addData(std::shared_ptr<Payload> value) { + this->data_.push_back(value); + } + + const std::string& getID() const { + return id_; + } + + void setID(const std::string& value) { + this->id_ = value ; + } + + private: + std::vector< std::shared_ptr<Payload> > data_; + std::string id_; + }; } diff --git a/Swiften/Elements/PubSubItems.cpp b/Swiften/Elements/PubSubItems.cpp index f235e11..a20346e 100644 --- a/Swiften/Elements/PubSubItems.cpp +++ b/Swiften/Elements/PubSubItems.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubItems.h b/Swiften/Elements/PubSubItems.h index 7cd279b..c8b7f53 100644 --- a/Swiften/Elements/PubSubItems.h +++ b/Swiften/Elements/PubSubItems.h @@ -1,71 +1,70 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubItem.h> #include <Swiften/Elements/PubSubPayload.h> namespace Swift { - class SWIFTEN_API PubSubItems : public PubSubPayload { - public: - - PubSubItems(); - PubSubItems(const std::string& node) : node(node) {} - virtual ~PubSubItems(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - const std::vector< boost::shared_ptr<PubSubItem> >& getItems() const { - return items; - } - - void setItems(const std::vector< boost::shared_ptr<PubSubItem> >& value) { - this->items = value ; - } - - void addItem(boost::shared_ptr<PubSubItem> value) { - this->items.push_back(value); - } - - const boost::optional< unsigned int >& getMaximumItems() const { - return maximumItems; - } - - void setMaximumItems(const boost::optional< unsigned int >& value) { - this->maximumItems = value ; - } - - const boost::optional< std::string >& getSubscriptionID() const { - return subscriptionID; - } - - void setSubscriptionID(const boost::optional< std::string >& value) { - this->subscriptionID = value ; - } - - - private: - std::string node; - std::vector< boost::shared_ptr<PubSubItem> > items; - boost::optional< unsigned int > maximumItems; - boost::optional< std::string > subscriptionID; - }; + class SWIFTEN_API PubSubItems : public PubSubPayload { + public: + + PubSubItems(); + PubSubItems(const std::string& node) : node(node) {} + virtual ~PubSubItems(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + const std::vector< std::shared_ptr<PubSubItem> >& getItems() const { + return items; + } + + void setItems(const std::vector< std::shared_ptr<PubSubItem> >& value) { + this->items = value ; + } + + void addItem(std::shared_ptr<PubSubItem> value) { + this->items.push_back(value); + } + + const boost::optional< unsigned int >& getMaximumItems() const { + return maximumItems; + } + + void setMaximumItems(const boost::optional< unsigned int >& value) { + this->maximumItems = value ; + } + + const boost::optional< std::string >& getSubscriptionID() const { + return subscriptionID; + } + + void setSubscriptionID(const boost::optional< std::string >& value) { + this->subscriptionID = value ; + } + + private: + std::string node; + std::vector< std::shared_ptr<PubSubItem> > items; + boost::optional< unsigned int > maximumItems; + boost::optional< std::string > subscriptionID; + }; } diff --git a/Swiften/Elements/PubSubOptions.cpp b/Swiften/Elements/PubSubOptions.cpp index 22c4054..210f62b 100644 --- a/Swiften/Elements/PubSubOptions.cpp +++ b/Swiften/Elements/PubSubOptions.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOptions.h b/Swiften/Elements/PubSubOptions.h index 0e9483e..80a3b03 100644 --- a/Swiften/Elements/PubSubOptions.h +++ b/Swiften/Elements/PubSubOptions.h @@ -1,67 +1,67 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubPayload.h> #include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API PubSubOptions : public PubSubPayload { - public: - - PubSubOptions(); - - virtual ~PubSubOptions(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - const JID& getJID() const { - return jid; - } - - void setJID(const JID& value) { - this->jid = value ; - } - - boost::shared_ptr<Form> getData() const { - return data; - } - - void setData(boost::shared_ptr<Form> value) { - this->data = value ; - } - - const boost::optional< std::string >& getSubscriptionID() const { - return subscriptionID; - } - - void setSubscriptionID(const boost::optional< std::string >& value) { - this->subscriptionID = value ; - } - - - private: - std::string node; - JID jid; - boost::shared_ptr<Form> data; - boost::optional< std::string > subscriptionID; - }; + class SWIFTEN_API PubSubOptions : public PubSubPayload { + public: + + PubSubOptions(); + + virtual ~PubSubOptions(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + const JID& getJID() const { + return jid; + } + + void setJID(const JID& value) { + this->jid = value ; + } + + std::shared_ptr<Form> getData() const { + return data; + } + + void setData(std::shared_ptr<Form> value) { + this->data = value ; + } + + const boost::optional< std::string >& getSubscriptionID() const { + return subscriptionID; + } + + void setSubscriptionID(const boost::optional< std::string >& value) { + this->subscriptionID = value ; + } + + + private: + std::string node; + JID jid; + std::shared_ptr<Form> data; + boost::optional< std::string > subscriptionID; + }; } diff --git a/Swiften/Elements/PubSubOwnerAffiliation.cpp b/Swiften/Elements/PubSubOwnerAffiliation.cpp index 8dc8be6..c8308ec 100644 --- a/Swiften/Elements/PubSubOwnerAffiliation.cpp +++ b/Swiften/Elements/PubSubOwnerAffiliation.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerAffiliation.h b/Swiften/Elements/PubSubOwnerAffiliation.h index 68851d3..77886d1 100644 --- a/Swiften/Elements/PubSubOwnerAffiliation.h +++ b/Swiften/Elements/PubSubOwnerAffiliation.h @@ -1,53 +1,50 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> - - #include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API PubSubOwnerAffiliation : public Payload { - public: - enum Type { - None, - Member, - Outcast, - Owner, - Publisher, - PublishOnly - }; - - PubSubOwnerAffiliation(); - - virtual ~PubSubOwnerAffiliation(); - - const JID& getJID() const { - return jid; - } - - void setJID(const JID& value) { - this->jid = value ; - } - - Type getType() const { - return type; - } - - void setType(Type value) { - this->type = value ; - } - - - private: - JID jid; - Type type; - }; + class SWIFTEN_API PubSubOwnerAffiliation : public Payload { + public: + enum Type { + None, + Member, + Outcast, + Owner, + Publisher, + PublishOnly + }; + + PubSubOwnerAffiliation(); + + virtual ~PubSubOwnerAffiliation(); + + const JID& getJID() const { + return jid; + } + + void setJID(const JID& value) { + this->jid = value ; + } + + Type getType() const { + return type; + } + + void setType(Type value) { + this->type = value ; + } + + + private: + JID jid; + Type type; + }; } diff --git a/Swiften/Elements/PubSubOwnerAffiliations.cpp b/Swiften/Elements/PubSubOwnerAffiliations.cpp index b87a78a..33b03ce 100644 --- a/Swiften/Elements/PubSubOwnerAffiliations.cpp +++ b/Swiften/Elements/PubSubOwnerAffiliations.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerAffiliations.h b/Swiften/Elements/PubSubOwnerAffiliations.h index 75578df..2434d4e 100644 --- a/Swiften/Elements/PubSubOwnerAffiliations.h +++ b/Swiften/Elements/PubSubOwnerAffiliations.h @@ -1,52 +1,51 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> -#include <Swiften/Elements/PubSubOwnerPayload.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubOwnerAffiliation.h> +#include <Swiften/Elements/PubSubOwnerPayload.h> namespace Swift { - class SWIFTEN_API PubSubOwnerAffiliations : public PubSubOwnerPayload { - public: - - PubSubOwnerAffiliations(); - - virtual ~PubSubOwnerAffiliations(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - const std::vector< boost::shared_ptr<PubSubOwnerAffiliation> >& getAffiliations() const { - return affiliations; - } - - void setAffiliations(const std::vector< boost::shared_ptr<PubSubOwnerAffiliation> >& value) { - this->affiliations = value ; - } - - void addAffiliation(boost::shared_ptr<PubSubOwnerAffiliation> value) { - this->affiliations.push_back(value); - } - - - private: - std::string node; - std::vector< boost::shared_ptr<PubSubOwnerAffiliation> > affiliations; - }; + class SWIFTEN_API PubSubOwnerAffiliations : public PubSubOwnerPayload { + public: + + PubSubOwnerAffiliations(); + + virtual ~PubSubOwnerAffiliations(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + const std::vector< std::shared_ptr<PubSubOwnerAffiliation> >& getAffiliations() const { + return affiliations; + } + + void setAffiliations(const std::vector< std::shared_ptr<PubSubOwnerAffiliation> >& value) { + this->affiliations = value ; + } + + void addAffiliation(std::shared_ptr<PubSubOwnerAffiliation> value) { + this->affiliations.push_back(value); + } + + + private: + std::string node; + std::vector< std::shared_ptr<PubSubOwnerAffiliation> > affiliations; + }; } diff --git a/Swiften/Elements/PubSubOwnerConfigure.cpp b/Swiften/Elements/PubSubOwnerConfigure.cpp index 8db923d..aa511ea 100644 --- a/Swiften/Elements/PubSubOwnerConfigure.cpp +++ b/Swiften/Elements/PubSubOwnerConfigure.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerConfigure.h b/Swiften/Elements/PubSubOwnerConfigure.h index d882ec4..2b84753 100644 --- a/Swiften/Elements/PubSubOwnerConfigure.h +++ b/Swiften/Elements/PubSubOwnerConfigure.h @@ -1,48 +1,48 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> -#include <Swiften/Elements/PubSubOwnerPayload.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Form.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/Elements/PubSubOwnerPayload.h> namespace Swift { - class SWIFTEN_API PubSubOwnerConfigure : public PubSubOwnerPayload { - public: - - PubSubOwnerConfigure(); - PubSubOwnerConfigure(const std::string& node) : node(node) {} - virtual ~PubSubOwnerConfigure(); - - const boost::optional< std::string >& getNode() const { - return node; - } - - void setNode(const boost::optional< std::string >& value) { - this->node = value ; - } - - boost::shared_ptr<Form> getData() const { - return data; - } - - void setData(boost::shared_ptr<Form> value) { - this->data = value ; - } - - - private: - boost::optional< std::string > node; - boost::shared_ptr<Form> data; - }; + class SWIFTEN_API PubSubOwnerConfigure : public PubSubOwnerPayload { + public: + + PubSubOwnerConfigure(); + PubSubOwnerConfigure(const std::string& node) : node(node) {} + virtual ~PubSubOwnerConfigure(); + + const boost::optional< std::string >& getNode() const { + return node; + } + + void setNode(const boost::optional< std::string >& value) { + this->node = value ; + } + + std::shared_ptr<Form> getData() const { + return data; + } + + void setData(std::shared_ptr<Form> value) { + this->data = value ; + } + + + private: + boost::optional< std::string > node; + std::shared_ptr<Form> data; + }; } diff --git a/Swiften/Elements/PubSubOwnerDefault.cpp b/Swiften/Elements/PubSubOwnerDefault.cpp index ebb51a7..4c49a08 100644 --- a/Swiften/Elements/PubSubOwnerDefault.cpp +++ b/Swiften/Elements/PubSubOwnerDefault.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerDefault.h b/Swiften/Elements/PubSubOwnerDefault.h index 1dbd3a2..a17d9f3 100644 --- a/Swiften/Elements/PubSubOwnerDefault.h +++ b/Swiften/Elements/PubSubOwnerDefault.h @@ -1,37 +1,36 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> +#include <Swiften/Elements/Form.h> #include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> - #include <Swiften/Elements/PubSubOwnerPayload.h> -#include <Swiften/Elements/Form.h> namespace Swift { - class SWIFTEN_API PubSubOwnerDefault : public PubSubOwnerPayload { - public: - - PubSubOwnerDefault(); - - virtual ~PubSubOwnerDefault(); + class SWIFTEN_API PubSubOwnerDefault : public PubSubOwnerPayload { + public: + + PubSubOwnerDefault(); + + virtual ~PubSubOwnerDefault(); - boost::shared_ptr<Form> getData() const { - return data; - } + std::shared_ptr<Form> getData() const { + return data; + } - void setData(boost::shared_ptr<Form> value) { - this->data = value ; - } + void setData(std::shared_ptr<Form> value) { + this->data = value ; + } - private: - boost::shared_ptr<Form> data; - }; + private: + std::shared_ptr<Form> data; + }; } diff --git a/Swiften/Elements/PubSubOwnerDelete.cpp b/Swiften/Elements/PubSubOwnerDelete.cpp index a785424..9d95bdb 100644 --- a/Swiften/Elements/PubSubOwnerDelete.cpp +++ b/Swiften/Elements/PubSubOwnerDelete.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerDelete.h b/Swiften/Elements/PubSubOwnerDelete.h index c6bb3e9..a222e85 100644 --- a/Swiften/Elements/PubSubOwnerDelete.h +++ b/Swiften/Elements/PubSubOwnerDelete.h @@ -1,47 +1,46 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubOwnerPayload.h> #include <Swiften/Elements/PubSubOwnerRedirect.h> namespace Swift { - class SWIFTEN_API PubSubOwnerDelete : public PubSubOwnerPayload { - public: - - PubSubOwnerDelete(); - PubSubOwnerDelete(const std::string& node) : node(node) {} - virtual ~PubSubOwnerDelete(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - boost::shared_ptr<PubSubOwnerRedirect> getRedirect() const { - return redirect; - } - - void setRedirect(boost::shared_ptr<PubSubOwnerRedirect> value) { - this->redirect = value ; - } - - - private: - std::string node; - boost::shared_ptr<PubSubOwnerRedirect> redirect; - }; + class SWIFTEN_API PubSubOwnerDelete : public PubSubOwnerPayload { + public: + + PubSubOwnerDelete(); + PubSubOwnerDelete(const std::string& node) : node(node) {} + virtual ~PubSubOwnerDelete(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + std::shared_ptr<PubSubOwnerRedirect> getRedirect() const { + return redirect; + } + + void setRedirect(std::shared_ptr<PubSubOwnerRedirect> value) { + this->redirect = value ; + } + + + private: + std::string node; + std::shared_ptr<PubSubOwnerRedirect> redirect; + }; } diff --git a/Swiften/Elements/PubSubOwnerPayload.cpp b/Swiften/Elements/PubSubOwnerPayload.cpp index 92c1dd2..0d3f9d6 100644 --- a/Swiften/Elements/PubSubOwnerPayload.cpp +++ b/Swiften/Elements/PubSubOwnerPayload.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerPayload.h b/Swiften/Elements/PubSubOwnerPayload.h index a2ddaaa..8381a17 100644 --- a/Swiften/Elements/PubSubOwnerPayload.h +++ b/Swiften/Elements/PubSubOwnerPayload.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -10,8 +10,8 @@ #include <Swiften/Elements/Payload.h> namespace Swift { - class SWIFTEN_API PubSubOwnerPayload : public Payload { - public: - virtual ~PubSubOwnerPayload(); - }; + class SWIFTEN_API PubSubOwnerPayload : public Payload { + public: + virtual ~PubSubOwnerPayload(); + }; } diff --git a/Swiften/Elements/PubSubOwnerPubSub.cpp b/Swiften/Elements/PubSubOwnerPubSub.cpp index 022452d..2407a73 100644 --- a/Swiften/Elements/PubSubOwnerPubSub.cpp +++ b/Swiften/Elements/PubSubOwnerPubSub.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerPubSub.h b/Swiften/Elements/PubSubOwnerPubSub.h index dd72abe..9989cde 100644 --- a/Swiften/Elements/PubSubOwnerPubSub.h +++ b/Swiften/Elements/PubSubOwnerPubSub.h @@ -1,21 +1,19 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/ContainerPayload.h> - #include <Swiften/Elements/PubSubOwnerPayload.h> namespace Swift { - class SWIFTEN_API PubSubOwnerPubSub : public ContainerPayload<PubSubOwnerPayload> { - public: - PubSubOwnerPubSub(); - virtual ~PubSubOwnerPubSub(); - }; + class SWIFTEN_API PubSubOwnerPubSub : public ContainerPayload<PubSubOwnerPayload> { + public: + PubSubOwnerPubSub(); + virtual ~PubSubOwnerPubSub(); + }; } diff --git a/Swiften/Elements/PubSubOwnerPurge.cpp b/Swiften/Elements/PubSubOwnerPurge.cpp index d0ac57d..cb1ab8b 100644 --- a/Swiften/Elements/PubSubOwnerPurge.cpp +++ b/Swiften/Elements/PubSubOwnerPurge.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerPurge.h b/Swiften/Elements/PubSubOwnerPurge.h index fc410f8..3631bd9 100644 --- a/Swiften/Elements/PubSubOwnerPurge.h +++ b/Swiften/Elements/PubSubOwnerPurge.h @@ -1,36 +1,35 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubOwnerPayload.h> namespace Swift { - class SWIFTEN_API PubSubOwnerPurge : public PubSubOwnerPayload { - public: - - PubSubOwnerPurge(); - - virtual ~PubSubOwnerPurge(); + class SWIFTEN_API PubSubOwnerPurge : public PubSubOwnerPayload { + public: + + PubSubOwnerPurge(); + + virtual ~PubSubOwnerPurge(); - const std::string& getNode() const { - return node; - } + const std::string& getNode() const { + return node; + } - void setNode(const std::string& value) { - this->node = value ; - } + void setNode(const std::string& value) { + this->node = value ; + } - private: - std::string node; - }; + private: + std::string node; + }; } diff --git a/Swiften/Elements/PubSubOwnerRedirect.cpp b/Swiften/Elements/PubSubOwnerRedirect.cpp index 164c216..b7c6882 100644 --- a/Swiften/Elements/PubSubOwnerRedirect.cpp +++ b/Swiften/Elements/PubSubOwnerRedirect.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerRedirect.h b/Swiften/Elements/PubSubOwnerRedirect.h index 61db1d1..f7deca8 100644 --- a/Swiften/Elements/PubSubOwnerRedirect.h +++ b/Swiften/Elements/PubSubOwnerRedirect.h @@ -1,36 +1,34 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <string> + #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> -#include <string> +namespace Swift { + class SWIFTEN_API PubSubOwnerRedirect : public Payload { + public: + PubSubOwnerRedirect(); -namespace Swift { - class SWIFTEN_API PubSubOwnerRedirect : public Payload { - public: - - PubSubOwnerRedirect(); - - virtual ~PubSubOwnerRedirect(); + virtual ~PubSubOwnerRedirect(); - const std::string& getURI() const { - return uri; - } + const std::string& getURI() const { + return uri; + } - void setURI(const std::string& value) { - this->uri = value ; - } + void setURI(const std::string& value) { + this->uri = value ; + } - private: - std::string uri; - }; + private: + std::string uri; + }; } diff --git a/Swiften/Elements/PubSubOwnerSubscription.cpp b/Swiften/Elements/PubSubOwnerSubscription.cpp index 3334e36..c5ed105 100644 --- a/Swiften/Elements/PubSubOwnerSubscription.cpp +++ b/Swiften/Elements/PubSubOwnerSubscription.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerSubscription.h b/Swiften/Elements/PubSubOwnerSubscription.h index 1c302df..cf2edd9 100644 --- a/Swiften/Elements/PubSubOwnerSubscription.h +++ b/Swiften/Elements/PubSubOwnerSubscription.h @@ -1,51 +1,48 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> - - #include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API PubSubOwnerSubscription : public Payload { - public: - enum SubscriptionType { - None, - Pending, - Subscribed, - Unconfigured - }; - - PubSubOwnerSubscription(); - - virtual ~PubSubOwnerSubscription(); - - const JID& getJID() const { - return jid; - } - - void setJID(const JID& value) { - this->jid = value ; - } - - SubscriptionType getSubscription() const { - return subscription; - } - - void setSubscription(SubscriptionType value) { - this->subscription = value ; - } - - - private: - JID jid; - SubscriptionType subscription; - }; + class SWIFTEN_API PubSubOwnerSubscription : public Payload { + public: + enum SubscriptionType { + None, + Pending, + Subscribed, + Unconfigured + }; + + PubSubOwnerSubscription(); + + virtual ~PubSubOwnerSubscription(); + + const JID& getJID() const { + return jid; + } + + void setJID(const JID& value) { + this->jid = value ; + } + + SubscriptionType getSubscription() const { + return subscription; + } + + void setSubscription(SubscriptionType value) { + this->subscription = value ; + } + + + private: + JID jid; + SubscriptionType subscription; + }; } diff --git a/Swiften/Elements/PubSubOwnerSubscriptions.cpp b/Swiften/Elements/PubSubOwnerSubscriptions.cpp index a4deb59..1560042 100644 --- a/Swiften/Elements/PubSubOwnerSubscriptions.cpp +++ b/Swiften/Elements/PubSubOwnerSubscriptions.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubOwnerSubscriptions.h b/Swiften/Elements/PubSubOwnerSubscriptions.h index 08a2f5c..d7cd8df 100644 --- a/Swiften/Elements/PubSubOwnerSubscriptions.h +++ b/Swiften/Elements/PubSubOwnerSubscriptions.h @@ -1,52 +1,51 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubOwnerPayload.h> #include <Swiften/Elements/PubSubOwnerSubscription.h> namespace Swift { - class SWIFTEN_API PubSubOwnerSubscriptions : public PubSubOwnerPayload { - public: - - PubSubOwnerSubscriptions(); - - virtual ~PubSubOwnerSubscriptions(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - const std::vector< boost::shared_ptr<PubSubOwnerSubscription> >& getSubscriptions() const { - return subscriptions; - } - - void setSubscriptions(const std::vector< boost::shared_ptr<PubSubOwnerSubscription> >& value) { - this->subscriptions = value ; - } - - void addSubscription(boost::shared_ptr<PubSubOwnerSubscription> value) { - this->subscriptions.push_back(value); - } - - - private: - std::string node; - std::vector< boost::shared_ptr<PubSubOwnerSubscription> > subscriptions; - }; + class SWIFTEN_API PubSubOwnerSubscriptions : public PubSubOwnerPayload { + public: + + PubSubOwnerSubscriptions(); + + virtual ~PubSubOwnerSubscriptions(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + const std::vector< std::shared_ptr<PubSubOwnerSubscription> >& getSubscriptions() const { + return subscriptions; + } + + void setSubscriptions(const std::vector< std::shared_ptr<PubSubOwnerSubscription> >& value) { + this->subscriptions = value ; + } + + void addSubscription(std::shared_ptr<PubSubOwnerSubscription> value) { + this->subscriptions.push_back(value); + } + + + private: + std::string node; + std::vector< std::shared_ptr<PubSubOwnerSubscription> > subscriptions; + }; } diff --git a/Swiften/Elements/PubSubPayload.cpp b/Swiften/Elements/PubSubPayload.cpp index b529959..3f6de5e 100644 --- a/Swiften/Elements/PubSubPayload.cpp +++ b/Swiften/Elements/PubSubPayload.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubPayload.h b/Swiften/Elements/PubSubPayload.h index 476939b..7fc1882 100644 --- a/Swiften/Elements/PubSubPayload.h +++ b/Swiften/Elements/PubSubPayload.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -10,8 +10,8 @@ #include <Swiften/Elements/Payload.h> namespace Swift { - class SWIFTEN_API PubSubPayload : public Payload { - public: - virtual ~PubSubPayload(); - }; + class SWIFTEN_API PubSubPayload : public Payload { + public: + virtual ~PubSubPayload(); + }; } diff --git a/Swiften/Elements/PubSubPublish.cpp b/Swiften/Elements/PubSubPublish.cpp index 2ee3880..ec3fb0c 100644 --- a/Swiften/Elements/PubSubPublish.cpp +++ b/Swiften/Elements/PubSubPublish.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubPublish.h b/Swiften/Elements/PubSubPublish.h index 1d99420..2d6d5bb 100644 --- a/Swiften/Elements/PubSubPublish.h +++ b/Swiften/Elements/PubSubPublish.h @@ -1,52 +1,51 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubItem.h> #include <Swiften/Elements/PubSubPayload.h> namespace Swift { - class SWIFTEN_API PubSubPublish : public PubSubPayload { - public: - - PubSubPublish(); - - virtual ~PubSubPublish(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - const std::vector< boost::shared_ptr<PubSubItem> >& getItems() const { - return items; - } - - void setItems(const std::vector< boost::shared_ptr<PubSubItem> >& value) { - this->items = value ; - } - - void addItem(boost::shared_ptr<PubSubItem> value) { - this->items.push_back(value); - } - - - private: - std::string node; - std::vector< boost::shared_ptr<PubSubItem> > items; - }; + class SWIFTEN_API PubSubPublish : public PubSubPayload { + public: + + PubSubPublish(); + + virtual ~PubSubPublish(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + const std::vector< std::shared_ptr<PubSubItem> >& getItems() const { + return items; + } + + void setItems(const std::vector< std::shared_ptr<PubSubItem> >& value) { + this->items = value ; + } + + void addItem(std::shared_ptr<PubSubItem> value) { + this->items.push_back(value); + } + + + private: + std::string node; + std::vector< std::shared_ptr<PubSubItem> > items; + }; } diff --git a/Swiften/Elements/PubSubRetract.cpp b/Swiften/Elements/PubSubRetract.cpp index 7e3676e..1b188ee 100644 --- a/Swiften/Elements/PubSubRetract.cpp +++ b/Swiften/Elements/PubSubRetract.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubRetract.h b/Swiften/Elements/PubSubRetract.h index e55897b..2629c16 100644 --- a/Swiften/Elements/PubSubRetract.h +++ b/Swiften/Elements/PubSubRetract.h @@ -1,61 +1,62 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> + +#include <boost/optional.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubItem.h> #include <Swiften/Elements/PubSubPayload.h> namespace Swift { - class SWIFTEN_API PubSubRetract : public PubSubPayload { - public: - - PubSubRetract(); - - virtual ~PubSubRetract(); - - const std::string& getNode() const { - return node; - } - - void setNode(const std::string& value) { - this->node = value ; - } - - const std::vector< boost::shared_ptr<PubSubItem> >& getItems() const { - return items; - } - - void setItems(const std::vector< boost::shared_ptr<PubSubItem> >& value) { - this->items = value ; - } - - void addItem(boost::shared_ptr<PubSubItem> value) { - this->items.push_back(value); - } - - bool isNotify() const { - return notify; - } - - void setNotify(bool value) { - this->notify = value ; - } - - - private: - std::string node; - std::vector< boost::shared_ptr<PubSubItem> > items; - bool notify; - }; + class SWIFTEN_API PubSubRetract : public PubSubPayload { + public: + + PubSubRetract(); + + virtual ~PubSubRetract(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + const std::vector< std::shared_ptr<PubSubItem> >& getItems() const { + return items; + } + + void setItems(const std::vector< std::shared_ptr<PubSubItem> >& value) { + this->items = value ; + } + + void addItem(std::shared_ptr<PubSubItem> value) { + this->items.push_back(value); + } + + boost::optional<bool> isNotify() const { + return notify; + } + + void setNotify(const boost::optional<bool>& value) { + this->notify = value ; + } + + + private: + std::string node; + std::vector< std::shared_ptr<PubSubItem> > items; + boost::optional<bool> notify; + }; } diff --git a/Swiften/Elements/PubSubSubscribe.cpp b/Swiften/Elements/PubSubSubscribe.cpp index 4720321..c461b54 100644 --- a/Swiften/Elements/PubSubSubscribe.cpp +++ b/Swiften/Elements/PubSubSubscribe.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubSubscribe.h b/Swiften/Elements/PubSubSubscribe.h index e2cc4ae..aaaca38 100644 --- a/Swiften/Elements/PubSubSubscribe.h +++ b/Swiften/Elements/PubSubSubscribe.h @@ -1,58 +1,58 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubOptions.h> #include <Swiften/Elements/PubSubPayload.h> #include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API PubSubSubscribe : public PubSubPayload { - public: - - PubSubSubscribe(); - - virtual ~PubSubSubscribe(); - - const boost::optional< std::string >& getNode() const { - return node; - } - - void setNode(const boost::optional< std::string >& value) { - this->node = value ; - } - - const JID& getJID() const { - return jid; - } - - void setJID(const JID& value) { - this->jid = value ; - } - - boost::shared_ptr<PubSubOptions> getOptions() const { - return options; - } - - void setOptions(boost::shared_ptr<PubSubOptions> value) { - this->options = value ; - } - - - private: - boost::optional< std::string > node; - JID jid; - boost::shared_ptr<PubSubOptions> options; - }; + class SWIFTEN_API PubSubSubscribe : public PubSubPayload { + public: + + PubSubSubscribe(); + + virtual ~PubSubSubscribe(); + + const boost::optional< std::string >& getNode() const { + return node; + } + + void setNode(const boost::optional< std::string >& value) { + this->node = value ; + } + + const JID& getJID() const { + return jid; + } + + void setJID(const JID& value) { + this->jid = value ; + } + + std::shared_ptr<PubSubOptions> getOptions() const { + return options; + } + + void setOptions(std::shared_ptr<PubSubOptions> value) { + this->options = value ; + } + + + private: + boost::optional< std::string > node; + JID jid; + std::shared_ptr<PubSubOptions> options; + }; } diff --git a/Swiften/Elements/PubSubSubscribeOptions.cpp b/Swiften/Elements/PubSubSubscribeOptions.cpp index 8770620..a4c7914 100644 --- a/Swiften/Elements/PubSubSubscribeOptions.cpp +++ b/Swiften/Elements/PubSubSubscribeOptions.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -8,7 +8,7 @@ using namespace Swift; -PubSubSubscribeOptions::PubSubSubscribeOptions() { +PubSubSubscribeOptions::PubSubSubscribeOptions() : required(false) { } PubSubSubscribeOptions::~PubSubSubscribeOptions() { diff --git a/Swiften/Elements/PubSubSubscribeOptions.h b/Swiften/Elements/PubSubSubscribeOptions.h index 6612d82..1521427 100644 --- a/Swiften/Elements/PubSubSubscribeOptions.h +++ b/Swiften/Elements/PubSubSubscribeOptions.h @@ -1,36 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> +namespace Swift { + class SWIFTEN_API PubSubSubscribeOptions : public Payload { + public: + PubSubSubscribeOptions(); + virtual ~PubSubSubscribeOptions(); -namespace Swift { - class SWIFTEN_API PubSubSubscribeOptions : public Payload { - public: - - PubSubSubscribeOptions(); - - virtual ~PubSubSubscribeOptions(); - - bool isRequired() const { - return required; - } + bool isRequired() const { + return required; + } - void setRequired(bool value) { - this->required = value ; - } + void setRequired(bool value) { + this->required = value ; + } - private: - bool required; - }; + private: + bool required; + }; } diff --git a/Swiften/Elements/PubSubSubscription.cpp b/Swiften/Elements/PubSubSubscription.cpp index a25fc06..2b2463e 100644 --- a/Swiften/Elements/PubSubSubscription.cpp +++ b/Swiften/Elements/PubSubSubscription.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubSubscription.h b/Swiften/Elements/PubSubSubscription.h index 977cd55..9645ebb 100644 --- a/Swiften/Elements/PubSubSubscription.h +++ b/Swiften/Elements/PubSubSubscription.h @@ -1,82 +1,82 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> -#include <Swiften/Elements/PubSubSubscribeOptions.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubPayload.h> +#include <Swiften/Elements/PubSubSubscribeOptions.h> #include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API PubSubSubscription : public PubSubPayload { - public: - enum SubscriptionType { - None, - Pending, - Subscribed, - Unconfigured - }; - - PubSubSubscription(); - - virtual ~PubSubSubscription(); - - const boost::optional< std::string >& getNode() const { - return node; - } - - void setNode(const boost::optional< std::string >& value) { - this->node = value ; - } - - const boost::optional< std::string >& getSubscriptionID() const { - return subscriptionID; - } - - void setSubscriptionID(const boost::optional< std::string >& value) { - this->subscriptionID = value ; - } - - const JID& getJID() const { - return jid; - } - - void setJID(const JID& value) { - this->jid = value ; - } - - boost::shared_ptr<PubSubSubscribeOptions> getOptions() const { - return options; - } - - void setOptions(boost::shared_ptr<PubSubSubscribeOptions> value) { - this->options = value ; - } - - SubscriptionType getSubscription() const { - return subscription; - } - - void setSubscription(SubscriptionType value) { - this->subscription = value ; - } - - - private: - boost::optional< std::string > node; - boost::optional< std::string > subscriptionID; - JID jid; - boost::shared_ptr<PubSubSubscribeOptions> options; - SubscriptionType subscription; - }; + class SWIFTEN_API PubSubSubscription : public PubSubPayload { + public: + enum SubscriptionType { + None, + Pending, + Subscribed, + Unconfigured + }; + + PubSubSubscription(); + + virtual ~PubSubSubscription(); + + const boost::optional< std::string >& getNode() const { + return node; + } + + void setNode(const boost::optional< std::string >& value) { + this->node = value ; + } + + const boost::optional< std::string >& getSubscriptionID() const { + return subscriptionID; + } + + void setSubscriptionID(const boost::optional< std::string >& value) { + this->subscriptionID = value ; + } + + const JID& getJID() const { + return jid; + } + + void setJID(const JID& value) { + this->jid = value ; + } + + std::shared_ptr<PubSubSubscribeOptions> getOptions() const { + return options; + } + + void setOptions(std::shared_ptr<PubSubSubscribeOptions> value) { + this->options = value ; + } + + SubscriptionType getSubscription() const { + return subscription; + } + + void setSubscription(SubscriptionType value) { + this->subscription = value ; + } + + + private: + boost::optional< std::string > node; + boost::optional< std::string > subscriptionID; + JID jid; + std::shared_ptr<PubSubSubscribeOptions> options; + SubscriptionType subscription; + }; } diff --git a/Swiften/Elements/PubSubSubscriptions.cpp b/Swiften/Elements/PubSubSubscriptions.cpp index 626e122..0c58962 100644 --- a/Swiften/Elements/PubSubSubscriptions.cpp +++ b/Swiften/Elements/PubSubSubscriptions.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubSubscriptions.h b/Swiften/Elements/PubSubSubscriptions.h index c7c19c5..f721bd5 100644 --- a/Swiften/Elements/PubSubSubscriptions.h +++ b/Swiften/Elements/PubSubSubscriptions.h @@ -1,53 +1,53 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> -#include <Swiften/Elements/PubSubSubscription.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubPayload.h> +#include <Swiften/Elements/PubSubSubscription.h> namespace Swift { - class SWIFTEN_API PubSubSubscriptions : public PubSubPayload { - public: - - PubSubSubscriptions(); - PubSubSubscriptions(const std::string& node) : node(node) {} - virtual ~PubSubSubscriptions(); - - const boost::optional< std::string >& getNode() const { - return node; - } - - void setNode(const boost::optional< std::string >& value) { - this->node = value ; - } - - const std::vector< boost::shared_ptr<PubSubSubscription> >& getSubscriptions() const { - return subscriptions; - } - - void setSubscriptions(const std::vector< boost::shared_ptr<PubSubSubscription> >& value) { - this->subscriptions = value ; - } - - void addSubscription(boost::shared_ptr<PubSubSubscription> value) { - this->subscriptions.push_back(value); - } - - - private: - boost::optional< std::string > node; - std::vector< boost::shared_ptr<PubSubSubscription> > subscriptions; - }; + class SWIFTEN_API PubSubSubscriptions : public PubSubPayload { + public: + + PubSubSubscriptions(); + PubSubSubscriptions(const std::string& node) : node(node) {} + virtual ~PubSubSubscriptions(); + + const boost::optional< std::string >& getNode() const { + return node; + } + + void setNode(const boost::optional< std::string >& value) { + this->node = value ; + } + + const std::vector< std::shared_ptr<PubSubSubscription> >& getSubscriptions() const { + return subscriptions; + } + + void setSubscriptions(const std::vector< std::shared_ptr<PubSubSubscription> >& value) { + this->subscriptions = value ; + } + + void addSubscription(std::shared_ptr<PubSubSubscription> value) { + this->subscriptions.push_back(value); + } + + + private: + boost::optional< std::string > node; + std::vector< std::shared_ptr<PubSubSubscription> > subscriptions; + }; } diff --git a/Swiften/Elements/PubSubUnsubscribe.cpp b/Swiften/Elements/PubSubUnsubscribe.cpp index a4b8318..1438b17 100644 --- a/Swiften/Elements/PubSubUnsubscribe.cpp +++ b/Swiften/Elements/PubSubUnsubscribe.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/PubSubUnsubscribe.h b/Swiften/Elements/PubSubUnsubscribe.h index 3969376..c0c25bd 100644 --- a/Swiften/Elements/PubSubUnsubscribe.h +++ b/Swiften/Elements/PubSubUnsubscribe.h @@ -1,56 +1,56 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> #include <string> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> #include <Swiften/Elements/PubSubPayload.h> #include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API PubSubUnsubscribe : public PubSubPayload { - public: - - PubSubUnsubscribe(); - - virtual ~PubSubUnsubscribe(); - - const boost::optional< std::string >& getNode() const { - return node; - } - - void setNode(const boost::optional< std::string >& value) { - this->node = value ; - } - - const JID& getJID() const { - return jid; - } - - void setJID(const JID& value) { - this->jid = value ; - } - - const boost::optional< std::string >& getSubscriptionID() const { - return subscriptionID; - } - - void setSubscriptionID(const boost::optional< std::string >& value) { - this->subscriptionID = value ; - } - - - private: - boost::optional< std::string > node; - JID jid; - boost::optional< std::string > subscriptionID; - }; + class SWIFTEN_API PubSubUnsubscribe : public PubSubPayload { + public: + + PubSubUnsubscribe(); + + virtual ~PubSubUnsubscribe(); + + const boost::optional< std::string >& getNode() const { + return node; + } + + void setNode(const boost::optional< std::string >& value) { + this->node = value ; + } + + const JID& getJID() const { + return jid; + } + + void setJID(const JID& value) { + this->jid = value ; + } + + const boost::optional< std::string >& getSubscriptionID() const { + return subscriptionID; + } + + void setSubscriptionID(const boost::optional< std::string >& value) { + this->subscriptionID = value ; + } + + + private: + boost::optional< std::string > node; + JID jid; + boost::optional< std::string > subscriptionID; + }; } diff --git a/Swiften/Elements/RawXMLPayload.h b/Swiften/Elements/RawXMLPayload.h index e583c12..65901bc 100644 --- a/Swiften/Elements/RawXMLPayload.h +++ b/Swiften/Elements/RawXMLPayload.h @@ -1,29 +1,30 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class RawXMLPayload : public Payload { - public: - RawXMLPayload(const std::string& data = "") : rawXML_(data) {} + class SWIFTEN_API RawXMLPayload : public Payload { + public: + RawXMLPayload(const std::string& data = "") : rawXML_(data) {} - void setRawXML(const std::string& data) { - rawXML_ = data; - } + void setRawXML(const std::string& data) { + rawXML_ = data; + } - const std::string& getRawXML() const { - return rawXML_; - } + const std::string& getRawXML() const { + return rawXML_; + } - private: - std::string rawXML_; - }; + private: + std::string rawXML_; + }; } diff --git a/Swiften/Elements/ReferencePayload.cpp b/Swiften/Elements/ReferencePayload.cpp new file mode 100644 index 0000000..288f28f --- /dev/null +++ b/Swiften/Elements/ReferencePayload.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/ReferencePayload.h> + +namespace Swift { + +ReferencePayload::ReferencePayload() + : type_(Type::Data) { +} + +const ReferencePayload::Type& ReferencePayload::getType() const { + return type_; +} + +void ReferencePayload::setType(const ReferencePayload::Type& type) { + type_ = type; +} + +const boost::optional<std::string>& ReferencePayload::getUri() const { + return uri_; +} + +void ReferencePayload::setUri(const boost::optional<std::string>& uri) { + uri_ = uri; +} + +const boost::optional<std::string>& ReferencePayload::getBegin() const { + return begin_; +} + +void ReferencePayload::setBegin(const boost::optional<std::string>& begin) { + begin_ = begin; +} + +const boost::optional<std::string>& ReferencePayload::getEnd() const { + return end_; +} + +void ReferencePayload::setEnd(const boost::optional<std::string>& end) { + end_ = end; +} + +const boost::optional<std::string>& ReferencePayload::getAnchor() const { + return anchor_; +} + +void ReferencePayload::setAnchor(const boost::optional<std::string>& anchor) { + anchor_ = anchor; +} + +const std::vector<std::shared_ptr<Payload>>& ReferencePayload::getPayloads() const { + return payloads_; +} + +void ReferencePayload::addPayload(const std::shared_ptr<Payload>& payload) { + payloads_.push_back(payload); +} + +} diff --git a/Swiften/Elements/ReferencePayload.h b/Swiften/Elements/ReferencePayload.h new file mode 100644 index 0000000..b9a394e --- /dev/null +++ b/Swiften/Elements/ReferencePayload.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> +#include <vector> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + /** + * reference from XEP-0372 + */ + class SWIFTEN_API ReferencePayload : public Payload { + + public: + + typedef std::shared_ptr<ReferencePayload> ref; + + enum class Type { + Data, + Mention, + PubSub, + Unknown + }; + + ReferencePayload(); + + const Type& getType() const; + const boost::optional<std::string>& getUri() const; + const boost::optional<std::string>& getBegin() const; + const boost::optional<std::string>& getEnd() const; + const boost::optional<std::string>& getAnchor() const; + + const std::vector<std::shared_ptr<Payload>>& getPayloads() const; + + void setType(const Type& type); + void setUri(const boost::optional<std::string>& uri); + void setBegin(const boost::optional<std::string>& begin); + void setEnd(const boost::optional<std::string>& end); + void setAnchor(const boost::optional<std::string>& anchor); + + void addPayload(const std::shared_ptr<Payload>& payload); + + private: + + Type type_; + boost::optional<std::string> uri_; + boost::optional<std::string> begin_; + boost::optional<std::string> end_; + boost::optional<std::string> anchor_; + + std::vector<std::shared_ptr<Payload>> payloads_; + }; +} diff --git a/Swiften/Elements/Replace.h b/Swiften/Elements/Replace.h index 96935f5..d51981d 100644 --- a/Swiften/Elements/Replace.h +++ b/Swiften/Elements/Replace.h @@ -4,25 +4,32 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class Replace : public Payload { - public: - typedef boost::shared_ptr<Replace> ref; - Replace(const std::string& id = std::string()) : replaceID_(id) {} - const std::string& getID() const { - return replaceID_; - } - void setID(const std::string& id) { - replaceID_ = id; - } - private: - std::string replaceID_; - }; + class SWIFTEN_API Replace : public Payload { + public: + typedef std::shared_ptr<Replace> ref; + Replace(const std::string& id = std::string()) : replaceID_(id) {} + const std::string& getID() const { + return replaceID_; + } + void setID(const std::string& id) { + replaceID_ = id; + } + private: + std::string replaceID_; + }; } diff --git a/Swiften/Elements/ResourceBind.h b/Swiften/Elements/ResourceBind.h index f67a995..fd6d4c7 100644 --- a/Swiften/Elements/ResourceBind.h +++ b/Swiften/Elements/ResourceBind.h @@ -1,38 +1,40 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> #include <Swiften/JID/JID.h> namespace Swift { - class ResourceBind : public Payload { - public: - ResourceBind() {} - - void setJID(const JID& jid) { - jid_ = jid; - } - - const JID& getJID() const { - return jid_; - } - - void setResource(const std::string& resource) { - resource_ = resource; - } - - const std::string& getResource() const { - return resource_; - } - - private: - JID jid_; - std::string resource_; - }; + class SWIFTEN_API ResourceBind : public Payload { + public: + ResourceBind() {} + + void setJID(const JID& jid) { + jid_ = jid; + } + + const JID& getJID() const { + return jid_; + } + + void setResource(const std::string& resource) { + resource_ = resource; + } + + const std::string& getResource() const { + return resource_; + } + + private: + JID jid_; + std::string resource_; + }; } diff --git a/Swiften/Elements/ResultSet.cpp b/Swiften/Elements/ResultSet.cpp new file mode 100644 index 0000000..4d04c38 --- /dev/null +++ b/Swiften/Elements/ResultSet.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file 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..c8e59d4 --- /dev/null +++ b/Swiften/Elements/ResultSet.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#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 setIndex(const boost::optional<int>& index) { index_ = index; } + const boost::optional<int>& getIndex() const { return index_; } + + 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 setBefore(const boost::optional<std::string>& before) { before_ = before; } + const boost::optional<std::string>& getBefore() const { return before_; } + + 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> index_; + boost::optional<int> firstIndex_; + boost::optional<std::string> firstID_; + boost::optional<std::string> lastID_; + boost::optional<std::string> before_; + boost::optional<std::string> after_; + }; +} diff --git a/Swiften/Elements/RosterItemExchangePayload.cpp b/Swiften/Elements/RosterItemExchangePayload.cpp index abd5296..79d0371 100644 --- a/Swiften/Elements/RosterItemExchangePayload.cpp +++ b/Swiften/Elements/RosterItemExchangePayload.cpp @@ -4,8 +4,13 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Elements/RosterItemExchangePayload.h> -#include <Swiften/Base/foreach.h> namespace Swift { diff --git a/Swiften/Elements/RosterItemExchangePayload.h b/Swiften/Elements/RosterItemExchangePayload.h index 622c775..fc61f3d 100644 --- a/Swiften/Elements/RosterItemExchangePayload.h +++ b/Swiften/Elements/RosterItemExchangePayload.h @@ -4,84 +4,90 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <vector> +#include <memory> #include <string> -#include <boost/shared_ptr.hpp> +#include <vector> #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> #include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API RosterItemExchangePayload : public Payload { - public: - typedef boost::shared_ptr<RosterItemExchangePayload> ref; + class SWIFTEN_API RosterItemExchangePayload : public Payload { + public: + typedef std::shared_ptr<RosterItemExchangePayload> ref; - class SWIFTEN_API Item { - public: - enum Action { Add, Modify, Delete }; + class SWIFTEN_API Item { + public: + enum Action { Add, Modify, Delete }; - Item(Action action = Add); + Item(Action action = Add); - Action getAction() const { - return action; - } + Action getAction() const { + return action; + } - void setAction(Action action) { - this->action = action; - } + void setAction(Action action) { + this->action = action; + } - const JID& getJID() const { - return jid; - } + const JID& getJID() const { + return jid; + } - void setJID(const JID& jid) { - this->jid = jid; - } + void setJID(const JID& jid) { + this->jid = jid; + } - const std::string& getName() const { - return name; - } + const std::string& getName() const { + return name; + } - void setName(const std::string& name) { - this->name = name; - } + void setName(const std::string& name) { + this->name = name; + } - const std::vector<std::string>& getGroups() const { - return groups; - } + const std::vector<std::string>& getGroups() const { + return groups; + } - void setGroups(const std::vector<std::string> &groups) { - this->groups = groups; - } + void setGroups(const std::vector<std::string> &groups) { + this->groups = groups; + } - void addGroup(const std::string& group) { - groups.push_back(group); - } + void addGroup(const std::string& group) { + groups.push_back(group); + } - private: - Action action; - JID jid; - std::string name; - std::vector<std::string> groups; - }; + private: + Action action; + JID jid; + std::string name; + std::vector<std::string> groups; + }; - typedef std::vector<RosterItemExchangePayload::Item> RosterItemExchangePayloadItems; + typedef std::vector<RosterItemExchangePayload::Item> RosterItemExchangePayloadItems; - public: - RosterItemExchangePayload(); + public: + RosterItemExchangePayload(); - void addItem(const RosterItemExchangePayload::Item& item) { - items_.push_back(item); - } + void addItem(const RosterItemExchangePayload::Item& item) { + items_.push_back(item); + } - const RosterItemExchangePayloadItems& getItems() const { - return items_; - } + const RosterItemExchangePayloadItems& getItems() const { + return items_; + } - private: - RosterItemExchangePayloadItems items_; - }; + private: + RosterItemExchangePayloadItems items_; + }; } diff --git a/Swiften/Elements/RosterItemPayload.h b/Swiften/Elements/RosterItemPayload.h index 915ae31..ea19fa5 100644 --- a/Swiften/Elements/RosterItemPayload.h +++ b/Swiften/Elements/RosterItemPayload.h @@ -1,51 +1,52 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <string> +#include <vector> +#include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> namespace Swift { - class RosterItemPayload { - public: - enum Subscription { None, To, From, Both, Remove }; - - RosterItemPayload() : subscription_(None), ask_(false) {} - RosterItemPayload(const JID& jid, const std::string& name, Subscription subscription, const std::vector<std::string>& groups = std::vector<std::string>()) : jid_(jid), name_(name), subscription_(subscription), groups_(groups), ask_(false) { } - - void setJID(const JID& jid) { jid_ = jid; } - const JID& getJID() const { return jid_; } - - void setName(const std::string& name) { name_ = name; } - const std::string& getName() const { return name_; } - - void setSubscription(Subscription subscription) { subscription_ = subscription; } - const Subscription& getSubscription() const { return subscription_; } - - void addGroup(const std::string& group) { groups_.push_back(group); } - void setGroups(const std::vector<std::string>& groups) { groups_ = groups; } - const std::vector<std::string>& getGroups() const { return groups_; } - - void setSubscriptionRequested() { ask_ = true; } - bool getSubscriptionRequested() const { return ask_; } - - const std::string& getUnknownContent() const { return unknownContent_; } - void addUnknownContent(const std::string& c) { - unknownContent_ += c; - } - - private: - JID jid_; - std::string name_; - Subscription subscription_; - std::vector<std::string> groups_; - bool ask_; - std::string unknownContent_; - }; + class SWIFTEN_API RosterItemPayload { + public: + enum Subscription { None, To, From, Both, Remove }; + + RosterItemPayload() : subscription_(None), ask_(false) {} + RosterItemPayload(const JID& jid, const std::string& name, Subscription subscription, const std::vector<std::string>& groups = std::vector<std::string>()) : jid_(jid), name_(name), subscription_(subscription), groups_(groups), ask_(false) { } + + void setJID(const JID& jid) { jid_ = jid; } + const JID& getJID() const { return jid_; } + + void setName(const std::string& name) { name_ = name; } + const std::string& getName() const { return name_; } + + void setSubscription(Subscription subscription) { subscription_ = subscription; } + const Subscription& getSubscription() const { return subscription_; } + + void addGroup(const std::string& group) { groups_.push_back(group); } + void setGroups(const std::vector<std::string>& groups) { groups_ = groups; } + const std::vector<std::string>& getGroups() const { return groups_; } + + void setSubscriptionRequested() { ask_ = true; } + bool getSubscriptionRequested() const { return ask_; } + + const std::string& getUnknownContent() const { return unknownContent_; } + void addUnknownContent(const std::string& c) { + unknownContent_ += c; + } + + private: + JID jid_; + std::string name_; + Subscription subscription_; + std::vector<std::string> groups_; + bool ask_; + std::string unknownContent_; + }; } diff --git a/Swiften/Elements/RosterPayload.cpp b/Swiften/Elements/RosterPayload.cpp index 6071cbc..d745357 100644 --- a/Swiften/Elements/RosterPayload.cpp +++ b/Swiften/Elements/RosterPayload.cpp @@ -1,23 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/RosterPayload.h> -#include <Swiften/Base/foreach.h> namespace Swift { boost::optional<RosterItemPayload> RosterPayload::getItem(const JID& jid) const { - foreach(const RosterItemPayload& item, items_) { - // FIXME: MSVC rejects this. Find out why. - //if (item.getJID() == jid) { - if (item.getJID().equals(jid, JID::WithResource)) { - return boost::optional<RosterItemPayload>(item); - } - } - return boost::optional<RosterItemPayload>(); + for (const auto& item : items_) { + // FIXME: MSVC rejects this. Find out why. + //if (item.getJID() == jid) { + if (item.getJID().equals(jid, JID::WithResource)) { + return boost::optional<RosterItemPayload>(item); + } + } + return boost::optional<RosterItemPayload>(); } } diff --git a/Swiften/Elements/RosterPayload.h b/Swiften/Elements/RosterPayload.h index 47d27f2..5fc6bd1 100644 --- a/Swiften/Elements/RosterPayload.h +++ b/Swiften/Elements/RosterPayload.h @@ -1,49 +1,49 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <vector> + #include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Elements/RosterItemPayload.h> #include <Swiften/Elements/Payload.h> - +#include <Swiften/Elements/RosterItemPayload.h> namespace Swift { - class SWIFTEN_API RosterPayload : public Payload { - public: - typedef boost::shared_ptr<RosterPayload> ref; - typedef std::vector<RosterItemPayload> RosterItemPayloads; + class SWIFTEN_API RosterPayload : public Payload { + public: + typedef std::shared_ptr<RosterPayload> ref; + typedef std::vector<RosterItemPayload> RosterItemPayloads; - public: - RosterPayload() {} + public: + RosterPayload() {} - boost::optional<RosterItemPayload> getItem(const JID& jid) const; + boost::optional<RosterItemPayload> getItem(const JID& jid) const; - void addItem(const RosterItemPayload& item) { - items_.push_back(item); - } + void addItem(const RosterItemPayload& item) { + items_.push_back(item); + } - const RosterItemPayloads& getItems() const { - return items_; - } + const RosterItemPayloads& getItems() const { + return items_; + } - const boost::optional<std::string>& getVersion() const { - return version_; - } + const boost::optional<std::string>& getVersion() const { + return version_; + } - void setVersion(const std::string& version) { - version_ = version; - } + void setVersion(const std::string& version) { + version_ = version; + } - private: - RosterItemPayloads items_; - boost::optional<std::string> version_; - }; + private: + RosterItemPayloads items_; + boost::optional<std::string> version_; + }; } diff --git a/Swiften/Elements/S5BProxyRequest.h b/Swiften/Elements/S5BProxyRequest.h index fcd0cb2..2fecae4 100644 --- a/Swiften/Elements/S5BProxyRequest.h +++ b/Swiften/Elements/S5BProxyRequest.h @@ -4,58 +4,66 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <string> #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> #include <Swiften/JID/JID.h> #include <Swiften/Network/HostAddressPort.h> namespace Swift { -class S5BProxyRequest : public Payload { +class SWIFTEN_API S5BProxyRequest : public Payload { public: - typedef boost::shared_ptr<S5BProxyRequest> ref; + typedef std::shared_ptr<S5BProxyRequest> ref; public: - struct StreamHost { - HostAddressPort addressPort; - JID jid; - }; + struct StreamHost { + std::string host; + unsigned short port; + JID jid; + }; public: - const boost::optional<StreamHost>& getStreamHost() const { - return streamHost; - } + const boost::optional<StreamHost>& getStreamHost() const { + return streamHost; + } - void setStreamHost(const StreamHost& streamHost) { - this->streamHost = boost::optional<StreamHost>(streamHost); - } + void setStreamHost(const StreamHost& streamHost) { + this->streamHost = boost::optional<StreamHost>(streamHost); + } - const std::string& getSID() const { - return sid; - } + const std::string& getSID() const { + return sid; + } - void setSID(const std::string& sid) { - this->sid = sid; - } + void setSID(const std::string& sid) { + this->sid = sid; + } - const boost::optional<JID>& getActivate() const { - return activate; - } + const boost::optional<JID>& getActivate() const { + return activate; + } - void setActivate(const JID& activate) { - this->activate = activate; - } + void setActivate(const JID& activate) { + this->activate = activate; + } private: - boost::optional<StreamHost> streamHost; + boost::optional<StreamHost> streamHost; - std::string sid; - boost::optional<JID> activate; + std::string sid; + boost::optional<JID> activate; }; } diff --git a/Swiften/Elements/SearchPayload.h b/Swiften/Elements/SearchPayload.h index 202007b..0fcb2b1 100644 --- a/Swiften/Elements/SearchPayload.h +++ b/Swiften/Elements/SearchPayload.h @@ -1,94 +1,96 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + #include <boost/optional.hpp> -#include <Swiften/Elements/Payload.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Form.h> -#include <string> +#include <Swiften/Elements/Payload.h> namespace Swift { - /** - * XEP-0055 search payload. - */ - class SearchPayload : public Payload { - public: - typedef boost::shared_ptr<SearchPayload> ref; - - struct Item { - std::string first; - std::string last; - std::string nick; - std::string email; - JID jid; - }; - - SearchPayload() {} - - Form::ref getForm() const { return form; } - void setForm(Form::ref f) { form = f; } - - const boost::optional<std::string>& getInstructions() const { - return instructions; - } - - const boost::optional<std::string>& getNick() const { - return nick; - } - - const boost::optional<std::string>& getFirst() const { - return first; - } - - const boost::optional<std::string>& getLast() const { - return last; - } - - const boost::optional<std::string>& getEMail() const { - return email; - } - - void setInstructions(const std::string& v) { - this->instructions = v; - } - - void setNick(const std::string& v) { - this->nick = v; - } - - void setFirst(const std::string& v) { - this->first = v; - } - - void setLast(const std::string& v) { - this->last = v; - } - - void setEMail(const std::string& v) { - this->email = v; - } - - const std::vector<Item>& getItems() const { - return items; - } - - void addItem(const Item& item) { - items.push_back(item); - } - - private: - Form::ref form; - boost::optional<std::string> instructions; - boost::optional<std::string> nick; - boost::optional<std::string> first; - boost::optional<std::string> last; - boost::optional<std::string> email; - std::vector<Item> items; - }; + /** + * XEP-0055 search payload. + */ + class SWIFTEN_API SearchPayload : public Payload { + public: + typedef std::shared_ptr<SearchPayload> ref; + + struct Item { + std::string first; + std::string last; + std::string nick; + std::string email; + JID jid; + }; + + SearchPayload() {} + + Form::ref getForm() const { return form; } + void setForm(Form::ref f) { form = f; } + + const boost::optional<std::string>& getInstructions() const { + return instructions; + } + + const boost::optional<std::string>& getNick() const { + return nick; + } + + const boost::optional<std::string>& getFirst() const { + return first; + } + + const boost::optional<std::string>& getLast() const { + return last; + } + + const boost::optional<std::string>& getEMail() const { + return email; + } + + void setInstructions(const std::string& v) { + this->instructions = v; + } + + void setNick(const std::string& v) { + this->nick = v; + } + + void setFirst(const std::string& v) { + this->first = v; + } + + void setLast(const std::string& v) { + this->last = v; + } + + void setEMail(const std::string& v) { + this->email = v; + } + + const std::vector<Item>& getItems() const { + return items; + } + + void addItem(const Item& item) { + items.push_back(item); + } + + private: + Form::ref form; + boost::optional<std::string> instructions; + boost::optional<std::string> nick; + boost::optional<std::string> first; + boost::optional<std::string> last; + boost::optional<std::string> email; + std::vector<Item> items; + }; } diff --git a/Swiften/Elements/SecurityLabel.cpp b/Swiften/Elements/SecurityLabel.cpp new file mode 100644 index 0000000..753c07e --- /dev/null +++ b/Swiften/Elements/SecurityLabel.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2010-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/SecurityLabel.h> + +using namespace Swift; + +SecurityLabel::SecurityLabel() { +} + +SecurityLabel::~SecurityLabel() { +} diff --git a/Swiften/Elements/SecurityLabel.h b/Swiften/Elements/SecurityLabel.h index a1714c8..fcaa610 100644 --- a/Swiften/Elements/SecurityLabel.h +++ b/Swiften/Elements/SecurityLabel.h @@ -1,61 +1,76 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <string> #include <vector> -#include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class SecurityLabel : public Payload { - public: - typedef boost::shared_ptr<SecurityLabel> ref; - SecurityLabel() {} + class SWIFTEN_API SecurityLabel : public Payload { + public: + using ref = std::shared_ptr<SecurityLabel>; + + SecurityLabel(); + + virtual ~SecurityLabel(); + + const std::vector< std::string >& getEquivalentLabels() const { + return equivalentLabels; + } + + void setEquivalentLabels(const std::vector< std::string >& value) { + this->equivalentLabels = value ; + } - const std::string& getDisplayMarking() const { return displayMarking_; } + void addEquivalentLabel(const std::string& value) { + this->equivalentLabels.push_back(value); + } - void setDisplayMarking(const std::string& displayMarking) { - displayMarking_ = displayMarking; - } + const std::string& getForegroundColor() const { + return foregroundColor; + } - const std::string& getForegroundColor() const { - return foregroundColor_; - } + void setForegroundColor(const std::string& value) { + this->foregroundColor = value ; + } - void setForegroundColor(const std::string& foregroundColor) { - foregroundColor_ = foregroundColor; - } + const std::string& getDisplayMarking() const { + return displayMarking; + } - const std::string& getBackgroundColor() const { - return backgroundColor_; - } + void setDisplayMarking(const std::string& value) { + this->displayMarking = value ; + } - void setBackgroundColor(const std::string& backgroundColor) { - backgroundColor_ = backgroundColor; - } + const std::string& getBackgroundColor() const { + return backgroundColor; + } - const std::string& getLabel() const { return label_; } + void setBackgroundColor(const std::string& value) { + this->backgroundColor = value ; + } - void setLabel(const std::string& label) { - label_ = label; - } + const std::string& getLabel() const { + return label; + } - const std::vector<std::string>& getEquivalentLabels() const { return equivalentLabels_; } + void setLabel(const std::string& value) { + this->label = value ; + } - void addEquivalentLabel(const std::string& label) { - equivalentLabels_.push_back(label); - } - private: - std::string displayMarking_; - std::string foregroundColor_; - std::string backgroundColor_; - std::string label_; - std::vector<std::string> equivalentLabels_; - }; + private: + std::vector< std::string > equivalentLabels; + std::string foregroundColor; + std::string displayMarking; + std::string backgroundColor; + std::string label; + }; } diff --git a/Swiften/Elements/SecurityLabelsCatalog.h b/Swiften/Elements/SecurityLabelsCatalog.h index 420cf6f..ba4d294 100644 --- a/Swiften/Elements/SecurityLabelsCatalog.h +++ b/Swiften/Elements/SecurityLabelsCatalog.h @@ -1,89 +1,89 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> +#include <memory> #include <string> -#include <boost/shared_ptr.hpp> +#include <vector> #include <Swiften/Base/API.h> -#include <Swiften/JID/JID.h> #include <Swiften/Elements/Payload.h> #include <Swiften/Elements/SecurityLabel.h> +#include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API SecurityLabelsCatalog : public Payload { - public: - typedef boost::shared_ptr<SecurityLabelsCatalog> ref; - class Item { - public: - Item() : default_(false) {} - SecurityLabel::ref getLabel() const { - return label_; - } - - void setLabel(SecurityLabel::ref label) { - label_ = label; - } - - const std::string& getSelector() const { return selector_; } - - void setSelector(const std::string& selector) { - selector_ = selector; - } - - bool getIsDefault() const { return default_; } - - void setIsDefault(bool isDefault) { - default_ = isDefault; - } - private: - SecurityLabel::ref label_; - std::string selector_; - bool default_; - }; - SecurityLabelsCatalog(const JID& to = JID()) : to_(to) {} - - const std::vector<Item>& getItems() const { - return items_; - } - - void addItem(const Item& item) { - items_.push_back(item); - } - - const JID& getTo() const { - return to_; - } - - void setTo(const JID& to) { - to_ = to; - } - - const std::string& getName() const { - return name_; - } - - void setName(const std::string& name) { - name_ = name; - } - - const std::string& getDescription() const { - return description_; - } - - void setDescription(const std::string& description) { - description_ = description; - } - - private: - JID to_; - std::string name_; - std::string description_; - std::vector<Item> items_; - }; + class SWIFTEN_API SecurityLabelsCatalog : public Payload { + public: + typedef std::shared_ptr<SecurityLabelsCatalog> ref; + class Item { + public: + Item() : default_(false) {} + std::shared_ptr<SecurityLabel> getLabel() const { + return label_; + } + + void setLabel(std::shared_ptr<SecurityLabel> label) { + label_ = label; + } + + const std::string& getSelector() const { return selector_; } + + void setSelector(const std::string& selector) { + selector_ = selector; + } + + bool getIsDefault() const { return default_; } + + void setIsDefault(bool isDefault) { + default_ = isDefault; + } + private: + std::shared_ptr<SecurityLabel> label_; + std::string selector_; + bool default_; + }; + SecurityLabelsCatalog(const JID& to = JID()) : to_(to) {} + + const std::vector<Item>& getItems() const { + return items_; + } + + void addItem(const Item& item) { + items_.push_back(item); + } + + const JID& getTo() const { + return to_; + } + + void setTo(const JID& to) { + to_ = to; + } + + const std::string& getName() const { + return name_; + } + + void setName(const std::string& name) { + name_ = name; + } + + const std::string& getDescription() const { + return description_; + } + + void setDescription(const std::string& description) { + description_ = description; + } + + private: + JID to_; + std::string name_; + std::string description_; + std::vector<Item> items_; + }; } diff --git a/Swiften/Elements/SoftwareVersion.h b/Swiften/Elements/SoftwareVersion.h index e0eeaa3..2bf582e 100644 --- a/Swiften/Elements/SoftwareVersion.h +++ b/Swiften/Elements/SoftwareVersion.h @@ -1,55 +1,55 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <string> -#include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class SWIFTEN_API SoftwareVersion : public Payload { - public: - typedef boost::shared_ptr<SoftwareVersion> ref; - - SoftwareVersion( - const std::string& name = "", - const std::string& version = "", - const std::string& os = "") : - name_(name), version_(version), os_(os) {} - - const std::string& getName() const { - return name_; - } - - void setName(const std::string& name) { - name_ = name; - } - - const std::string& getVersion() const { - return version_; - } - - void setVersion(const std::string& version) { - version_ = version; - } - - const std::string& getOS() const { - return os_; - } - - void setOS(const std::string& os) { - os_ = os; - } - - private: - std::string name_; - std::string version_; - std::string os_; - }; + class SWIFTEN_API SoftwareVersion : public Payload { + public: + typedef std::shared_ptr<SoftwareVersion> ref; + + SoftwareVersion( + const std::string& name = "", + const std::string& version = "", + const std::string& os = "") : + name_(name), version_(version), os_(os) {} + + const std::string& getName() const { + return name_; + } + + void setName(const std::string& name) { + name_ = name; + } + + const std::string& getVersion() const { + return version_; + } + + void setVersion(const std::string& version) { + version_ = version; + } + + const std::string& getOS() const { + return os_; + } + + void setOS(const std::string& os) { + os_ = os; + } + + private: + std::string name_; + std::string version_; + std::string os_; + }; } diff --git a/Swiften/Elements/Stanza.cpp b/Swiften/Elements/Stanza.cpp index 23f2d89..0ff6b3c 100644 --- a/Swiften/Elements/Stanza.cpp +++ b/Swiften/Elements/Stanza.cpp @@ -1,57 +1,68 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/Stanza.h> -#include <Swiften/Elements/Delay.h> #include <typeinfo> -#include <Swiften/Base/foreach.h> +#include <boost/bind.hpp> + +#include <Swiften/Elements/Delay.h> namespace Swift { Stanza::Stanza() { } - + Stanza::~Stanza() { - payloads_.clear(); + payloads_.clear(); +} + +void Stanza::updatePayload(std::shared_ptr<Payload> payload) { + for (auto&& i : payloads_) { + if (typeid(*i.get()) == typeid(*payload.get())) { + i = payload; + return; + } + } + addPayload(payload); +} + +static bool sameType(std::shared_ptr<Payload> a, std::shared_ptr<Payload> b) { + return typeid(*a.get()) == typeid(*b.get()); } -void Stanza::updatePayload(boost::shared_ptr<Payload> payload) { - foreach (boost::shared_ptr<Payload>& i, payloads_) { - if (typeid(*i.get()) == typeid(*payload.get())) { - i = payload; - return; - } - } - addPayload(payload); +void Stanza::removePayloadOfSameType(std::shared_ptr<Payload> payload) { + payloads_.erase(std::remove_if(payloads_.begin(), payloads_.end(), + boost::bind<bool>(&sameType, payload, _1)), + payloads_.end()); } -boost::shared_ptr<Payload> Stanza::getPayloadOfSameType(boost::shared_ptr<Payload> payload) const { - foreach (const boost::shared_ptr<Payload>& i, payloads_) { - if (typeid(*i.get()) == typeid(*payload.get())) { - return i; - } - } - return boost::shared_ptr<Payload>(); +std::shared_ptr<Payload> Stanza::getPayloadOfSameType(std::shared_ptr<Payload> payload) const { + for (const auto& i : payloads_) { + if (typeid(*i.get()) == typeid(*payload.get())) { + return i; + } + } + return std::shared_ptr<Payload>(); } boost::optional<boost::posix_time::ptime> Stanza::getTimestamp() const { - boost::shared_ptr<Delay> delay = getPayload<Delay>(); - return delay ? delay->getStamp() : boost::optional<boost::posix_time::ptime>(); + std::shared_ptr<Delay> delay = getPayload<Delay>(); + return delay ? delay->getStamp() : boost::optional<boost::posix_time::ptime>(); } boost::optional<boost::posix_time::ptime> Stanza::getTimestampFrom(const JID& jid) const { - std::vector< boost::shared_ptr<Delay> > delays = getPayloads<Delay>(); - for (size_t i = 0; i < delays.size(); ++i) { - if (delays[i]->getFrom() == jid) { - return delays[i]->getStamp(); - } - } - return getTimestamp(); + std::vector< std::shared_ptr<Delay> > delays = getPayloads<Delay>(); + for (auto& delay : delays) { + if (delay->getFrom() == jid) { + return delay->getStamp(); + } + } + return getTimestamp(); } diff --git a/Swiften/Elements/Stanza.h b/Swiften/Elements/Stanza.h index fbb0139..8b4916e 100644 --- a/Swiften/Elements/Stanza.h +++ b/Swiften/Elements/Stanza.h @@ -1,85 +1,101 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> +#include <memory> #include <string> -#include <boost/shared_ptr.hpp> -#include <boost/optional/optional_fwd.hpp> +#include <vector> + #include <boost/date_time/posix_time/ptime.hpp> +#include <boost/optional/optional.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Elements/Element.h> +#include <Swiften/Elements/ToplevelElement.h> #include <Swiften/JID/JID.h> namespace Swift { - class Payload; - - class SWIFTEN_API Stanza : public Element { - public: - typedef boost::shared_ptr<Stanza> ref; - - Stanza(); - virtual ~Stanza(); - - template<typename T> - boost::shared_ptr<T> getPayload() const { - for (size_t i = 0; i < payloads_.size(); ++i) { - boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(payloads_[i])); - if (result) { - return result; - } - } - return boost::shared_ptr<T>(); - } - - template<typename T> - std::vector< boost::shared_ptr<T> > getPayloads() const { - std::vector< boost::shared_ptr<T> > results; - for (size_t i = 0; i < payloads_.size(); ++i) { - boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(payloads_[i])); - if (result) { - results.push_back(result); - } - } - return results; - } - - - const std::vector< boost::shared_ptr<Payload> >& getPayloads() const { - return payloads_; - } - - void addPayload(boost::shared_ptr<Payload> payload) { - payloads_.push_back(payload); - } - - void updatePayload(boost::shared_ptr<Payload> payload); - - boost::shared_ptr<Payload> getPayloadOfSameType(boost::shared_ptr<Payload>) const; - - const JID& getFrom() const { return from_; } - void setFrom(const JID& from) { from_ = from; } - - const JID& getTo() const { return to_; } - void setTo(const JID& to) { to_ = to; } - - const std::string& getID() const { return id_; } - void setID(const std::string& id) { id_ = id; } - - boost::optional<boost::posix_time::ptime> getTimestamp() const; - - // Falls back to any timestamp if no specific timestamp for the given JID is found. - boost::optional<boost::posix_time::ptime> getTimestampFrom(const JID& jid) const; - - private: - std::string id_; - JID from_; - JID to_; - std::vector< boost::shared_ptr<Payload> > payloads_; - }; + class Payload; + + class SWIFTEN_API Stanza : public ToplevelElement { + public: + typedef std::shared_ptr<Stanza> ref; + + protected: + Stanza(); + + public: + virtual ~Stanza(); + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(Stanza) + + template<typename T> + std::shared_ptr<T> getPayload() const { + for (const auto& payload : payloads_) { + std::shared_ptr<T> result(std::dynamic_pointer_cast<T>(payload)); + if (result) { + return result; + } + } + return std::shared_ptr<T>(); + } + + template<typename T> + std::vector< std::shared_ptr<T> > getPayloads() const { + std::vector< std::shared_ptr<T> > results; + for (const auto& payload : payloads_) { + std::shared_ptr<T> result(std::dynamic_pointer_cast<T>(payload)); + if (result) { + results.push_back(result); + } + } + return results; + } + + + const std::vector< std::shared_ptr<Payload> >& getPayloads() const { + return payloads_; + } + + void addPayload(std::shared_ptr<Payload> payload) { + payloads_.push_back(payload); + } + + template<typename InputIterator> + void addPayloads(InputIterator begin, InputIterator end) { + payloads_.insert(payloads_.end(), begin, end); + } + + template<typename Container> + void addPayloads(const Container& container) { + payloads_.insert(payloads_.end(), std::begin(container), std::end(container)); + } + + void updatePayload(std::shared_ptr<Payload> payload); + + void removePayloadOfSameType(std::shared_ptr<Payload>); + std::shared_ptr<Payload> getPayloadOfSameType(std::shared_ptr<Payload>) const; + + const JID& getFrom() const { return from_; } + void setFrom(const JID& from) { from_ = from; } + + const JID& getTo() const { return to_; } + void setTo(const JID& to) { to_ = to; } + + const std::string& getID() const { return id_; } + void setID(const std::string& id) { id_ = id; } + + boost::optional<boost::posix_time::ptime> getTimestamp() const; + + // Falls back to any timestamp if no specific timestamp for the given JID is found. + boost::optional<boost::posix_time::ptime> getTimestampFrom(const JID& jid) const; + + private: + std::string id_; + JID from_; + JID to_; + std::vector< std::shared_ptr<Payload> > payloads_; + }; } diff --git a/Swiften/Elements/StanzaAck.cpp b/Swiften/Elements/StanzaAck.cpp index 5bcab73..dda97f5 100644 --- a/Swiften/Elements/StanzaAck.cpp +++ b/Swiften/Elements/StanzaAck.cpp @@ -1,19 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/StanzaAck.h> -#include <boost/numeric/conversion/cast.hpp> - using namespace Swift; StanzaAck::~StanzaAck() { } -void StanzaAck::setHandledStanzasCount(int i) { - handledStanzasCount = boost::numeric_cast<unsigned int>(i); - valid = true; +void StanzaAck::setHandledStanzasCount(unsigned int i) { + handledStanzasCount = i; + valid = true; } diff --git a/Swiften/Elements/StanzaAck.h b/Swiften/Elements/StanzaAck.h index 8fe64e0..f664aca 100644 --- a/Swiften/Elements/StanzaAck.h +++ b/Swiften/Elements/StanzaAck.h @@ -1,36 +1,37 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class StanzaAck : public Element { - public: - typedef boost::shared_ptr<StanzaAck> ref; + class SWIFTEN_API StanzaAck : public ToplevelElement { + public: + typedef std::shared_ptr<StanzaAck> ref; - StanzaAck() : valid(false), handledStanzasCount(0) {} - StanzaAck(unsigned int handledStanzasCount) : valid(true), handledStanzasCount(handledStanzasCount) {} - virtual ~StanzaAck(); + StanzaAck() : valid(false), handledStanzasCount(0) {} + StanzaAck(unsigned int handledStanzasCount) : valid(true), handledStanzasCount(handledStanzasCount) {} + virtual ~StanzaAck(); - unsigned int getHandledStanzasCount() const { - return handledStanzasCount; - } + unsigned int getHandledStanzasCount() const { + return handledStanzasCount; + } - void setHandledStanzasCount(int i); + void setHandledStanzasCount(unsigned int i); - bool isValid() const { - return valid; - } + bool isValid() const { + return valid; + } - private: - bool valid; - unsigned int handledStanzasCount; - }; + private: + bool valid; + unsigned int handledStanzasCount; + }; } diff --git a/Swiften/Elements/StanzaAckRequest.h b/Swiften/Elements/StanzaAckRequest.h index 81b3871..e9b95b5 100644 --- a/Swiften/Elements/StanzaAckRequest.h +++ b/Swiften/Elements/StanzaAckRequest.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Element.h> - +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class StanzaAckRequest : public Element { - }; + class SWIFTEN_API StanzaAckRequest : public ToplevelElement { + }; } diff --git a/Swiften/Elements/StartSession.h b/Swiften/Elements/StartSession.h index 7aeb611..a40865e 100644 --- a/Swiften/Elements/StartSession.h +++ b/Swiften/Elements/StartSession.h @@ -1,17 +1,19 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class StartSession : public Payload { - public: - StartSession() {} - }; + class SWIFTEN_API StartSession : public Payload { + public: + StartSession() {} + }; } diff --git a/Swiften/Elements/StartTLSFailure.h b/Swiften/Elements/StartTLSFailure.h index 5e233fb..5867e3f 100644 --- a/Swiften/Elements/StartTLSFailure.h +++ b/Swiften/Elements/StartTLSFailure.h @@ -1,16 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class StartTLSFailure : public Element { - public: - StartTLSFailure() {} - }; + class SWIFTEN_API StartTLSFailure : public ToplevelElement { + public: + StartTLSFailure() {} + }; } diff --git a/Swiften/Elements/StartTLSRequest.h b/Swiften/Elements/StartTLSRequest.h index e284f75..f47a21d 100644 --- a/Swiften/Elements/StartTLSRequest.h +++ b/Swiften/Elements/StartTLSRequest.h @@ -1,16 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class StartTLSRequest : public Element { - public: - StartTLSRequest() {} - }; + class SWIFTEN_API StartTLSRequest : public ToplevelElement { + public: + StartTLSRequest() {} + }; } diff --git a/Swiften/Elements/Status.h b/Swiften/Elements/Status.h index 956f33d..2fd2eff 100644 --- a/Swiften/Elements/Status.h +++ b/Swiften/Elements/Status.h @@ -1,29 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Payload.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + namespace Swift { - class Status : public Payload { - public: - Status(const std::string& text = "") : text_(text) { - } + class SWIFTEN_API Status : public Payload { + public: + Status(const std::string& text = "") : text_(text) { + } - void setText(const std::string& text) { - text_ = text; - } + void setText(const std::string& text) { + text_ = text; + } - const std::string& getText() const { - return text_; - } + const std::string& getText() const { + return text_; + } - private: - std::string text_; - }; + private: + std::string text_; + }; } diff --git a/Swiften/Elements/StatusShow.cpp b/Swiften/Elements/StatusShow.cpp index 656e5c4..633816e 100644 --- a/Swiften/Elements/StatusShow.cpp +++ b/Swiften/Elements/StatusShow.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/StatusShow.h> diff --git a/Swiften/Elements/StatusShow.h b/Swiften/Elements/StatusShow.h index afa30de..b339fa1 100644 --- a/Swiften/Elements/StatusShow.h +++ b/Swiften/Elements/StatusShow.h @@ -1,48 +1,49 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <cassert> + #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> -#include <cassert> namespace Swift { - class SWIFTEN_API StatusShow : public Payload { - public: - enum Type { Online, Away, FFC, XA, DND, None }; - - StatusShow(const Type& type = Online); - - void setType(const Type& type) { - type_ = type; - } - - const Type& getType() const { - return type_; - } - - /** - * Can be used for rough ordering of Types. - * Greater magnitude = more available. - */ - static int typeToAvailabilityOrdering(Type type) { - switch (type) { - case Online: return 4; - case FFC: return 5; - case Away: return 2; - case XA: return 1; - case DND: return 3; - case None: return 0; - } - assert(false); - return 0; - } - - private: - Type type_; - }; + class SWIFTEN_API StatusShow : public Payload { + public: + enum Type { Online, Away, FFC, XA, DND, None }; + + StatusShow(const Type& type = Online); + + void setType(const Type& type) { + type_ = type; + } + + const Type& getType() const { + return type_; + } + + /** + * Can be used for rough ordering of Types. + * Greater magnitude = more available. + */ + static int typeToAvailabilityOrdering(Type type) { + switch (type) { + case Online: return 4; + case FFC: return 5; + case Away: return 2; + case XA: return 1; + case DND: return 3; + case None: return 0; + } + assert(false); + return 0; + } + + private: + Type type_; + }; } diff --git a/Swiften/Elements/Storage.h b/Swiften/Elements/Storage.h index 03c958c..87cfb39 100644 --- a/Swiften/Elements/Storage.h +++ b/Swiften/Elements/Storage.h @@ -1,66 +1,67 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <string> #include <vector> #include <boost/optional.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Base/SafeString.h> #include <Swiften/Elements/Payload.h> -#include <string> #include <Swiften/JID/JID.h> -#include <Swiften/Base/SafeString.h> namespace Swift { - class Storage : public Payload { - public: - struct Room { - Room() : autoJoin(false) {} - - std::string name; - JID jid; - bool autoJoin; - std::string nick; - boost::optional<std::string> password; - }; - - struct URL { - URL() {} - - std::string name; - std::string url; - }; - - Storage() { - } - - - void clearRooms() { - rooms.clear(); - } - - const std::vector<Room>& getRooms() const { - return rooms; - } - - void addRoom(const Room& room) { - rooms.push_back(room); - } - - const std::vector<URL>& getURLs() const { - return urls; - } - - void addURL(const URL& url) { - urls.push_back(url); - } - - private: - std::vector<Room> rooms; - std::vector<URL> urls; - }; + class SWIFTEN_API Storage : public Payload { + public: + struct Room { + Room() : autoJoin(false) {} + + std::string name; + JID jid; + bool autoJoin; + std::string nick; + boost::optional<std::string> password; + }; + + struct URL { + URL() {} + + std::string name; + std::string url; + }; + + Storage() { + } + + + void clearRooms() { + rooms.clear(); + } + + const std::vector<Room>& getRooms() const { + return rooms; + } + + void addRoom(const Room& room) { + rooms.push_back(room); + } + + const std::vector<URL>& getURLs() const { + return urls; + } + + void addURL(const URL& url) { + urls.push_back(url); + } + + private: + std::vector<Room> rooms; + std::vector<URL> urls; + }; } diff --git a/Swiften/Elements/StreamError.h b/Swiften/Elements/StreamError.h index a58d3ae..6dda15c 100644 --- a/Swiften/Elements/StreamError.h +++ b/Swiften/Elements/StreamError.h @@ -1,69 +1,70 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> - -#include <Swiften/Elements/Element.h> +#include <memory> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> + namespace Swift { - class StreamError : public Element { - public: - typedef boost::shared_ptr<StreamError> ref; + class SWIFTEN_API StreamError : public ToplevelElement { + public: + typedef std::shared_ptr<StreamError> ref; - enum Type { - BadFormat, - BadNamespacePrefix, - Conflict, - ConnectionTimeout, - HostGone, - HostUnknown, - ImproperAddressing, - InternalServerError, - InvalidFrom, - InvalidID, - InvalidNamespace, - InvalidXML, - NotAuthorized, - NotWellFormed, - PolicyViolation, - RemoteConnectionFailed, - Reset, - ResourceConstraint, - RestrictedXML, - SeeOtherHost, - SystemShutdown, - UndefinedCondition, - UnsupportedEncoding, - UnsupportedStanzaType, - UnsupportedVersion - }; + enum Type { + BadFormat, + BadNamespacePrefix, + Conflict, + ConnectionTimeout, + HostGone, + HostUnknown, + ImproperAddressing, + InternalServerError, + InvalidFrom, + InvalidNamespace, + InvalidXML, + NotAuthorized, + NotWellFormed, + PolicyViolation, + RemoteConnectionFailed, + Reset, + ResourceConstraint, + RestrictedXML, + SeeOtherHost, + SystemShutdown, + UndefinedCondition, + UnsupportedEncoding, + UnsupportedFeature, + UnsupportedStanzaType, + UnsupportedVersion + }; - StreamError(Type type = UndefinedCondition, const std::string& text = std::string()) : type_(type), text_(text) { } + StreamError(Type type = UndefinedCondition, const std::string& text = std::string()) : type_(type), text_(text) { } - Type getType() const { - return type_; - } + Type getType() const { + return type_; + } - void setType(Type type) { - type_ = type; - } + void setType(Type type) { + type_ = type; + } - void setText(const std::string& text) { - text_ = text; - } + void setText(const std::string& text) { + text_ = text; + } - const std::string& getText() const { - return text_; - } + const std::string& getText() const { + return text_; + } - private: - Type type_; - std::string text_; - }; + private: + Type type_; + std::string text_; + }; } diff --git a/Swiften/Elements/StreamFeatures.cpp b/Swiften/Elements/StreamFeatures.cpp index c6f6c04..77bafac 100644 --- a/Swiften/Elements/StreamFeatures.cpp +++ b/Swiften/Elements/StreamFeatures.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/StreamFeatures.h> @@ -11,11 +11,11 @@ namespace Swift { bool StreamFeatures::hasCompressionMethod(const std::string& mechanism) const { - return std::find(compressionMethods_.begin(), compressionMethods_.end(), mechanism) != compressionMethods_.end(); + return std::find(compressionMethods_.begin(), compressionMethods_.end(), mechanism) != compressionMethods_.end(); } bool StreamFeatures::hasAuthenticationMechanism(const std::string& mechanism) const { - return std::find(authenticationMechanisms_.begin(), authenticationMechanisms_.end(), mechanism) != authenticationMechanisms_.end(); + return std::find(authenticationMechanisms_.begin(), authenticationMechanisms_.end(), mechanism) != authenticationMechanisms_.end(); } } diff --git a/Swiften/Elements/StreamFeatures.h b/Swiften/Elements/StreamFeatures.h index 5e7b6c9..5832a24 100644 --- a/Swiften/Elements/StreamFeatures.h +++ b/Swiften/Elements/StreamFeatures.h @@ -1,96 +1,107 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> +#include <memory> #include <string> -#include <boost/shared_ptr.hpp> +#include <vector> + +#include <boost/optional.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Elements/Element.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class SWIFTEN_API StreamFeatures : public Element { - public: - typedef boost::shared_ptr<StreamFeatures> ref; - - StreamFeatures() : hasStartTLS_(false), hasResourceBind_(false), hasSession_(false), hasStreamManagement_(false), hasRosterVersioning_(false) {} - - void setHasStartTLS() { - hasStartTLS_ = true; - } - - bool hasStartTLS() const { - return hasStartTLS_; - } - - void setHasSession() { - hasSession_ = true; - } - - bool hasSession() const { - return hasSession_; - } - - void setHasResourceBind() { - hasResourceBind_ = true; - } - - bool hasResourceBind() const { - return hasResourceBind_; - } - - const std::vector<std::string>& getCompressionMethods() const { - return compressionMethods_; - } - - void addCompressionMethod(const std::string& mechanism) { - compressionMethods_.push_back(mechanism); - } - - bool hasCompressionMethod(const std::string& mechanism) const; - - const std::vector<std::string>& getAuthenticationMechanisms() const { - return authenticationMechanisms_; - } - - void addAuthenticationMechanism(const std::string& mechanism) { - authenticationMechanisms_.push_back(mechanism); - } - - bool hasAuthenticationMechanism(const std::string& mechanism) const; - - bool hasAuthenticationMechanisms() const { - return !authenticationMechanisms_.empty(); - } - - bool hasStreamManagement() const { - return hasStreamManagement_; - } - - void setHasStreamManagement() { - hasStreamManagement_ = true; - } - - bool hasRosterVersioning() const { - return hasRosterVersioning_; - } - - void setHasRosterVersioning() { - hasRosterVersioning_ = true; - } - - private: - bool hasStartTLS_; - std::vector<std::string> compressionMethods_; - std::vector<std::string> authenticationMechanisms_; - bool hasResourceBind_; - bool hasSession_; - bool hasStreamManagement_; - bool hasRosterVersioning_; - }; + class SWIFTEN_API StreamFeatures : public ToplevelElement { + public: + typedef std::shared_ptr<StreamFeatures> ref; + + StreamFeatures() : hasStartTLS_(false), hasResourceBind_(false), hasSession_(false), hasStreamManagement_(false), hasRosterVersioning_(false) {} + + void setHasStartTLS() { + hasStartTLS_ = true; + } + + bool hasStartTLS() const { + return hasStartTLS_; + } + + void setHasSession() { + hasSession_ = true; + } + + bool hasSession() const { + return hasSession_; + } + + void setHasResourceBind() { + hasResourceBind_ = true; + } + + bool hasResourceBind() const { + return hasResourceBind_; + } + + const std::vector<std::string>& getCompressionMethods() const { + return compressionMethods_; + } + + void addCompressionMethod(const std::string& mechanism) { + compressionMethods_.push_back(mechanism); + } + + bool hasCompressionMethod(const std::string& mechanism) const; + + const std::vector<std::string>& getAuthenticationMechanisms() const { + return authenticationMechanisms_; + } + + void addAuthenticationMechanism(const std::string& mechanism) { + authenticationMechanisms_.push_back(mechanism); + } + + bool hasAuthenticationMechanism(const std::string& mechanism) const; + + bool hasAuthenticationMechanisms() const { + return !authenticationMechanisms_.empty(); + } + + const boost::optional<std::string> getAuthenticationHostname() const { + return authenticationHostname_; + } + + void setAuthenticationHostname(const boost::optional<std::string> authenticationHostname) { + authenticationHostname_ = authenticationHostname; + } + + bool hasStreamManagement() const { + return hasStreamManagement_; + } + + void setHasStreamManagement() { + hasStreamManagement_ = true; + } + + bool hasRosterVersioning() const { + return hasRosterVersioning_; + } + + void setHasRosterVersioning() { + hasRosterVersioning_ = true; + } + + private: + bool hasStartTLS_; + std::vector<std::string> compressionMethods_; + std::vector<std::string> authenticationMechanisms_; + bool hasResourceBind_; + bool hasSession_; + bool hasStreamManagement_; + bool hasRosterVersioning_; + boost::optional<std::string> authenticationHostname_; + }; } diff --git a/Swiften/Elements/StreamInitiation.h b/Swiften/Elements/StreamInitiation.h index c1f0b4d..2bb9a0e 100644 --- a/Swiften/Elements/StreamInitiation.h +++ b/Swiften/Elements/StreamInitiation.h @@ -1,71 +1,73 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> +#include <string> #include <vector> + #include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> -#include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> #include <Swiften/Elements/StreamInitiationFileInfo.h> namespace Swift { - class StreamInitiation : public Payload { - public: - typedef boost::shared_ptr<StreamInitiation> ref; - - StreamInitiation() : isFileTransfer(true) {} - - const std::string& getID() const { - return id; - } - - void setID(const std::string& id) { - this->id = id; - } - - const boost::optional<StreamInitiationFileInfo>& getFileInfo() const { - return fileInfo; - } - - void setFileInfo(const StreamInitiationFileInfo& info) { - fileInfo = info; - } - - const std::vector<std::string>& getProvidedMethods() const { - return providedMethods; - } - - void addProvidedMethod(const std::string& method) { - providedMethods.push_back(method); - } - - void setRequestedMethod(const std::string& method) { - requestedMethod = method; - } - - const std::string& getRequestedMethod() const { - return requestedMethod; - } - - bool getIsFileTransfer() const { - return isFileTransfer; - } - - void setIsFileTransfer(bool b) { - isFileTransfer = b; - } - - private: - bool isFileTransfer; - std::string id; - boost::optional<StreamInitiationFileInfo> fileInfo; - std::vector<std::string> providedMethods; - std::string requestedMethod; - }; + class SWIFTEN_API StreamInitiation : public Payload { + public: + typedef std::shared_ptr<StreamInitiation> ref; + + StreamInitiation() : isFileTransfer(true) {} + + const std::string& getID() const { + return id; + } + + void setID(const std::string& id) { + this->id = id; + } + + const boost::optional<StreamInitiationFileInfo>& getFileInfo() const { + return fileInfo; + } + + void setFileInfo(const StreamInitiationFileInfo& info) { + fileInfo = info; + } + + const std::vector<std::string>& getProvidedMethods() const { + return providedMethods; + } + + void addProvidedMethod(const std::string& method) { + providedMethods.push_back(method); + } + + void setRequestedMethod(const std::string& method) { + requestedMethod = method; + } + + const std::string& getRequestedMethod() const { + return requestedMethod; + } + + bool getIsFileTransfer() const { + return isFileTransfer; + } + + void setIsFileTransfer(bool b) { + isFileTransfer = b; + } + + private: + bool isFileTransfer; + std::string id; + boost::optional<StreamInitiationFileInfo> fileInfo; + std::vector<std::string> providedMethods; + std::string requestedMethod; + }; } diff --git a/Swiften/Elements/StreamInitiationFileInfo.h b/Swiften/Elements/StreamInitiationFileInfo.h index d7907b9..773814f 100644 --- a/Swiften/Elements/StreamInitiationFileInfo.h +++ b/Swiften/Elements/StreamInitiationFileInfo.h @@ -1,102 +1,104 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Payload.h> -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + #include <boost/date_time/posix_time/posix_time_types.hpp> -#include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> namespace Swift { -class StreamInitiationFileInfo : public Payload { +class SWIFTEN_API StreamInitiationFileInfo : public Payload { public: - typedef boost::shared_ptr<StreamInitiationFileInfo> ref; - + typedef std::shared_ptr<StreamInitiationFileInfo> ref; + public: - StreamInitiationFileInfo(const std::string& name = "", const std::string& description = "", unsigned long long size = 0, - const std::string& hash = "", const boost::posix_time::ptime &date = boost::posix_time::ptime(), const std::string& algo="md5") : - name(name), description(description), size(size), hash(hash), date(date), algo(algo), supportsRangeRequests(false), rangeOffset(0) {} - - void setName(const std::string& name) { - this->name = name;; - } - - const std::string& getName() const { - return this->name; - } - - void setDescription(const std::string& description) { - this->description = description; - } - - const std::string& getDescription() const { - return this->description; - } - - void setSize(const unsigned long long size) { - this->size = size; - } - - unsigned long long getSize() const { - return this->size; - } - - void setHash(const std::string& hash) { - this->hash = hash; - } - - const std::string& getHash() const { - return this->hash; - } - - void setDate(const boost::posix_time::ptime& date) { - this->date = date; - } - - const boost::posix_time::ptime& getDate() const { - return this->date; - } - - void setAlgo(const std::string& algo) { - this->algo = algo; - } - - const std::string& getAlgo() const { - return this->algo; - } - - void setSupportsRangeRequests(const bool supportsIt) { - supportsRangeRequests = supportsIt; - } - - bool getSupportsRangeRequests() const { - return supportsRangeRequests; - } - - void setRangeOffset(unsigned long long offset) { - supportsRangeRequests = true; - rangeOffset = offset; - } - - unsigned long long getRangeOffset() const { - return rangeOffset; - } + StreamInitiationFileInfo(const std::string& name = "", const std::string& description = "", unsigned long long size = 0, + const std::string& hash = "", const boost::posix_time::ptime &date = boost::posix_time::ptime(), const std::string& algo="md5") : + name(name), description(description), size(size), hash(hash), date(date), algo(algo), supportsRangeRequests(false), rangeOffset(0) {} + + void setName(const std::string& name) { + this->name = name; + } + + const std::string& getName() const { + return this->name; + } + + void setDescription(const std::string& description) { + this->description = description; + } + + const std::string& getDescription() const { + return this->description; + } + + void setSize(const unsigned long long size) { + this->size = size; + } + + unsigned long long getSize() const { + return this->size; + } + + void setHash(const std::string& hash) { + this->hash = hash; + } + + const std::string& getHash() const { + return this->hash; + } + + void setDate(const boost::posix_time::ptime& date) { + this->date = date; + } + + const boost::posix_time::ptime& getDate() const { + return this->date; + } + + void setAlgo(const std::string& algo) { + this->algo = algo; + } + + const std::string& getAlgo() const { + return this->algo; + } + + void setSupportsRangeRequests(const bool supportsIt) { + supportsRangeRequests = supportsIt; + } + + bool getSupportsRangeRequests() const { + return supportsRangeRequests; + } + + void setRangeOffset(unsigned long long offset) { + supportsRangeRequests = true; + rangeOffset = offset; + } + + unsigned long long getRangeOffset() const { + return rangeOffset; + } private: - std::string name; - std::string description; - unsigned long long size; - std::string hash; - boost::posix_time::ptime date; - std::string algo; - bool supportsRangeRequests; - unsigned long long rangeOffset; + std::string name; + std::string description; + unsigned long long size; + std::string hash; + boost::posix_time::ptime date; + std::string algo; + bool supportsRangeRequests; + unsigned long long rangeOffset; }; } diff --git a/Swiften/Elements/StreamManagementEnabled.cpp b/Swiften/Elements/StreamManagementEnabled.cpp index bab7516..8dacdab 100644 --- a/Swiften/Elements/StreamManagementEnabled.cpp +++ b/Swiften/Elements/StreamManagementEnabled.cpp @@ -1,14 +1,14 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/StreamManagementEnabled.h> using namespace Swift; -StreamManagementEnabled::StreamManagementEnabled() { +StreamManagementEnabled::StreamManagementEnabled() : resumeSupported(false) { } StreamManagementEnabled::~StreamManagementEnabled() { diff --git a/Swiften/Elements/StreamManagementEnabled.h b/Swiften/Elements/StreamManagementEnabled.h index 0985574..7cb640d 100644 --- a/Swiften/Elements/StreamManagementEnabled.h +++ b/Swiften/Elements/StreamManagementEnabled.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,32 +9,32 @@ #include <string> #include <Swiften/Base/API.h> -#include <Swiften/Elements/Element.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class SWIFTEN_API StreamManagementEnabled : public Element { - public: - StreamManagementEnabled(); - ~StreamManagementEnabled(); - - void setResumeSupported() { - resumeSupported = true; - } - - bool getResumeSupported() const { - return resumeSupported; - } - - void setResumeID(const std::string& id) { - resumeID = id; - } - - const std::string& getResumeID() const { - return resumeID; - } - - private: - bool resumeSupported; - std::string resumeID; - }; + class SWIFTEN_API StreamManagementEnabled : public ToplevelElement { + public: + StreamManagementEnabled(); + ~StreamManagementEnabled(); + + void setResumeSupported() { + resumeSupported = true; + } + + bool getResumeSupported() const { + return resumeSupported; + } + + void setResumeID(const std::string& id) { + resumeID = id; + } + + const std::string& getResumeID() const { + return resumeID; + } + + private: + bool resumeSupported; + std::string resumeID; + }; } diff --git a/Swiften/Elements/StreamManagementFailed.h b/Swiften/Elements/StreamManagementFailed.h index 7c6d1b7..062d9bd 100644 --- a/Swiften/Elements/StreamManagementFailed.h +++ b/Swiften/Elements/StreamManagementFailed.h @@ -1,17 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Element.h> - +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class StreamManagementFailed : public Element { - public: - StreamManagementFailed() {} - }; + class SWIFTEN_API StreamManagementFailed : public ToplevelElement { + public: + StreamManagementFailed() {} + }; } diff --git a/Swiften/Elements/StreamResume.cpp b/Swiften/Elements/StreamResume.cpp index d55ef78..6fdc83b 100644 --- a/Swiften/Elements/StreamResume.cpp +++ b/Swiften/Elements/StreamResume.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/StreamResume.h> diff --git a/Swiften/Elements/StreamResume.h b/Swiften/Elements/StreamResume.h index aec0909..0ded077 100644 --- a/Swiften/Elements/StreamResume.h +++ b/Swiften/Elements/StreamResume.h @@ -1,40 +1,42 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + #include <boost/optional.hpp> -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class StreamResume : public Element { - public: - StreamResume(); - ~StreamResume(); - - void setResumeID(const std::string& id) { - resumeID = id; - } - - const std::string& getResumeID() const { - return resumeID; - } - - const boost::optional<unsigned int> getHandledStanzasCount() const { - return handledStanzasCount; - } - - void setHandledStanzasCount(unsigned int i) { - handledStanzasCount = i; - } - - private: - std::string resumeID; - boost::optional<unsigned int> handledStanzasCount; - }; + class SWIFTEN_API StreamResume : public ToplevelElement { + public: + StreamResume(); + ~StreamResume(); + + void setResumeID(const std::string& id) { + resumeID = id; + } + + const std::string& getResumeID() const { + return resumeID; + } + + const boost::optional<unsigned int> getHandledStanzasCount() const { + return handledStanzasCount; + } + + void setHandledStanzasCount(unsigned int i) { + handledStanzasCount = i; + } + + private: + std::string resumeID; + boost::optional<unsigned int> handledStanzasCount; + }; } diff --git a/Swiften/Elements/StreamResumed.cpp b/Swiften/Elements/StreamResumed.cpp index 552e654..a5b7ec4 100644 --- a/Swiften/Elements/StreamResumed.cpp +++ b/Swiften/Elements/StreamResumed.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/StreamResumed.h> diff --git a/Swiften/Elements/StreamResumed.h b/Swiften/Elements/StreamResumed.h index cf9a755..e1c80d9 100644 --- a/Swiften/Elements/StreamResumed.h +++ b/Swiften/Elements/StreamResumed.h @@ -1,40 +1,42 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + #include <boost/optional.hpp> -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class StreamResumed : public Element { - public: - StreamResumed(); - ~StreamResumed(); - - void setResumeID(const std::string& id) { - resumeID = id; - } - - const std::string& getResumeID() const { - return resumeID; - } - - const boost::optional<unsigned int> getHandledStanzasCount() const { - return handledStanzasCount; - } - - void setHandledStanzasCount(unsigned int i) { - handledStanzasCount = i; - } - - private: - std::string resumeID; - boost::optional<unsigned int> handledStanzasCount; - }; + class SWIFTEN_API StreamResumed : public ToplevelElement { + public: + StreamResumed(); + ~StreamResumed(); + + void setResumeID(const std::string& id) { + resumeID = id; + } + + const std::string& getResumeID() const { + return resumeID; + } + + const boost::optional<unsigned int> getHandledStanzasCount() const { + return handledStanzasCount; + } + + void setHandledStanzasCount(unsigned int i) { + handledStanzasCount = i; + } + + private: + std::string resumeID; + boost::optional<unsigned int> handledStanzasCount; + }; } diff --git a/Swiften/Elements/StreamType.h b/Swiften/Elements/StreamType.h index 7ca9ed5..d6b820e 100644 --- a/Swiften/Elements/StreamType.h +++ b/Swiften/Elements/StreamType.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once namespace Swift { - enum StreamType { - ClientStreamType, - ServerStreamType, - ComponentStreamType - }; + enum StreamType { + ClientStreamType, + ServerStreamType, + ComponentStreamType + }; } diff --git a/Swiften/Elements/Subject.h b/Swiften/Elements/Subject.h index bc757af..4f9444a 100644 --- a/Swiften/Elements/Subject.h +++ b/Swiften/Elements/Subject.h @@ -1,29 +1,31 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Payload.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + namespace Swift { - class Subject : public Payload { - public: - Subject(const std::string& text = "") : text_(text) { - } + class SWIFTEN_API Subject : public Payload { + public: + Subject(const std::string& text = "") : text_(text) { + } - void setText(const std::string& text) { - text_ = text; - } + void setText(const std::string& text) { + text_ = text; + } - const std::string& getText() const { - return text_; - } + const std::string& getText() const { + return text_; + } - private: - std::string text_; - }; + private: + std::string text_; + }; } diff --git a/Swiften/Elements/TLSProceed.h b/Swiften/Elements/TLSProceed.h index 4bd790a..3cd5360 100644 --- a/Swiften/Elements/TLSProceed.h +++ b/Swiften/Elements/TLSProceed.h @@ -1,16 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class TLSProceed : public Element { - public: - TLSProceed() {} - }; + class SWIFTEN_API TLSProceed : public ToplevelElement { + public: + TLSProceed() {} + }; } diff --git a/Swiften/Elements/Thread.cpp b/Swiften/Elements/Thread.cpp new file mode 100644 index 0000000..5ac371b --- /dev/null +++ b/Swiften/Elements/Thread.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/Thread.h> + +namespace Swift { + + Thread::Thread(const std::string& text, const std::string& parent) : text_(text), parent_(parent) { + + } + + Thread::~Thread() { + + } + + void Thread::setText(const std::string& text) { + text_ = text; + } + + const std::string& Thread::getText() const { + return text_; + } + + void Thread::setParent(const std::string& parent) { + parent_ = parent; + } + + const std::string& Thread::getParent() const { + return parent_; + } +} diff --git a/Swiften/Elements/Thread.h b/Swiften/Elements/Thread.h new file mode 100644 index 0000000..e736e7f --- /dev/null +++ b/Swiften/Elements/Thread.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API Thread : public Payload { + public: + Thread(const std::string& text = "", const std::string& parent = ""); + virtual ~Thread(); + void setText(const std::string& text); + const std::string& getText() const; + void setParent(const std::string& parent); + const std::string& getParent() const; + + private: + std::string text_; + std::string parent_; + }; +} diff --git a/Swiften/Elements/ToplevelElement.cpp b/Swiften/Elements/ToplevelElement.cpp new file mode 100644 index 0000000..1a858bd --- /dev/null +++ b/Swiften/Elements/ToplevelElement.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2010-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/ToplevelElement.h> + +namespace Swift { + +ToplevelElement::~ToplevelElement() { +} + +} diff --git a/Swiften/Elements/ToplevelElement.h b/Swiften/Elements/ToplevelElement.h new file mode 100644 index 0000000..55e055a --- /dev/null +++ b/Swiften/Elements/ToplevelElement.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2010-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Element.h> + +namespace Swift { + class SWIFTEN_API ToplevelElement : public Element { + public: + ToplevelElement() {} + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(ToplevelElement) + virtual ~ToplevelElement(); + }; +} diff --git a/Swiften/Elements/UnblockPayload.h b/Swiften/Elements/UnblockPayload.h index c5e7c80..7d6574d 100644 --- a/Swiften/Elements/UnblockPayload.h +++ b/Swiften/Elements/UnblockPayload.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <vector> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class UnblockPayload : public Payload { - public: - UnblockPayload(const std::vector<JID>& jids = std::vector<JID>()) : items(jids) { - } + class SWIFTEN_API UnblockPayload : public Payload { + public: + UnblockPayload(const std::vector<JID>& jids = std::vector<JID>()) : items(jids) { + } - void addItem(const JID& item) { - items.push_back(item); - } + void addItem(const JID& item) { + items.push_back(item); + } - const std::vector<JID>& getItems() const { - return items; - } + const std::vector<JID>& getItems() const { + return items; + } - private: - std::vector<JID> items; - }; + private: + std::vector<JID> items; + }; } diff --git a/Swiften/Elements/UnitTest/FormTest.cpp b/Swiften/Elements/UnitTest/FormTest.cpp index 3000c22..c728bde 100644 --- a/Swiften/Elements/UnitTest/FormTest.cpp +++ b/Swiften/Elements/UnitTest/FormTest.cpp @@ -1,57 +1,57 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Elements/Form.h> using namespace Swift; class FormTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(FormTest); - CPPUNIT_TEST(testGetFormType); - CPPUNIT_TEST(testGetFormType_InvalidFormType); - CPPUNIT_TEST(testGetFormType_NoFormType); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(FormTest); + CPPUNIT_TEST(testGetFormType); + CPPUNIT_TEST(testGetFormType_InvalidFormType); + CPPUNIT_TEST(testGetFormType_NoFormType); + CPPUNIT_TEST_SUITE_END(); - public: - void testGetFormType() { - Form form; + public: + void testGetFormType() { + Form form; - form.addField(boost::make_shared<FormField>(FormField::FixedType, "Foo")); + form.addField(std::make_shared<FormField>(FormField::FixedType, "Foo")); - FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:bot"); - field->setName("FORM_TYPE"); - form.addField(field); + FormField::ref field = std::make_shared<FormField>(FormField::HiddenType, "jabber:bot"); + field->setName("FORM_TYPE"); + form.addField(field); - form.addField(boost::make_shared<FormField>(FormField::FixedType, "Bar")); + form.addField(std::make_shared<FormField>(FormField::FixedType, "Bar")); - CPPUNIT_ASSERT_EQUAL(std::string("jabber:bot"), form.getFormType()); - } + CPPUNIT_ASSERT_EQUAL(std::string("jabber:bot"), form.getFormType()); + } - void testGetFormType_InvalidFormType() { - Form form; + void testGetFormType_InvalidFormType() { + Form form; - FormField::ref field = boost::make_shared<FormField>(FormField::FixedType, "jabber:bot"); - field->setName("FORM_TYPE"); - form.addField(field); + FormField::ref field = std::make_shared<FormField>(FormField::FixedType, "jabber:bot"); + field->setName("FORM_TYPE"); + form.addField(field); - CPPUNIT_ASSERT_EQUAL(std::string(""), form.getFormType()); - } + CPPUNIT_ASSERT_EQUAL(std::string(""), form.getFormType()); + } - void testGetFormType_NoFormType() { - Form form; + void testGetFormType_NoFormType() { + Form form; - form.addField(boost::make_shared<FormField>(FormField::FixedType, "Foo")); + form.addField(std::make_shared<FormField>(FormField::FixedType, "Foo")); - CPPUNIT_ASSERT_EQUAL(std::string(""), form.getFormType()); - } + CPPUNIT_ASSERT_EQUAL(std::string(""), form.getFormType()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(FormTest); diff --git a/Swiften/Elements/UnitTest/IQTest.cpp b/Swiften/Elements/UnitTest/IQTest.cpp index 23255b8..ed98c75 100644 --- a/Swiften/Elements/UnitTest/IQTest.cpp +++ b/Swiften/Elements/UnitTest/IQTest.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> #include <Swiften/Elements/IQ.h> #include <Swiften/Elements/SoftwareVersion.h> @@ -15,43 +16,43 @@ using namespace Swift; class IQTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IQTest); - CPPUNIT_TEST(testCreateResult); - CPPUNIT_TEST(testCreateResult_WithoutPayload); - CPPUNIT_TEST(testCreateError); - CPPUNIT_TEST_SUITE_END(); - - public: - IQTest() {} - - void testCreateResult() { - boost::shared_ptr<Payload> payload(new SoftwareVersion("myclient")); - boost::shared_ptr<IQ> iq(IQ::createResult(JID("foo@bar/fum"), "myid", payload)); - - CPPUNIT_ASSERT_EQUAL(JID("foo@bar/fum"), iq->getTo()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), iq->getID()); - CPPUNIT_ASSERT(iq->getPayload<SoftwareVersion>()); - CPPUNIT_ASSERT(payload == iq->getPayload<SoftwareVersion>()); - } - - void testCreateResult_WithoutPayload() { - boost::shared_ptr<IQ> iq(IQ::createResult(JID("foo@bar/fum"), "myid")); - - CPPUNIT_ASSERT_EQUAL(JID("foo@bar/fum"), iq->getTo()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), iq->getID()); - CPPUNIT_ASSERT(!iq->getPayload<SoftwareVersion>()); - } - - void testCreateError() { - boost::shared_ptr<IQ> iq(IQ::createError(JID("foo@bar/fum"), "myid", ErrorPayload::BadRequest, ErrorPayload::Modify)); - - CPPUNIT_ASSERT_EQUAL(JID("foo@bar/fum"), iq->getTo()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), iq->getID()); - boost::shared_ptr<ErrorPayload> error(iq->getPayload<ErrorPayload>()); - CPPUNIT_ASSERT(error); - CPPUNIT_ASSERT_EQUAL(ErrorPayload::BadRequest, error->getCondition()); - CPPUNIT_ASSERT_EQUAL(ErrorPayload::Modify, error->getType()); - } + CPPUNIT_TEST_SUITE(IQTest); + CPPUNIT_TEST(testCreateResult); + CPPUNIT_TEST(testCreateResult_WithoutPayload); + CPPUNIT_TEST(testCreateError); + CPPUNIT_TEST_SUITE_END(); + + public: + IQTest() {} + + void testCreateResult() { + std::shared_ptr<Payload> payload(new SoftwareVersion("myclient")); + std::shared_ptr<IQ> iq(IQ::createResult(JID("foo@bar/fum"), "myid", payload)); + + CPPUNIT_ASSERT_EQUAL(JID("foo@bar/fum"), iq->getTo()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), iq->getID()); + CPPUNIT_ASSERT(iq->getPayload<SoftwareVersion>()); + CPPUNIT_ASSERT(payload == iq->getPayload<SoftwareVersion>()); + } + + void testCreateResult_WithoutPayload() { + std::shared_ptr<IQ> iq(IQ::createResult(JID("foo@bar/fum"), "myid")); + + CPPUNIT_ASSERT_EQUAL(JID("foo@bar/fum"), iq->getTo()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), iq->getID()); + CPPUNIT_ASSERT(!iq->getPayload<SoftwareVersion>()); + } + + void testCreateError() { + std::shared_ptr<IQ> iq(IQ::createError(JID("foo@bar/fum"), "myid", ErrorPayload::BadRequest, ErrorPayload::Modify)); + + CPPUNIT_ASSERT_EQUAL(JID("foo@bar/fum"), iq->getTo()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), iq->getID()); + std::shared_ptr<ErrorPayload> error(iq->getPayload<ErrorPayload>()); + CPPUNIT_ASSERT(error); + CPPUNIT_ASSERT_EQUAL(ErrorPayload::BadRequest, error->getCondition()); + CPPUNIT_ASSERT_EQUAL(ErrorPayload::Modify, error->getType()); + } }; diff --git a/Swiften/Elements/UnitTest/StanzaTest.cpp b/Swiften/Elements/UnitTest/StanzaTest.cpp index 4bb59b1..6a45bd8 100644 --- a/Swiften/Elements/UnitTest/StanzaTest.cpp +++ b/Swiften/Elements/UnitTest/StanzaTest.cpp @@ -1,231 +1,233 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + +#include <boost/date_time/posix_time/posix_time.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> -#include <boost/date_time/posix_time/posix_time.hpp> -#include <Swiften/Elements/Stanza.h> -#include <Swiften/Elements/Payload.h> -#include <Swiften/Elements/Message.h> #include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/Elements/Stanza.h> using namespace Swift; class StanzaTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StanzaTest); - CPPUNIT_TEST(testConstructor_Copy); - CPPUNIT_TEST(testGetPayload); - CPPUNIT_TEST(testGetPayloads); - CPPUNIT_TEST(testGetPayload_NoSuchPayload); - CPPUNIT_TEST(testDestructor); - CPPUNIT_TEST(testDestructor_Copy); - CPPUNIT_TEST(testUpdatePayload_ExistingPayload); - CPPUNIT_TEST(testUpdatePayload_NewPayload); - CPPUNIT_TEST(testGetPayloadOfSameType); - CPPUNIT_TEST(testGetPayloadOfSameType_NoSuchPayload); - CPPUNIT_TEST(testGetTimestamp); - CPPUNIT_TEST(testGetTimestamp_TimestampWithFrom); - CPPUNIT_TEST(testGetTimestamp_NoDelay); - CPPUNIT_TEST(testGetTimestampFrom); - CPPUNIT_TEST(testGetTimestampFrom_Fallsback); - CPPUNIT_TEST_SUITE_END(); - - public: - class MyPayload1 : public Payload { - public: - MyPayload1() {} - }; - - class MyPayload2 : public Payload { - public: - MyPayload2(const std::string& s = "") : text_(s) {} - - std::string text_; - }; - - class MyPayload3 : public Payload { - public: - MyPayload3() {} - }; - - class DestroyingPayload : public Payload { - public: - DestroyingPayload(bool* alive) : alive_(alive) { - } - - ~DestroyingPayload() { - (*alive_) = false; - } - - private: - bool* alive_; - }; - - void testConstructor_Copy() { - Message m; - m.addPayload(boost::make_shared<MyPayload1>()); - m.addPayload(boost::make_shared<MyPayload2>()); - Message copy(m); - - CPPUNIT_ASSERT(copy.getPayload<MyPayload1>()); - CPPUNIT_ASSERT(copy.getPayload<MyPayload2>()); - } - - void testDestructor() { - bool payloadAlive = true; - { - Message m; - m.addPayload(boost::make_shared<DestroyingPayload>(&payloadAlive)); - } - - CPPUNIT_ASSERT(!payloadAlive); - } - - void testDestructor_Copy() { - bool payloadAlive = true; - Message* m1 = new Message(); - m1->addPayload(boost::make_shared<DestroyingPayload>(&payloadAlive)); - Message* m2 = new Message(*m1); - - delete m1; - CPPUNIT_ASSERT(payloadAlive); - - delete m2; - CPPUNIT_ASSERT(!payloadAlive); - } - - void testGetPayload() { - Message m; - m.addPayload(boost::make_shared<MyPayload1>()); - m.addPayload(boost::make_shared<MyPayload2>()); - m.addPayload(boost::make_shared<MyPayload3>()); - - boost::shared_ptr<MyPayload2> p(m.getPayload<MyPayload2>()); - CPPUNIT_ASSERT(p); - } - - void testGetPayload_NoSuchPayload() { - Message m; - m.addPayload(boost::make_shared<MyPayload1>()); - m.addPayload(boost::make_shared<MyPayload3>()); - - boost::shared_ptr<MyPayload2> p(m.getPayload<MyPayload2>()); - CPPUNIT_ASSERT(!p); - } - - void testGetPayloads() { - Message m; - boost::shared_ptr<MyPayload2> payload1(new MyPayload2()); - boost::shared_ptr<MyPayload2> payload2(new MyPayload2()); - m.addPayload(boost::make_shared<MyPayload1>()); - m.addPayload(payload1); - m.addPayload(boost::make_shared<MyPayload3>()); - m.addPayload(payload2); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), m.getPayloads<MyPayload2>().size()); - CPPUNIT_ASSERT_EQUAL(payload1, m.getPayloads<MyPayload2>()[0]); - CPPUNIT_ASSERT_EQUAL(payload2, m.getPayloads<MyPayload2>()[1]); - } - - - void testUpdatePayload_ExistingPayload() { - Message m; - m.addPayload(boost::make_shared<MyPayload1>()); - m.addPayload(boost::make_shared<MyPayload2>("foo")); - m.addPayload(boost::make_shared<MyPayload3>()); - - m.updatePayload(boost::make_shared<MyPayload2>("bar")); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), m.getPayloads().size()); - boost::shared_ptr<MyPayload2> p(m.getPayload<MyPayload2>()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), p->text_); - } - - void testUpdatePayload_NewPayload() { - Message m; - m.addPayload(boost::make_shared<MyPayload1>()); - m.addPayload(boost::make_shared<MyPayload3>()); - - m.updatePayload(boost::make_shared<MyPayload2>("bar")); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), m.getPayloads().size()); - boost::shared_ptr<MyPayload2> p(m.getPayload<MyPayload2>()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), p->text_); - } - - void testGetPayloadOfSameType() { - Message m; - m.addPayload(boost::make_shared<MyPayload1>()); - m.addPayload(boost::make_shared<MyPayload2>("foo")); - m.addPayload(boost::make_shared<MyPayload3>()); - - boost::shared_ptr<MyPayload2> payload(boost::dynamic_pointer_cast<MyPayload2>(m.getPayloadOfSameType(boost::make_shared<MyPayload2>("bar")))); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT_EQUAL(std::string("foo"), payload->text_); - } - - void testGetPayloadOfSameType_NoSuchPayload() { - Message m; - m.addPayload(boost::make_shared<MyPayload1>()); - m.addPayload(boost::make_shared<MyPayload3>()); - - CPPUNIT_ASSERT(!m.getPayloadOfSameType(boost::make_shared<MyPayload2>("bar"))); - } - - void testGetTimestamp() { - Message m; - m.addPayload(boost::make_shared<Delay>(boost::posix_time::from_time_t(1))); - - boost::optional<boost::posix_time::ptime> timestamp = m.getTimestamp(); - - CPPUNIT_ASSERT(timestamp); - CPPUNIT_ASSERT_EQUAL(std::string("1970-Jan-01 00:00:01"), boost::posix_time::to_simple_string(*timestamp)); - } - - void testGetTimestamp_TimestampWithFrom() { - Message m; - m.addPayload(boost::make_shared<Delay>(boost::posix_time::from_time_t(1), JID("foo@bar.com"))); - - boost::optional<boost::posix_time::ptime> timestamp = m.getTimestamp(); - - CPPUNIT_ASSERT(timestamp); - CPPUNIT_ASSERT_EQUAL(std::string("1970-Jan-01 00:00:01"), boost::posix_time::to_simple_string(*timestamp)); - } - - void testGetTimestamp_NoDelay() { - Message m; - CPPUNIT_ASSERT(!m.getTimestamp()); - } - - void testGetTimestampFrom() { - Message m; - m.addPayload(boost::make_shared<Delay>(boost::posix_time::from_time_t(0))); - m.addPayload(boost::make_shared<Delay>(boost::posix_time::from_time_t(1), JID("foo1@bar.com"))); - m.addPayload(boost::make_shared<Delay>(boost::posix_time::from_time_t(2), JID("foo2@bar.com"))); - m.addPayload(boost::make_shared<Delay>(boost::posix_time::from_time_t(3), JID("foo3@bar.com"))); - - boost::optional<boost::posix_time::ptime> timestamp = m.getTimestampFrom(JID("foo2@bar.com")); - - CPPUNIT_ASSERT(timestamp); - CPPUNIT_ASSERT_EQUAL(std::string("1970-Jan-01 00:00:02"), boost::posix_time::to_simple_string(*timestamp)); - } - - void testGetTimestampFrom_Fallsback() { - Message m; - m.addPayload(boost::make_shared<Delay>(boost::posix_time::from_time_t(1), JID("foo1@bar.com"))); - m.addPayload(boost::make_shared<Delay>(boost::posix_time::from_time_t(3), JID("foo3@bar.com"))); - - boost::optional<boost::posix_time::ptime> timestamp = m.getTimestampFrom(JID("foo2@bar.com")); - - CPPUNIT_ASSERT(timestamp); - CPPUNIT_ASSERT_EQUAL(std::string("1970-Jan-01 00:00:01"), boost::posix_time::to_simple_string(*timestamp)); - } + CPPUNIT_TEST_SUITE(StanzaTest); + CPPUNIT_TEST(testConstructor_Copy); + CPPUNIT_TEST(testGetPayload); + CPPUNIT_TEST(testGetPayloads); + CPPUNIT_TEST(testGetPayload_NoSuchPayload); + CPPUNIT_TEST(testDestructor); + CPPUNIT_TEST(testDestructor_Copy); + CPPUNIT_TEST(testUpdatePayload_ExistingPayload); + CPPUNIT_TEST(testUpdatePayload_NewPayload); + CPPUNIT_TEST(testGetPayloadOfSameType); + CPPUNIT_TEST(testGetPayloadOfSameType_NoSuchPayload); + CPPUNIT_TEST(testGetTimestamp); + CPPUNIT_TEST(testGetTimestamp_TimestampWithFrom); + CPPUNIT_TEST(testGetTimestamp_NoDelay); + CPPUNIT_TEST(testGetTimestampFrom); + CPPUNIT_TEST(testGetTimestampFrom_Fallsback); + CPPUNIT_TEST_SUITE_END(); + + public: + class MyPayload1 : public Payload { + public: + MyPayload1() {} + }; + + class MyPayload2 : public Payload { + public: + MyPayload2(const std::string& s = "") : text_(s) {} + + std::string text_; + }; + + class MyPayload3 : public Payload { + public: + MyPayload3() {} + }; + + class DestroyingPayload : public Payload { + public: + DestroyingPayload(bool* alive) : alive_(alive) { + } + + ~DestroyingPayload() { + (*alive_) = false; + } + + private: + bool* alive_; + }; + + void testConstructor_Copy() { + Message m; + m.addPayload(std::make_shared<MyPayload1>()); + m.addPayload(std::make_shared<MyPayload2>()); + Message copy(m); + + CPPUNIT_ASSERT(copy.getPayload<MyPayload1>()); + CPPUNIT_ASSERT(copy.getPayload<MyPayload2>()); + } + + void testDestructor() { + bool payloadAlive = true; + { + Message m; + m.addPayload(std::make_shared<DestroyingPayload>(&payloadAlive)); + } + + CPPUNIT_ASSERT(!payloadAlive); + } + + void testDestructor_Copy() { + bool payloadAlive = true; + Message* m1 = new Message(); + m1->addPayload(std::make_shared<DestroyingPayload>(&payloadAlive)); + Message* m2 = new Message(*m1); + + delete m1; + CPPUNIT_ASSERT(payloadAlive); + + delete m2; + CPPUNIT_ASSERT(!payloadAlive); + } + + void testGetPayload() { + Message m; + m.addPayload(std::make_shared<MyPayload1>()); + m.addPayload(std::make_shared<MyPayload2>()); + m.addPayload(std::make_shared<MyPayload3>()); + + std::shared_ptr<MyPayload2> p(m.getPayload<MyPayload2>()); + CPPUNIT_ASSERT(p); + } + + void testGetPayload_NoSuchPayload() { + Message m; + m.addPayload(std::make_shared<MyPayload1>()); + m.addPayload(std::make_shared<MyPayload3>()); + + std::shared_ptr<MyPayload2> p(m.getPayload<MyPayload2>()); + CPPUNIT_ASSERT(!p); + } + + void testGetPayloads() { + Message m; + std::shared_ptr<MyPayload2> payload1(new MyPayload2()); + std::shared_ptr<MyPayload2> payload2(new MyPayload2()); + m.addPayload(std::make_shared<MyPayload1>()); + m.addPayload(payload1); + m.addPayload(std::make_shared<MyPayload3>()); + m.addPayload(payload2); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), m.getPayloads<MyPayload2>().size()); + CPPUNIT_ASSERT_EQUAL(payload1, m.getPayloads<MyPayload2>()[0]); + CPPUNIT_ASSERT_EQUAL(payload2, m.getPayloads<MyPayload2>()[1]); + } + + + void testUpdatePayload_ExistingPayload() { + Message m; + m.addPayload(std::make_shared<MyPayload1>()); + m.addPayload(std::make_shared<MyPayload2>("foo")); + m.addPayload(std::make_shared<MyPayload3>()); + + m.updatePayload(std::make_shared<MyPayload2>("bar")); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), m.getPayloads().size()); + std::shared_ptr<MyPayload2> p(m.getPayload<MyPayload2>()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), p->text_); + } + + void testUpdatePayload_NewPayload() { + Message m; + m.addPayload(std::make_shared<MyPayload1>()); + m.addPayload(std::make_shared<MyPayload3>()); + + m.updatePayload(std::make_shared<MyPayload2>("bar")); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), m.getPayloads().size()); + std::shared_ptr<MyPayload2> p(m.getPayload<MyPayload2>()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), p->text_); + } + + void testGetPayloadOfSameType() { + Message m; + m.addPayload(std::make_shared<MyPayload1>()); + m.addPayload(std::make_shared<MyPayload2>("foo")); + m.addPayload(std::make_shared<MyPayload3>()); + + std::shared_ptr<MyPayload2> payload(std::dynamic_pointer_cast<MyPayload2>(m.getPayloadOfSameType(std::make_shared<MyPayload2>("bar")))); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string("foo"), payload->text_); + } + + void testGetPayloadOfSameType_NoSuchPayload() { + Message m; + m.addPayload(std::make_shared<MyPayload1>()); + m.addPayload(std::make_shared<MyPayload3>()); + + CPPUNIT_ASSERT(!m.getPayloadOfSameType(std::make_shared<MyPayload2>("bar"))); + } + + void testGetTimestamp() { + Message m; + m.addPayload(std::make_shared<Delay>(boost::posix_time::from_time_t(1))); + + boost::optional<boost::posix_time::ptime> timestamp = m.getTimestamp(); + + CPPUNIT_ASSERT(timestamp); + CPPUNIT_ASSERT_EQUAL(std::string("1970-Jan-01 00:00:01"), boost::posix_time::to_simple_string(*timestamp)); + } + + void testGetTimestamp_TimestampWithFrom() { + Message m; + m.addPayload(std::make_shared<Delay>(boost::posix_time::from_time_t(1), JID("foo@bar.com"))); + + boost::optional<boost::posix_time::ptime> timestamp = m.getTimestamp(); + + CPPUNIT_ASSERT(timestamp); + CPPUNIT_ASSERT_EQUAL(std::string("1970-Jan-01 00:00:01"), boost::posix_time::to_simple_string(*timestamp)); + } + + void testGetTimestamp_NoDelay() { + Message m; + CPPUNIT_ASSERT(!m.getTimestamp()); + } + + void testGetTimestampFrom() { + Message m; + m.addPayload(std::make_shared<Delay>(boost::posix_time::from_time_t(0))); + m.addPayload(std::make_shared<Delay>(boost::posix_time::from_time_t(1), JID("foo1@bar.com"))); + m.addPayload(std::make_shared<Delay>(boost::posix_time::from_time_t(2), JID("foo2@bar.com"))); + m.addPayload(std::make_shared<Delay>(boost::posix_time::from_time_t(3), JID("foo3@bar.com"))); + + boost::optional<boost::posix_time::ptime> timestamp = m.getTimestampFrom(JID("foo2@bar.com")); + + CPPUNIT_ASSERT(timestamp); + CPPUNIT_ASSERT_EQUAL(std::string("1970-Jan-01 00:00:02"), boost::posix_time::to_simple_string(*timestamp)); + } + + void testGetTimestampFrom_Fallsback() { + Message m; + m.addPayload(std::make_shared<Delay>(boost::posix_time::from_time_t(1), JID("foo1@bar.com"))); + m.addPayload(std::make_shared<Delay>(boost::posix_time::from_time_t(3), JID("foo3@bar.com"))); + + boost::optional<boost::posix_time::ptime> timestamp = m.getTimestampFrom(JID("foo2@bar.com")); + + CPPUNIT_ASSERT(timestamp); + CPPUNIT_ASSERT_EQUAL(std::string("1970-Jan-01 00:00:01"), boost::posix_time::to_simple_string(*timestamp)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StanzaTest); diff --git a/Swiften/Elements/UnknownElement.h b/Swiften/Elements/UnknownElement.h index 100ba92..b6f8021 100644 --- a/Swiften/Elements/UnknownElement.h +++ b/Swiften/Elements/UnknownElement.h @@ -1,16 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Element.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class UnknownElement : public Element { - public: - UnknownElement() {} - }; + class SWIFTEN_API UnknownElement : public ToplevelElement { + public: + UnknownElement() {} + }; } diff --git a/Swiften/Elements/UserLocation.cpp b/Swiften/Elements/UserLocation.cpp index f22973e..bc8c584 100644 --- a/Swiften/Elements/UserLocation.cpp +++ b/Swiften/Elements/UserLocation.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Elements/UserLocation.h b/Swiften/Elements/UserLocation.h index 2355838..b59fc5c 100644 --- a/Swiften/Elements/UserLocation.h +++ b/Swiften/Elements/UserLocation.h @@ -1,227 +1,226 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Payload.h> -#include <boost/optional.hpp> #include <string> -#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/optional.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> namespace Swift { - class SWIFTEN_API UserLocation : public Payload { - public: - - UserLocation(); - - virtual ~UserLocation(); + class SWIFTEN_API UserLocation : public Payload { + public: + + UserLocation(); + + virtual ~UserLocation(); + + const boost::optional< std::string >& getArea() const { + return area; + } + + void setArea(const boost::optional< std::string >& value) { + this->area = value ; + } - const boost::optional< std::string >& getArea() const { - return area; - } + const boost::optional< double >& getAltitude() const { + return altitude; + } - void setArea(const boost::optional< std::string >& value) { - this->area = value ; - } + void setAltitude(const boost::optional< double >& value) { + this->altitude = value ; + } - const boost::optional< float >& getAltitude() const { - return altitude; - } + const boost::optional< std::string >& getLocality() const { + return locality; + } - void setAltitude(const boost::optional< float >& value) { - this->altitude = value ; - } + void setLocality(const boost::optional< std::string >& value) { + this->locality = value ; + } - const boost::optional< std::string >& getLocality() const { - return locality; - } + const boost::optional< double >& getLatitude() const { + return latitude; + } - void setLocality(const boost::optional< std::string >& value) { - this->locality = value ; - } + void setLatitude(const boost::optional< double >& value) { + this->latitude = value ; + } - const boost::optional< float >& getLatitude() const { - return latitude; - } + const boost::optional< double >& getAccuracy() const { + return accuracy; + } - void setLatitude(const boost::optional< float >& value) { - this->latitude = value ; - } + void setAccuracy(const boost::optional< double >& value) { + this->accuracy = value ; + } - const boost::optional< float >& getAccuracy() const { - return accuracy; - } + const boost::optional< std::string >& getDescription() const { + return description; + } - void setAccuracy(const boost::optional< float >& value) { - this->accuracy = value ; - } + void setDescription(const boost::optional< std::string >& value) { + this->description = value ; + } - const boost::optional< std::string >& getDescription() const { - return description; - } + const boost::optional< std::string >& getCountryCode() const { + return countryCode; + } - void setDescription(const boost::optional< std::string >& value) { - this->description = value ; - } + void setCountryCode(const boost::optional< std::string >& value) { + this->countryCode = value ; + } - const boost::optional< std::string >& getCountryCode() const { - return countryCode; - } + const boost::optional< boost::posix_time::ptime >& getTimestamp() const { + return timestamp; + } - void setCountryCode(const boost::optional< std::string >& value) { - this->countryCode = value ; - } + void setTimestamp(const boost::optional< boost::posix_time::ptime >& value) { + this->timestamp = value ; + } - const boost::optional< boost::posix_time::ptime >& getTimestamp() const { - return timestamp; - } + const boost::optional< std::string >& getFloor() const { + return floor; + } - void setTimestamp(const boost::optional< boost::posix_time::ptime >& value) { - this->timestamp = value ; - } + void setFloor(const boost::optional< std::string >& value) { + this->floor = value ; + } - const boost::optional< std::string >& getFloor() const { - return floor; - } + const boost::optional< std::string >& getBuilding() const { + return building; + } - void setFloor(const boost::optional< std::string >& value) { - this->floor = value ; - } + void setBuilding(const boost::optional< std::string >& value) { + this->building = value ; + } - const boost::optional< std::string >& getBuilding() const { - return building; - } + const boost::optional< std::string >& getRoom() const { + return room; + } - void setBuilding(const boost::optional< std::string >& value) { - this->building = value ; - } + void setRoom(const boost::optional< std::string >& value) { + this->room = value ; + } - const boost::optional< std::string >& getRoom() const { - return room; - } - - void setRoom(const boost::optional< std::string >& value) { - this->room = value ; - } - - const boost::optional< std::string >& getCountry() const { - return country; - } - - void setCountry(const boost::optional< std::string >& value) { - this->country = value ; - } - - const boost::optional< std::string >& getRegion() const { - return region; - } - - void setRegion(const boost::optional< std::string >& value) { - this->region = value ; - } - - const boost::optional< std::string >& getURI() const { - return uri; - } - - void setURI(const boost::optional< std::string >& value) { - this->uri = value ; - } - - const boost::optional< float >& getLongitude() const { - return longitude; - } - - void setLongitude(const boost::optional< float >& value) { - this->longitude = value ; - } - - const boost::optional< float >& getError() const { - return error; - } - - void setError(const boost::optional< float >& value) { - this->error = value ; - } - - const boost::optional< std::string >& getPostalCode() const { - return postalCode; - } - - void setPostalCode(const boost::optional< std::string >& value) { - this->postalCode = value ; - } - - const boost::optional< float >& getBearing() const { - return bearing; - } - - void setBearing(const boost::optional< float >& value) { - this->bearing = value ; - } - - const boost::optional< std::string >& getText() const { - return text; - } - - void setText(const boost::optional< std::string >& value) { - this->text = value ; - } - - const boost::optional< std::string >& getDatum() const { - return datum; - } - - void setDatum(const boost::optional< std::string >& value) { - this->datum = value ; - } - - const boost::optional< std::string >& getStreet() const { - return street; - } - - void setStreet(const boost::optional< std::string >& value) { - this->street = value ; - } - - const boost::optional< float >& getSpeed() const { - return speed; - } - - void setSpeed(const boost::optional< float >& value) { - this->speed = value ; - } - - - private: - boost::optional< std::string > area; - boost::optional< float > altitude; - boost::optional< std::string > locality; - boost::optional< float > latitude; - boost::optional< float > accuracy; - boost::optional< std::string > description; - boost::optional< std::string > countryCode; - boost::optional< boost::posix_time::ptime > timestamp; - boost::optional< std::string > floor; - boost::optional< std::string > building; - boost::optional< std::string > room; - boost::optional< std::string > country; - boost::optional< std::string > region; - boost::optional< std::string > uri; - boost::optional< float > longitude; - boost::optional< float > error; - boost::optional< std::string > postalCode; - boost::optional< float > bearing; - boost::optional< std::string > text; - boost::optional< std::string > datum; - boost::optional< std::string > street; - boost::optional< float > speed; - }; + const boost::optional< std::string >& getCountry() const { + return country; + } + + void setCountry(const boost::optional< std::string >& value) { + this->country = value ; + } + + const boost::optional< std::string >& getRegion() const { + return region; + } + + void setRegion(const boost::optional< std::string >& value) { + this->region = value ; + } + + const boost::optional< std::string >& getURI() const { + return uri; + } + + void setURI(const boost::optional< std::string >& value) { + this->uri = value ; + } + + const boost::optional< double >& getLongitude() const { + return longitude; + } + + void setLongitude(const boost::optional< double >& value) { + this->longitude = value ; + } + + const boost::optional< double >& getError() const { + return error; + } + + void setError(const boost::optional< double >& value) { + this->error = value ; + } + + const boost::optional< std::string >& getPostalCode() const { + return postalCode; + } + + void setPostalCode(const boost::optional< std::string >& value) { + this->postalCode = value ; + } + + const boost::optional< double >& getBearing() const { + return bearing; + } + + void setBearing(const boost::optional< double >& value) { + this->bearing = value ; + } + + const boost::optional< std::string >& getText() const { + return text; + } + + void setText(const boost::optional< std::string >& value) { + this->text = value ; + } + + const boost::optional< std::string >& getDatum() const { + return datum; + } + + void setDatum(const boost::optional< std::string >& value) { + this->datum = value ; + } + + const boost::optional< std::string >& getStreet() const { + return street; + } + + void setStreet(const boost::optional< std::string >& value) { + this->street = value ; + } + + const boost::optional< double >& getSpeed() const { + return speed; + } + + void setSpeed(const boost::optional< double >& value) { + this->speed = value ; + } + + + private: + boost::optional< std::string > area; + boost::optional< double > altitude; + boost::optional< std::string > locality; + boost::optional< double > latitude; + boost::optional< double > accuracy; + boost::optional< std::string > description; + boost::optional< std::string > countryCode; + boost::optional< boost::posix_time::ptime > timestamp; + boost::optional< std::string > floor; + boost::optional< std::string > building; + boost::optional< std::string > room; + boost::optional< std::string > country; + boost::optional< std::string > region; + boost::optional< std::string > uri; + boost::optional< double > longitude; + boost::optional< double > error; + boost::optional< std::string > postalCode; + boost::optional< double > bearing; + boost::optional< std::string > text; + boost::optional< std::string > datum; + boost::optional< std::string > street; + boost::optional< double > speed; + }; } diff --git a/Swiften/Elements/UserTune.cpp b/Swiften/Elements/UserTune.cpp new file mode 100644 index 0000000..abd97d2 --- /dev/null +++ b/Swiften/Elements/UserTune.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/UserTune.h> + +using namespace Swift; + +UserTune::UserTune() { +} + +UserTune::~UserTune() { +} diff --git a/Swiften/Elements/UserTune.h b/Swiften/Elements/UserTune.h new file mode 100644 index 0000000..5413085 --- /dev/null +++ b/Swiften/Elements/UserTune.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API UserTune : public Payload { + public: + + UserTune(); + + virtual ~UserTune(); + + const boost::optional< unsigned int >& getRating() const { + return rating; + } + + void setRating(const boost::optional< unsigned int >& value) { + this->rating = value ; + } + + const boost::optional< std::string >& getTitle() const { + return title; + } + + void setTitle(const boost::optional< std::string >& value) { + this->title = value ; + } + + const boost::optional< std::string >& getTrack() const { + return track; + } + + void setTrack(const boost::optional< std::string >& value) { + this->track = value ; + } + + const boost::optional< std::string >& getArtist() const { + return artist; + } + + void setArtist(const boost::optional< std::string >& value) { + this->artist = value ; + } + + const boost::optional< std::string >& getURI() const { + return uri; + } + + void setURI(const boost::optional< std::string >& value) { + this->uri = value ; + } + + const boost::optional< std::string >& getSource() const { + return source; + } + + void setSource(const boost::optional< std::string >& value) { + this->source = value ; + } + + const boost::optional< unsigned int >& getLength() const { + return length; + } + + void setLength(const boost::optional< unsigned int >& value) { + this->length = value ; + } + + + private: + boost::optional< unsigned int > rating; + boost::optional< std::string > title; + boost::optional< std::string > track; + boost::optional< std::string > artist; + boost::optional< std::string > uri; + boost::optional< std::string > source; + boost::optional< unsigned int > length; + }; +} diff --git a/Swiften/Elements/VCard.cpp b/Swiften/Elements/VCard.cpp index 8bf3eb9..571ead4 100644 --- a/Swiften/Elements/VCard.cpp +++ b/Swiften/Elements/VCard.cpp @@ -1,25 +1,23 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Elements/VCard.h> -#include <Swiften/Base/foreach.h> - namespace Swift { VCard::EMailAddress VCard::getPreferredEMailAddress() const { - foreach(const EMailAddress& address, emailAddresses_) { - if (address.isPreferred) { - return address; - } - } - if (!emailAddresses_.empty()) { - return emailAddresses_[0]; - } - return EMailAddress(); + for (const auto& address : emailAddresses_) { + if (address.isPreferred) { + return address; + } + } + if (!emailAddresses_.empty()) { + return emailAddresses_[0]; + } + return EMailAddress(); } diff --git a/Swiften/Elements/VCard.h b/Swiften/Elements/VCard.h index 84b6cfe..5a43c3c 100644 --- a/Swiften/Elements/VCard.h +++ b/Swiften/Elements/VCard.h @@ -1,291 +1,303 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + #include <boost/date_time/posix_time/ptime.hpp> -#include <string> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/Elements/Payload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class VCard : public Payload { - public: - typedef boost::shared_ptr<VCard> ref; - - struct EMailAddress { - EMailAddress() : isHome(false), isWork(false), isInternet(false), isPreferred(false), isX400(false) { - } - - bool isHome; - bool isWork; - bool isInternet; - bool isPreferred; - bool isX400; - std::string address; - }; - - struct Telephone { - Telephone() : isHome(false), isWork(false), isVoice(false), isFax(false), isPager(false), isMSG(false), isCell(false), - isVideo(false), isBBS(false), isModem(false), isISDN(false), isPCS(false), isPreferred(false) { - } - - bool isHome; - bool isWork; - bool isVoice; - bool isFax; - bool isPager; - bool isMSG; - bool isCell; - bool isVideo; - bool isBBS; - bool isModem; - bool isISDN; - bool isPCS; - bool isPreferred; - std::string number; - }; - - enum DeliveryType { - DomesticDelivery, - InternationalDelivery, - None - }; - - struct Address { - Address() : isHome(false), isWork(false), isPostal(false), isParcel(false), deliveryType(None), isPreferred(false) { - } - - bool isHome; - bool isWork; - bool isPostal; - bool isParcel; - DeliveryType deliveryType; - bool isPreferred; - - std::string poBox; - std::string addressExtension; - std::string street; - std::string locality; - std::string region; - std::string postalCode; - std::string country; - }; - - struct AddressLabel { - AddressLabel() : isHome(false), isWork(false), isPostal(false), isParcel(false), deliveryType(None), isPreferred(false) { - } - - bool isHome; - bool isWork; - bool isPostal; - bool isParcel; - DeliveryType deliveryType; - bool isPreferred; - std::vector<std::string> lines; - }; - - struct Organization { - std::string name; - std::vector<std::string> units; - }; - - VCard() {} - - void setVersion(const std::string& version) { version_ = version; } - const std::string& getVersion() const { return version_; } - - void setFullName(const std::string& fullName) { fullName_ = fullName; } - const std::string& getFullName() const { return fullName_; } - - void setFamilyName(const std::string& familyName) { familyName_ = familyName; } - const std::string& getFamilyName() const { return familyName_; } - - void setGivenName(const std::string& givenName) { givenName_ = givenName; } - const std::string& getGivenName() const { return givenName_; } - - void setMiddleName(const std::string& middleName) { middleName_ = middleName; } - const std::string& getMiddleName() const { return middleName_; } - - void setPrefix(const std::string& prefix) { prefix_ = prefix; } - const std::string& getPrefix() const { return prefix_; } - - void setSuffix(const std::string& suffix) { suffix_ = suffix; } - const std::string& getSuffix() const { return suffix_; } - - - //void setEMailAddress(const std::string& email) { email_ = email; } - //const std::string& getEMailAddress() const { return email_; } - - void setNickname(const std::string& nick) { nick_ = nick; } - const std::string& getNickname() const { return nick_; } - - void setPhoto(const ByteArray& photo) { photo_ = photo; } - const ByteArray& getPhoto() const { return photo_; } - - void setPhotoType(const std::string& photoType) { photoType_ = photoType; } - const std::string& getPhotoType() const { return photoType_; } - - const std::string& getUnknownContent() const { return unknownContent_; } - void addUnknownContent(const std::string& c) { - unknownContent_ += c; - } - - const std::vector<EMailAddress>& getEMailAddresses() const { - return emailAddresses_; - } - - void addEMailAddress(const EMailAddress& email) { - emailAddresses_.push_back(email); - } - - void clearEMailAddresses() { - emailAddresses_.clear(); - } + class SWIFTEN_API VCard : public Payload { + public: + typedef std::shared_ptr<VCard> ref; + + struct EMailAddress { + EMailAddress() : isHome(false), isWork(false), isInternet(false), isPreferred(false), isX400(false) { + } + + bool isHome; + bool isWork; + bool isInternet; + bool isPreferred; + bool isX400; + std::string address; + }; + + struct Telephone { + Telephone() : isHome(false), isWork(false), isVoice(false), isFax(false), isPager(false), isMSG(false), isCell(false), + isVideo(false), isBBS(false), isModem(false), isISDN(false), isPCS(false), isPreferred(false) { + } + + bool isHome; + bool isWork; + bool isVoice; + bool isFax; + bool isPager; + bool isMSG; + bool isCell; + bool isVideo; + bool isBBS; + bool isModem; + bool isISDN; + bool isPCS; + bool isPreferred; + std::string number; + }; + + enum DeliveryType { + DomesticDelivery, + InternationalDelivery, + None + }; + + struct Address { + Address() : isHome(false), isWork(false), isPostal(false), isParcel(false), deliveryType(None), isPreferred(false) { + } + + bool isHome; + bool isWork; + bool isPostal; + bool isParcel; + DeliveryType deliveryType; + bool isPreferred; + + std::string poBox; + std::string addressExtension; + std::string street; + std::string locality; + std::string region; + std::string postalCode; + std::string country; + }; + + struct AddressLabel { + AddressLabel() : isHome(false), isWork(false), isPostal(false), isParcel(false), deliveryType(None), isPreferred(false) { + } + + bool isHome; + bool isWork; + bool isPostal; + bool isParcel; + DeliveryType deliveryType; + bool isPreferred; + std::vector<std::string> lines; + }; + + struct Organization { + std::string name; + std::vector<std::string> units; + }; + + VCard() {} + + void setVersion(const std::string& version) { version_ = version; } + const std::string& getVersion() const { return version_; } + + void setFullName(const std::string& fullName) { fullName_ = fullName; } + const std::string& getFullName() const { return fullName_; } + + void setFamilyName(const std::string& familyName) { familyName_ = familyName; } + const std::string& getFamilyName() const { return familyName_; } + + void setGivenName(const std::string& givenName) { givenName_ = givenName; } + const std::string& getGivenName() const { return givenName_; } + + void setMiddleName(const std::string& middleName) { middleName_ = middleName; } + const std::string& getMiddleName() const { return middleName_; } + + void setPrefix(const std::string& prefix) { prefix_ = prefix; } + const std::string& getPrefix() const { return prefix_; } + + void setSuffix(const std::string& suffix) { suffix_ = suffix; } + const std::string& getSuffix() const { return suffix_; } + + + //void setEMailAddress(const std::string& email) { email_ = email; } + //const std::string& getEMailAddress() const { return email_; } + + void setNickname(const std::string& nick) { nick_ = nick; } + const std::string& getNickname() const { return nick_; } + + void setPhoto(const ByteArray& photo) { photo_ = photo; } + const ByteArray& getPhoto() const { return photo_; } + + void setPhotoType(const std::string& photoType) { photoType_ = photoType; } + const std::string& getPhotoType() const { return photoType_; } + + const std::string& getUnknownContent() const { return unknownContent_; } + void addUnknownContent(const std::string& c) { + unknownContent_ += c; + } + + const std::vector<EMailAddress>& getEMailAddresses() const { + return emailAddresses_; + } + + void addEMailAddress(const EMailAddress& email) { + emailAddresses_.push_back(email); + } + + void clearEMailAddresses() { + emailAddresses_.clear(); + } + + EMailAddress getPreferredEMailAddress() const; - EMailAddress getPreferredEMailAddress() const; + void setBirthday(const boost::posix_time::ptime& birthday) { + birthday_ = birthday; + } - void setBirthday(const boost::posix_time::ptime& birthday) { - birthday_ = birthday; - } + const boost::posix_time::ptime& getBirthday() const { + return birthday_; + } - const boost::posix_time::ptime& getBirthday() const { - return birthday_; - } + const std::vector<Telephone>& getTelephones() const { + return telephones_; + } - const std::vector<Telephone>& getTelephones() const { - return telephones_; - } + void addTelephone(const Telephone& phone) { + telephones_.push_back(phone); + } - void addTelephone(const Telephone& phone) { - telephones_.push_back(phone); - } + void clearTelephones() { + telephones_.clear(); + } - void clearTelephones() { - telephones_.clear(); - } + const std::vector<Address>& getAddresses() const { + return addresses_; + } - const std::vector<Address>& getAddresses() const { - return addresses_; - } + void addAddress(const Address& address) { + addresses_.push_back(address); + } - void addAddress(const Address& address) { - addresses_.push_back(address); - } - - void clearAddresses() { - addresses_.clear(); - } - - const std::vector<AddressLabel>& getAddressLabels() const { - return addressLabels_; - } - - void addAddressLabel(const AddressLabel& addressLabel) { - addressLabels_.push_back(addressLabel); - } - - void clearAddressLabels() { - addressLabels_.clear(); - } - - const std::vector<JID>& getJIDs() const { - return jids_; - } - - void addJID(const JID& jid) { - jids_.push_back(jid); - } - - void clearJIDs() { - jids_.clear(); - } - - const std::string& getDescription() const { - return description_; - } - - void setDescription(const std::string& description) { - this->description_ = description; - } - - const std::vector<Organization>& getOrganizations() const { - return organizations_; - } - - void addOrganization(const Organization& organization) { - organizations_.push_back(organization); - } - - void clearOrganizations() { - organizations_.clear(); - } - - const std::vector<std::string>& getTitles() const { - return titles_; - } - - void addTitle(const std::string& title) { - titles_.push_back(title); - } - - void clearTitles() { - titles_.clear(); - } - - const std::vector<std::string>& getRoles() const { - return roles_; - } - - void addRole(const std::string& role) { - roles_.push_back(role); - } - - void clearRoles() { - roles_.clear(); - } - - const std::vector<std::string>& getURLs() const { - return urls_; - } - - void addURL(const std::string& url) { - urls_.push_back(url); - } - - void clearURLs() { - urls_.clear(); - } - - private: - std::string version_; - std::string fullName_; - std::string familyName_; - std::string givenName_; - std::string middleName_; - std::string prefix_; - std::string suffix_; - //std::string email_; - ByteArray photo_; - std::string photoType_; - std::string nick_; - boost::posix_time::ptime birthday_; - std::string unknownContent_; - std::vector<EMailAddress> emailAddresses_; - std::vector<Telephone> telephones_; - std::vector<Address> addresses_; - std::vector<AddressLabel> addressLabels_; - std::vector<JID> jids_; - std::string description_; - std::vector<Organization> organizations_; - std::vector<std::string> titles_; - std::vector<std::string> roles_; - std::vector<std::string> urls_; - }; + void clearAddresses() { + addresses_.clear(); + } + + const std::vector<AddressLabel>& getAddressLabels() const { + return addressLabels_; + } + + void addAddressLabel(const AddressLabel& addressLabel) { + addressLabels_.push_back(addressLabel); + } + + void clearAddressLabels() { + addressLabels_.clear(); + } + + const std::vector<JID>& getJIDs() const { + return jids_; + } + + void addJID(const JID& jid) { + jids_.push_back(jid); + } + + void clearJIDs() { + jids_.clear(); + } + + const std::string& getDescription() const { + return description_; + } + + void setDescription(const std::string& description) { + this->description_ = description; + } + + const std::vector<Organization>& getOrganizations() const { + return organizations_; + } + + void addOrganization(const Organization& organization) { + organizations_.push_back(organization); + } + + void clearOrganizations() { + organizations_.clear(); + } + + const std::vector<std::string>& getTitles() const { + return titles_; + } + + void addTitle(const std::string& title) { + titles_.push_back(title); + } + + void clearTitles() { + titles_.clear(); + } + + const std::vector<std::string>& getRoles() const { + return roles_; + } + + void addRole(const std::string& role) { + roles_.push_back(role); + } + + void clearRoles() { + roles_.clear(); + } + + const std::vector<std::string>& getURLs() const { + return urls_; + } + + void addURL(const std::string& url) { + urls_.push_back(url); + } + + void clearURLs() { + urls_.clear(); + } + + bool isEmpty() const { + bool empty = version_.empty() && fullName_.empty() && familyName_.empty() && givenName_.empty() && middleName_.empty() && prefix_.empty() && suffix_.empty(); + empty &= photo_.empty() && photoType_.empty() && nick_.empty(); + empty &= birthday_.is_not_a_date_time(); + empty &= unknownContent_.empty(); + empty &= emailAddresses_.empty() && telephones_.empty() && addresses_.empty() && addressLabels_.empty() && jids_.empty(); + empty &= description_.empty() && organizations_.empty() && titles_.empty() && roles_.empty() && urls_.empty(); + return empty; + } + + private: + std::string version_; + std::string fullName_; + std::string familyName_; + std::string givenName_; + std::string middleName_; + std::string prefix_; + std::string suffix_; + //std::string email_; + ByteArray photo_; + std::string photoType_; + std::string nick_; + boost::posix_time::ptime birthday_; + std::string unknownContent_; + std::vector<EMailAddress> emailAddresses_; + std::vector<Telephone> telephones_; + std::vector<Address> addresses_; + std::vector<AddressLabel> addressLabels_; + std::vector<JID> jids_; + std::string description_; + std::vector<Organization> organizations_; + std::vector<std::string> titles_; + std::vector<std::string> roles_; + std::vector<std::string> urls_; + }; } diff --git a/Swiften/Elements/VCardUpdate.h b/Swiften/Elements/VCardUpdate.h index 782106c..e3b5377 100644 --- a/Swiften/Elements/VCardUpdate.h +++ b/Swiften/Elements/VCardUpdate.h @@ -1,23 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class VCardUpdate : public Payload { - public: - VCardUpdate(const std::string& photoHash = "") : photoHash_(photoHash) {} + class SWIFTEN_API VCardUpdate : public Payload { + public: + VCardUpdate(const std::string& photoHash = "") : photoHash_(photoHash) {} - void setPhotoHash(const std::string& photoHash) { photoHash_ = photoHash; } - const std::string& getPhotoHash() const { return photoHash_; } + void setPhotoHash(const std::string& photoHash) { photoHash_ = photoHash; } + const std::string& getPhotoHash() const { return photoHash_; } - private: - std::string photoHash_; - }; + private: + std::string photoHash_; + }; } diff --git a/Swiften/Elements/Version.h b/Swiften/Elements/Version.h index 350fd91..1d734be 100644 --- a/Swiften/Elements/Version.h +++ b/Swiften/Elements/Version.h @@ -1,26 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class Version : public Payload { - public: - Version(const std::string& name = "", const std::string& version = "", const std::string& os = "") : name_(name), version_(version), os_(os) { } + class SWIFTEN_API Version : public Payload { + public: + Version(const std::string& name = "", const std::string& version = "", const std::string& os = "") : name_(name), version_(version), os_(os) { } - const std::string& getName() const { return name_; } - const std::string& getVersion() const { return version_; } - const std::string& getOS() const { return os_; } + const std::string& getName() const { return name_; } + const std::string& getVersion() const { return version_; } + const std::string& getOS() const { return os_; } - private: - std::string name_; - std::string version_; - std::string os_; - }; + private: + std::string name_; + std::string version_; + std::string os_; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardColor.cpp b/Swiften/Elements/Whiteboard/WhiteboardColor.cpp index f4ff01a..037fde4 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardColor.cpp +++ b/Swiften/Elements/Whiteboard/WhiteboardColor.cpp @@ -4,52 +4,59 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Elements/Whiteboard/WhiteboardColor.h> -#include <Swiften/Base/String.h> + #include <cstdio> #include <iomanip> #include <sstream> -#include <iostream> + +#include <Swiften/Base/String.h> namespace Swift { - WhiteboardColor::WhiteboardColor() : red_(0), green_(0), blue_(0), alpha_(255) { - } - - WhiteboardColor::WhiteboardColor(int red, int green, int blue, int alpha) : red_(red), green_(green), blue_(blue), alpha_(alpha) { - } - - WhiteboardColor::WhiteboardColor(const std::string& hex) : alpha_(255) { - int value = String::convertHexStringToInt(hex.substr(1)); - red_ = (value >> 16)&0xFF; - green_ = (value >> 8)&0xFF; - blue_ = value&0xFF; - } - - std::string WhiteboardColor::toHex() const { - std::string value = String::convertIntToHexString((red_ << 16) + (green_ << 8) + blue_); - while (value.size() < 6) { - value.insert(0, "0"); - } - return "#"+value; - } - - int WhiteboardColor::getRed() const { - return red_; - } - - int WhiteboardColor::getGreen() const { - return green_; - } - - int WhiteboardColor::getBlue() const { - return blue_; - } - - int WhiteboardColor::getAlpha() const { - return alpha_; - } - - void WhiteboardColor::setAlpha(int alpha) { - alpha_ = alpha; - } + WhiteboardColor::WhiteboardColor() : red_(0), green_(0), blue_(0), alpha_(255) { + } + + WhiteboardColor::WhiteboardColor(int red, int green, int blue, int alpha) : red_(red), green_(green), blue_(blue), alpha_(alpha) { + } + + WhiteboardColor::WhiteboardColor(const std::string& hex) : alpha_(255) { + int value = String::convertHexStringToInt(hex.substr(1)); + red_ = (value >> 16)&0xFF; + green_ = (value >> 8)&0xFF; + blue_ = value&0xFF; + } + + std::string WhiteboardColor::toHex() const { + std::string value = String::convertIntToHexString((red_ << 16) + (green_ << 8) + blue_); + while (value.size() < 6) { + value.insert(0, "0"); + } + return "#"+value; + } + + int WhiteboardColor::getRed() const { + return red_; + } + + int WhiteboardColor::getGreen() const { + return green_; + } + + int WhiteboardColor::getBlue() const { + return blue_; + } + + int WhiteboardColor::getAlpha() const { + return alpha_; + } + + void WhiteboardColor::setAlpha(int alpha) { + alpha_ = alpha; + } } diff --git a/Swiften/Elements/Whiteboard/WhiteboardColor.h b/Swiften/Elements/Whiteboard/WhiteboardColor.h index 3b3d93c..6402efd 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardColor.h +++ b/Swiften/Elements/Whiteboard/WhiteboardColor.h @@ -11,20 +11,20 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API WhiteboardColor { - public: - WhiteboardColor(); - WhiteboardColor(int red, int green, int blue, int alpha = 255); - WhiteboardColor(const std::string& hex); - std::string toHex() const; - int getRed() const; - int getGreen() const; - int getBlue() const; - int getAlpha() const; - void setAlpha(int alpha); + class SWIFTEN_API WhiteboardColor { + public: + WhiteboardColor(); + WhiteboardColor(int red, int green, int blue, int alpha = 255); + WhiteboardColor(const std::string& hex); + std::string toHex() const; + int getRed() const; + int getGreen() const; + int getBlue() const; + int getAlpha() const; + void setAlpha(int alpha); - private: - int red_, green_, blue_; - int alpha_; - }; + private: + int red_, green_, blue_; + int alpha_; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h b/Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h index 091ee30..ae0fe17 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h +++ b/Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h @@ -4,29 +4,32 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#pragma once +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> +#pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Whiteboard/WhiteboardElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> namespace Swift { - class WhiteboardDeleteOperation : public WhiteboardOperation { - public: - typedef boost::shared_ptr<WhiteboardDeleteOperation> ref; - public: - ~WhiteboardDeleteOperation() { - } - - std::string getElementID() const { - return elementID_; - } + class SWIFTEN_API WhiteboardDeleteOperation : public WhiteboardOperation { + public: + typedef std::shared_ptr<WhiteboardDeleteOperation> ref; + public: + std::string getElementID() const { + return elementID_; + } - void setElementID(const std::string& elementID) { - elementID_ = elementID; - } + void setElementID(const std::string& elementID) { + elementID_ = elementID; + } - private: - std::string elementID_; - }; + private: + std::string elementID_; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardElement.h b/Swiften/Elements/Whiteboard/WhiteboardElement.h index df774d9..6f6ff4f 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardElement.h +++ b/Swiften/Elements/Whiteboard/WhiteboardElement.h @@ -4,29 +4,37 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + #include <Swiften/Elements/Whiteboard/WhiteboardElementVisitor.h> namespace Swift { - class WhiteboardElement { - public: - typedef boost::shared_ptr<WhiteboardElement> ref; + class WhiteboardElement { + public: + typedef std::shared_ptr<WhiteboardElement> ref; - public: - virtual ~WhiteboardElement() {} - virtual void accept(WhiteboardElementVisitor& visitor) = 0; + public: + virtual ~WhiteboardElement() {} + virtual void accept(WhiteboardElementVisitor& visitor) = 0; - const std::string& getID() const { - return id_; - } + const std::string& getID() const { + return id_; + } - void setID(const std::string& id) { - id_ = id; - } + void setID(const std::string& id) { + id_ = id; + } - private: - std::string id_; - }; + private: + std::string id_; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardElementVisitor.h b/Swiften/Elements/Whiteboard/WhiteboardElementVisitor.h index 413d6cf..090af56 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardElementVisitor.h +++ b/Swiften/Elements/Whiteboard/WhiteboardElementVisitor.h @@ -7,21 +7,21 @@ #pragma once namespace Swift { - class WhiteboardLineElement; - class WhiteboardFreehandPathElement; - class WhiteboardRectElement; - class WhiteboardPolygonElement; - class WhiteboardTextElement; - class WhiteboardEllipseElement; + class WhiteboardLineElement; + class WhiteboardFreehandPathElement; + class WhiteboardRectElement; + class WhiteboardPolygonElement; + class WhiteboardTextElement; + class WhiteboardEllipseElement; - class WhiteboardElementVisitor { - public: - virtual ~WhiteboardElementVisitor() {} - virtual void visit(WhiteboardLineElement& /*element*/) = 0; - virtual void visit(WhiteboardFreehandPathElement& /*element*/) = 0; - virtual void visit(WhiteboardRectElement& /*element*/) = 0; - virtual void visit(WhiteboardPolygonElement& /*element*/) = 0; - virtual void visit(WhiteboardTextElement& /*element*/) = 0; - virtual void visit(WhiteboardEllipseElement& /*element*/) = 0; - }; + class WhiteboardElementVisitor { + public: + virtual ~WhiteboardElementVisitor() {} + virtual void visit(WhiteboardLineElement& /*element*/) = 0; + virtual void visit(WhiteboardFreehandPathElement& /*element*/) = 0; + virtual void visit(WhiteboardRectElement& /*element*/) = 0; + virtual void visit(WhiteboardPolygonElement& /*element*/) = 0; + virtual void visit(WhiteboardTextElement& /*element*/) = 0; + virtual void visit(WhiteboardEllipseElement& /*element*/) = 0; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h b/Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h index 0078479..8086aed 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h +++ b/Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h @@ -4,71 +4,78 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Whiteboard/WhiteboardColor.h> +#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> namespace Swift { - class WhiteboardEllipseElement : public WhiteboardElement { - public: - typedef boost::shared_ptr<WhiteboardEllipseElement> ref; - public: - WhiteboardEllipseElement(int cx, int cy, int rx, int ry) { - cx_ = cx; - cy_ = cy; - rx_ = rx; - ry_ = ry; - } - - int getCX() const { - return cx_; - } - - int getCY() const { - return cy_; - } - - int getRX() const { - return rx_; - } - - int getRY() const { - return ry_; - } - - const WhiteboardColor& getPenColor() const { - return penColor_; - } - - void setPenColor(const WhiteboardColor& color) { - penColor_ = color; - } - - const WhiteboardColor& getBrushColor() const { - return brushColor_; - } - - void setBrushColor(const WhiteboardColor& color) { - brushColor_ = color; - } - - int getPenWidth() const { - return penWidth_; - } - - void setPenWidth(const int penWidth) { - penWidth_ = penWidth; - } - - void accept(WhiteboardElementVisitor& visitor) { - visitor.visit(*this); - } - - private: - int cx_, cy_, rx_, ry_; - WhiteboardColor penColor_; - WhiteboardColor brushColor_; - int penWidth_; - }; + class SWIFTEN_API WhiteboardEllipseElement : public WhiteboardElement { + public: + typedef std::shared_ptr<WhiteboardEllipseElement> ref; + public: + WhiteboardEllipseElement(int cx, int cy, int rx, int ry) { + cx_ = cx; + cy_ = cy; + rx_ = rx; + ry_ = ry; + } + + int getCX() const { + return cx_; + } + + int getCY() const { + return cy_; + } + + int getRX() const { + return rx_; + } + + int getRY() const { + return ry_; + } + + const WhiteboardColor& getPenColor() const { + return penColor_; + } + + void setPenColor(const WhiteboardColor& color) { + penColor_ = color; + } + + const WhiteboardColor& getBrushColor() const { + return brushColor_; + } + + void setBrushColor(const WhiteboardColor& color) { + brushColor_ = color; + } + + int getPenWidth() const { + return penWidth_; + } + + void setPenWidth(const int penWidth) { + penWidth_ = penWidth; + } + + void accept(WhiteboardElementVisitor& visitor) { + visitor.visit(*this); + } + + private: + int cx_, cy_, rx_, ry_; + WhiteboardColor penColor_; + WhiteboardColor brushColor_; + int penWidth_ = 0; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardFreehandPathElement.h b/Swiften/Elements/Whiteboard/WhiteboardFreehandPathElement.h index bcf3bf9..bc6c846 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardFreehandPathElement.h +++ b/Swiften/Elements/Whiteboard/WhiteboardFreehandPathElement.h @@ -4,54 +4,61 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#pragma once +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> -#include <Swiften/Elements/Whiteboard/WhiteboardColor.h> +#pragma once -#include <vector> #include <utility> +#include <vector> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Whiteboard/WhiteboardColor.h> +#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> namespace Swift { - class WhiteboardFreehandPathElement : public WhiteboardElement { - typedef std::pair<int, int> Point; - public: - typedef boost::shared_ptr<WhiteboardFreehandPathElement> ref; - public: - WhiteboardFreehandPathElement() { - } - - void setPoints(const std::vector<Point>& points) { - points_ = points; - } - - const std::vector<Point>& getPoints() const { - return points_; - } - - const WhiteboardColor& getColor() const { - return color_; - } - - void setColor(const WhiteboardColor& color) { - color_ = color; - } - - int getPenWidth() const { - return penWidth_; - } - - void setPenWidth(const int penWidth) { - penWidth_ = penWidth; - } - - void accept(WhiteboardElementVisitor& visitor) { - visitor.visit(*this); - } - - private: - std::vector<Point> points_; - WhiteboardColor color_; - int penWidth_; - }; + class SWIFTEN_API WhiteboardFreehandPathElement : public WhiteboardElement { + typedef std::pair<int, int> Point; + public: + typedef std::shared_ptr<WhiteboardFreehandPathElement> ref; + public: + WhiteboardFreehandPathElement() { + } + + void setPoints(const std::vector<Point>& points) { + points_ = points; + } + + const std::vector<Point>& getPoints() const { + return points_; + } + + const WhiteboardColor& getColor() const { + return color_; + } + + void setColor(const WhiteboardColor& color) { + color_ = color; + } + + int getPenWidth() const { + return penWidth_; + } + + void setPenWidth(const int penWidth) { + penWidth_ = penWidth; + } + + void accept(WhiteboardElementVisitor& visitor) { + visitor.visit(*this); + } + + private: + std::vector<Point> points_; + WhiteboardColor color_; + int penWidth_ = 0; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h b/Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h index 8c20044..256c17e 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h +++ b/Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h @@ -4,29 +4,32 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#pragma once +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> +#pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Whiteboard/WhiteboardElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> namespace Swift { - class WhiteboardInsertOperation : public WhiteboardOperation { - public: - typedef boost::shared_ptr<WhiteboardInsertOperation> ref; - public: - ~WhiteboardInsertOperation() { - } - - WhiteboardElement::ref getElement() const { - return element_; - } + class SWIFTEN_API WhiteboardInsertOperation : public WhiteboardOperation { + public: + typedef std::shared_ptr<WhiteboardInsertOperation> ref; + public: + WhiteboardElement::ref getElement() const { + return element_; + } - void setElement(WhiteboardElement::ref element) { - element_ = element; - } + void setElement(WhiteboardElement::ref element) { + element_ = element; + } - private: - WhiteboardElement::ref element_; - }; + private: + WhiteboardElement::ref element_; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardLineElement.h b/Swiften/Elements/Whiteboard/WhiteboardLineElement.h index 3c63afc..9c64977 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardLineElement.h +++ b/Swiften/Elements/Whiteboard/WhiteboardLineElement.h @@ -4,62 +4,70 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + + #pragma once -#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Whiteboard/WhiteboardColor.h> +#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> namespace Swift { - class WhiteboardLineElement : public WhiteboardElement { - public: - typedef boost::shared_ptr<WhiteboardLineElement> ref; - public: - WhiteboardLineElement(int x1, int y1, int x2, int y2) { - x1_ = x1; - y1_ = y1; - x2_ = x2; - y2_ = y2; - } + class SWIFTEN_API WhiteboardLineElement : public WhiteboardElement { + public: + typedef std::shared_ptr<WhiteboardLineElement> ref; + public: + WhiteboardLineElement(int x1, int y1, int x2, int y2) : penWidth_(1) { + x1_ = x1; + y1_ = y1; + x2_ = x2; + y2_ = y2; + } - int x1() const { - return x1_; - } + int x1() const { + return x1_; + } - int y1() const { - return y1_; - } + int y1() const { + return y1_; + } - int x2() const { - return x2_; - } + int x2() const { + return x2_; + } - int y2() const { - return y2_; - } + int y2() const { + return y2_; + } - const WhiteboardColor& getColor() const { - return color_; - } + const WhiteboardColor& getColor() const { + return color_; + } - void setColor(const WhiteboardColor& color) { - color_ = color; - } + void setColor(const WhiteboardColor& color) { + color_ = color; + } - int getPenWidth() const { - return penWidth_; - } + int getPenWidth() const { + return penWidth_; + } - void setPenWidth(const int penWidth) { - penWidth_ = penWidth; - } + void setPenWidth(const int penWidth) { + penWidth_ = penWidth; + } - void accept(WhiteboardElementVisitor& visitor) { - visitor.visit(*this); - } + void accept(WhiteboardElementVisitor& visitor) { + visitor.visit(*this); + } - private: - int x1_, y1_, x2_, y2_; - WhiteboardColor color_; - int penWidth_; - }; + private: + int x1_, y1_, x2_, y2_; + WhiteboardColor color_; + int penWidth_; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardOperation.h b/Swiften/Elements/Whiteboard/WhiteboardOperation.h index 75f6e6a..2e90c69 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardOperation.h +++ b/Swiften/Elements/Whiteboard/WhiteboardOperation.h @@ -4,45 +4,56 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/smart_ptr/shared_ptr.hpp> #include <string> +#include <boost/smart_ptr/shared_ptr.hpp> + +#include <Swiften/Base/API.h> + namespace Swift { - class WhiteboardOperation { - public: - typedef boost::shared_ptr<WhiteboardOperation> ref; - public: - virtual ~WhiteboardOperation(){} - - std::string getID() const { - return id_; - } - - void setID(const std::string& id) { - id_ = id; - } - - std::string getParentID() const { - return parentID_; - } - - void setParentID(const std::string& parentID) { - parentID_ = parentID; - } - - int getPos() const { - return pos_; - } - - void setPos(int pos) { - pos_ = pos; - } - - private: - std::string id_; - std::string parentID_; - int pos_; - }; + class WhiteboardOperation { + public: + typedef std::shared_ptr<WhiteboardOperation> ref; + public: + WhiteboardOperation() {} + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(WhiteboardOperation) + virtual ~WhiteboardOperation(){} + + std::string getID() const { + return id_; + } + + void setID(const std::string& id) { + id_ = id; + } + + std::string getParentID() const { + return parentID_; + } + + void setParentID(const std::string& parentID) { + parentID_ = parentID; + } + + int getPos() const { + return pos_; + } + + void setPos(int pos) { + pos_ = pos; + } + + private: + std::string id_; + std::string parentID_; + int pos_ = 0; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardPolygonElement.h b/Swiften/Elements/Whiteboard/WhiteboardPolygonElement.h index 679ac01..6ad5dc7 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardPolygonElement.h +++ b/Swiften/Elements/Whiteboard/WhiteboardPolygonElement.h @@ -4,60 +4,69 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> +#include <vector> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Whiteboard/WhiteboardColor.h> +#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> namespace Swift { - class WhiteboardPolygonElement : public WhiteboardElement { - typedef std::pair<int, int> Point; - public: - typedef boost::shared_ptr<WhiteboardPolygonElement> ref; - public: - WhiteboardPolygonElement() { - } - - const std::vector<Point>& getPoints() const { - return points_; - } - - void setPoints(const std::vector<Point>& points) { - points_ = points; - } - - const WhiteboardColor& getPenColor() const { - return penColor_; - } - - void setPenColor(const WhiteboardColor& color) { - penColor_ = color; - } - - const WhiteboardColor& getBrushColor() const { - return brushColor_; - } - - void setBrushColor(const WhiteboardColor& color) { - brushColor_ = color; - } - - int getPenWidth() const { - return penWidth_; - } - - void setPenWidth(const int penWidth) { - penWidth_ = penWidth; - } - - void accept(WhiteboardElementVisitor& visitor) { - visitor.visit(*this); - } - - private: - std::vector<Point> points_; - WhiteboardColor penColor_; - WhiteboardColor brushColor_; - int penWidth_; - }; + class SWIFTEN_API WhiteboardPolygonElement : public WhiteboardElement { + typedef std::pair<int, int> Point; + public: + typedef std::shared_ptr<WhiteboardPolygonElement> ref; + public: + WhiteboardPolygonElement() { + } + + const std::vector<Point>& getPoints() const { + return points_; + } + + void setPoints(const std::vector<Point>& points) { + points_ = points; + } + + const WhiteboardColor& getPenColor() const { + return penColor_; + } + + void setPenColor(const WhiteboardColor& color) { + penColor_ = color; + } + + const WhiteboardColor& getBrushColor() const { + return brushColor_; + } + + void setBrushColor(const WhiteboardColor& color) { + brushColor_ = color; + } + + int getPenWidth() const { + return penWidth_; + } + + void setPenWidth(const int penWidth) { + penWidth_ = penWidth; + } + + void accept(WhiteboardElementVisitor& visitor) { + visitor.visit(*this); + } + + private: + std::vector<Point> points_; + WhiteboardColor penColor_; + WhiteboardColor brushColor_; + int penWidth_ = 0; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardRectElement.h b/Swiften/Elements/Whiteboard/WhiteboardRectElement.h index 233b3fa..4dcdc8a 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardRectElement.h +++ b/Swiften/Elements/Whiteboard/WhiteboardRectElement.h @@ -4,71 +4,78 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Whiteboard/WhiteboardColor.h> +#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> namespace Swift { - class WhiteboardRectElement : public WhiteboardElement { - public: - typedef boost::shared_ptr<WhiteboardRectElement> ref; - public: - WhiteboardRectElement(int x, int y, int width, int height) { - x_ = x; - y_ = y; - width_ = width; - height_ = height; - } - - int getX() const { - return x_; - } - - int getY() const { - return y_; - } - - int getWidth() const { - return width_; - } - - int getHeight() const { - return height_; - } - - const WhiteboardColor& getPenColor() const { - return penColor_; - } - - void setPenColor(const WhiteboardColor& color) { - penColor_ = color; - } - - const WhiteboardColor& getBrushColor() const { - return brushColor_; - } - - void setBrushColor(const WhiteboardColor& color) { - brushColor_ = color; - } - - int getPenWidth() const { - return penWidth_; - } - - void setPenWidth(const int penWidth) { - penWidth_ = penWidth; - } - - void accept(WhiteboardElementVisitor& visitor) { - visitor.visit(*this); - } - - private: - int x_, y_, width_, height_; - WhiteboardColor penColor_; - WhiteboardColor brushColor_; - int penWidth_; - }; + class SWIFTEN_API WhiteboardRectElement : public WhiteboardElement { + public: + typedef std::shared_ptr<WhiteboardRectElement> ref; + public: + WhiteboardRectElement(int x, int y, int width, int height) : penWidth_(1) { + x_ = x; + y_ = y; + width_ = width; + height_ = height; + } + + int getX() const { + return x_; + } + + int getY() const { + return y_; + } + + int getWidth() const { + return width_; + } + + int getHeight() const { + return height_; + } + + const WhiteboardColor& getPenColor() const { + return penColor_; + } + + void setPenColor(const WhiteboardColor& color) { + penColor_ = color; + } + + const WhiteboardColor& getBrushColor() const { + return brushColor_; + } + + void setBrushColor(const WhiteboardColor& color) { + brushColor_ = color; + } + + int getPenWidth() const { + return penWidth_; + } + + void setPenWidth(const int penWidth) { + penWidth_ = penWidth; + } + + void accept(WhiteboardElementVisitor& visitor) { + visitor.visit(*this); + } + + private: + int x_, y_, width_, height_; + WhiteboardColor penColor_; + WhiteboardColor brushColor_; + int penWidth_; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardTextElement.h b/Swiften/Elements/Whiteboard/WhiteboardTextElement.h index 7118ac9..2e1c145 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardTextElement.h +++ b/Swiften/Elements/Whiteboard/WhiteboardTextElement.h @@ -4,61 +4,68 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Whiteboard/WhiteboardColor.h> +#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> namespace Swift { - class WhiteboardTextElement : public WhiteboardElement { - public: - typedef boost::shared_ptr<WhiteboardTextElement> ref; - public: - WhiteboardTextElement(int x, int y) { - x_ = x; - y_ = y; - } + class SWIFTEN_API WhiteboardTextElement : public WhiteboardElement { + public: + typedef std::shared_ptr<WhiteboardTextElement> ref; + public: + WhiteboardTextElement(int x, int y) { + x_ = x; + y_ = y; + } - void setText(const std::string text) { - text_ = text; - } + void setText(const std::string text) { + text_ = text; + } - const std::string& getText() const { - return text_; - } + const std::string& getText() const { + return text_; + } - int getX() const { - return x_; - } + int getX() const { + return x_; + } - int getY() const { - return y_; - } + int getY() const { + return y_; + } - const WhiteboardColor& getColor() const { - return color_; - } + const WhiteboardColor& getColor() const { + return color_; + } - void setColor(const WhiteboardColor& color) { - color_ = color; - } + void setColor(const WhiteboardColor& color) { + color_ = color; + } - int getSize() const { - return size_; - } + int getSize() const { + return size_; + } - void setSize(const int size) { - size_ = size; - } + void setSize(const int size) { + size_ = size; + } - void accept(WhiteboardElementVisitor& visitor) { - visitor.visit(*this); - } + void accept(WhiteboardElementVisitor& visitor) { + visitor.visit(*this); + } - private: - int x_, y_; - int size_; - std::string text_; - WhiteboardColor color_; - }; + private: + int x_, y_; + int size_ = 0; + std::string text_; + WhiteboardColor color_; + }; } diff --git a/Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h b/Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h index a52a341..36cbc6d 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h +++ b/Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h @@ -4,38 +4,41 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#pragma once +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> +#pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Whiteboard/WhiteboardElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> namespace Swift { - class WhiteboardUpdateOperation : public WhiteboardOperation { - public: - typedef boost::shared_ptr<WhiteboardUpdateOperation> ref; - public: - ~WhiteboardUpdateOperation() { - } - - WhiteboardElement::ref getElement() const { - return element_; - } - - void setElement(WhiteboardElement::ref element) { - element_ = element; - } - - int getNewPos() const { - return newPos_; - } - - void setNewPos(int newPos) { - newPos_ = newPos; - } - - private: - WhiteboardElement::ref element_; - int newPos_; - }; + class SWIFTEN_API WhiteboardUpdateOperation : public WhiteboardOperation { + public: + typedef std::shared_ptr<WhiteboardUpdateOperation> ref; + public: + WhiteboardElement::ref getElement() const { + return element_; + } + + void setElement(WhiteboardElement::ref element) { + element_ = element; + } + + int getNewPos() const { + return newPos_; + } + + void setNewPos(int newPos) { + newPos_ = newPos; + } + + private: + WhiteboardElement::ref element_; + int newPos_ = 0; + }; } diff --git a/Swiften/Elements/WhiteboardPayload.h b/Swiften/Elements/WhiteboardPayload.h index ceb2b27..41c0acd 100644 --- a/Swiften/Elements/WhiteboardPayload.h +++ b/Swiften/Elements/WhiteboardPayload.h @@ -4,61 +4,68 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> #include <Swiften/Elements/Whiteboard/WhiteboardElement.h> #include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> namespace Swift { - class WhiteboardPayload : public Payload { - public: - typedef boost::shared_ptr<WhiteboardPayload> ref; - - public: - enum Type {UnknownType, Data, SessionRequest, SessionAccept, SessionTerminate}; - - WhiteboardPayload(Type type = WhiteboardPayload::Data) : type_(type) { - } - - void setData(const std::string &data) { - data_ = data; - } - - std::string getData() const { - return data_; - } - - Type getType() const { - return type_; - } - - void setType(Type type) { - type_ = type; - } - - WhiteboardElement::ref getElement() const { - return element_; - } - - void setElement(WhiteboardElement::ref element) { - element_ = element; - } - - WhiteboardOperation::ref getOperation() const { - return operation_; - } - - void setOperation(WhiteboardOperation::ref operation) { - operation_ = operation; - } - - private: - std::string data_; - Type type_; - WhiteboardElement::ref element_; - WhiteboardOperation::ref operation_; - }; + class SWIFTEN_API WhiteboardPayload : public Payload { + public: + typedef std::shared_ptr<WhiteboardPayload> ref; + + public: + enum Type {UnknownType, Data, SessionRequest, SessionAccept, SessionTerminate}; + + WhiteboardPayload(Type type = WhiteboardPayload::Data) : type_(type) { + } + + void setData(const std::string &data) { + data_ = data; + } + + std::string getData() const { + return data_; + } + + Type getType() const { + return type_; + } + + void setType(Type type) { + type_ = type; + } + + WhiteboardElement::ref getElement() const { + return element_; + } + + void setElement(WhiteboardElement::ref element) { + element_ = element; + } + + WhiteboardOperation::ref getOperation() const { + return operation_; + } + + void setOperation(WhiteboardOperation::ref operation) { + operation_ = operation; + } + + private: + std::string data_; + Type type_; + WhiteboardElement::ref element_; + WhiteboardOperation::ref operation_; + }; } diff --git a/Swiften/Entity/Entity.cpp b/Swiften/Entity/Entity.cpp index 44f9fbf..0875fb1 100644 --- a/Swiften/Entity/Entity.cpp +++ b/Swiften/Entity/Entity.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Entity/Entity.h> @@ -9,42 +9,41 @@ #include <Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h> #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> - namespace Swift { Entity::Entity() { - payloadParserFactories = new FullPayloadParserFactoryCollection(); - payloadSerializers = new FullPayloadSerializerCollection(); + payloadParserFactories = new FullPayloadParserFactoryCollection(); + payloadSerializers = new FullPayloadSerializerCollection(); } Entity::~Entity() { - delete payloadSerializers; - delete payloadParserFactories; + delete payloadSerializers; + delete payloadParserFactories; } void Entity::addPayloadParserFactory(PayloadParserFactory* payloadParserFactory) { - payloadParserFactories->addFactory(payloadParserFactory); + payloadParserFactories->addFactory(payloadParserFactory); } void Entity::removePayloadParserFactory(PayloadParserFactory* payloadParserFactory) { - payloadParserFactories->removeFactory(payloadParserFactory); + payloadParserFactories->removeFactory(payloadParserFactory); } void Entity::addPayloadSerializer(PayloadSerializer* payloadSerializer) { - payloadSerializers->addSerializer(payloadSerializer); + payloadSerializers->addSerializer(payloadSerializer); } void Entity::removePayloadSerializer(PayloadSerializer* payloadSerializer) { - payloadSerializers->removeSerializer(payloadSerializer); + payloadSerializers->removeSerializer(payloadSerializer); } PayloadParserFactoryCollection* Entity::getPayloadParserFactories() { - return payloadParserFactories; + return payloadParserFactories; } PayloadSerializerCollection* Entity::getPayloadSerializers() { - return payloadSerializers; + return payloadSerializers; } } diff --git a/Swiften/Entity/Entity.h b/Swiften/Entity/Entity.h index 0dc2929..a44c145 100644 --- a/Swiften/Entity/Entity.h +++ b/Swiften/Entity/Entity.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,33 +9,33 @@ #include <Swiften/Base/API.h> namespace Swift { - class PayloadParserFactory; - class PayloadSerializer; - class FullPayloadParserFactoryCollection; - class FullPayloadSerializerCollection; - class PayloadParserFactoryCollection; - class PayloadSerializerCollection; - - /** - * The base class for XMPP entities (Clients, Components). - */ - class SWIFTEN_API Entity { - public: - Entity(); - virtual ~Entity(); - - void addPayloadParserFactory(PayloadParserFactory* payloadParserFactory); - void removePayloadParserFactory(PayloadParserFactory* payloadParserFactory); - - void addPayloadSerializer(PayloadSerializer* payloadSerializer); - void removePayloadSerializer(PayloadSerializer* payloadSerializer); - - protected: - PayloadParserFactoryCollection* getPayloadParserFactories(); - PayloadSerializerCollection* getPayloadSerializers(); - - private: - FullPayloadParserFactoryCollection* payloadParserFactories; - FullPayloadSerializerCollection* payloadSerializers; - }; + class PayloadParserFactory; + class PayloadSerializer; + class FullPayloadParserFactoryCollection; + class FullPayloadSerializerCollection; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + + /** + * The base class for XMPP entities (Clients, Components). + */ + class SWIFTEN_API Entity { + public: + Entity(); + virtual ~Entity(); + + void addPayloadParserFactory(PayloadParserFactory* payloadParserFactory); + void removePayloadParserFactory(PayloadParserFactory* payloadParserFactory); + + void addPayloadSerializer(PayloadSerializer* payloadSerializer); + void removePayloadSerializer(PayloadSerializer* payloadSerializer); + + protected: + PayloadParserFactoryCollection* getPayloadParserFactories(); + PayloadSerializerCollection* getPayloadSerializers(); + + private: + FullPayloadParserFactoryCollection* payloadParserFactories; + FullPayloadSerializerCollection* payloadSerializers; + }; } diff --git a/Swiften/Entity/GenericPayloadPersister.h b/Swiften/Entity/GenericPayloadPersister.h index 63553de..7cef857 100644 --- a/Swiften/Entity/GenericPayloadPersister.h +++ b/Swiften/Entity/GenericPayloadPersister.h @@ -1,36 +1,37 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Entity/PayloadPersister.h> #include <Swiften/Parser/GenericPayloadParserFactory.h> namespace Swift { - template<typename PAYLOAD, typename PARSER, typename SERIALIZER> - class GenericPayloadPersister : public PayloadPersister { - public: - GenericPayloadPersister() { - } + template<typename PAYLOAD, typename PARSER, typename SERIALIZER> + class SWIFTEN_API GenericPayloadPersister : public PayloadPersister { + public: + GenericPayloadPersister() { + } - public: - boost::shared_ptr<PAYLOAD> loadPayloadGeneric(const boost::filesystem::path& path) { - return boost::dynamic_pointer_cast<PAYLOAD>(loadPayload(path)); - } + public: + std::shared_ptr<PAYLOAD> loadPayloadGeneric(const boost::filesystem::path& path) { + return std::dynamic_pointer_cast<PAYLOAD>(loadPayload(path)); + } - protected: - virtual const PayloadSerializer* getSerializer() const { - return &serializer; - } + protected: + virtual const PayloadSerializer* getSerializer() const { + return &serializer; + } - virtual PayloadParser* createParser() const { - return new PARSER(); - } + virtual PayloadParser* createParser() const { + return new PARSER(); + } - private: - SERIALIZER serializer; - }; + private: + SERIALIZER serializer; + }; } diff --git a/Swiften/Entity/PayloadPersister.cpp b/Swiften/Entity/PayloadPersister.cpp index ace7b4a..fe51d86 100644 --- a/Swiften/Entity/PayloadPersister.cpp +++ b/Swiften/Entity/PayloadPersister.cpp @@ -1,19 +1,19 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Entity/PayloadPersister.h> -#include <boost/filesystem/fstream.hpp> #include <boost/filesystem.hpp> -#include <iostream> +#include <boost/filesystem/fstream.hpp> -#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Log.h> #include <Swiften/Parser/PayloadParser.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h> #include <Swiften/Serializer/PayloadSerializer.h> using namespace Swift; @@ -24,33 +24,33 @@ PayloadPersister::PayloadPersister() { PayloadPersister::~PayloadPersister() { } -void PayloadPersister::savePayload(boost::shared_ptr<Payload> payload, const boost::filesystem::path& path) { - try { - if (!boost::filesystem::exists(path.parent_path())) { - boost::filesystem::create_directories(path.parent_path()); - } - boost::filesystem::ofstream file(path); - file << getSerializer()->serialize(payload); - file.close(); - } - catch (const boost::filesystem::filesystem_error& e) { - std::cerr << "ERROR: " << e.what() << std::endl; - } +void PayloadPersister::savePayload(std::shared_ptr<Payload> payload, const boost::filesystem::path& path) { + try { + if (!boost::filesystem::exists(path.parent_path())) { + boost::filesystem::create_directories(path.parent_path()); + } + boost::filesystem::ofstream file(path); + file << getSerializer()->serialize(payload); + file.close(); + } + catch (const boost::filesystem::filesystem_error& e) { + SWIFT_LOG(error) << e.what(); + } } -boost::shared_ptr<Payload> PayloadPersister::loadPayload(const boost::filesystem::path& path) { - try { - if (boost::filesystem::exists(path)) { - ByteArray data; - readByteArrayFromFile(data, path); - boost::shared_ptr<PayloadParser> parser(createParser()); - PayloadParserTester tester(parser.get()); - tester.parse(byteArrayToString(data)); - return parser->getPayload(); - } - } - catch (const boost::filesystem::filesystem_error& e) { - std::cerr << "ERROR: " << e.what() << std::endl; - } - return boost::shared_ptr<Payload>(); +std::shared_ptr<Payload> PayloadPersister::loadPayload(const boost::filesystem::path& path) { + try { + if (boost::filesystem::exists(path)) { + ByteArray data; + readByteArrayFromFile(data, path); + std::shared_ptr<PayloadParser> parser(createParser()); + PayloadParserTester tester(parser.get()); + tester.parse(byteArrayToString(data)); + return parser->getPayload(); + } + } + catch (const boost::filesystem::filesystem_error& e) { + SWIFT_LOG(error) << e.what(); + } + return std::shared_ptr<Payload>(); } diff --git a/Swiften/Entity/PayloadPersister.h b/Swiften/Entity/PayloadPersister.h index bc406ab..c747a41 100644 --- a/Swiften/Entity/PayloadPersister.h +++ b/Swiften/Entity/PayloadPersister.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/filesystem/path.hpp> #include <Swiften/Base/API.h> namespace Swift { - class Payload; - class PayloadSerializer; - class PayloadParser; + class Payload; + class PayloadSerializer; + class PayloadParser; - class SWIFTEN_API PayloadPersister { - public: - PayloadPersister(); - virtual ~PayloadPersister(); + class SWIFTEN_API PayloadPersister { + public: + PayloadPersister(); + virtual ~PayloadPersister(); - void savePayload(boost::shared_ptr<Payload>, const boost::filesystem::path&); - boost::shared_ptr<Payload> loadPayload(const boost::filesystem::path&); + void savePayload(std::shared_ptr<Payload>, const boost::filesystem::path&); + std::shared_ptr<Payload> loadPayload(const boost::filesystem::path&); - protected: + protected: - virtual const PayloadSerializer* getSerializer() const = 0; - virtual PayloadParser* createParser() const = 0; - }; + virtual const PayloadSerializer* getSerializer() const = 0; + virtual PayloadParser* createParser() const = 0; + }; } diff --git a/Swiften/Entity/SConscript b/Swiften/Entity/SConscript index 1342ec1..284e0c0 100644 --- a/Swiften/Entity/SConscript +++ b/Swiften/Entity/SConscript @@ -1,6 +1,6 @@ Import("swiften_env") objects = swiften_env.SwiftenObject([ - "Entity.cpp", - ]) + "Entity.cpp", + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/EventLoop/BoostASIOEventLoop.cpp b/Swiften/EventLoop/BoostASIOEventLoop.cpp new file mode 100644 index 0000000..45dd4a2 --- /dev/null +++ b/Swiften/EventLoop/BoostASIOEventLoop.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/EventLoop/BoostASIOEventLoop.h> + +#include <boost/bind.hpp> + +namespace Swift { + +BoostASIOEventLoop::BoostASIOEventLoop(std::shared_ptr<boost::asio::io_service> ioService) : ioService_(ioService) { + +} + +BoostASIOEventLoop::~BoostASIOEventLoop() { + +} + +void BoostASIOEventLoop::handleASIOEvent() { + { + std::unique_lock<std::recursive_mutex> lock(isEventInASIOEventLoopMutex_); + isEventInASIOEventLoop_ = false; + } + handleNextEvent(); +} + +void BoostASIOEventLoop::eventPosted() { + std::unique_lock<std::recursive_mutex> lock(isEventInASIOEventLoopMutex_); + if (!isEventInASIOEventLoop_) { + isEventInASIOEventLoop_ = true; + ioService_->post(boost::bind(&BoostASIOEventLoop::handleASIOEvent, this)); + } +} + +} diff --git a/Swiften/EventLoop/BoostASIOEventLoop.h b/Swiften/EventLoop/BoostASIOEventLoop.h new file mode 100644 index 0000000..fbdf443 --- /dev/null +++ b/Swiften/EventLoop/BoostASIOEventLoop.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> +#include <mutex> + +#include <boost/asio/io_service.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/EventLoop/Event.h> +#include <Swiften/EventLoop/EventLoop.h> + +namespace Swift { + class SWIFTEN_API BoostASIOEventLoop : public EventLoop { + public: + BoostASIOEventLoop(std::shared_ptr<boost::asio::io_service> ioService); + virtual ~BoostASIOEventLoop(); + + protected: + void handleASIOEvent(); + + virtual void eventPosted(); + + private: + std::shared_ptr<boost::asio::io_service> ioService_; + + bool isEventInASIOEventLoop_ = false; + std::recursive_mutex isEventInASIOEventLoopMutex_; + }; +} diff --git a/Swiften/EventLoop/Cocoa/CocoaEvent.h b/Swiften/EventLoop/Cocoa/CocoaEvent.h index 89d056f..945056e 100644 --- a/Swiften/EventLoop/Cocoa/CocoaEvent.h +++ b/Swiften/EventLoop/Cocoa/CocoaEvent.h @@ -1,16 +1,19 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Foundation/Foundation.h> +// The following line is a workaround for a bug in Boost 1.60 when building as C++11. +// See ticket #11897 and #11863 in Boost's bug tracker. +#undef check + namespace Swift { - class Event; - class CocoaEventLoop; + class CocoaEventLoop; } // Using deprecated declaration of instance vars in interface, because this @@ -19,14 +22,13 @@ namespace Swift { #pragma clang diagnostic ignored "-Wobjc-interface-ivars" @interface CocoaEvent : NSObject { - Swift::Event* event; - Swift::CocoaEventLoop* eventLoop; + Swift::CocoaEventLoop* eventLoop; } #pragma clang diagnostic pop // Takes ownership of event -- (id) initWithEvent: (Swift::Event*) e eventLoop: (Swift::CocoaEventLoop*) el; +- (id) init:(Swift::CocoaEventLoop*) el; - (void) process; - (void) dealloc; diff --git a/Swiften/EventLoop/Cocoa/CocoaEvent.mm b/Swiften/EventLoop/Cocoa/CocoaEvent.mm index 7b1b4b0..fc9695b 100644 --- a/Swiften/EventLoop/Cocoa/CocoaEvent.mm +++ b/Swiften/EventLoop/Cocoa/CocoaEvent.mm @@ -1,25 +1,29 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/EventLoop/Cocoa/CocoaEvent.h> -#include <Swiften/EventLoop/Event.h> + #include <Swiften/EventLoop/Cocoa/CocoaEventLoop.h> @implementation CocoaEvent -- (id) initWithEvent: (Swift::Event*) e eventLoop: (Swift::CocoaEventLoop*) el { - self = [super init]; - if (self != nil) { - event = e; - eventLoop = el; - } - return self; +- (id) init:(Swift::CocoaEventLoop*) el { + self = [super init]; + if (self != nil) { + eventLoop = el; + } + return self; } - (void) process { - eventLoop->handleEvent(*event); + eventLoop->handleNextCocoaEvent(); } - (void) dealloc { - delete event; - [super dealloc]; + [super dealloc]; } @end diff --git a/Swiften/EventLoop/Cocoa/CocoaEventLoop.h b/Swiften/EventLoop/Cocoa/CocoaEventLoop.h index 60ef32b..7f20e6c 100644 --- a/Swiften/EventLoop/Cocoa/CocoaEventLoop.h +++ b/Swiften/EventLoop/Cocoa/CocoaEventLoop.h @@ -1,20 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <mutex> + #include <Swiften/EventLoop/EventLoop.h> namespace Swift { - class CocoaEventLoop : public EventLoop { - public: - CocoaEventLoop(); + class CocoaEventLoop : public EventLoop { + public: + CocoaEventLoop(); + virtual ~CocoaEventLoop(); + + void handleNextCocoaEvent(); - virtual void post(const Event& event); + protected: + virtual void eventPosted(); - using EventLoop::handleEvent; - }; + private: + bool isEventInCocoaEventLoop_; + std::recursive_mutex isEventInCocoaEventLoopMutex_; + }; } diff --git a/Swiften/EventLoop/Cocoa/CocoaEventLoop.mm b/Swiften/EventLoop/Cocoa/CocoaEventLoop.mm index ba73884..39dc7ec 100644 --- a/Swiften/EventLoop/Cocoa/CocoaEventLoop.mm +++ b/Swiften/EventLoop/Cocoa/CocoaEventLoop.mm @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/EventLoop/Cocoa/CocoaEventLoop.h> #include <Swiften/EventLoop/Cocoa/CocoaEvent.h> @@ -5,17 +11,33 @@ namespace Swift { -CocoaEventLoop::CocoaEventLoop() { +CocoaEventLoop::CocoaEventLoop() : isEventInCocoaEventLoop_(false) { +} + +CocoaEventLoop::~CocoaEventLoop() { + } -void CocoaEventLoop::post(const Event& event) { - Event* eventCopy = new Event(event); - CocoaEvent* cocoaEvent = [[CocoaEvent alloc] initWithEvent: eventCopy eventLoop: this]; - [cocoaEvent - performSelectorOnMainThread:@selector(process) - withObject: nil - waitUntilDone: NO]; - [cocoaEvent release]; +void CocoaEventLoop::handleNextCocoaEvent() { + { + std::unique_lock<std::recursive_mutex> lock(isEventInCocoaEventLoopMutex_); + isEventInCocoaEventLoop_ = false; + } + handleNextEvent(); +} + +void CocoaEventLoop::eventPosted() { + std::unique_lock<std::recursive_mutex> lock(isEventInCocoaEventLoopMutex_); + if (!isEventInCocoaEventLoop_) { + isEventInCocoaEventLoop_ = true; + + CocoaEvent* cocoaEvent = [[CocoaEvent alloc] init: this]; + [cocoaEvent + performSelectorOnMainThread:@selector(process) + withObject: nil + waitUntilDone: NO]; + [cocoaEvent release]; + } } } diff --git a/Swiften/EventLoop/DummyEventLoop.cpp b/Swiften/EventLoop/DummyEventLoop.cpp index 3741eec..234ba7a 100644 --- a/Swiften/EventLoop/DummyEventLoop.cpp +++ b/Swiften/EventLoop/DummyEventLoop.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/EventLoop/DummyEventLoop.h> -#include <iostream> +#include <Swiften/Base/Log.h> namespace Swift { @@ -14,11 +14,24 @@ DummyEventLoop::DummyEventLoop() { } DummyEventLoop::~DummyEventLoop() { - if (!events_.empty()) { - std::cerr << "DummyEventLoop: Unhandled events at destruction time" << std::endl; - } - events_.clear(); + if (hasEvents()) { + SWIFT_LOG(warning) << "DummyEventLoop: Unhandled events at destruction time"; + } } +void DummyEventLoop::processEvents() { + while(hasEvents()) { + hasEvents_ = false; + handleNextEvent(); + } +} + +bool DummyEventLoop::hasEvents() { + return hasEvents_; +} + +void DummyEventLoop::eventPosted() { + hasEvents_ = true; +} } diff --git a/Swiften/EventLoop/DummyEventLoop.h b/Swiften/EventLoop/DummyEventLoop.h index 0e5e06d..da2a360 100644 --- a/Swiften/EventLoop/DummyEventLoop.h +++ b/Swiften/EventLoop/DummyEventLoop.h @@ -1,38 +1,29 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <deque> +#include <atomic> #include <Swiften/Base/API.h> #include <Swiften/EventLoop/EventLoop.h> namespace Swift { - class SWIFTEN_API DummyEventLoop : public EventLoop { - public: - DummyEventLoop(); - ~DummyEventLoop(); - - void processEvents() { - while (!events_.empty()) { - handleEvent(events_[0]); - events_.pop_front(); - } - } - - bool hasEvents() { - return !events_.empty(); - } - - virtual void post(const Event& event) { - events_.push_back(event); - } - - private: - std::deque<Event> events_; - }; + class SWIFTEN_API DummyEventLoop : public EventLoop { + public: + DummyEventLoop(); + virtual ~DummyEventLoop(); + + void processEvents(); + + bool hasEvents(); + + virtual void eventPosted(); + + private: + std::atomic<bool> hasEvents_ = ATOMIC_VAR_INIT(false); + }; } diff --git a/Swiften/EventLoop/Event.cpp b/Swiften/EventLoop/Event.cpp index aa002d3..15d7146 100644 --- a/Swiften/EventLoop/Event.cpp +++ b/Swiften/EventLoop/Event.cpp @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/EventLoop/Event.h> -#include <typeinfo> #include <iostream> +#include <typeinfo> std::ostream& operator<<(std::ostream& os, const Swift::Event& e) { - os << "Event(" << e.id << ","; - if (e.owner) { - os << typeid(*e.owner.get()).name(); - } - else { - os << "null"; - } - os << ")"; - return os; + os << "Event(" << e.id << ","; + if (e.owner) { + os << typeid(*e.owner.get()).name(); + } + else { + os << "null"; + } + os << ")"; + return os; } diff --git a/Swiften/EventLoop/Event.h b/Swiften/EventLoop/Event.h index b1d7cac..e92bb33 100644 --- a/Swiften/EventLoop/Event.h +++ b/Swiften/EventLoop/Event.h @@ -1,30 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/function.hpp> #include <Swiften/EventLoop/EventOwner.h> namespace Swift { - class Event { - public: - Event(boost::shared_ptr<EventOwner> owner, const boost::function<void()>& callback) : id(~0U), owner(owner), callback(callback) { - } - - bool operator==(const Event& o) const { - return o.id == id; - } - - unsigned int id; - boost::shared_ptr<EventOwner> owner; - boost::function<void()> callback; - }; + class Event { + public: + Event(std::shared_ptr<EventOwner> owner, const boost::function<void()>& callback) : id(~0U), owner(owner), callback(callback) { + } + + bool operator==(const Event& o) const { + return o.id == id; + } + + unsigned int id; + std::shared_ptr<EventOwner> owner; + boost::function<void()> callback; + }; } std::ostream& operator<<(std::ostream& os, const Swift::Event& e); diff --git a/Swiften/EventLoop/EventLoop.cpp b/Swiften/EventLoop/EventLoop.cpp index 502bc49..1852f3f 100644 --- a/Swiften/EventLoop/EventLoop.cpp +++ b/Swiften/EventLoop/EventLoop.cpp @@ -1,36 +1,32 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/EventLoop/EventLoop.h> #include <algorithm> -#include <iostream> #include <cassert> -#include <boost/bind.hpp> -#include <boost/lambda/lambda.hpp> -#include <boost/lambda/bind.hpp> -#include <boost/thread/locks.hpp> +#include <vector> -#include <Swiften/Base/Log.h> +#include <boost/optional.hpp> -namespace lambda = boost::lambda; +#include <Swiften/Base/Log.h> namespace Swift { inline void invokeCallback(const Event& event) { - try { - assert(!event.callback.empty()); - event.callback(); - } - catch (const std::exception& e) { - std::cerr << "Uncaught exception in event loop: " << e.what() << std::endl; - } - catch (...) { - std::cerr << "Uncaught non-exception in event loop" << std::endl; - } + try { + assert(!event.callback.empty()); + event.callback(); + } + catch (const std::exception& e) { + SWIFT_LOG(error) << "Uncaught exception in event loop: " << e.what(); + } + catch (...) { + SWIFT_LOG(error) << "Uncaught non-exception in event loop"; + } } EventLoop::EventLoop() : nextEventID_(0), handlingEvents_(false) { @@ -39,55 +35,62 @@ EventLoop::EventLoop() : nextEventID_(0), handlingEvents_(false) { EventLoop::~EventLoop() { } -void EventLoop::handleEvent(const Event& event) { - //SWIFT_LOG(debug) << "Handling event " << event.id << std::endl; - - if (handlingEvents_) { - // We're being called recursively. Push in the list of events to - // handle in the parent handleEvent() - eventsToHandle_.push_back(event); - return; - } - - bool doCallback = false; - { - boost::lock_guard<boost::mutex> lock(eventsMutex_); - std::list<Event>::iterator i = std::find(events_.begin(), events_.end(), event); - if (i != events_.end()) { - doCallback = true; - events_.erase(i); - } - } - if (doCallback) { - handlingEvents_ = true; - invokeCallback(event); - - // Process events that were passed to handleEvent during the callback - // (i.e. through recursive calls of handleEvent) - while (!eventsToHandle_.empty()) { - Event nextEvent = eventsToHandle_.front(); - eventsToHandle_.pop_front(); - invokeCallback(nextEvent); - } - handlingEvents_ = false; - } +void EventLoop::handleNextEvent() { + // If handleNextEvent is already in progress, e.g. in case of a recursive call due to + // the event loop implementation, then do no handle further events. Instead call + // eventPosted() to continue event handling later. + bool callEventPosted = handlingEvents_; + if (!handlingEvents_) { + handlingEvents_ = true; + std::unique_lock<std::recursive_mutex> lock(removeEventsMutex_); + { + boost::optional<Event> nextEvent; + { + std::unique_lock<std::recursive_mutex> eventsLock(eventsMutex_); + if (!events_.empty()) { + nextEvent = events_.front(); + events_.pop_front(); + } + callEventPosted = !events_.empty(); + } + if (nextEvent) { + invokeCallback(*nextEvent); + } + } + handlingEvents_ = false; + } + + if (callEventPosted) { + eventPosted(); + } } -void EventLoop::postEvent(boost::function<void ()> callback, boost::shared_ptr<EventOwner> owner) { - Event event(owner, callback); - { - boost::lock_guard<boost::mutex> lock(eventsMutex_); - event.id = nextEventID_; - nextEventID_++; - events_.push_back(event); - } - //SWIFT_LOG(debug) << "Posting event " << event.id << std::endl; - post(event); +void EventLoop::postEvent(boost::function<void ()> callback, std::shared_ptr<EventOwner> owner) { + Event event(owner, callback); + bool callEventPosted = false; + { + std::unique_lock<std::recursive_mutex> lock(eventsMutex_); + + callEventPosted = events_.empty(); + + event.id = nextEventID_; + nextEventID_++; + events_.push_back(event); + } + if (callEventPosted) { + eventPosted(); + } } -void EventLoop::removeEventsFromOwner(boost::shared_ptr<EventOwner> owner) { - boost::lock_guard<boost::mutex> lock(eventsMutex_); - events_.remove_if(lambda::bind(&Event::owner, lambda::_1) == owner); +void EventLoop::removeEventsFromOwner(std::shared_ptr<EventOwner> owner) { + std::unique_lock<std::recursive_mutex> removeLock(removeEventsMutex_, std::defer_lock); + std::unique_lock<std::recursive_mutex> eventsLock(eventsMutex_, std::defer_lock); + + std::lock(removeLock, eventsLock); + + events_.remove_if([&](const Event& event) { + return event.owner == owner; + }); } } diff --git a/Swiften/EventLoop/EventLoop.h b/Swiften/EventLoop/EventLoop.h index 587ba22..f61b9bc 100644 --- a/Swiften/EventLoop/EventLoop.h +++ b/Swiften/EventLoop/EventLoop.h @@ -1,44 +1,70 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/function.hpp> -#include <boost/thread/mutex.hpp> #include <list> -#include <deque> +#include <mutex> + +#include <boost/function.hpp> #include <Swiften/Base/API.h> #include <Swiften/EventLoop/Event.h> namespace Swift { - class EventOwner; - - class SWIFTEN_API EventLoop { - public: - EventLoop(); - virtual ~EventLoop(); - - void postEvent(boost::function<void ()> event, boost::shared_ptr<EventOwner> owner = boost::shared_ptr<EventOwner>()); - void removeEventsFromOwner(boost::shared_ptr<EventOwner> owner); - - protected: - /** - * Reimplement this to call handleEvent(event) from the thread in which - * the event loop is residing. - */ - virtual void post(const Event& event) = 0; - - void handleEvent(const Event& event); - - private: - boost::mutex eventsMutex_; - unsigned int nextEventID_; - std::list<Event> events_; - bool handlingEvents_; - std::deque<Event> eventsToHandle_; - }; + class EventOwner; + + /** + * The \ref EventLoop class provides the abstract interface for implementing event loops to use with Swiften. + * + * Events are added to the event queue using the \ref postEvent method and can be removed from the queue using + * the \ref removeEventsFromOwner method. + */ + class SWIFTEN_API EventLoop { + public: + EventLoop(); + virtual ~EventLoop(); + + /** + * The \ref postEvent method allows events to be added to the event queue of the \ref EventLoop. + * An optional \ref EventOwner can be passed as \p owner, allowing later removal of events that have not yet been + * executed using the \ref removeEventsFromOwner method. + */ + void postEvent(boost::function<void ()> event, std::shared_ptr<EventOwner> owner = std::shared_ptr<EventOwner>()); + + /** + * The \ref removeEventsFromOwner method removes all events from the specified \p owner from the + * event queue. + */ + void removeEventsFromOwner(std::shared_ptr<EventOwner> owner); + + protected: + /** + * The \ref handleNextEvent method is called by an implementation of the abstract \ref EventLoop class + * at any point after the virtual \ref eventPosted method has been called. + * This method does not block, except for short-time synchronization. + * If called recursively, the event queue is not further processed. Instead, \ref eventPosted + * is called to notify the implementing event loop of the non-empty event queue. + * It is recommended to not call \ref handleNextEvent inside an event posted to the event loop + * as this can lead to an infinite loop. + */ + void handleNextEvent(); + + /** + * The \ref eventPosted virtual method serves as notification for when events are still available in the queue. + * It is called after the first event is posted to an empty queue or after an event has been handled in + * \ref handleNextEvent and there are still remaining events in the queue. + */ + virtual void eventPosted() = 0; + + private: + unsigned int nextEventID_; + std::list<Event> events_; + bool handlingEvents_; + std::recursive_mutex eventsMutex_; + std::recursive_mutex removeEventsMutex_; + }; } diff --git a/Swiften/EventLoop/EventOwner.cpp b/Swiften/EventLoop/EventOwner.cpp index 9970499..56e0faa 100644 --- a/Swiften/EventLoop/EventOwner.cpp +++ b/Swiften/EventLoop/EventOwner.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/EventLoop/EventOwner.h> diff --git a/Swiften/EventLoop/EventOwner.h b/Swiften/EventLoop/EventOwner.h index 43a059b..cd4a80b 100644 --- a/Swiften/EventLoop/EventOwner.h +++ b/Swiften/EventLoop/EventOwner.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,8 +9,8 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API EventOwner { - public: - virtual ~EventOwner(); - }; + class SWIFTEN_API EventOwner { + public: + virtual ~EventOwner(); + }; } diff --git a/Swiften/EventLoop/Qt/QtEventLoop.h b/Swiften/EventLoop/Qt/QtEventLoop.h index 0097cf9..cf374ab 100644 --- a/Swiften/EventLoop/Qt/QtEventLoop.h +++ b/Swiften/EventLoop/Qt/QtEventLoop.h @@ -1,47 +1,59 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <QObject> -#include <QEvent> +#include <mutex> + #include <QCoreApplication> +#include <QEvent> +#include <QObject> #include <Swiften/EventLoop/EventLoop.h> namespace Swift { - class QtEventLoop : public QObject, public EventLoop { - public: - QtEventLoop() {} - ~QtEventLoop() { - QCoreApplication::removePostedEvents(this); - } - - virtual void post(const Swift::Event& event) { - QCoreApplication::postEvent(this, new Event(event)); - } - - virtual bool event(QEvent* qevent) { - Event* event = dynamic_cast<Event*>(qevent); - if (event) { - handleEvent(event->event_); - //event->deleteLater(); FIXME: Leak? - return true; - } - - return false; - } - - private: - struct Event : public QEvent { - Event(const Swift::Event& event) : - QEvent(QEvent::User), event_(event) { - } - - Swift::Event event_; - }; - }; + class QtEventLoop : public QObject, public EventLoop { + public: + QtEventLoop() : isEventInQtEventLoop_(false) {} + virtual ~QtEventLoop() { + QCoreApplication::removePostedEvents(this); + } + + protected: + virtual void eventPosted() { + std::unique_lock<std::recursive_mutex> lock(isEventInQtEventLoopMutex_); + if (!isEventInQtEventLoop_) { + isEventInQtEventLoop_ = true; + QCoreApplication::postEvent(this, new Event()); + } + } + + virtual bool event(QEvent* qevent) { + Event* event = dynamic_cast<Event*>(qevent); + if (event) { + { + std::unique_lock<std::recursive_mutex> lock(isEventInQtEventLoopMutex_); + isEventInQtEventLoop_ = false; + } + handleNextEvent(); + //event->deleteLater(); FIXME: Leak? + return true; + } + + return false; + } + + private: + struct Event : public QEvent { + Event() : + QEvent(QEvent::User) { + } + }; + + bool isEventInQtEventLoop_; + std::recursive_mutex isEventInQtEventLoopMutex_; + }; } diff --git a/Swiften/EventLoop/SConscript b/Swiften/EventLoop/SConscript index 8bef8fb..7aea53f 100644 --- a/Swiften/EventLoop/SConscript +++ b/Swiften/EventLoop/SConscript @@ -1,22 +1,23 @@ Import("swiften_env") sources = [ - "EventLoop.cpp", - "EventOwner.cpp", - "Event.cpp", - "SimpleEventLoop.cpp", - "DummyEventLoop.cpp", - "SingleThreadedEventLoop.cpp", - ] + "BoostASIOEventLoop.cpp", + "DummyEventLoop.cpp", + "Event.cpp", + "EventLoop.cpp", + "EventOwner.cpp", + "SimpleEventLoop.cpp", + "SingleThreadedEventLoop.cpp", + ] objects = swiften_env.SwiftenObject(sources) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) -if swiften_env["PLATFORM"] == "darwin" and swiften_env["target"] == "native": - myenv = swiften_env.Clone() - myenv.Append(CXXFLAGS = myenv["OBJCCFLAGS"]) - objects = myenv.SwiftenObject([ - "Cocoa/CocoaEventLoop.mm", - "Cocoa/CocoaEvent.mm" - ]) - swiften_env.Append(SWIFTEN_OBJECTS = [objects]) +if swiften_env["PLATFORM"] == "darwin" and swiften_env["target"] == "native" or swiften_env["target"] == 'xcode': + myenv = swiften_env.Clone() + myenv.Append(CXXFLAGS = myenv["OBJCCFLAGS"]) + objects = myenv.SwiftenObject([ + "Cocoa/CocoaEventLoop.mm", + "Cocoa/CocoaEvent.mm" + ]) + swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/EventLoop/SimpleEventLoop.cpp b/Swiften/EventLoop/SimpleEventLoop.cpp index 42a5481..745fadb 100644 --- a/Swiften/EventLoop/SimpleEventLoop.cpp +++ b/Swiften/EventLoop/SimpleEventLoop.cpp @@ -1,72 +1,56 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/EventLoop/SimpleEventLoop.h> #include <boost/bind.hpp> -#include <iostream> - -#include <Swiften/Base/foreach.h> - namespace Swift { -SimpleEventLoop::SimpleEventLoop() : isRunning_(true) { +SimpleEventLoop::SimpleEventLoop() : isRunning_(true), eventAvailable_(false) { } SimpleEventLoop::~SimpleEventLoop() { - if (!events_.empty()) { - std::cerr << "Warning: Pending events in SimpleEventLoop at destruction time" << std::endl; - } } void SimpleEventLoop::doRun(bool breakAfterEvents) { - while (isRunning_) { - std::vector<Event> events; - { - boost::unique_lock<boost::mutex> lock(eventsMutex_); - while (events_.empty()) { - eventsAvailable_.wait(lock); - } - events.swap(events_); - } - foreach(const Event& event, events) { - handleEvent(event); - } - if (breakAfterEvents) { - return; - } - } + while (isRunning_) { + { + std::unique_lock<std::mutex> lock(eventAvailableMutex_); + while (!eventAvailable_) { + eventAvailableCondition_.wait(lock); + } + + eventAvailable_ = false; + } + runOnce(); + if (breakAfterEvents) { + return; + } + } } void SimpleEventLoop::runOnce() { - std::vector<Event> events; - { - boost::unique_lock<boost::mutex> lock(eventsMutex_); - events.swap(events_); - } - foreach(const Event& event, events) { - handleEvent(event); - } + handleNextEvent(); } void SimpleEventLoop::stop() { - postEvent(boost::bind(&SimpleEventLoop::doStop, this)); + postEvent(boost::bind(&SimpleEventLoop::doStop, this)); } void SimpleEventLoop::doStop() { - isRunning_ = false; + isRunning_ = false; } -void SimpleEventLoop::post(const Event& event) { - { - boost::lock_guard<boost::mutex> lock(eventsMutex_); - events_.push_back(event); - } - eventsAvailable_.notify_one(); +void SimpleEventLoop::eventPosted() { + { + std::unique_lock<std::mutex> lock(eventAvailableMutex_); + eventAvailable_ = true; + } + eventAvailableCondition_.notify_one(); } diff --git a/Swiften/EventLoop/SimpleEventLoop.h b/Swiften/EventLoop/SimpleEventLoop.h index da1c039..fe5f509 100644 --- a/Swiften/EventLoop/SimpleEventLoop.h +++ b/Swiften/EventLoop/SimpleEventLoop.h @@ -1,47 +1,47 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> -#include <boost/function.hpp> -#include <boost/thread/mutex.hpp> -#include <boost/thread/condition_variable.hpp> +#include <condition_variable> +#include <mutex> #include <Swiften/Base/API.h> #include <Swiften/EventLoop/EventLoop.h> namespace Swift { - class SWIFTEN_API SimpleEventLoop : public EventLoop { - public: - SimpleEventLoop(); - ~SimpleEventLoop(); + class SWIFTEN_API SimpleEventLoop : public EventLoop { + public: + SimpleEventLoop(); + virtual ~SimpleEventLoop(); - void run() { - doRun(false); - } + void run() { + doRun(false); + } - void runUntilEvents() { - doRun(true); - } + void runUntilEvents() { + doRun(true); + } - void runOnce(); + void runOnce(); - void stop(); + void stop(); - virtual void post(const Event& event); + protected: + virtual void eventPosted(); - private: - void doRun(bool breakAfterEvents); - void doStop(); + private: + void doRun(bool breakAfterEvents); + void doStop(); - private: - bool isRunning_; - std::vector<Event> events_; - boost::mutex eventsMutex_; - boost::condition_variable eventsAvailable_; - }; + private: + bool isRunning_; + + bool eventAvailable_; + std::mutex eventAvailableMutex_; + std::condition_variable eventAvailableCondition_; + }; } diff --git a/Swiften/EventLoop/SingleThreadedEventLoop.cpp b/Swiften/EventLoop/SingleThreadedEventLoop.cpp index c2235b1..89b4460 100644 --- a/Swiften/EventLoop/SingleThreadedEventLoop.cpp +++ b/Swiften/EventLoop/SingleThreadedEventLoop.cpp @@ -4,62 +4,58 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "Swiften/EventLoop/SingleThreadedEventLoop.h" +/* + * Copyright (c) 2016-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <boost/bind.hpp> -#include <iostream> +#include <Swiften/EventLoop/SingleThreadedEventLoop.h> -#include "Swiften/Base/foreach.h" +#include <iostream> +#include <boost/bind.hpp> namespace Swift { -SingleThreadedEventLoop::SingleThreadedEventLoop() -: shouldShutDown_(false) +SingleThreadedEventLoop::SingleThreadedEventLoop() +: shouldShutDown_(false), eventAvailable_(false) { } SingleThreadedEventLoop::~SingleThreadedEventLoop() { - if (!events_.empty()) { - std::cerr << "Warning: Pending events in SingleThreadedEventLoop at destruction time." << std::endl; - } + } void SingleThreadedEventLoop::waitForEvents() { - boost::unique_lock<boost::mutex> lock(eventsMutex_); - while (events_.empty() && !shouldShutDown_) { - eventsAvailable_.wait(lock); - } - - if (shouldShutDown_) - throw EventLoopCanceledException(); + std::unique_lock<std::mutex> lock(eventAvailableMutex_); + while (!eventAvailable_ && !shouldShutDown_) { + eventAvailableCondition_.wait(lock); + } + + if (shouldShutDown_) { + throw EventLoopCanceledException(); + } } void SingleThreadedEventLoop::handleEvents() { - // Make a copy of the list of events so we don't block any threads that post - // events while we process them. - std::vector<Event> events; - { - boost::unique_lock<boost::mutex> lock(eventsMutex_); - events.swap(events_); - } - - // Loop through all the events and handle them - foreach(const Event& event, events) { - handleEvent(event); - } + { + std::lock_guard<std::mutex> lock(eventAvailableMutex_); + eventAvailable_ = false; + } + handleNextEvent(); } void SingleThreadedEventLoop::stop() { - boost::unique_lock<boost::mutex> lock(eventsMutex_); - shouldShutDown_ = true; - eventsAvailable_.notify_one(); + std::unique_lock<std::mutex> lock(eventAvailableMutex_); + shouldShutDown_ = true; + eventAvailableCondition_.notify_one(); } -void SingleThreadedEventLoop::post(const Event& event) { - boost::lock_guard<boost::mutex> lock(eventsMutex_); - events_.push_back(event); - eventsAvailable_.notify_one(); +void SingleThreadedEventLoop::eventPosted() { + std::lock_guard<std::mutex> lock(eventAvailableMutex_); + eventAvailable_ = true; + eventAvailableCondition_.notify_one(); } } // namespace Swift diff --git a/Swiften/EventLoop/SingleThreadedEventLoop.h b/Swiften/EventLoop/SingleThreadedEventLoop.h index 75ffad0..9f8cb0a 100644 --- a/Swiften/EventLoop/SingleThreadedEventLoop.h +++ b/Swiften/EventLoop/SingleThreadedEventLoop.h @@ -4,13 +4,19 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <condition_variable> +#include <mutex> #include <vector> -#include <boost/thread/mutex.hpp> -#include <boost/thread/condition_variable.hpp> -#include "Swiften/EventLoop/EventLoop.h" +#include <Swiften/EventLoop/EventLoop.h> // DESCRIPTION: // @@ -22,37 +28,39 @@ // The SingleThreadedEventLoop class implements an event loop that can be used from such applications. // // USAGE: -// -// Spawn a new thread in the desired framework and call SingleThreadedEventLoop::waitForEvents(). The method +// +// Spawn a new thread in the desired framework and call SingleThreadedEventLoop::waitForEvents(). The method // blocks until a new event has arrived at which time it'll return, or until the wait is canceled -// at which time it throws EventLoopCanceledException. +// at which time it throws EventLoopCanceledException. // // When a new event has arrived and SingleThreadedEventLoop::waitForEvents() returns, the caller should then -// call SingleThreadedEventLoop::handleEvents() on the main GUI thread. For WPF applications, for instance, +// call SingleThreadedEventLoop::handleEvents() on the main GUI thread. For WPF applications, for instance, // the Dispatcher class can be used to execute the call on the GUI thread. // namespace Swift { - class SingleThreadedEventLoop : public EventLoop { - public: - class EventLoopCanceledException : public std::exception { }; - - public: - SingleThreadedEventLoop(); - ~SingleThreadedEventLoop(); - - // Blocks while waiting for new events and returns when new events are available. - // Throws EventLoopCanceledException when the wait is canceled. - void waitForEvents(); - void handleEvents(); - void stop(); - - virtual void post(const Event& event); - - private: - bool shouldShutDown_; - std::vector<Event> events_; - boost::mutex eventsMutex_; - boost::condition_variable eventsAvailable_; - }; + class SingleThreadedEventLoop : public EventLoop { + public: + class EventLoopCanceledException : public std::exception { }; + + public: + SingleThreadedEventLoop(); + virtual ~SingleThreadedEventLoop(); + + // Blocks while waiting for new events and returns when new events are available. + // Throws EventLoopCanceledException when the wait is canceled. + void waitForEvents(); + void handleEvents(); + void stop(); + + protected: + virtual void eventPosted(); + + private: + bool shouldShutDown_; + + bool eventAvailable_; + std::mutex eventAvailableMutex_; + std::condition_variable eventAvailableCondition_; + }; } diff --git a/Swiften/EventLoop/UnitTest/EventLoopTest.cpp b/Swiften/EventLoop/UnitTest/EventLoopTest.cpp index 58396e6..26c56d3 100644 --- a/Swiften/EventLoop/UnitTest/EventLoopTest.cpp +++ b/Swiften/EventLoop/UnitTest/EventLoopTest.cpp @@ -1,90 +1,105 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <thread> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/thread.hpp> -#include <boost/bind.hpp> +#include <Swiften/Base/sleep.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/EventLoop/EventOwner.h> #include <Swiften/EventLoop/SimpleEventLoop.h> -#include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/Base/sleep.h> using namespace Swift; class EventLoopTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(EventLoopTest); - CPPUNIT_TEST(testPost); - CPPUNIT_TEST(testRemove); - CPPUNIT_TEST(testHandleEvent_Recursive); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - events_.clear(); - } - - void testPost() { - SimpleEventLoop testling; - - testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 1)); - testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 2)); - testling.stop(); - testling.run(); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(events_.size())); - CPPUNIT_ASSERT_EQUAL(1, events_[0]); - CPPUNIT_ASSERT_EQUAL(2, events_[1]); - } - - void testRemove() { - SimpleEventLoop testling; - boost::shared_ptr<MyEventOwner> eventOwner1(new MyEventOwner()); - boost::shared_ptr<MyEventOwner> eventOwner2(new MyEventOwner()); - - testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 1), eventOwner1); - testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 2), eventOwner2); - testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 3), eventOwner1); - testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 4), eventOwner2); - testling.removeEventsFromOwner(eventOwner2); - testling.stop(); - testling.run(); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(events_.size())); - CPPUNIT_ASSERT_EQUAL(1, events_[0]); - CPPUNIT_ASSERT_EQUAL(3, events_[1]); - } - - void testHandleEvent_Recursive() { - DummyEventLoop testling; - boost::shared_ptr<MyEventOwner> eventOwner(new MyEventOwner()); - - testling.postEvent(boost::bind(&EventLoopTest::runEventLoop, this, &testling, eventOwner), eventOwner); - testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 0), eventOwner); - testling.processEvents(); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(events_.size())); - CPPUNIT_ASSERT_EQUAL(0, events_[0]); - CPPUNIT_ASSERT_EQUAL(1, events_[1]); - } - - private: - struct MyEventOwner : public EventOwner {}; - void logEvent(int i) { - events_.push_back(i); - } - void runEventLoop(DummyEventLoop* loop, boost::shared_ptr<MyEventOwner> eventOwner) { - loop->processEvents(); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(events_.size())); - loop->postEvent(boost::bind(&EventLoopTest::logEvent, this, 1), eventOwner); - } - - private: - std::vector<int> events_; + CPPUNIT_TEST_SUITE(EventLoopTest); + CPPUNIT_TEST(testPost); + CPPUNIT_TEST(testRemove); + CPPUNIT_TEST(testHandleEvent_Recursive); + CPPUNIT_TEST(testHandleEvent_FirstEventRemovesSecondEvent); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + events_.clear(); + } + + void testPost() { + SimpleEventLoop testling; + + testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 1)); + testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 2)); + testling.stop(); + testling.run(); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(events_.size())); + CPPUNIT_ASSERT_EQUAL(1, events_[0]); + CPPUNIT_ASSERT_EQUAL(2, events_[1]); + } + + void testRemove() { + SimpleEventLoop testling; + std::shared_ptr<MyEventOwner> eventOwner1(new MyEventOwner()); + std::shared_ptr<MyEventOwner> eventOwner2(new MyEventOwner()); + + testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 1), eventOwner1); + testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 2), eventOwner2); + testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 3), eventOwner1); + testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 4), eventOwner2); + testling.removeEventsFromOwner(eventOwner2); + testling.stop(); + testling.run(); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(events_.size())); + CPPUNIT_ASSERT_EQUAL(1, events_[0]); + CPPUNIT_ASSERT_EQUAL(3, events_[1]); + } + + void testHandleEvent_Recursive() { + DummyEventLoop testling; + std::shared_ptr<MyEventOwner> eventOwner(new MyEventOwner()); + + testling.postEvent(boost::bind(&EventLoopTest::runEventLoop, this, &testling, eventOwner), eventOwner); + testling.postEvent(boost::bind(&EventLoopTest::logEvent, this, 0), eventOwner); + testling.processEvents(); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(events_.size())); + CPPUNIT_ASSERT_EQUAL(0, events_[0]); + CPPUNIT_ASSERT_EQUAL(1, events_[1]); + } + + void testHandleEvent_FirstEventRemovesSecondEvent() { + DummyEventLoop testling; + auto eventOwner = std::make_shared<MyEventOwner>(); + auto secondEventFired = false; + + testling.postEvent([&](){ testling.removeEventsFromOwner(eventOwner); }, eventOwner); + testling.postEvent([&](){ secondEventFired = true; }, eventOwner); + testling.processEvents(); + + CPPUNIT_ASSERT_EQUAL(false, secondEventFired); + } + + private: + struct MyEventOwner : public EventOwner {}; + void logEvent(int i) { + events_.push_back(i); + } + void runEventLoop(DummyEventLoop* loop, std::shared_ptr<MyEventOwner> eventOwner) { + loop->processEvents(); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(events_.size())); + loop->postEvent(boost::bind(&EventLoopTest::logEvent, this, 1), eventOwner); + } + + private: + std::vector<int> events_; }; CPPUNIT_TEST_SUITE_REGISTRATION(EventLoopTest); diff --git a/Swiften/EventLoop/UnitTest/SimpleEventLoopTest.cpp b/Swiften/EventLoop/UnitTest/SimpleEventLoopTest.cpp index 475b6b5..3d096d3 100644 --- a/Swiften/EventLoop/UnitTest/SimpleEventLoopTest.cpp +++ b/Swiften/EventLoop/UnitTest/SimpleEventLoopTest.cpp @@ -1,67 +1,69 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <thread> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/thread.hpp> -#include <boost/bind.hpp> -#include <Swiften/EventLoop/SimpleEventLoop.h> #include <Swiften/Base/sleep.h> +#include <Swiften/EventLoop/SimpleEventLoop.h> using namespace Swift; class SimpleEventLoopTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SimpleEventLoopTest); - // FIXME: Temporarily disabling run, because it generates a "vector - // iterator not incrementable" on XP - //CPPUNIT_TEST(testRun); - CPPUNIT_TEST(testPostFromMainThread); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - counter_ = 0; - } - - void testRun() { - SimpleEventLoop testling; - boost::thread thread(boost::bind(&SimpleEventLoopTest::runIncrementingThread, this, &testling)); - testling.run(); - - CPPUNIT_ASSERT_EQUAL(10, counter_); - } - - void testPostFromMainThread() { - SimpleEventLoop testling; - testling.postEvent(boost::bind(&SimpleEventLoopTest::incrementCounterAndStop, this, &testling)); - testling.run(); - - CPPUNIT_ASSERT_EQUAL(1, counter_); - } - - private: - void runIncrementingThread(SimpleEventLoop* loop) { - for (unsigned int i = 0; i < 10; ++i) { - Swift::sleep(1); - loop->postEvent(boost::bind(&SimpleEventLoopTest::incrementCounter, this)); - } - loop->stop(); - } - - void incrementCounter() { - counter_++; - } - - void incrementCounterAndStop(SimpleEventLoop* loop) { - counter_++; - loop->stop(); - } - - int counter_; + CPPUNIT_TEST_SUITE(SimpleEventLoopTest); + // FIXME: Temporarily disabling run, because it generates a "vector + // iterator not incrementable" on XP + //CPPUNIT_TEST(testRun); + CPPUNIT_TEST(testPostFromMainThread); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + counter_ = 0; + } + + void testRun() { + SimpleEventLoop testling; + std::thread thread(boost::bind(&SimpleEventLoopTest::runIncrementingThread, this, &testling)); + testling.run(); + + CPPUNIT_ASSERT_EQUAL(10, counter_); + } + + void testPostFromMainThread() { + SimpleEventLoop testling; + testling.postEvent(boost::bind(&SimpleEventLoopTest::incrementCounterAndStop, this, &testling)); + testling.run(); + + CPPUNIT_ASSERT_EQUAL(1, counter_); + } + + private: + void runIncrementingThread(SimpleEventLoop* loop) { + for (unsigned int i = 0; i < 10; ++i) { + Swift::sleep(1); + loop->postEvent(boost::bind(&SimpleEventLoopTest::incrementCounter, this)); + } + loop->stop(); + } + + void incrementCounter() { + counter_++; + } + + void incrementCounterAndStop(SimpleEventLoop* loop) { + counter_++; + loop->stop(); + } + + int counter_; }; CPPUNIT_TEST_SUITE_REGISTRATION(SimpleEventLoopTest); diff --git a/Swiften/Examples/BenchTool/BenchTool.cpp b/Swiften/Examples/BenchTool/BenchTool.cpp index 9725b7e..97d760d 100644 --- a/Swiften/Examples/BenchTool/BenchTool.cpp +++ b/Swiften/Examples/BenchTool/BenchTool.cpp @@ -1,21 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/bind.hpp> -#include <boost/thread.hpp> #include <iostream> +#include <thread> + +#include <boost/bind.hpp> +#include <Swiften/Base/sleep.h> #include <Swiften/Client/Client.h> -#include <Swiften/Network/TimerFactory.h> -#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Client/ClientXMLTracer.h> #include <Swiften/EventLoop/EventLoop.h> #include <Swiften/EventLoop/SimpleEventLoop.h> +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Network/TimerFactory.h> #include <Swiften/Roster/GetRosterRequest.h> -#include <Swiften/Client/ClientXMLTracer.h> -#include <Swiften/Base/sleep.h> #include <Swiften/TLS/BlindCertificateTrustChecker.h> using namespace Swift; @@ -27,40 +28,40 @@ static int numberOfInstances = 100; static void handleConnected() { - numberOfConnectedClients++; - std::cout << "Connected " << numberOfConnectedClients << std::endl; + numberOfConnectedClients++; + std::cout << "Connected " << numberOfConnectedClients << std::endl; } int main(int, char**) { - char* jid = getenv("SWIFT_BENCHTOOL_JID"); - if (!jid) { - std::cerr << "Please set the SWIFT_BENCHTOOL_JID environment variable" << std::endl; - return -1; - } - char* pass = getenv("SWIFT_BENCHTOOL_PASS"); - if (!pass) { - std::cerr << "Please set the SWIFT_BENCHTOOL_PASS environment variable" << std::endl; - return -1; - } + char* jid = getenv("SWIFT_BENCHTOOL_JID"); + if (!jid) { + std::cerr << "Please set the SWIFT_BENCHTOOL_JID environment variable" << std::endl; + return -1; + } + char* pass = getenv("SWIFT_BENCHTOOL_PASS"); + if (!pass) { + std::cerr << "Please set the SWIFT_BENCHTOOL_PASS environment variable" << std::endl; + return -1; + } + + BlindCertificateTrustChecker trustChecker; + std::vector<CoreClient*> clients; + for (int i = 0; i < numberOfInstances; ++i) { + CoreClient* client = new Swift::CoreClient(JID(jid), createSafeByteArray(std::string(pass)), &networkFactories); + client->setCertificateTrustChecker(&trustChecker); + client->onConnected.connect(&handleConnected); + clients.push_back(client); + } - BlindCertificateTrustChecker trustChecker; - std::vector<CoreClient*> clients; - for (int i = 0; i < numberOfInstances; ++i) { - CoreClient* client = new Swift::CoreClient(JID(jid), createSafeByteArray(std::string(pass)), &networkFactories); - client->setCertificateTrustChecker(&trustChecker); - client->onConnected.connect(&handleConnected); - clients.push_back(client); - } - - for (size_t i = 0; i < clients.size(); ++i) { - clients[i]->connect(); - } + for (auto& client : clients) { + client->connect(); + } - eventLoop.run(); + eventLoop.run(); - for (size_t i = 0; i < clients.size(); ++i) { - delete clients[i]; - } + for (auto& client : clients) { + delete client; + } - return 0; + return 0; } diff --git a/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp b/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp index df2a23d..cc783c6 100644 --- a/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp +++ b/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp @@ -1,21 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/bind.hpp> -#include <boost/thread.hpp> #include <iostream> +#include <thread> + +#include <boost/bind.hpp> #include <Swiften/Client/Client.h> -#include <Swiften/Network/Timer.h> -#include <Swiften/Network/TimerFactory.h> -#include <Swiften/Network/BoostNetworkFactories.h> -#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/Client/ClientXMLTracer.h> -#include <Swiften/EventLoop/SimpleEventLoop.h> #include <Swiften/Disco/GetDiscoInfoRequest.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/EventLoop/SimpleEventLoop.h> +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Network/Timer.h> +#include <Swiften/Network/TimerFactory.h> using namespace Swift; @@ -24,78 +25,78 @@ enum ExitCodes {OK = 0, CANNOT_CONNECT, CANNOT_AUTH, NO_RESPONSE, DISCO_ERROR}; static SimpleEventLoop eventLoop; static BoostNetworkFactories networkFactories(&eventLoop); -static Client* client = 0; +static Client* client = nullptr; static JID recipient; static int exitCode = CANNOT_CONNECT; -static boost::bsignals::connection errorConnection; - -static void handleServerDiscoInfoResponse(boost::shared_ptr<DiscoInfo> /*info*/, ErrorPayload::ref error) { - if (!error) { - errorConnection.disconnect(); - client->disconnect(); - eventLoop.stop(); - exitCode = OK; - } else { - errorConnection.disconnect(); - exitCode = DISCO_ERROR; - } +static boost::signals2::connection errorConnection; + +static void handleServerDiscoInfoResponse(std::shared_ptr<DiscoInfo> /*info*/, ErrorPayload::ref error) { + if (!error) { + errorConnection.disconnect(); + client->disconnect(); + eventLoop.stop(); + exitCode = OK; + } else { + errorConnection.disconnect(); + exitCode = DISCO_ERROR; + } } static void handleConnected() { - exitCode = NO_RESPONSE; - GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(JID(), client->getIQRouter()); - discoInfoRequest->onResponse.connect(&handleServerDiscoInfoResponse); - discoInfoRequest->send(); + exitCode = NO_RESPONSE; + GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(JID(), client->getIQRouter()); + discoInfoRequest->onResponse.connect(&handleServerDiscoInfoResponse); + discoInfoRequest->send(); } static void handleDisconnected(const boost::optional<ClientError>&) { - exitCode = CANNOT_AUTH; - eventLoop.stop(); + exitCode = CANNOT_AUTH; + eventLoop.stop(); } int main(int argc, char* argv[]) { - if (argc < 4 || argc > 5) { - std::cerr << "Usage: " << argv[0] << " <jid> [<connect_host>] <password> <timeout_seconds>" << std::endl; - return -1; - } - - int argi = 1; - - std::string jid = argv[argi++]; - std::string connectHost = ""; - if (argc == 5) { - connectHost = argv[argi++]; - } - - client = new Swift::Client(JID(jid), std::string(argv[argi++]), &networkFactories); - char* timeoutChar = argv[argi++]; - int timeout = atoi(timeoutChar); - timeout = (timeout ? timeout : 30) * 1000; - ClientXMLTracer* tracer = new ClientXMLTracer(client); - client->onConnected.connect(&handleConnected); - errorConnection = client->onDisconnected.connect(&handleDisconnected); - std::cout << "Connecting to JID " << jid << " with timeout " << timeout << "ms on host: "; ; - if (!connectHost.empty()) { - std::cout << connectHost << std::endl; - ClientOptions options; - options.manualHostname = connectHost; - client->connect(options); - } else { - std::cout << " Default" << std::endl; - client->connect(); - } - - { - Timer::ref timer = networkFactories.getTimerFactory()->createTimer(timeout); - timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); - timer->start(); - - eventLoop.run(); - } - - delete tracer; - delete client; - return exitCode; + if (argc < 4 || argc > 5) { + std::cerr << "Usage: " << argv[0] << " <jid> [<connect_host>] <password> <timeout_seconds>" << std::endl; + return -1; + } + + int argi = 1; + + std::string jid = argv[argi++]; + std::string connectHost = ""; + if (argc == 5) { + connectHost = argv[argi++]; + } + + client = new Swift::Client(JID(jid), std::string(argv[argi++]), &networkFactories); + char* timeoutChar = argv[argi++]; + int timeout = atoi(timeoutChar); + timeout = (timeout ? timeout : 30) * 1000; + ClientXMLTracer* tracer = new ClientXMLTracer(client); + client->onConnected.connect(&handleConnected); + errorConnection = client->onDisconnected.connect(&handleDisconnected); + std::cout << "Connecting to JID " << jid << " with timeout " << timeout << "ms on host: "; + if (!connectHost.empty()) { + std::cout << connectHost << std::endl; + ClientOptions options; + options.manualHostname = connectHost; + client->connect(options); + } else { + std::cout << " Default" << std::endl; + client->connect(); + } + + { + Timer::ref timer = networkFactories.getTimerFactory()->createTimer(timeout); + timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); + timer->start(); + + eventLoop.run(); + } + + delete tracer; + delete client; + return exitCode; } diff --git a/Swiften/Examples/LinkLocalTool/SConscript b/Swiften/Examples/LinkLocalTool/SConscript index 18eb91f..d7617ed 100644 --- a/Swiften/Examples/LinkLocalTool/SConscript +++ b/Swiften/Examples/LinkLocalTool/SConscript @@ -5,5 +5,5 @@ myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) linkLocalTool = myenv.Program("LinkLocalTool", [ - "main.cpp" - ]) + "main.cpp" + ]) diff --git a/Swiften/Examples/LinkLocalTool/main.cpp b/Swiften/Examples/LinkLocalTool/main.cpp index 18e282b..a853f0e 100644 --- a/Swiften/Examples/LinkLocalTool/main.cpp +++ b/Swiften/Examples/LinkLocalTool/main.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ // FIXME: This example is not complete yet @@ -9,41 +9,41 @@ #include <iostream> #include <Swiften/EventLoop/SimpleEventLoop.h> -#include <Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDQuerier.h> #include <Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDQuerier.h> #include <Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h> +#include <Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.h> using namespace Swift; int main(int argc, char* argv[]) { - if (argc < 2) { - std::cerr << "Invalid parameters" << std::endl; - return -1; - } - - SimpleEventLoop eventLoop; - PlatformDNSSDQuerierFactory factory(&eventLoop); - boost::shared_ptr<DNSSDQuerier> querier = factory.createQuerier(); - querier->start(); - - if (std::string(argv[1]) == "browse") { - boost::shared_ptr<DNSSDBrowseQuery> browseQuery = querier->createBrowseQuery(); - browseQuery->startBrowsing(); - eventLoop.run(); - browseQuery->stopBrowsing(); - } - else if (std::string(argv[1]) == "resolve-service") { - if (argc < 5) { - std::cerr << "Invalid parameters" << std::endl; - return -1; - } - boost::shared_ptr<DNSSDResolveServiceQuery> resolveQuery = querier->createResolveServiceQuery(DNSSDServiceID(argv[2], argv[3], argv[4])); - resolveQuery->start(); - eventLoop.run(); - std::cerr << "Done running" << std::endl; - resolveQuery->stop(); - } - - querier->stop(); + if (argc < 2) { + std::cerr << "Invalid parameters" << std::endl; + return -1; + } + + SimpleEventLoop eventLoop; + PlatformDNSSDQuerierFactory factory(&eventLoop); + std::shared_ptr<DNSSDQuerier> querier = factory.createQuerier(); + querier->start(); + + if (std::string(argv[1]) == "browse") { + std::shared_ptr<DNSSDBrowseQuery> browseQuery = querier->createBrowseQuery(); + browseQuery->startBrowsing(); + eventLoop.run(); + browseQuery->stopBrowsing(); + } + else if (std::string(argv[1]) == "resolve-service") { + if (argc < 5) { + std::cerr << "Invalid parameters" << std::endl; + return -1; + } + std::shared_ptr<DNSSDResolveServiceQuery> resolveQuery = querier->createResolveServiceQuery(DNSSDServiceID(argv[2], argv[3], argv[4])); + resolveQuery->start(); + eventLoop.run(); + std::cerr << "Done running" << std::endl; + resolveQuery->stop(); + } + + querier->stop(); } diff --git a/Swiften/Examples/MUCListAndJoin/.gitignore b/Swiften/Examples/MUCListAndJoin/.gitignore new file mode 100644 index 0000000..85cf8db --- /dev/null +++ b/Swiften/Examples/MUCListAndJoin/.gitignore @@ -0,0 +1 @@ +MUCListAndJoin diff --git a/Swiften/Examples/MUCListAndJoin/MUCListAndJoin.cpp b/Swiften/Examples/MUCListAndJoin/MUCListAndJoin.cpp new file mode 100644 index 0000000..10b0b40 --- /dev/null +++ b/Swiften/Examples/MUCListAndJoin/MUCListAndJoin.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <iostream> +#include <memory> + +#include <boost/optional.hpp> + +#include <Swiften/Client/Client.h> +#include <Swiften/Client/ClientXMLTracer.h> +#include <Swiften/Disco/GetDiscoItemsRequest.h> +#include <Swiften/EventLoop/SimpleEventLoop.h> +#include <Swiften/JID/JID.h> +#include <Swiften/MUC/MUC.h> +#include <Swiften/MUC/MUCManager.h> +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Network/Timer.h> +#include <Swiften/Network/TimerFactory.h> + +using namespace Swift; +using namespace std; + +static SimpleEventLoop eventLoop; +static BoostNetworkFactories networkFactories(&eventLoop); + +static std::shared_ptr<Client> client; +static MUC::ref muc; +static JID mucJID; +static JID roomJID; + +static void joinMUC() { + cout << "Joining " << roomJID.toString() << endl; + + muc = client->getMUCManager()->createMUC(roomJID); + muc->joinAs("SwiftExample"); +} + +static void handleRoomsItemsResponse(std::shared_ptr<DiscoItems> items, ErrorPayload::ref error) { + if (error) { + cout << "Error fetching list of rooms." << endl; + return; + } + + int roomCount = 0; + cout << "List of rooms at " << mucJID.toString() << endl; + for (auto&& item : items->getItems()) { + roomCount++; + cout << "\t" << roomCount << ". " << item.getJID().getNode() << " - " << item.getName() << std::endl; + if (roomCount == 1) { + roomJID = item.getJID(); + } + } + cout << endl; + joinMUC(); +} + +static void handleConnected() { + cout << "Connected." << endl; + // search for MUC rooms + + GetDiscoItemsRequest::ref discoItemsRequest = GetDiscoItemsRequest::create(mucJID, client->getIQRouter()); + discoItemsRequest->onResponse.connect(&handleRoomsItemsResponse); + + cout << "Request list of rooms." << endl; + discoItemsRequest->send(); +} + +static void handleDisconnected(const boost::optional<ClientError>&) { + cout << "Disconnected." << endl; +} + +static void handleIncomingMessage(std::shared_ptr<Message> message) { + if (message->getFrom().toBare() == roomJID) { + cout << "[ " << roomJID << " ] " << message->getFrom().getResource() << ": " << message->getBody().get_value_or("") << endl; + } +} + +/* + * Usage: ./MUCListAndJoin <jid> <password> <muc_domain> + */ +int main(int argc, char* argv[]) { + int ret = 0; + + if (argc != 4) { + cout << "Usage: ./" << argv[0] << " <jid> <password> <muc_domain>" << endl; + ret = -1; + } + else { + mucJID = JID(argv[3]); + client = std::make_shared<Client>(JID(argv[1]), string(argv[2]), &networkFactories); + client->setAlwaysTrustCertificates(); + + // Enable the following line for detailed XML logging + // ClientXMLTracer* tracer = new ClientXMLTracer(client.get()); + + client->onConnected.connect(&handleConnected); + client->onDisconnected.connect(&handleDisconnected); + client->onMessageReceived.connect(&handleIncomingMessage); + + cout << "Connecting..." << flush; + client->connect(); + { + Timer::ref timer = networkFactories.getTimerFactory()->createTimer(30000); + timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); + + Timer::ref disconnectTimer = networkFactories.getTimerFactory()->createTimer(25000); + disconnectTimer->onTick.connect(boost::bind(&Client::disconnect, client.get())); + + timer->start(); + disconnectTimer->start(); + + eventLoop.run(); + } + } + return ret; +} diff --git a/Swiften/Examples/MUCListAndJoin/SConscript b/Swiften/Examples/MUCListAndJoin/SConscript new file mode 100644 index 0000000..73cc372 --- /dev/null +++ b/Swiften/Examples/MUCListAndJoin/SConscript @@ -0,0 +1,7 @@ +Import("env") + +myenv = env.Clone() +myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) + +tester = myenv.Program("MUCListAndJoin", ["MUCListAndJoin.cpp"]) diff --git a/Swiften/Examples/NetworkTool/SConscript b/Swiften/Examples/NetworkTool/SConscript index 38622ff..c850232 100644 --- a/Swiften/Examples/NetworkTool/SConscript +++ b/Swiften/Examples/NetworkTool/SConscript @@ -1,10 +1,10 @@ Import("env") if env["experimental"] : - myenv = env.Clone() - myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) - myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) + myenv = env.Clone() + myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) - linkLocalTool = myenv.Program("NetworkTool", [ - "main.cpp" - ]) + linkLocalTool = myenv.Program("NetworkTool", [ + "main.cpp" + ]) diff --git a/Swiften/Examples/NetworkTool/main.cpp b/Swiften/Examples/NetworkTool/main.cpp index 10a0aa6..c50ab67 100644 --- a/Swiften/Examples/NetworkTool/main.cpp +++ b/Swiften/Examples/NetworkTool/main.cpp @@ -1,17 +1,18 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <iostream> + #include <boost/lexical_cast.hpp> #include <Swiften/EventLoop/SimpleEventLoop.h> -#include <Swiften/Network/PlatformNATTraversalWorker.h> -#include <Swiften/Network/NATTraversalGetPublicIPRequest.h> #include <Swiften/Network/NATTraversalForwardPortRequest.h> +#include <Swiften/Network/NATTraversalGetPublicIPRequest.h> #include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h> +#include <Swiften/Network/PlatformNATTraversalWorker.h> #include <Swiften/Network/PlatformNetworkEnvironment.h> using namespace Swift; @@ -19,67 +20,67 @@ using namespace Swift; static SimpleEventLoop eventLoop; static void handleGetPublicIPRequestResponse(const boost::optional<HostAddress>& result) { - if (result) { - std::cerr << "Result: " << result->toString() << std::endl;; - } - else { - std::cerr << "No result" << std::endl; - } - eventLoop.stop(); + if (result) { + std::cerr << "Result: " << result->toString() << std::endl;; + } + else { + std::cerr << "No result" << std::endl; + } + eventLoop.stop(); } static void handleGetForwardPortRequestResponse(const boost::optional<NATPortMapping>& result) { - if (result) { - std::cerr << "Result: " << result->getPublicPort() << " -> " << result->getLocalPort() << std::endl;; - } - else { - std::cerr << "No result" << std::endl; - } - eventLoop.stop(); + if (result) { + std::cerr << "Result: " << result->getPublicPort() << " -> " << result->getLocalPort() << std::endl;; + } + else { + std::cerr << "No result" << std::endl; + } + eventLoop.stop(); } -static void handleRemovePortForwardingRequestResponse(bool result) { - if (result) { - std::cerr << "Result: OK" << std::endl; - } - else { - std::cerr << "Result: ERROR" << std::endl; - } - eventLoop.stop(); +static void handleRemovePortForwardingRequestResponse(const boost::optional<bool> result) { + if (result && result.get()) { + std::cerr << "Result: OK" << std::endl; + } + else { + std::cerr << "Result: ERROR" << std::endl; + } + eventLoop.stop(); } int main(int argc, char* argv[]) { - if (argc < 2) { - std::cerr << "Invalid parameters" << std::endl; - return -1; - } + if (argc < 2) { + std::cerr << "Invalid parameters" << std::endl; + return -1; + } - PlatformNATTraversalWorker natTraverser(&eventLoop); - if (std::string(argv[1]) == "get-public-ip") { - boost::shared_ptr<NATTraversalGetPublicIPRequest> query = natTraverser.createGetPublicIPRequest(); - query->onResult.connect(boost::bind(&handleGetPublicIPRequestResponse, _1)); - query->start(); - eventLoop.run(); - } - else if (std::string(argv[1]) == "add-port-forward") { - if (argc < 4) { - std::cerr << "Invalid parameters" << std::endl; - } - boost::shared_ptr<NATTraversalForwardPortRequest> query = natTraverser.createForwardPortRequest(boost::lexical_cast<int>(argv[2]), boost::lexical_cast<int>(argv[3])); - query->onResult.connect(boost::bind(&handleGetForwardPortRequestResponse, _1)); - query->start(); - eventLoop.run(); - } - else if (std::string(argv[1]) == "remove-port-forward") { - if (argc < 4) { - std::cerr << "Invalid parameters" << std::endl; - } - boost::shared_ptr<NATTraversalRemovePortForwardingRequest> query = natTraverser.createRemovePortForwardingRequest(boost::lexical_cast<int>(argv[2]), boost::lexical_cast<int>(argv[3])); - query->onResult.connect(boost::bind(&handleRemovePortForwardingRequestResponse, _1)); - query->start(); - eventLoop.run(); - } - else if (std::string(argv[1]) == "get-local-ip") { - std::cout << PlatformNetworkEnvironment().getLocalAddress().toString() << std::endl; - } + PlatformNATTraversalWorker natTraverser(&eventLoop); + if (std::string(argv[1]) == "get-public-ip") { + std::shared_ptr<NATTraversalGetPublicIPRequest> query = natTraverser.createGetPublicIPRequest(); + query->onResult.connect(boost::bind(&handleGetPublicIPRequestResponse, _1)); + query->start(); + eventLoop.run(); + } + else if (std::string(argv[1]) == "add-port-forward") { + if (argc < 4) { + std::cerr << "Invalid parameters" << std::endl; + } + std::shared_ptr<NATTraversalForwardPortRequest> query = natTraverser.createForwardPortRequest(boost::lexical_cast<int>(argv[2]), boost::lexical_cast<int>(argv[3])); + query->onResult.connect(boost::bind(&handleGetForwardPortRequestResponse, _1)); + query->start(); + eventLoop.run(); + } + else if (std::string(argv[1]) == "remove-port-forward") { + if (argc < 4) { + std::cerr << "Invalid parameters" << std::endl; + } + std::shared_ptr<NATTraversalRemovePortForwardingRequest> query = natTraverser.createRemovePortForwardingRequest(boost::lexical_cast<int>(argv[2]), boost::lexical_cast<int>(argv[3])); + query->onResult.connect(boost::bind(&handleRemovePortForwardingRequestResponse, _1)); + query->start(); + eventLoop.run(); + } + else if (std::string(argv[1]) == "get-local-ip") { + std::cout << PlatformNetworkEnvironment().getLocalAddress().toString() << std::endl; + } } diff --git a/Swiften/Examples/ParserTester/ParserTester.cpp b/Swiften/Examples/ParserTester/ParserTester.cpp index 009eef4..71b0611 100644 --- a/Swiften/Examples/ParserTester/ParserTester.cpp +++ b/Swiften/Examples/ParserTester/ParserTester.cpp @@ -1,60 +1,61 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <iostream> +#include <Swiften/Parser/UnitTest/ParserTester.h> + #include <fstream> +#include <iostream> #include <typeinfo> -#include <Swiften/Parser/UnitTest/ParserTester.h> +#include <Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h> +#include <Swiften/Parser/PlatformXMLParserFactory.h> #include <Swiften/Parser/XMPPParser.h> #include <Swiften/Parser/XMPPParserClient.h> -#include <Swiften/Parser/PlatformXMLParserFactory.h> -#include <Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h> using namespace Swift; class MyXMPPParserClient : public XMPPParserClient { - public: - virtual void handleStreamStart(const ProtocolHeader&) { - std::cout << "-> Stream start" << std::endl; - } - virtual void handleElement(boost::shared_ptr<Element> element) { - std::cout << "-> Element " << typeid(*element.get()).name() << std::endl; - } - virtual void handleStreamEnd() { - std::cout << "-> Stream end" << std::endl; - } + public: + virtual void handleStreamStart(const ProtocolHeader&) { + std::cout << "-> Stream start" << std::endl; + } + virtual void handleElement(std::shared_ptr<ToplevelElement> element) { + std::cout << "-> Element " << typeid(*element.get()).name() << std::endl; + } + virtual void handleStreamEnd() { + std::cout << "-> Stream end" << std::endl; + } }; int main(int argc, char* argv[]) { - if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " file" << std::endl; - return 0; - } - FullPayloadParserFactoryCollection factories; - MyXMPPParserClient parserClient; - PlatformXMLParserFactory xmlParserFactory; - XMPPParser parser(&parserClient, &factories, &xmlParserFactory); - ParserTester<XMLParserClient> tester(&parser); + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " file" << std::endl; + return 0; + } + FullPayloadParserFactoryCollection factories; + MyXMPPParserClient parserClient; + PlatformXMLParserFactory xmlParserFactory; + XMPPParser parser(&parserClient, &factories, &xmlParserFactory); + ParserTester<XMLParserClient> tester(&parser); - std::string line; - std::ifstream myfile (argv[1]); - if (myfile.is_open()) { - while (!myfile.eof()) { - getline (myfile,line); - std::cout << "Parsing: " << line << std::endl; - if (!tester.parse(line)) { - std::cerr << "PARSE ERROR" << std::endl; - return -1; - } - } - myfile.close(); - } - else { - std::cerr << "Unable to open file " << argv[1] << std::endl; - } - return 0; + std::string line; + std::ifstream myfile (argv[1]); + if (myfile.is_open()) { + while (!myfile.eof()) { + getline (myfile,line); + std::cout << "Parsing: " << line << std::endl; + if (!tester.parse(line)) { + std::cerr << "PARSE ERROR" << std::endl; + return -1; + } + } + myfile.close(); + } + else { + std::cerr << "Unable to open file " << argv[1] << std::endl; + } + return 0; } diff --git a/Swiften/Examples/SConscript b/Swiften/Examples/SConscript index fb568fc..601cba2 100644 --- a/Swiften/Examples/SConscript +++ b/Swiften/Examples/SConscript @@ -3,11 +3,12 @@ Import("swiften_env") myenv = swiften_env.Clone() SConscript(dirs = [ - "SendMessage", - "SendFile", - "ConnectivityTest", - "LinkLocalTool", - "NetworkTool", - "ParserTester", - "BenchTool", + "SendMessage", + "SendFile", + "ConnectivityTest", + "LinkLocalTool", + "NetworkTool", + "ParserTester", + "BenchTool", + "MUCListAndJoin", ]) diff --git a/Swiften/Examples/SendFile/ReceiveFile.cpp b/Swiften/Examples/SendFile/ReceiveFile.cpp index c777fee..d641662 100644 --- a/Swiften/Examples/SendFile/ReceiveFile.cpp +++ b/Swiften/Examples/SendFile/ReceiveFile.cpp @@ -1,28 +1,28 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <iostream> +#include <memory> + #include <boost/bind.hpp> #include <boost/filesystem.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <iostream> -#include <Swiften/Elements/Presence.h> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Client/Client.h> -#include <Swiften/Elements/DiscoInfo.h> -#include <Swiften/Network/BoostNetworkFactories.h> -#include <Swiften/EventLoop/SimpleEventLoop.h> #include <Swiften/Client/ClientXMLTracer.h> #include <Swiften/Disco/ClientDiscoManager.h> -#include <Swiften/FileTransfer/IncomingFileTransferManager.h> +#include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/EventLoop/SimpleEventLoop.h> +#include <Swiften/FileTransfer/FileTransferManager.h> #include <Swiften/FileTransfer/FileWriteBytestream.h> -#include <Swiften/Jingle/JingleSessionManager.h> +#include <Swiften/FileTransfer/IncomingFileTransferManager.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <Swiften/FileTransfer/FileTransferManager.h> +#include <Swiften/Jingle/JingleSessionManager.h> +#include <Swiften/Network/BoostNetworkFactories.h> using namespace Swift; @@ -35,101 +35,102 @@ static const std::string CLIENT_NAME = "Swiften FT Test"; static const std::string CLIENT_NODE = "http://swift.im"; class FileReceiver { - public: - FileReceiver(const JID& jid, const std::string& password) : jid(jid), password(password) { - client = new Swift::Client(jid, password, &networkFactories); - client->onConnected.connect(boost::bind(&FileReceiver::handleConnected, this)); - client->onDisconnected.connect(boost::bind(&FileReceiver::handleDisconnected, this, _1)); - tracer = new ClientXMLTracer(client); - } - - ~FileReceiver() { - delete tracer; - client->onDisconnected.disconnect(boost::bind(&FileReceiver::handleDisconnected, this, _1)); - client->onConnected.disconnect(boost::bind(&FileReceiver::handleConnected, this)); - delete client; - } - - void start() { - client->connect(); - } - - void stop() { - foreach(const IncomingFileTransfer::ref transfer, incomingFileTransfers) { - //transfer->stop(); - } - client->disconnect(); - } - - private: - void handleConnected() { - Log::setLogLevel(Log::debug); - client->getFileTransferManager()->onIncomingFileTransfer.connect(boost::bind(&FileReceiver::handleIncomingFileTransfer, this, _1)); - - DiscoInfo discoInfo; - discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc")); - discoInfo.addFeature(DiscoInfo::JingleFeature); - discoInfo.addFeature(DiscoInfo::JingleFTFeature); - discoInfo.addFeature(DiscoInfo::Bytestream); - discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); - discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature); - client->getDiscoManager()->setCapsNode(CLIENT_NODE); - client->getDiscoManager()->setDiscoInfo(discoInfo); - client->getPresenceSender()->sendPresence(Presence::create()); - } - - void handleIncomingFileTransfer(IncomingFileTransfer::ref transfer) { - SWIFT_LOG(debug) << "foo" << std::endl; - incomingFileTransfers.push_back(transfer); - boost::shared_ptr<FileWriteBytestream> out = boost::make_shared<FileWriteBytestream>("out"); - transfer->onFinished.connect(boost::bind(&FileReceiver::handleFileTransferFinished, this, _1, out)); - transfer->accept(out); - } - - void handleDisconnected(const boost::optional<ClientError>&) { - std::cerr << "Error!" << std::endl; - exit(-1); - } - - void handleFileTransferFinished( - const boost::optional<FileTransferError>& error, - boost::shared_ptr<FileWriteBytestream> out) { - std::cout << "File transfer finished" << std::endl; - out->close(); - if (error) { - exit(-1); - } - else { - exit(0); - } - } - - void exit(int code) { - exitCode = code; - stop(); - eventLoop.stop(); - } - - private: - JID jid; - std::string password; - Client* client; - ClientXMLTracer* tracer; - std::vector<IncomingFileTransfer::ref> incomingFileTransfers; + public: + FileReceiver(const JID& jid, const std::string& password) : jid(jid), password(password) { + client = new Swift::Client(jid, password, &networkFactories); + client->onConnected.connect(boost::bind(&FileReceiver::handleConnected, this)); + client->onDisconnected.connect(boost::bind(&FileReceiver::handleDisconnected, this, _1)); + tracer = new ClientXMLTracer(client); + } + + ~FileReceiver() { + delete tracer; + client->onDisconnected.disconnect(boost::bind(&FileReceiver::handleDisconnected, this, _1)); + client->onConnected.disconnect(boost::bind(&FileReceiver::handleConnected, this)); + delete client; + } + + void start() { + client->connect(); + } + + void stop() { + for (const auto& transfer : incomingFileTransfers) { + (void)transfer; + //transfer->stop(); + } + client->disconnect(); + } + + private: + void handleConnected() { + Log::setLogLevel(Log::debug); + client->getFileTransferManager()->onIncomingFileTransfer.connect(boost::bind(&FileReceiver::handleIncomingFileTransfer, this, _1)); + + DiscoInfo discoInfo; + discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc")); + discoInfo.addFeature(DiscoInfo::JingleFeature); + discoInfo.addFeature(DiscoInfo::JingleFTFeature); + discoInfo.addFeature(DiscoInfo::Bytestream); + discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); + discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature); + client->getDiscoManager()->setCapsNode(CLIENT_NODE); + client->getDiscoManager()->setDiscoInfo(discoInfo); + client->getPresenceSender()->sendPresence(Presence::create()); + } + + void handleIncomingFileTransfer(IncomingFileTransfer::ref transfer) { + SWIFT_LOG(debug) << "foo"; + incomingFileTransfers.push_back(transfer); + std::shared_ptr<FileWriteBytestream> out = std::make_shared<FileWriteBytestream>("out"); + transfer->onFinished.connect(boost::bind(&FileReceiver::handleFileTransferFinished, this, _1, out)); + transfer->accept(out); + } + + void handleDisconnected(const boost::optional<ClientError>&) { + std::cerr << "Error!" << std::endl; + exit(-1); + } + + void handleFileTransferFinished( + const boost::optional<FileTransferError>& error, + std::shared_ptr<FileWriteBytestream> out) { + std::cout << "File transfer finished" << std::endl; + out->close(); + if (error) { + exit(-1); + } + else { + exit(0); + } + } + + void exit(int code) { + exitCode = code; + stop(); + eventLoop.stop(); + } + + private: + JID jid; + std::string password; + Client* client; + ClientXMLTracer* tracer; + std::vector<IncomingFileTransfer::ref> incomingFileTransfers; }; int main(int argc, char* argv[]) { - if (argc != 3) { - std::cerr << "Usage: " << argv[0] << " <jid> <password>" << std::endl; - return -1; - } + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " <jid> <password>" << std::endl; + return -1; + } - JID jid(argv[1]); - FileReceiver fileReceiver(jid, std::string(argv[2])); - fileReceiver.start(); + JID jid(argv[1]); + FileReceiver fileReceiver(jid, std::string(argv[2])); + fileReceiver.start(); - eventLoop.run(); + eventLoop.run(); - return exitCode; + return exitCode; } diff --git a/Swiften/Examples/SendFile/SendFile.cpp b/Swiften/Examples/SendFile/SendFile.cpp index b056842..2b701c7 100644 --- a/Swiften/Examples/SendFile/SendFile.cpp +++ b/Swiften/Examples/SendFile/SendFile.cpp @@ -1,34 +1,34 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/date_time/posix_time/posix_time.hpp> +#include <iostream> + #include <boost/bind.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/filesystem.hpp> -#include <iostream> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Log.h> #include <Swiften/Client/Client.h> +#include <Swiften/Client/ClientXMLTracer.h> +#include <Swiften/Disco/EntityCapsManager.h> #include <Swiften/Elements/Presence.h> -#include <Swiften/Base/Log.h> -#include <Swiften/Network/BoostTimer.h> -#include <Swiften/Network/TimerFactory.h> -#include <Swiften/Network/BoostNetworkFactories.h> #include <Swiften/EventLoop/EventLoop.h> -#include <Swiften/Client/ClientXMLTracer.h> #include <Swiften/EventLoop/SimpleEventLoop.h> -#include <Swiften/FileTransfer/OutgoingSIFileTransfer.h> #include <Swiften/FileTransfer/FileReadBytestream.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> -#include <Swiften/Network/BoostConnectionServer.h> -#include <Swiften/FileTransfer/OutgoingFileTransferManager.h> +#include <Swiften/FileTransfer/FileTransferManager.h> #include <Swiften/FileTransfer/OutgoingFileTransfer.h> +#include <Swiften/FileTransfer/OutgoingFileTransferManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> #include <Swiften/Jingle/JingleSessionManager.h> -#include <Swiften/Disco/EntityCapsManager.h> -#include <Swiften/Base/ByteArray.h> +#include <Swiften/Network/BoostConnectionServer.h> +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Network/BoostTimer.h> +#include <Swiften/Network/TimerFactory.h> #include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/FileTransfer/FileTransferManager.h> using namespace Swift; @@ -38,117 +38,107 @@ static BoostNetworkFactories networkFactories(&eventLoop); static int exitCode = 2; class FileSender { - public: - FileSender(const JID& jid, const std::string& password, const JID& recipient, const boost::filesystem::path& file) : jid(jid), password(password), recipient(recipient), file(file) { - - client = new Swift::Client(jid, password, &networkFactories); - client->onConnected.connect(boost::bind(&FileSender::handleConnected, this)); - client->onDisconnected.connect(boost::bind(&FileSender::handleDisconnected, this, _1)); - tracer = new ClientXMLTracer(client); - client->getEntityCapsProvider()->onCapsChanged.connect(boost::bind(&FileSender::handleCapsChanged, this, _1)); - } - - ~FileSender() { - delete tracer; - client->onDisconnected.disconnect(boost::bind(&FileSender::handleDisconnected, this, _1)); - client->onConnected.disconnect(boost::bind(&FileSender::handleConnected, this)); - delete client; - } - - void start() { - client->connect(); - } - - private: - void handleConnected() { - client->sendPresence(Presence::create()); - - //ByteArray fileData; - //readByteArrayFromFile(fileData, file); - - // gather file information - /*StreamInitiationFileInfo fileInfo; - - fileInfo.setName(file.filename()); - fileInfo.setSize(boost::filesystem::file_size(file)); - fileInfo.setDescription("Some file!"); - fileInfo.setDate(boost::posix_time::from_time_t(boost::filesystem::last_write_time(file)));*/ - //fileInfo.setHash(Hexify::hexify(MD5::getHash(fileData))); - /* - transfer = new OutgoingSIFileTransfer("myid", client->getJID(), recipient, file.filename(), boost::filesystem::file_size(file), "A file", boost::make_shared<FileReadBytestream>(file)), client->getIQRouter(), socksBytestreamServer); - transfer->onFinished.connect(boost::bind(&FileSender::handleFileTransferFinished, this, _1)); - transfer->start(); - */ - } - - void handleCapsChanged(JID jid) { - if (jid.toBare() == recipient) { - // create ReadBytestream from file - boost::shared_ptr<FileReadBytestream> fileStream = boost::make_shared<FileReadBytestream>(file); - - outgoingFileTransfer = client->getFileTransferManager()->createOutgoingFileTransfer(recipient, file, "Some File!", fileStream); - - if (outgoingFileTransfer) { - std::cout << "started FT" << std::endl; - outgoingFileTransfer->start(); - // TODO: getting notified about FT status and end - } else { - std::cout << "[ ERROR ] " << recipient << " doesn't support any kind of file transfer!" << std::endl; - //client->disconnect(); - } - } - } - - void handleDisconnected(const boost::optional<ClientError>&) { - std::cerr << "Error!" << std::endl; - exit(-1); - } - - void handleFileTransferFinished(const boost::optional<FileTransferError>& error) { - std::cout << "File transfer finished" << std::endl; - if (error) { - exit(-1); - } - else { - exit(0); - } - } - - void exit(int code) { - exitCode = code; - eventLoop.stop(); - } - - private: - BoostConnectionServer::ref connectionServer; - OutgoingFileTransfer::ref outgoingFileTransfer; - JID jid; - std::string password; - JID recipient; - boost::filesystem::path file; - Client* client; - ClientXMLTracer* tracer; + public: + FileSender(const JID& jid, const std::string& password, const JID& recipient, const boost::filesystem::path& file) : jid(jid), password(password), recipient(recipient), file(file), tracer(nullptr), client(std::unique_ptr<Swift::Client>(new Swift::Client(jid, password, &networkFactories))) { + client->onConnected.connect(boost::bind(&FileSender::handleConnected, this)); + client->onDisconnected.connect(boost::bind(&FileSender::handleDisconnected, this, _1)); + //tracer = new ClientXMLTracer(client); + client->getEntityCapsProvider()->onCapsChanged.connect(boost::bind(&FileSender::handleCapsChanged, this, _1)); + } + + ~FileSender() { + delete tracer; + client->onDisconnected.disconnect(boost::bind(&FileSender::handleDisconnected, this, _1)); + client->onConnected.disconnect(boost::bind(&FileSender::handleConnected, this)); + } + + void start() { + client->connect(); + } + + private: + void handleConnected() { + std::cout << "Connected. Awaiting presence from receipient." << std::endl; + client->sendPresence(Presence::create()); + } + + void handleCapsChanged(JID jid) { + if (jid.toBare() == recipient) { + // create ReadBytestream from file + std::shared_ptr<FileReadBytestream> fileStream = std::make_shared<FileReadBytestream>(file); + + outgoingFileTransfer = client->getFileTransferManager()->createOutgoingFileTransfer(recipient, file, "Some File!", fileStream); + + if (outgoingFileTransfer) { + outgoingFileTransfer->onFinished.connect(boost::bind(&FileSender::handleFileTransferFinished, this, _1)); + std::cout << "Starting file-transfer to " << recipient.toString() << "." << std::endl; + outgoingFileTransfer->start(); + // TODO: getting notified about FT status and end + } else { + std::cout << recipient << " doesn't support any kind of file transfer!" << std::endl; + client->disconnect(); + } + } + } + + void handleDisconnected(const boost::optional<ClientError>& err) { + if (err) { + std::cout << "Disconnected due to error ( " << err.get().getType() << " )." << std::endl; + exit(-1); + } + else { + std::cout << "Successfully disconnected." << std::endl; + } + } + + void handleFileTransferFinished(const boost::optional<FileTransferError>& error) { + std::cout << "File transfer finished." << std::endl; + if (error) { + client->disconnect(); + exit(-1); + } + else { + client->disconnect(); + exit(0); + } + } + + void exit(int code) { + exitCode = code; + eventLoop.stop(); + } + + private: + BoostConnectionServer::ref connectionServer; + OutgoingFileTransfer::ref outgoingFileTransfer; + JID jid; + std::string password; + JID recipient; + boost::filesystem::path file; + ClientXMLTracer* tracer; + std::unique_ptr<Swift::Client> client; }; int main(int argc, char* argv[]) { - if (argc != 5) { - std::cerr << "Usage: " << argv[0] << " <jid> <password> <recipient> <file>" << std::endl; - return -1; - } - - JID sender(argv[1]); - JID recipient(argv[3]); - Log::setLogLevel(Log::debug); - FileSender fileSender(sender, std::string(argv[2]), recipient, boost::filesystem::path(argv[4])); - fileSender.start(); - { - /*BoostTimer::ref timer(BoostTimer::create(30000, &MainBoostIOServiceThread::getInstance().getIOService())); - timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); - timer->start();*/ - - eventLoop.run(); - } - - return exitCode; + if (argc != 5) { + std::cerr << "Usage: " << argv[0] << " <jid> <password> <recipient> <file>" << std::endl; + return -1; + } + + //Log::setLogLevel(Log::debug); + + JID sender(argv[1]); + JID recipient(argv[3]); + FileSender fileSender(sender, std::string(argv[2]), recipient, boost::filesystem::path(argv[4])); + fileSender.start(); + { + Timer::ref timer = networkFactories.getTimerFactory()->createTimer(30000); + timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); + timer->start(); + + eventLoop.run(); + } + + return exitCode; } diff --git a/Swiften/Examples/SendMessage/SendMessage.cpp b/Swiften/Examples/SendMessage/SendMessage.cpp index 2a3170f..0b46b41 100644 --- a/Swiften/Examples/SendMessage/SendMessage.cpp +++ b/Swiften/Examples/SendMessage/SendMessage.cpp @@ -1,90 +1,91 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/bind.hpp> -#include <boost/thread.hpp> #include <iostream> +#include <thread> + +#include <boost/bind.hpp> #include <Swiften/Client/Client.h> +#include <Swiften/Client/ClientXMLTracer.h> #include <Swiften/Elements/Message.h> -#include <Swiften/Network/BoostNetworkFactories.h> -#include <Swiften/Network/TimerFactory.h> #include <Swiften/EventLoop/EventLoop.h> -#include <Swiften/Client/ClientXMLTracer.h> #include <Swiften/EventLoop/SimpleEventLoop.h> +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Network/TimerFactory.h> using namespace Swift; static SimpleEventLoop eventLoop; static BoostNetworkFactories networkFactories(&eventLoop); -static Client* client = 0; +static Client* client = nullptr; static JID recipient; static std::string messageBody; static int exitCode = 2; -static boost::bsignals::connection errorConnection; +static boost::signals2::connection errorConnection; static void handleConnected() { - boost::shared_ptr<Message> message(new Message()); - message->setBody(messageBody); - message->setTo(recipient); - client->sendMessage(message); - exitCode = 0; - errorConnection.disconnect(); - client->disconnect(); - eventLoop.stop(); + std::shared_ptr<Message> message(new Message()); + message->setBody(messageBody); + message->setTo(recipient); + client->sendMessage(message); + exitCode = 0; + errorConnection.disconnect(); + client->disconnect(); + eventLoop.stop(); } static void handleDisconnected(const boost::optional<ClientError>&) { - std::cerr << "Error!" << std::endl; - exitCode = 1; - eventLoop.stop(); + std::cerr << "Error!" << std::endl; + exitCode = 1; + eventLoop.stop(); } int main(int argc, char* argv[]) { - if (argc < 5 || argc > 6) { - std::cerr << "Usage: " << argv[0] << " <jid> [<connect_host>]<password> <recipient> <message>" << std::endl; - return -1; - } - - int argi = 1; - - std::string jid = argv[argi++]; - std::string connectHost = ""; - if (argc == 6) { - connectHost = argv[argi++]; - } - - client = new Swift::Client(JID(jid), std::string(argv[argi++]), &networkFactories); - client->setAlwaysTrustCertificates(); - - recipient = JID(argv[argi++]); - messageBody = std::string(argv[argi++]); - - ClientXMLTracer* tracer = new ClientXMLTracer(client); - client->onConnected.connect(&handleConnected); - errorConnection = client->onDisconnected.connect(&handleDisconnected); - if (!connectHost.empty()) { - ClientOptions options; - options.manualHostname = connectHost; - client->connect(options); - } else { - client->connect(); - } - - { - Timer::ref timer = networkFactories.getTimerFactory()->createTimer(30000); - timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); - timer->start(); - - eventLoop.run(); - } - - delete tracer; - delete client; - return exitCode; + if (argc < 5 || argc > 6) { + std::cerr << "Usage: " << argv[0] << " <jid> [<connect_host>]<password> <recipient> <message>" << std::endl; + return -1; + } + + int argi = 1; + + std::string jid = argv[argi++]; + std::string connectHost = ""; + if (argc == 6) { + connectHost = argv[argi++]; + } + + client = new Swift::Client(JID(jid), std::string(argv[argi++]), &networkFactories); + client->setAlwaysTrustCertificates(); + + recipient = JID(argv[argi++]); + messageBody = std::string(argv[argi++]); + + ClientXMLTracer* tracer = new ClientXMLTracer(client); + client->onConnected.connect(&handleConnected); + errorConnection = client->onDisconnected.connect(&handleDisconnected); + if (!connectHost.empty()) { + ClientOptions options; + options.manualHostname = connectHost; + client->connect(options); + } else { + client->connect(); + } + + { + Timer::ref timer = networkFactories.getTimerFactory()->createTimer(30000); + timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); + timer->start(); + + eventLoop.run(); + } + + delete tracer; + delete client; + return exitCode; } diff --git a/Swiften/FileTransfer/ByteArrayReadBytestream.cpp b/Swiften/FileTransfer/ByteArrayReadBytestream.cpp index 4ba791f..3fdff27 100644 --- a/Swiften/FileTransfer/ByteArrayReadBytestream.cpp +++ b/Swiften/FileTransfer/ByteArrayReadBytestream.cpp @@ -1,33 +1,40 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/Algorithm.h> using namespace Swift; -boost::shared_ptr<ByteArray> ByteArrayReadBytestream::read(size_t size) { - size_t readSize = size; - if (position + readSize > data.size()) { - readSize = data.size() - position; - } - boost::shared_ptr<ByteArray> result = boost::make_shared<ByteArray>( - data.begin() + boost::numeric_cast<long long>(position), - data.begin() + boost::numeric_cast<long long>(position) + boost::numeric_cast<long long>(readSize)); - - onRead(*result); - position += readSize; - return result; +std::shared_ptr<ByteArray> ByteArrayReadBytestream::read(size_t size) { + size_t readSize = size; + if (position + readSize > data.size()) { + readSize = data.size() - position; + } + try { + std::shared_ptr<ByteArray> result = std::make_shared<ByteArray>( + data.begin() + boost::numeric_cast<long long>(position), + data.begin() + boost::numeric_cast<long long>(position) + boost::numeric_cast<long long>(readSize)); + onRead(*result); + position += readSize; + return result; + } + catch (const boost::numeric::bad_numeric_cast&) { + // If we cannot cast to long long, we probably ran out of memory long ago + assert(false); + return {}; + } } void ByteArrayReadBytestream::addData(const std::vector<unsigned char>& moreData) { - append(data, moreData); - onDataAvailable(); + append(data, moreData); + onDataAvailable(); } diff --git a/Swiften/FileTransfer/ByteArrayReadBytestream.h b/Swiften/FileTransfer/ByteArrayReadBytestream.h index 664698a..d90e5cc 100644 --- a/Swiften/FileTransfer/ByteArrayReadBytestream.h +++ b/Swiften/FileTransfer/ByteArrayReadBytestream.h @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <vector> -#include <Swiften/FileTransfer/ReadBytestream.h> +#include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/FileTransfer/ReadBytestream.h> namespace Swift { - class ByteArrayReadBytestream : public ReadBytestream { - public: - ByteArrayReadBytestream(const std::vector<unsigned char>& data) : data(data), position(0), dataComplete(true) { - } + class SWIFTEN_API ByteArrayReadBytestream : public ReadBytestream { + public: + ByteArrayReadBytestream(const std::vector<unsigned char>& data) : data(data), position(0), dataComplete(true) { + } - virtual boost::shared_ptr<ByteArray> read(size_t size); + virtual std::shared_ptr<ByteArray> read(size_t size); - virtual bool isFinished() const { - return position >= data.size() && dataComplete; - } + virtual bool isFinished() const { + return position >= data.size() && dataComplete; + } - virtual void setDataComplete(bool b) { - dataComplete = b; - } + virtual void setDataComplete(bool b) { + dataComplete = b; + } - void addData(const std::vector<unsigned char>& moreData); + void addData(const std::vector<unsigned char>& moreData); - private: - std::vector<unsigned char> data; - size_t position; - bool dataComplete; - }; + private: + std::vector<unsigned char> data; + size_t position; + bool dataComplete; + }; } diff --git a/Swiften/FileTransfer/ByteArrayWriteBytestream.h b/Swiften/FileTransfer/ByteArrayWriteBytestream.h index ef97ed9..ec9d101 100644 --- a/Swiften/FileTransfer/ByteArrayWriteBytestream.h +++ b/Swiften/FileTransfer/ByteArrayWriteBytestream.h @@ -1,29 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/FileTransfer/WriteBytestream.h> namespace Swift { - class ByteArrayWriteBytestream : public WriteBytestream { - public: - ByteArrayWriteBytestream() { - } + class SWIFTEN_API ByteArrayWriteBytestream : public WriteBytestream { + public: + ByteArrayWriteBytestream() { + } - virtual void write(const std::vector<unsigned char>& bytes) { - data.insert(data.end(), bytes.begin(), bytes.end()); - onWrite(bytes); - } + virtual bool write(const std::vector<unsigned char>& bytes) { + data.insert(data.end(), bytes.begin(), bytes.end()); + onWrite(bytes); + return true; + } - const std::vector<unsigned char>& getData() const { - return data; - } + const std::vector<unsigned char>& getData() const { + return data; + } - private: - std::vector<unsigned char> data; - }; + private: + std::vector<unsigned char> data; + }; } diff --git a/Swiften/FileTransfer/BytestreamException.h b/Swiften/FileTransfer/BytestreamException.h index f38ef86..02d1e98 100644 --- a/Swiften/FileTransfer/BytestreamException.h +++ b/Swiften/FileTransfer/BytestreamException.h @@ -1,17 +1,19 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <stdexcept> +#include <Swiften/Base/API.h> + namespace Swift { - class BytestreamException : public std::exception { - public: - BytestreamException() { - } - }; + class SWIFTEN_API BytestreamException : public std::exception { + public: + BytestreamException() { + } + }; } diff --git a/Swiften/FileTransfer/BytestreamsRequest.h b/Swiften/FileTransfer/BytestreamsRequest.h index fee09ee..d278e79 100644 --- a/Swiften/FileTransfer/BytestreamsRequest.h +++ b/Swiften/FileTransfer/BytestreamsRequest.h @@ -1,34 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Bytestreams.h> +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class BytestreamsRequest : public GenericRequest<Bytestreams> { - public: - typedef boost::shared_ptr<BytestreamsRequest> ref; + class SWIFTEN_API BytestreamsRequest : public GenericRequest<Bytestreams> { + public: + typedef std::shared_ptr<BytestreamsRequest> ref; - static ref create(const JID& jid, boost::shared_ptr<Bytestreams> payload, IQRouter* router) { - return ref(new BytestreamsRequest(jid, payload, router)); - } + static ref create(const JID& jid, std::shared_ptr<Bytestreams> payload, IQRouter* router) { + return ref(new BytestreamsRequest(jid, payload, router)); + } - static ref create(const JID& from, const JID& to, boost::shared_ptr<Bytestreams> payload, IQRouter* router) { - return ref(new BytestreamsRequest(from, to, payload, router)); - } + static ref create(const JID& from, const JID& to, std::shared_ptr<Bytestreams> payload, IQRouter* router) { + return ref(new BytestreamsRequest(from, to, payload, router)); + } - private: - BytestreamsRequest(const JID& jid, boost::shared_ptr<Bytestreams> payload, IQRouter* router) : GenericRequest<Bytestreams>(IQ::Set, jid, payload, router) { - } + private: + BytestreamsRequest(const JID& jid, std::shared_ptr<Bytestreams> payload, IQRouter* router) : GenericRequest<Bytestreams>(IQ::Set, jid, payload, router) { + } - BytestreamsRequest(const JID& from, const JID& to, boost::shared_ptr<Bytestreams> payload, IQRouter* router) : GenericRequest<Bytestreams>(IQ::Set, from, to, payload, router) { - } - }; + BytestreamsRequest(const JID& from, const JID& to, std::shared_ptr<Bytestreams> payload, IQRouter* router) : GenericRequest<Bytestreams>(IQ::Set, from, to, payload, router) { + } + }; } diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp index af87fd2..ae3d7e0 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp +++ b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp @@ -1,322 +1,308 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2019 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/DefaultFileTransferTransporter.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/FileTransfer/FailingTransportSession.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> +#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/FileTransfer/IBBReceiveTransportSession.h> +#include <Swiften/FileTransfer/IBBSendSession.h> +#include <Swiften/FileTransfer/IBBSendTransportSession.h> #include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> +#include <Swiften/FileTransfer/S5BTransportSession.h> #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> -#include <Swiften/FileTransfer/IBBSendSession.h> -#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <Swiften/FileTransfer/TransportSession.h> -#include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Queries/GenericRequest.h> +#include <Swiften/StringCodecs/Hexify.h> using namespace Swift; -namespace { - class IBBSendTransportSession : public TransportSession { - public: - IBBSendTransportSession(boost::shared_ptr<IBBSendSession> session) : session(session) { - finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); - bytesSentConnection = session->onBytesSent.connect(boost::bind(boost::ref(onBytesSent), _1)); - } - - virtual void start() SWIFTEN_OVERRIDE { - session->start(); - } - - virtual void stop() SWIFTEN_OVERRIDE { - session->stop(); - } - - private: - boost::shared_ptr<IBBSendSession> session; - boost::bsignals::scoped_connection finishedConnection; - boost::bsignals::scoped_connection bytesSentConnection; - }; - - class IBBReceiveTransportSession : public TransportSession { - public: - IBBReceiveTransportSession(boost::shared_ptr<IBBReceiveSession> session) : session(session) { - finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); - } - - virtual void start() SWIFTEN_OVERRIDE { - session->start(); - } - - virtual void stop() SWIFTEN_OVERRIDE { - session->stop(); - } - - private: - boost::shared_ptr<IBBReceiveSession> session; - boost::bsignals::scoped_connection finishedConnection; - boost::bsignals::scoped_connection bytesSentConnection; - }; - - class FailingTransportSession : public TransportSession { - public: - virtual void start() SWIFTEN_OVERRIDE { - onFinished(FileTransferError(FileTransferError::PeerError)); - } - - virtual void stop() SWIFTEN_OVERRIDE { - } - }; - - template <typename T> - class S5BTransportSession : public TransportSession { - public: - S5BTransportSession( - boost::shared_ptr<T> session, - boost::shared_ptr<ReadBytestream> readStream) : - session(session), - readStream(readStream) { - initialize(); - } - - S5BTransportSession( - boost::shared_ptr<T> session, - boost::shared_ptr<WriteBytestream> writeStream) : - session(session), - writeStream(writeStream) { - initialize(); - } - - virtual void start() SWIFTEN_OVERRIDE { - if (readStream) { - session->startSending(readStream); - } - else { - session->startReceiving(writeStream); - } - } - - virtual void stop() SWIFTEN_OVERRIDE { - session->stop(); - } - - private: - void initialize() { - finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); - bytesSentConnection = session->onBytesSent.connect(boost::bind(boost::ref(onBytesSent), _1)); - } - - private: - boost::shared_ptr<T> session; - boost::shared_ptr<ReadBytestream> readStream; - boost::shared_ptr<WriteBytestream> writeStream; - - boost::bsignals::scoped_connection finishedConnection; - boost::bsignals::scoped_connection bytesSentConnection; - }; -} - DefaultFileTransferTransporter::DefaultFileTransferTransporter( - const JID& initiator, - const JID& responder, - Role role, - SOCKS5BytestreamRegistry* s5bRegistry, - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - IDGenerator* idGenerator, - ConnectionFactory* connectionFactory, - TimerFactory* timerFactory, - CryptoProvider* crypto, - IQRouter* router) : - initiator(initiator), - responder(responder), - role(role), - s5bRegistry(s5bRegistry), - s5bServerManager(s5bServerManager), - crypto(crypto), - router(router) { - - localCandidateGenerator = new LocalJingleTransportCandidateGenerator( - s5bServerManager, - s5bProxy, - role == Initiator ? initiator : responder, - idGenerator); - localCandidateGenerator->onLocalTransportCandidatesGenerated.connect( - boost::bind(&DefaultFileTransferTransporter::handleLocalCandidatesGenerated, this, _1)); - - remoteCandidateSelector = new RemoteJingleTransportCandidateSelector( - connectionFactory, - timerFactory); - remoteCandidateSelector->onCandidateSelectFinished.connect( - boost::bind(&DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished, this, _1, _2)); + const JID& initiator, + const JID& responder, + Role role, + SOCKS5BytestreamRegistry* s5bRegistry, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + IDGenerator* idGenerator, + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto, + IQRouter* router, + const FileTransferOptions& options) : + initiator(initiator), + responder(responder), + role(role), + s5bRegistry(s5bRegistry), + s5bServerManager(s5bServerManager), + s5bProxy(s5bProxy), + crypto(crypto), + router(router) { + + localCandidateGenerator = new LocalJingleTransportCandidateGenerator( + s5bServerManager, + s5bProxy, + role == Initiator ? initiator : responder, + idGenerator, + options); + localCandidateGenerator->onLocalTransportCandidatesGenerated.connect( + boost::bind(&DefaultFileTransferTransporter::handleLocalCandidatesGenerated, this, _1)); + + remoteCandidateSelector = new RemoteJingleTransportCandidateSelector( + connectionFactory, + timerFactory, + options); + remoteCandidateSelector->onCandidateSelectFinished.connect( + boost::bind(&DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished, this, _1, _2)); } DefaultFileTransferTransporter::~DefaultFileTransferTransporter() { - delete remoteCandidateSelector; - delete localCandidateGenerator; + DefaultFileTransferTransporter::stopGeneratingLocalCandidates(); + remoteCandidateSelector->onCandidateSelectFinished.disconnect( + boost::bind(&DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished, this, _1, _2)); + delete remoteCandidateSelector; + + localCandidateGenerator->onLocalTransportCandidatesGenerated.disconnect( + boost::bind(&DefaultFileTransferTransporter::handleLocalCandidatesGenerated, this, _1)); + delete localCandidateGenerator; } void DefaultFileTransferTransporter::initialize() { - s5bSessionID = s5bRegistry->generateSessionID(); + s5bSessionID = s5bRegistry->generateSessionID(); } void DefaultFileTransferTransporter::initialize(const std::string& s5bSessionID) { - this->s5bSessionID = s5bSessionID; + this->s5bSessionID = s5bSessionID; } void DefaultFileTransferTransporter::startGeneratingLocalCandidates() { - localCandidateGenerator->start(); + localCandidateGenerator->start(); } void DefaultFileTransferTransporter::stopGeneratingLocalCandidates() { - localCandidateGenerator->stop(); + localCandidateGenerator->stop(); } - + void DefaultFileTransferTransporter::handleLocalCandidatesGenerated( - const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), true); - onLocalCandidatesGenerated(s5bSessionID, candidates); + const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { + s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), true); + s5bProxy->connectToProxies(getSOCKS5DstAddr()); + onLocalCandidatesGenerated(s5bSessionID, candidates, getSOCKS5DstAddr()); } void DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished( - const boost::optional<JingleS5BTransportPayload::Candidate>& candidate, - boost::shared_ptr<SOCKS5BytestreamClientSession> session) { - remoteS5BClientSession = session; - onRemoteCandidateSelectFinished(s5bSessionID, candidate); + const boost::optional<JingleS5BTransportPayload::Candidate>& candidate, + std::shared_ptr<SOCKS5BytestreamClientSession> session) { + remoteS5BClientSession = session; + onRemoteCandidateSelectFinished(s5bSessionID, candidate); } void DefaultFileTransferTransporter::addRemoteCandidates( - const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - remoteCandidateSelector->setSOCKS5DstAddr(getSOCKS5DstAddr()); - remoteCandidateSelector->addCandidates(candidates); + const std::vector<JingleS5BTransportPayload::Candidate>& candidates, const std::string& dstAddr) { + remoteCandidateSelector->setSOCKS5DstAddr(dstAddr.empty() ? getRemoteCandidateSOCKS5DstAddr() : dstAddr); + remoteCandidateSelector->addCandidates(candidates); } void DefaultFileTransferTransporter::startTryingRemoteCandidates() { - remoteCandidateSelector->startSelectingCandidate(); + remoteCandidateSelector->startSelectingCandidate(); } void DefaultFileTransferTransporter::stopTryingRemoteCandidates() { - remoteCandidateSelector->stopSelectingCandidate(); + remoteCandidateSelector->stopSelectingCandidate(); } -void DefaultFileTransferTransporter::startActivatingProxy(const JID&) { - // TODO - assert(false); - /* - S5BProxyRequest::ref proxyRequest = boost::make_shared<S5BProxyRequest>(); - proxyRequest->setSID(s5bSessionID); - proxyRequest->setActivate(getTarget()); - - boost::shared_ptr<GenericRequest<S5BProxyRequest> > request = boost::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Set, proxy, proxyRequest, router); - request->onResponse.connect(boost::bind(&OutgoingJingleFileTransfer::handleActivateProxySessionResult, this, _1, _2)); - request->send(); - */ +void DefaultFileTransferTransporter::handleActivateProxySessionResult(const std::string& sessionID, ErrorPayload::ref error) { + onProxyActivated(sessionID, error); } -void DefaultFileTransferTransporter::stopActivatingProxy() { - // TODO - assert(false); +void DefaultFileTransferTransporter::startActivatingProxy(const JID& proxyServiceJID) { + // activate proxy + SWIFT_LOG(debug) << "Start activating proxy " << proxyServiceJID.toString() << " with sid = " << s5bSessionID << "."; + S5BProxyRequest::ref proxyRequest = std::make_shared<S5BProxyRequest>(); + proxyRequest->setSID(s5bSessionID); + proxyRequest->setActivate(role == Initiator ? responder : initiator); + + std::shared_ptr<GenericRequest<S5BProxyRequest> > request = std::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Set, proxyServiceJID, proxyRequest, router); + request->onResponse.connect(boost::bind(&DefaultFileTransferTransporter::handleActivateProxySessionResult, this, s5bSessionID, _2)); + request->send(); } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBSendSession( - const std::string& sessionID, unsigned int blockSize, boost::shared_ptr<ReadBytestream> stream) { - closeLocalSession(); - closeRemoteSession(); - boost::shared_ptr<IBBSendSession> ibbSession = boost::make_shared<IBBSendSession>( - sessionID, initiator, responder, stream, router); - ibbSession->setBlockSize(blockSize); - return boost::make_shared<IBBSendTransportSession>(ibbSession); +void DefaultFileTransferTransporter::stopActivatingProxy() { + // TODO + assert(false); } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBReceiveSession( - const std::string& sessionID, unsigned long long size, boost::shared_ptr<WriteBytestream> stream) { - closeLocalSession(); - closeRemoteSession(); - boost::shared_ptr<IBBReceiveSession> ibbSession = boost::make_shared<IBBReceiveSession>( - sessionID, initiator, responder, size, stream, router); - return boost::make_shared<IBBReceiveTransportSession>(ibbSession); +std::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBSendSession( + const std::string& sessionID, unsigned int blockSize, std::shared_ptr<ReadBytestream> stream) { + if (s5bServerManager->getServer()) { + closeLocalSession(); + } + closeRemoteSession(); + std::shared_ptr<IBBSendSession> ibbSession = std::make_shared<IBBSendSession>( + sessionID, initiator, responder, stream, router); + ibbSession->setBlockSize(blockSize); + return std::make_shared<IBBSendTransportSession>(ibbSession); } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( - boost::shared_ptr<ReadBytestream> stream) { - closeLocalSession(); - return boost::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( - remoteS5BClientSession, stream); +std::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBReceiveSession( + const std::string& sessionID, unsigned long long size, std::shared_ptr<WriteBytestream> stream) { + if (s5bServerManager->getServer()) { + closeLocalSession(); + } + closeRemoteSession(); + std::shared_ptr<IBBReceiveSession> ibbSession = std::make_shared<IBBReceiveSession>( + sessionID, initiator, responder, size, stream, router); + return std::make_shared<IBBReceiveTransportSession>(ibbSession); } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( - boost::shared_ptr<WriteBytestream> stream) { - closeLocalSession(); - return boost::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( - remoteS5BClientSession, stream); +std::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( + std::shared_ptr<ReadBytestream> stream, const JingleS5BTransportPayload::Candidate& /* candidate */) { + closeLocalSession(); + return std::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( + remoteS5BClientSession, stream); } -boost::shared_ptr<SOCKS5BytestreamServerSession> DefaultFileTransferTransporter::getServerSession() { - s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), false); - std::vector<boost::shared_ptr<SOCKS5BytestreamServerSession> > serverSessions = - s5bServerManager->getServer()->getSessions(getSOCKS5DstAddr()); - while (serverSessions.size() > 1) { - boost::shared_ptr<SOCKS5BytestreamServerSession> session = serverSessions.back(); - serverSessions.pop_back(); - session->stop(); - } - return !serverSessions.empty() ? serverSessions.front() : boost::shared_ptr<SOCKS5BytestreamServerSession>(); +std::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( + std::shared_ptr<WriteBytestream> stream, const JingleS5BTransportPayload::Candidate& /* candidate */) { + closeLocalSession(); + return std::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( + remoteS5BClientSession, stream); } +std::shared_ptr<SOCKS5BytestreamServerSession> DefaultFileTransferTransporter::getServerSession() { + s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), false); + std::vector<std::shared_ptr<SOCKS5BytestreamServerSession> > serverSessions = + s5bServerManager->getServer()->getSessions(getSOCKS5DstAddr()); + while (serverSessions.size() > 1) { + std::shared_ptr<SOCKS5BytestreamServerSession> session = serverSessions.back(); + serverSessions.pop_back(); + session->stop(); + } + return !serverSessions.empty() ? serverSessions.front() : std::shared_ptr<SOCKS5BytestreamServerSession>(); +} -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createLocalCandidateSession( - boost::shared_ptr<ReadBytestream> stream) { - closeRemoteSession(); - boost::shared_ptr<SOCKS5BytestreamServerSession> serverSession = getServerSession(); - if (serverSession) { - return boost::make_shared<S5BTransportSession<SOCKS5BytestreamServerSession> >(serverSession, stream); - } - else { - return boost::make_shared<FailingTransportSession>(); - } +std::shared_ptr<TransportSession> DefaultFileTransferTransporter::createLocalCandidateSession( + std::shared_ptr<ReadBytestream> stream, const JingleS5BTransportPayload::Candidate& candidate) { + closeRemoteSession(); + std::shared_ptr<TransportSession> transportSession; + if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { + SOCKS5BytestreamClientSession::ref proxySession = s5bProxy->getProxySessionAndCloseOthers(candidate.jid, getLocalCandidateSOCKS5DstAddr()); + if (proxySession) { + transportSession = std::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >(proxySession, stream); + } + else { + SWIFT_LOG(error) << "Failed obtaining proxy session with candidate JID " << candidate.jid << " and dstAddr " << getLocalCandidateSOCKS5DstAddr() << "."; + } + } + + if (!transportSession) { + std::shared_ptr<SOCKS5BytestreamServerSession> serverSession = getServerSession(); + if (serverSession) { + transportSession = std::make_shared<S5BTransportSession<SOCKS5BytestreamServerSession> >(serverSession, stream); + } + } + + if (!transportSession) { + transportSession = std::make_shared<FailingTransportSession>(); + } + return transportSession; } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createLocalCandidateSession( - boost::shared_ptr<WriteBytestream> stream) { - closeRemoteSession(); - boost::shared_ptr<SOCKS5BytestreamServerSession> serverSession = getServerSession(); - if (serverSession) { - return boost::make_shared<S5BTransportSession<SOCKS5BytestreamServerSession> >(serverSession, stream); - } - else { - return boost::make_shared<FailingTransportSession>(); - } +std::shared_ptr<TransportSession> DefaultFileTransferTransporter::createLocalCandidateSession( + std::shared_ptr<WriteBytestream> stream, const JingleS5BTransportPayload::Candidate& candidate) { + closeRemoteSession(); + std::shared_ptr<TransportSession> transportSession; + if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { + SOCKS5BytestreamClientSession::ref proxySession = s5bProxy->getProxySessionAndCloseOthers(candidate.jid, getLocalCandidateSOCKS5DstAddr()); + if (proxySession) { + transportSession = std::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >(proxySession, stream); + } + else { + SWIFT_LOG(error) << "Failed obtaining proxy session with candidate JID " << candidate.jid << " and dstAddr " << getLocalCandidateSOCKS5DstAddr() << "."; + } + } + + if (!transportSession) { + std::shared_ptr<SOCKS5BytestreamServerSession> serverSession = getServerSession(); + if (serverSession) { + transportSession = std::make_shared<S5BTransportSession<SOCKS5BytestreamServerSession> >(serverSession, stream); + } + } + + if (!transportSession) { + transportSession = std::make_shared<FailingTransportSession>(); + } + return transportSession; } std::string DefaultFileTransferTransporter::getSOCKS5DstAddr() const { - return Hexify::hexify(crypto->getSHA1Hash( - createSafeByteArray(s5bSessionID + initiator.toString() + initiator.toString()))); + std::string result; + if (role == Initiator) { + result = getInitiatorCandidateSOCKS5DstAddr(); + SWIFT_LOG(debug) << "Initiator S5B DST.ADDR = " << s5bSessionID << " + " << initiator.toString() << " + " << responder.toString() << " : " << result; + } + else { + result = getResponderCandidateSOCKS5DstAddr(); + SWIFT_LOG(debug) << "Responder S5B DST.ADDR = " << s5bSessionID << " + " << responder.toString() << " + " << initiator.toString() << " : " << result; + } + return result; +} + +std::string DefaultFileTransferTransporter::getInitiatorCandidateSOCKS5DstAddr() const { + return Hexify::hexify(crypto->getSHA1Hash(createSafeByteArray(s5bSessionID + initiator.toString() + responder.toString()))); +} + +std::string DefaultFileTransferTransporter::getResponderCandidateSOCKS5DstAddr() const { + return Hexify::hexify(crypto->getSHA1Hash(createSafeByteArray(s5bSessionID + responder.toString() + initiator.toString()))); +} + +std::string DefaultFileTransferTransporter::getRemoteCandidateSOCKS5DstAddr() const { + if (role == Initiator) { + return getResponderCandidateSOCKS5DstAddr(); + } + else { + return getInitiatorCandidateSOCKS5DstAddr(); + } +} + +std::string DefaultFileTransferTransporter::getLocalCandidateSOCKS5DstAddr() const { + if (role == Responder) { + return getResponderCandidateSOCKS5DstAddr(); + } + else { + return getInitiatorCandidateSOCKS5DstAddr(); + } } void DefaultFileTransferTransporter::closeLocalSession() { - s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), false); - std::vector<boost::shared_ptr<SOCKS5BytestreamServerSession> > serverSessions = - s5bServerManager->getServer()->getSessions(getSOCKS5DstAddr()); - foreach(boost::shared_ptr<SOCKS5BytestreamServerSession> session, serverSessions) { - session->stop(); - } + s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), false); + if (s5bServerManager->getServer()) { + std::vector<std::shared_ptr<SOCKS5BytestreamServerSession> > serverSessions = s5bServerManager->getServer()->getSessions(getSOCKS5DstAddr()); + for (auto&& session : serverSessions) { + session->stop(); + } + } } void DefaultFileTransferTransporter::closeRemoteSession() { - if (remoteS5BClientSession) { - remoteS5BClientSession->stop(); - remoteS5BClientSession.reset(); - } + if (remoteS5BClientSession) { + remoteS5BClientSession->stop(); + remoteS5BClientSession.reset(); + } } diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporter.h b/Swiften/FileTransfer/DefaultFileTransferTransporter.h index ef982c0..1bfe799 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporter.h +++ b/Swiften/FileTransfer/DefaultFileTransferTransporter.h @@ -1,102 +1,111 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> +#include <Swiften/Elements/ErrorPayload.h> #include <Swiften/FileTransfer/FileTransferTransporter.h> namespace Swift { - class LocalJingleTransportCandidateGenerator; - class RemoteJingleTransportCandidateSelector; - class SOCKS5BytestreamRegistry; - class SOCKS5BytestreamServerManager; - class SOCKS5BytestreamProxiesManager; - class SOCKS5BytestreamClientSession; - class SOCKS5BytestreamServerSession; - class IDGenerator; - class IQRouter; - class ReadBytestream; - class WriteBytestream; - class ConnectionFactory; - class TimerFactory; - class CryptoProvider; + class LocalJingleTransportCandidateGenerator; + class RemoteJingleTransportCandidateSelector; + class SOCKS5BytestreamRegistry; + class SOCKS5BytestreamServerManager; + class SOCKS5BytestreamProxiesManager; + class SOCKS5BytestreamClientSession; + class SOCKS5BytestreamServerSession; + class IDGenerator; + class IQRouter; + class ReadBytestream; + class WriteBytestream; + class ConnectionFactory; + class TimerFactory; + class CryptoProvider; + class FileTransferOptions; - class SWIFTEN_API DefaultFileTransferTransporter : public FileTransferTransporter { - public: - enum Role { - Initiator, - Responder - }; + class SWIFTEN_API DefaultFileTransferTransporter : public FileTransferTransporter { + public: + enum Role { + Initiator, + Responder + }; - DefaultFileTransferTransporter( - const JID& initiator, - const JID& responder, - Role role, - SOCKS5BytestreamRegistry*, - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - IDGenerator* idGenerator, - ConnectionFactory*, - TimerFactory*, - CryptoProvider*, - IQRouter*); - virtual ~DefaultFileTransferTransporter(); + DefaultFileTransferTransporter( + const JID& initiator, + const JID& responder, + Role role, + SOCKS5BytestreamRegistry*, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + IDGenerator* idGenerator, + ConnectionFactory*, + TimerFactory*, + CryptoProvider*, + IQRouter*, + const FileTransferOptions&); + virtual ~DefaultFileTransferTransporter() override; - - virtual void initialize(); - virtual void initialize(const std::string& s5bSessionID); - virtual void startGeneratingLocalCandidates() SWIFTEN_OVERRIDE; - virtual void stopGeneratingLocalCandidates() SWIFTEN_OVERRIDE; + virtual void initialize(); + virtual void initialize(const std::string& s5bSessionID); - virtual void addRemoteCandidates( - const std::vector<JingleS5BTransportPayload::Candidate>&) SWIFTEN_OVERRIDE; - virtual void startTryingRemoteCandidates() SWIFTEN_OVERRIDE; - virtual void stopTryingRemoteCandidates() SWIFTEN_OVERRIDE; + virtual void startGeneratingLocalCandidates() override; + virtual void stopGeneratingLocalCandidates() override; - virtual void startActivatingProxy(const JID& jid); - virtual void stopActivatingProxy(); + virtual void addRemoteCandidates( + const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string&) override; + virtual void startTryingRemoteCandidates() override; + virtual void stopTryingRemoteCandidates() override; - virtual boost::shared_ptr<TransportSession> createIBBSendSession( - const std::string& sessionID, unsigned int blockSize, boost::shared_ptr<ReadBytestream>) SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createIBBReceiveSession( - const std::string& sessionID, unsigned long long size, boost::shared_ptr<WriteBytestream>) SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<ReadBytestream>) SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<WriteBytestream>) SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<ReadBytestream>) SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<WriteBytestream>) SWIFTEN_OVERRIDE; + virtual void startActivatingProxy(const JID& jid) override; + virtual void stopActivatingProxy() override; - private: - void handleLocalCandidatesGenerated(const std::vector<JingleS5BTransportPayload::Candidate>&); - void handleRemoteCandidateSelectFinished( - const boost::optional<JingleS5BTransportPayload::Candidate>&, - boost::shared_ptr<SOCKS5BytestreamClientSession>); - std::string getSOCKS5DstAddr() const; - void closeLocalSession(); - void closeRemoteSession(); - boost::shared_ptr<SOCKS5BytestreamServerSession> getServerSession(); + virtual std::shared_ptr<TransportSession> createIBBSendSession( + const std::string& sessionID, unsigned int blockSize, std::shared_ptr<ReadBytestream>) override; + virtual std::shared_ptr<TransportSession> createIBBReceiveSession( + const std::string& sessionID, unsigned long long size, std::shared_ptr<WriteBytestream>) override; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) override; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) override; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) override; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) override; - private: - JID initiator; - JID responder; - Role role; - SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamServerManager* s5bServerManager; - CryptoProvider* crypto; - IQRouter* router; - LocalJingleTransportCandidateGenerator* localCandidateGenerator; - RemoteJingleTransportCandidateSelector* remoteCandidateSelector; - std::string s5bSessionID; - boost::shared_ptr<SOCKS5BytestreamClientSession> remoteS5BClientSession; - }; + private: + void handleLocalCandidatesGenerated(const std::vector<JingleS5BTransportPayload::Candidate>&); + void handleRemoteCandidateSelectFinished( + const boost::optional<JingleS5BTransportPayload::Candidate>&, + std::shared_ptr<SOCKS5BytestreamClientSession>); + void handleActivateProxySessionResult(const std::string& sessionID, ErrorPayload::ref error); + void closeLocalSession(); + void closeRemoteSession(); + std::shared_ptr<SOCKS5BytestreamServerSession> getServerSession(); + + std::string getSOCKS5DstAddr() const; + std::string getInitiatorCandidateSOCKS5DstAddr() const; + std::string getResponderCandidateSOCKS5DstAddr() const; + std::string getRemoteCandidateSOCKS5DstAddr() const; + std::string getLocalCandidateSOCKS5DstAddr() const; + + private: + JID initiator; + JID responder; + Role role; + SOCKS5BytestreamRegistry* s5bRegistry; + SOCKS5BytestreamServerManager* s5bServerManager; + SOCKS5BytestreamProxiesManager* s5bProxy; + CryptoProvider* crypto; + IQRouter* router; + LocalJingleTransportCandidateGenerator* localCandidateGenerator; + RemoteJingleTransportCandidateSelector* remoteCandidateSelector; + std::string s5bSessionID; + std::shared_ptr<SOCKS5BytestreamClientSession> remoteS5BClientSession; + }; } diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp index 4c8a55e..3af2cad 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp +++ b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2015 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -11,22 +11,22 @@ using namespace Swift; DefaultFileTransferTransporterFactory::DefaultFileTransferTransporterFactory( - SOCKS5BytestreamRegistry* s5bRegistry, - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxiesManager, - IDGenerator* idGenerator, - ConnectionFactory* connectionFactory, - TimerFactory* timerFactory, - CryptoProvider* cryptoProvider, - IQRouter* iqRouter) : - s5bRegistry(s5bRegistry), - s5bServerManager(s5bServerManager), - s5bProxiesManager(s5bProxiesManager), - idGenerator(idGenerator), - connectionFactory(connectionFactory), - timerFactory(timerFactory), - cryptoProvider(cryptoProvider), - iqRouter(iqRouter) + SOCKS5BytestreamRegistry* s5bRegistry, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxiesManager, + IDGenerator* idGenerator, + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + CryptoProvider* cryptoProvider, + IQRouter* iqRouter) : + s5bRegistry(s5bRegistry), + s5bServerManager(s5bServerManager), + s5bProxiesManager(s5bProxiesManager), + idGenerator(idGenerator), + connectionFactory(connectionFactory), + timerFactory(timerFactory), + cryptoProvider(cryptoProvider), + iqRouter(iqRouter) { } @@ -34,37 +34,39 @@ DefaultFileTransferTransporterFactory::~DefaultFileTransferTransporterFactory() } FileTransferTransporter* DefaultFileTransferTransporterFactory::createInitiatorTransporter( - const JID& initiator, const JID& responder) { - DefaultFileTransferTransporter* transporter = new DefaultFileTransferTransporter( - initiator, - responder, - DefaultFileTransferTransporter::Initiator, - s5bRegistry, - s5bServerManager, - s5bProxiesManager, - idGenerator, - connectionFactory, - timerFactory, - cryptoProvider, - iqRouter); - transporter->initialize(); - return transporter; + const JID& initiator, const JID& responder, const FileTransferOptions& options) { + DefaultFileTransferTransporter* transporter = new DefaultFileTransferTransporter( + initiator, + responder, + DefaultFileTransferTransporter::Initiator, + s5bRegistry, + s5bServerManager, + s5bProxiesManager, + idGenerator, + connectionFactory, + timerFactory, + cryptoProvider, + iqRouter, + options); + transporter->initialize(); + return transporter; } FileTransferTransporter* DefaultFileTransferTransporterFactory::createResponderTransporter( - const JID& initiator, const JID& responder, const std::string& s5bSessionID) { - DefaultFileTransferTransporter* transporter = new DefaultFileTransferTransporter( - initiator, - responder, - DefaultFileTransferTransporter::Initiator, - s5bRegistry, - s5bServerManager, - s5bProxiesManager, - idGenerator, - connectionFactory, - timerFactory, - cryptoProvider, - iqRouter); - transporter->initialize(s5bSessionID); - return transporter; + const JID& initiator, const JID& responder, const std::string& s5bSessionID, const FileTransferOptions& options) { + DefaultFileTransferTransporter* transporter = new DefaultFileTransferTransporter( + initiator, + responder, + DefaultFileTransferTransporter::Responder, + s5bRegistry, + s5bServerManager, + s5bProxiesManager, + idGenerator, + connectionFactory, + timerFactory, + cryptoProvider, + iqRouter, + options); + transporter->initialize(s5bSessionID); + return transporter; } diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h index b5e8f95..fe4f6ea 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h +++ b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h @@ -1,51 +1,50 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/FileTransfer/FileTransferTransporterFactory.h> namespace Swift { - class SOCKS5BytestreamRegistry; - class SOCKS5BytestreamServerManager; - class SOCKS5BytestreamProxiesManager; - class IDGenerator; - class ConnectionFactory; - class TimerFactory; - class CryptoProvider; - class IQRouter; + class SOCKS5BytestreamRegistry; + class SOCKS5BytestreamServerManager; + class SOCKS5BytestreamProxiesManager; + class IDGenerator; + class ConnectionFactory; + class TimerFactory; + class CryptoProvider; + class IQRouter; - class SWIFTEN_API DefaultFileTransferTransporterFactory : public FileTransferTransporterFactory { - public: - DefaultFileTransferTransporterFactory( - SOCKS5BytestreamRegistry*, - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - IDGenerator* idGenerator, - ConnectionFactory*, - TimerFactory*, - CryptoProvider*, - IQRouter*); - virtual ~DefaultFileTransferTransporterFactory(); + class SWIFTEN_API DefaultFileTransferTransporterFactory : public FileTransferTransporterFactory { + public: + DefaultFileTransferTransporterFactory( + SOCKS5BytestreamRegistry*, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + IDGenerator* idGenerator, + ConnectionFactory*, + TimerFactory*, + CryptoProvider*, + IQRouter*); + virtual ~DefaultFileTransferTransporterFactory() override; - virtual FileTransferTransporter* createInitiatorTransporter( - const JID& initiator, const JID& responder) SWIFTEN_OVERRIDE; - virtual FileTransferTransporter* createResponderTransporter( - const JID& initiator, const JID& responder, const std::string& s5bSessionID) SWIFTEN_OVERRIDE; + virtual FileTransferTransporter* createInitiatorTransporter( + const JID& initiator, const JID& responder, const FileTransferOptions&) override; + virtual FileTransferTransporter* createResponderTransporter( + const JID& initiator, const JID& responder, const std::string& s5bSessionID, const FileTransferOptions&) override; - private: - SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamServerManager* s5bServerManager; - SOCKS5BytestreamProxiesManager* s5bProxiesManager; - IDGenerator* idGenerator; - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; - CryptoProvider* cryptoProvider; - IQRouter* iqRouter; - }; + private: + SOCKS5BytestreamRegistry* s5bRegistry; + SOCKS5BytestreamServerManager* s5bServerManager; + SOCKS5BytestreamProxiesManager* s5bProxiesManager; + IDGenerator* idGenerator; + ConnectionFactory* connectionFactory; + TimerFactory* timerFactory; + CryptoProvider* cryptoProvider; + IQRouter* iqRouter; + }; } diff --git a/Swiften/FileTransfer/FailingTransportSession.cpp b/Swiften/FileTransfer/FailingTransportSession.cpp new file mode 100644 index 0000000..b9c79a0 --- /dev/null +++ b/Swiften/FileTransfer/FailingTransportSession.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/FailingTransportSession.h> + +#include <Swiften/Base/Log.h> + +namespace Swift { + +FailingTransportSession::~FailingTransportSession() { +} + +void FailingTransportSession::start() { + SWIFT_LOG(error) << "Trying to start failing transport."; + onFinished(FileTransferError(FileTransferError::PeerError)); +} + +void FailingTransportSession::stop() { +} + +} diff --git a/Swiften/FileTransfer/FailingTransportSession.h b/Swiften/FileTransfer/FailingTransportSession.h new file mode 100644 index 0000000..489786b --- /dev/null +++ b/Swiften/FileTransfer/FailingTransportSession.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/FileTransfer/TransportSession.h> + +namespace Swift { + +class SWIFTEN_API FailingTransportSession : public TransportSession { + public: + virtual ~FailingTransportSession() override; + + virtual void start() override; + virtual void stop() override; +}; + +} diff --git a/Swiften/FileTransfer/FileReadBytestream.cpp b/Swiften/FileTransfer/FileReadBytestream.cpp index 4257f8b..2ff00dc 100644 --- a/Swiften/FileTransfer/FileReadBytestream.cpp +++ b/Swiften/FileTransfer/FileReadBytestream.cpp @@ -1,44 +1,47 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/filesystem/fstream.hpp> +#include <Swiften/FileTransfer/FileReadBytestream.h> + #include <cassert> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + +#include <boost/filesystem/fstream.hpp> #include <boost/numeric/conversion/cast.hpp> -#include <Swiften/FileTransfer/FileReadBytestream.h> #include <Swiften/Base/ByteArray.h> namespace Swift { -FileReadBytestream::FileReadBytestream(const boost::filesystem::path& file) : file(file), stream(NULL) { +FileReadBytestream::FileReadBytestream(const boost::filesystem::path& file) : file(file), stream(nullptr) { } FileReadBytestream::~FileReadBytestream() { - if (stream) { - stream->close(); - stream = NULL; - } + if (stream) { + stream->close(); + delete stream; + stream = nullptr; + } } -boost::shared_ptr<ByteArray> FileReadBytestream::read(size_t size) { - if (!stream) { - stream = new boost::filesystem::ifstream(file, std::ios_base::in|std::ios_base::binary); - } - boost::shared_ptr<ByteArray> result = boost::make_shared<ByteArray>(); - result->resize(size); - assert(stream->good()); - stream->read(reinterpret_cast<char*>(vecptr(*result)), boost::numeric_cast<std::streamsize>(size)); - result->resize(boost::numeric_cast<size_t>(stream->gcount())); - onRead(*result); - return result; +std::shared_ptr<ByteArray> FileReadBytestream::read(size_t size) { + if (!stream) { + stream = new boost::filesystem::ifstream(file, std::ios_base::in|std::ios_base::binary); + } + std::shared_ptr<ByteArray> result = std::make_shared<ByteArray>(); + result->resize(size); + assert(stream->good()); + stream->read(reinterpret_cast<char*>(vecptr(*result)), boost::numeric_cast<std::streamsize>(size)); + result->resize(boost::numeric_cast<size_t>(stream->gcount())); + onRead(*result); + return result; } bool FileReadBytestream::isFinished() const { - return stream && !stream->good(); + return stream && !stream->good(); } } diff --git a/Swiften/FileTransfer/FileReadBytestream.h b/Swiften/FileTransfer/FileReadBytestream.h index 4a2d738..aaf3de3 100644 --- a/Swiften/FileTransfer/FileReadBytestream.h +++ b/Swiften/FileTransfer/FileReadBytestream.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/filesystem/path.hpp> #include <boost/filesystem/fstream.hpp> +#include <boost/filesystem/path.hpp> #include <Swiften/Base/API.h> #include <Swiften/FileTransfer/ReadBytestream.h> namespace Swift { - class SWIFTEN_API FileReadBytestream : public ReadBytestream { - public: - FileReadBytestream(const boost::filesystem::path& file); - ~FileReadBytestream(); + class SWIFTEN_API FileReadBytestream : public ReadBytestream { + public: + FileReadBytestream(const boost::filesystem::path& file); + virtual ~FileReadBytestream(); - virtual boost::shared_ptr< std::vector<unsigned char> > read(size_t size); - virtual bool isFinished() const; + virtual std::shared_ptr< std::vector<unsigned char> > read(size_t size); + virtual bool isFinished() const; - private: - boost::filesystem::path file; - boost::filesystem::ifstream* stream; - }; + private: + boost::filesystem::path file; + boost::filesystem::ifstream* stream; + }; } diff --git a/Swiften/FileTransfer/FileTransfer.cpp b/Swiften/FileTransfer/FileTransfer.cpp index c11e8e4..32c9f53 100644 --- a/Swiften/FileTransfer/FileTransfer.cpp +++ b/Swiften/FileTransfer/FileTransfer.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2015 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -8,13 +8,19 @@ using namespace Swift; -FileTransfer::FileTransfer() { +FileTransfer::FileTransfer() : fileSizeInBytes_(0), state_(State::Initial) { } FileTransfer::~FileTransfer() { } -void FileTransfer::setFileInfo(const std::string& name, boost::uintmax_t size) { - filename = name; - fileSizeInBytes = size; +void FileTransfer::setState(const State& state) { + state_ = state; + onStateChanged(state); +} + +void FileTransfer::setFileInfo(const std::string& name, boost::uintmax_t size, const std::string& description) { + filename_ = name; + fileSizeInBytes_ = size; + description_ = description; } diff --git a/Swiften/FileTransfer/FileTransfer.h b/Swiften/FileTransfer/FileTransfer.h index c01aadb..1d74a84 100644 --- a/Swiften/FileTransfer/FileTransfer.h +++ b/Swiften/FileTransfer/FileTransfer.h @@ -5,66 +5,85 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <boost/cstdint.hpp> #include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> -#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Base/API.h> #include <Swiften/FileTransfer/FileTransferError.h> namespace Swift { - class FileTransfer { - public: - struct State { - enum Type { - Initial, - WaitingForStart, - Negotiating, - WaitingForAccept, - Transferring, - Canceled, - Failed, - Finished - }; - - State(Type type, const std::string& message = "") : type(type), message(message) {} - - Type type; - std::string message; - }; - typedef boost::shared_ptr<FileTransfer> ref; - - public: - FileTransfer(); - virtual ~FileTransfer(); - - virtual void cancel() = 0; - - const std::string& getFileName() const { - return filename; - } - - boost::uintmax_t getFileSizeInBytes() const { - return fileSizeInBytes; - } - - public: - boost::signal<void (size_t /* proccessedBytes */)> onProcessedBytes; - boost::signal<void (const State&)> onStateChanged; - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - - protected: - void setFileInfo(const std::string& name, boost::uintmax_t size); - - private: - boost::uintmax_t fileSizeInBytes; - std::string filename; - }; + /** + * The FileTransfer class provides a general interface for file-transfer + * implmenetations. Currently, only Jingle File Transfer based on XEP-0234 is + * implementated in the \ref OutgoingJingleFileTransfer and + * \ref IncomingJingleFileTransfer classes. + */ + class SWIFTEN_API FileTransfer { + public: + struct State { + enum Type { + Initial, + WaitingForStart, + Negotiating, + WaitingForAccept, + Transferring, + Canceled, + Failed, + Finished + }; + + State(Type type, const std::string& message = "") : type(type), message(message) {} + + Type type; + std::string message; + }; + typedef std::shared_ptr<FileTransfer> ref; + + public: + FileTransfer(); + virtual ~FileTransfer(); + + virtual void cancel() = 0; + + const std::string& getFileName() const { + return filename_; + } + + boost::uintmax_t getFileSizeInBytes() const { + return fileSizeInBytes_; + } + + const State& getState() const { + return state_; + } + + const std::string& getDescription() const { + return description_; + } + + public: + boost::signals2::signal<void (size_t /* proccessedBytes */)> onProcessedBytes; + boost::signals2::signal<void (const State&)> onStateChanged; + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + + protected: + void setState(const State& state); + void setFileInfo(const std::string& name, boost::uintmax_t size, const std::string& description); + + private: + boost::uintmax_t fileSizeInBytes_; + std::string filename_; + std::string description_; + State state_; + }; } diff --git a/Swiften/FileTransfer/FileTransferError.h b/Swiften/FileTransfer/FileTransferError.h index eb1e8f8..e94ee7a 100644 --- a/Swiften/FileTransfer/FileTransferError.h +++ b/Swiften/FileTransfer/FileTransferError.h @@ -1,28 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> + namespace Swift { - class FileTransferError { - public: - enum Type { - UnknownError, - PeerError, - ReadError, - ClosedError - }; + class SWIFTEN_API FileTransferError { + public: + enum Type { + UnknownError, + PeerError, + ReadError, + WriteError, + ClosedError + }; - FileTransferError(Type type = UnknownError) : type(type) {} + FileTransferError(Type type = UnknownError) : type(type) {} - Type getType() const { - return type; - } + Type getType() const { + return type; + } - private: - Type type; - }; + private: + Type type; + }; } diff --git a/Swiften/FileTransfer/FileTransferManager.cpp b/Swiften/FileTransfer/FileTransferManager.cpp index 69be852..a5d7313 100644 --- a/Swiften/FileTransfer/FileTransferManager.cpp +++ b/Swiften/FileTransfer/FileTransferManager.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/FileTransfer/FileTransferManager.h> namespace Swift { diff --git a/Swiften/FileTransfer/FileTransferManager.h b/Swiften/FileTransfer/FileTransferManager.h index 3b793c5..07cfc90 100644 --- a/Swiften/FileTransfer/FileTransferManager.h +++ b/Swiften/FileTransfer/FileTransferManager.h @@ -5,46 +5,48 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <string> -#include <boost/filesystem/path.hpp> + #include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/filesystem/path.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/JID/JID.h> +#include <Swiften/Elements/DiscoInfo.h> #include <Swiften/FileTransfer/FileTransferOptions.h> -#include <Swiften/FileTransfer/OutgoingFileTransfer.h> #include <Swiften/FileTransfer/IncomingFileTransfer.h> +#include <Swiften/FileTransfer/OutgoingFileTransfer.h> +#include <Swiften/JID/JID.h> namespace Swift { - class ReadBytestream; - - class SWIFTEN_API FileTransferManager { - public: - virtual ~FileTransferManager(); - - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID& to, - const boost::filesystem::path& filepath, - const std::string& description, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions& = FileTransferOptions()) = 0; - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID& to, - const std::string& filename, - const std::string& description, - const boost::uintmax_t sizeInBytes, - const boost::posix_time::ptime& lastModified, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions& = FileTransferOptions()) = 0; - - boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer; - }; + class ReadBytestream; + + class SWIFTEN_API FileTransferManager { + public: + virtual ~FileTransferManager(); + + virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID& to, + const boost::filesystem::path& filepath, + const std::string& description, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions& = FileTransferOptions()) = 0; + virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID& to, + const std::string& filename, + const std::string& description, + const boost::uintmax_t sizeInBytes, + const boost::posix_time::ptime& lastModified, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions& = FileTransferOptions()) = 0; + + boost::signals2::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer; + }; } diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp index b832d7e..98eb50e 100644 --- a/Swiften/FileTransfer/FileTransferManagerImpl.cpp +++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp @@ -5,166 +5,161 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2019 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/FileTransferManagerImpl.h> #include <boost/bind.hpp> -#include <boost/filesystem.hpp> #include <boost/cstdint.hpp> +#include <boost/filesystem.hpp> -#include <Swiften/Base/foreach.h> +#include <Swiften/Base/BoostFilesystemVersion.h> #include <Swiften/Base/Log.h> #include <Swiften/Base/Path.h> -#include "Swiften/Disco/EntityCapsProvider.h" -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/StreamInitiationFileInfo.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> -#include <Swiften/FileTransfer/OutgoingFileTransferManager.h> -#include <Swiften/FileTransfer/IncomingFileTransferManager.h> +#include <Swiften/Disco/EntityCapsProvider.h> +#include <Swiften/Disco/FeatureOracle.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h> +#include <Swiften/Elements/Presence.h> #include <Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/IncomingFileTransferManager.h> +#include <Swiften/FileTransfer/OutgoingFileTransferManager.h> #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> -#include <Swiften/Presence/PresenceOracle.h> -#include <Swiften/Elements/Presence.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <Swiften/JID/JID.h> #include <Swiften/Network/ConnectionFactory.h> #include <Swiften/Network/ConnectionServerFactory.h> #include <Swiften/Network/HostAddress.h> #include <Swiften/Network/NATTraverser.h> - -#include <Swiften/Base/BoostFilesystemVersion.h> +#include <Swiften/Presence/PresenceOracle.h> +#include <Swiften/Queries/IQRouter.h> namespace Swift { FileTransferManagerImpl::FileTransferManagerImpl( - const JID& ownFullJID, - JingleSessionManager* jingleSessionManager, - IQRouter* router, - EntityCapsProvider* capsProvider, - PresenceOracle* presOracle, - ConnectionFactory* connectionFactory, - ConnectionServerFactory* connectionServerFactory, - TimerFactory* timerFactory, - NetworkEnvironment* networkEnvironment, - NATTraverser* natTraverser, - CryptoProvider* crypto) : - ownJID(ownFullJID), - iqRouter(router), - capsProvider(capsProvider), - presenceOracle(presOracle) { - assert(!ownFullJID.isBare()); - - bytestreamRegistry = new SOCKS5BytestreamRegistry(); - s5bServerManager = new SOCKS5BytestreamServerManager( - bytestreamRegistry, connectionServerFactory, networkEnvironment, natTraverser); - bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory); - - transporterFactory = new DefaultFileTransferTransporterFactory( - bytestreamRegistry, - s5bServerManager, - bytestreamProxy, - &idGenerator, - connectionFactory, - timerFactory, - crypto, - iqRouter); - outgoingFTManager = new OutgoingFileTransferManager( - jingleSessionManager, - iqRouter, - transporterFactory, - crypto); - incomingFTManager = new IncomingFileTransferManager( - jingleSessionManager, - iqRouter, - transporterFactory, - timerFactory, - crypto); - incomingFTManager->onIncomingFileTransfer.connect(onIncomingFileTransfer); + const JID& ownJID, + JingleSessionManager* jingleSessionManager, + IQRouter* router, + EntityCapsProvider* capsProvider, + PresenceOracle* presOracle, + ConnectionFactory* connectionFactory, + ConnectionServerFactory* connectionServerFactory, + TimerFactory* timerFactory, + DomainNameResolver* domainNameResolver, + NetworkEnvironment* networkEnvironment, + NATTraverser* natTraverser, + CryptoProvider* crypto) : + iqRouter(router), + capsProvider(capsProvider), + presenceOracle(presOracle) { + bytestreamRegistry = new SOCKS5BytestreamRegistry(); + s5bServerManager = new SOCKS5BytestreamServerManager( + bytestreamRegistry, connectionServerFactory, networkEnvironment, natTraverser); + bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, domainNameResolver, iqRouter, JID(ownJID.getDomain())); + + transporterFactory = new DefaultFileTransferTransporterFactory( + bytestreamRegistry, + s5bServerManager, + bytestreamProxy, + &idGenerator, + connectionFactory, + timerFactory, + crypto, + iqRouter); + outgoingFTManager = new OutgoingFileTransferManager( + jingleSessionManager, + iqRouter, + transporterFactory, + timerFactory, + crypto); + incomingFTManager = new IncomingFileTransferManager( + jingleSessionManager, + transporterFactory, + timerFactory, + crypto); + incomingFTManager->onIncomingFileTransfer.connect(onIncomingFileTransfer); } FileTransferManagerImpl::~FileTransferManagerImpl() { - delete s5bServerManager; - delete incomingFTManager; - delete outgoingFTManager; - delete transporterFactory; + delete incomingFTManager; + delete outgoingFTManager; + delete transporterFactory; + delete bytestreamProxy; + delete s5bServerManager; + delete bytestreamRegistry; } void FileTransferManagerImpl::start() { } void FileTransferManagerImpl::stop() { - s5bServerManager->stop(); -} - -boost::optional<JID> FileTransferManagerImpl::highestPriorityJIDSupportingFileTransfer(const JID& bareJID) { - JID fullReceipientJID; - int priority = INT_MIN; - - //getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11 - std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID); - - //iterate over them - foreach(Presence::ref pres, presences) { - if (pres->getPriority() > priority) { - // look up caps from the jid - DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom()); - if (info && info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) && (info->hasFeature(DiscoInfo::JingleTransportsIBBFeature) || info->hasFeature(DiscoInfo::JingleTransportsS5BFeature))) { - - priority = pres->getPriority(); - fullReceipientJID = pres->getFrom(); - } - } - } - - return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>(); + s5bServerManager->stop(); } OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer( - const JID& to, - const boost::filesystem::path& filepath, - const std::string& description, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions& config) { + const JID& to, + const boost::filesystem::path& filepath, + const std::string& description, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions& config) { #if BOOST_FILESYSTEM_VERSION == 2 // TODO: Delete this when boost 1.44 becomes a minimum requirement, and we no longer need v2 - std::string filename = filepath.filename(); + std::string filename = filepath.filename(); #else - std::string filename = pathToString(filepath.filename()); + std::string filename = pathToString(filepath.filename()); #endif - boost::uintmax_t sizeInBytes = boost::filesystem::file_size(filepath); - boost::posix_time::ptime lastModified = boost::posix_time::from_time_t(boost::filesystem::last_write_time(filepath)); - return createOutgoingFileTransfer(to, filename, description, sizeInBytes, lastModified, bytestream, config); + boost::uintmax_t sizeInBytes = boost::filesystem::file_size(filepath); + boost::posix_time::ptime lastModified = boost::posix_time::from_time_t(boost::filesystem::last_write_time(filepath)); + return createOutgoingFileTransfer(to, filename, description, sizeInBytes, lastModified, bytestream, config); } OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer( - const JID& to, - const std::string& filename, - const std::string& description, - const boost::uintmax_t sizeInBytes, - const boost::posix_time::ptime& lastModified, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions& config) { - StreamInitiationFileInfo fileInfo; - fileInfo.setDate(lastModified); - fileInfo.setSize(sizeInBytes); - fileInfo.setName(filename); - fileInfo.setDescription(description); - - JID receipient = to; - - if(receipient.isBare()) { - boost::optional<JID> fullJID = highestPriorityJIDSupportingFileTransfer(receipient); - if (fullJID.is_initialized()) { - receipient = fullJID.get(); - } else { - return OutgoingFileTransfer::ref(); - } - } - - return outgoingFTManager->createOutgoingFileTransfer(ownJID, receipient, bytestream, fileInfo, config); + const JID& to, + const std::string& filename, + const std::string& description, + const boost::uintmax_t sizeInBytes, + const boost::posix_time::ptime& lastModified, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions& config) { + JingleFileTransferFileInfo fileInfo; + fileInfo.setDate(lastModified); + fileInfo.setSize(sizeInBytes); + fileInfo.setName(filename); + fileInfo.setDescription(description); + + JID receipient = to; + + if(receipient.isBare()) { + auto featureOracle = FeatureOracle(capsProvider, presenceOracle); + JID fullJID = featureOracle.getMostAvailableClientForFileTrasfer(receipient); + if (!fullJID.toString().empty()) { + receipient = fullJID; + } else { + return OutgoingFileTransfer::ref(); + } + } + + assert(!iqRouter->getJID().isBare()); + + DiscoInfo::ref capabilities = capsProvider->getCaps(receipient); + + FileTransferOptions options = config; + if (capabilities) { + if (!capabilities->hasFeature(DiscoInfo::JingleTransportsS5BFeature)) { + options = options.withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false); + } + if (!capabilities->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) { + options = options.withInBandAllowed(false); + } + } + else { + SWIFT_LOG(warning) << "No entity capabilities information for " << receipient.toString(); + } + + return outgoingFTManager->createOutgoingFileTransfer(iqRouter->getJID(), receipient, bytestream, fileInfo, options); } } diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.h b/Swiften/FileTransfer/FileTransferManagerImpl.h index addbbd7..d3d55f0 100644 --- a/Swiften/FileTransfer/FileTransferManagerImpl.h +++ b/Swiften/FileTransfer/FileTransferManagerImpl.h @@ -5,99 +5,98 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <vector> #include <string> +#include <vector> -#include <boost/filesystem/path.hpp> #include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/filesystem/path.hpp> #include <boost/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/Override.h> +#include <Swiften/Base/IDGenerator.h> +#include <Swiften/Elements/S5BProxyRequest.h> #include <Swiften/FileTransfer/FileTransferManager.h> #include <Swiften/FileTransfer/FileTransferOptions.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Base/IDGenerator.h> -#include <Swiften/JID/JID.h> -#include <Swiften/FileTransfer/OutgoingFileTransfer.h> #include <Swiften/FileTransfer/IncomingFileTransfer.h> -#include <Swiften/Elements/S5BProxyRequest.h> +#include <Swiften/FileTransfer/OutgoingFileTransfer.h> namespace Swift { - class ConnectionFactory; - class ConnectionServerFactory; - class SOCKS5BytestreamServerManager; - class EntityCapsProvider; - class IQRouter; - class IncomingFileTransferManager; - class JingleSessionManager; - class OutgoingFileTransferManager; - class NATTraverser; - class PresenceOracle; - class ReadBytestream; - class FileTransferTransporterFactory; - class SOCKS5BytestreamRegistry; - class SOCKS5BytestreamProxiesManager; - class TimerFactory; - class CryptoProvider; - class NetworkEnvironment; + class ConnectionFactory; + class ConnectionServerFactory; + class CryptoProvider; + class DomainNameResolver; + class EntityCapsProvider; + class FileTransferTransporterFactory; + class IQRouter; + class IncomingFileTransferManager; + class JID; + class JingleSessionManager; + class NATTraverser; + class NetworkEnvironment; + class OutgoingFileTransferManager; + class PresenceOracle; + class ReadBytestream; + class SOCKS5BytestreamProxiesManager; + class SOCKS5BytestreamRegistry; + class SOCKS5BytestreamServerManager; + class TimerFactory; + + class SWIFTEN_API FileTransferManagerImpl : public FileTransferManager { + public: + FileTransferManagerImpl( + const JID& ownFullJID, + JingleSessionManager* jingleSessionManager, + IQRouter* router, + EntityCapsProvider* capsProvider, + PresenceOracle* presOracle, + ConnectionFactory* connectionFactory, + ConnectionServerFactory* connectionServerFactory, + TimerFactory* timerFactory, + DomainNameResolver* domainNameResolver, + NetworkEnvironment* networkEnvironment, + NATTraverser* natTraverser, + CryptoProvider* crypto); + virtual ~FileTransferManagerImpl() override; + + OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID& to, + const boost::filesystem::path& filepath, + const std::string& description, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions&) override; + OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID& to, + const std::string& filename, + const std::string& description, + const boost::uintmax_t sizeInBytes, + const boost::posix_time::ptime& lastModified, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions&) override; + + void start(); + void stop(); - class SWIFTEN_API FileTransferManagerImpl : public FileTransferManager { - public: - FileTransferManagerImpl( - const JID& ownFullJID, - JingleSessionManager* jingleSessionManager, - IQRouter* router, - EntityCapsProvider* capsProvider, - PresenceOracle* presOracle, - ConnectionFactory* connectionFactory, - ConnectionServerFactory* connectionServerFactory, - TimerFactory* timerFactory, - NetworkEnvironment* networkEnvironment, - NATTraverser* natTraverser, - CryptoProvider* crypto); - ~FileTransferManagerImpl(); - - OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID& to, - const boost::filesystem::path& filepath, - const std::string& description, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions&) SWIFTEN_OVERRIDE; - OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID& to, - const std::string& filename, - const std::string& description, - const boost::uintmax_t sizeInBytes, - const boost::posix_time::ptime& lastModified, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions&) SWIFTEN_OVERRIDE; + private: + boost::optional<JID> highestPriorityJIDSupportingFileTransfer(const JID& bareJID); - void start(); - void stop(); - - private: - boost::optional<JID> highestPriorityJIDSupportingFileTransfer(const JID& bareJID); - - private: - JID ownJID; - - OutgoingFileTransferManager* outgoingFTManager; - IncomingFileTransferManager* incomingFTManager; - FileTransferTransporterFactory* transporterFactory; - IQRouter* iqRouter; - EntityCapsProvider* capsProvider; - PresenceOracle* presenceOracle; - IDGenerator idGenerator; - SOCKS5BytestreamRegistry* bytestreamRegistry; - SOCKS5BytestreamProxiesManager* bytestreamProxy; - SOCKS5BytestreamServerManager* s5bServerManager; - }; + private: + OutgoingFileTransferManager* outgoingFTManager; + IncomingFileTransferManager* incomingFTManager; + FileTransferTransporterFactory* transporterFactory; + IQRouter* iqRouter; + EntityCapsProvider* capsProvider; + PresenceOracle* presenceOracle; + IDGenerator idGenerator; + SOCKS5BytestreamRegistry* bytestreamRegistry; + SOCKS5BytestreamProxiesManager* bytestreamProxy; + SOCKS5BytestreamServerManager* s5bServerManager; + }; } diff --git a/Swiften/FileTransfer/FileTransferOptions.cpp b/Swiften/FileTransfer/FileTransferOptions.cpp index af816ec..3a90d79 100644 --- a/Swiften/FileTransfer/FileTransferOptions.cpp +++ b/Swiften/FileTransfer/FileTransferOptions.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/FileTransfer/FileTransferOptions.h b/Swiften/FileTransfer/FileTransferOptions.h index 304ced8..aa9aa97 100644 --- a/Swiften/FileTransfer/FileTransferOptions.h +++ b/Swiften/FileTransfer/FileTransferOptions.h @@ -1,32 +1,65 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API FileTransferOptions { - public: - FileTransferOptions() : allowInBand(false) { - } + class SWIFTEN_API FileTransferOptions { + public: + FileTransferOptions() : allowInBand_(true), allowAssisted_(true), allowProxied_(true), allowDirect_(true) { + } + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(FileTransferOptions) + ~FileTransferOptions(); - ~FileTransferOptions(); + FileTransferOptions& withInBandAllowed(bool b) { + allowInBand_ = b; + return *this; + } - FileTransferOptions& withInBandAllowed(bool b) { - allowInBand = b; - return *this; - } + bool isInBandAllowed() const { + return allowInBand_; + } - bool isInBandAllowed() const { - return allowInBand; - } + FileTransferOptions& withAssistedAllowed(bool b) { + allowAssisted_ = b; + return *this; + } - private: - bool allowInBand; - }; + bool isAssistedAllowed() const { + return allowAssisted_; + } + + FileTransferOptions& withProxiedAllowed(bool b) { + allowProxied_ = b; + return *this; + } + + bool isProxiedAllowed() const { + return allowProxied_; + } + + FileTransferOptions& withDirectAllowed(bool b) { + allowDirect_ = b; + return *this; + } + + bool isDirectAllowed() const { + return allowDirect_; + } + + + + SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(FileTransferOptions) + + private: + bool allowInBand_; + bool allowAssisted_; + bool allowProxied_; + bool allowDirect_; + }; } diff --git a/Swiften/FileTransfer/FileTransferTransporter.cpp b/Swiften/FileTransfer/FileTransferTransporter.cpp index 30966c4..c4e418c 100644 --- a/Swiften/FileTransfer/FileTransferTransporter.cpp +++ b/Swiften/FileTransfer/FileTransferTransporter.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/FileTransfer/FileTransferTransporter.h b/Swiften/FileTransfer/FileTransferTransporter.h index b7b7090..e0ffc87 100644 --- a/Swiften/FileTransfer/FileTransferTransporter.h +++ b/Swiften/FileTransfer/FileTransferTransporter.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -8,48 +8,53 @@ #include <vector> -#include <boost/optional/optional_fwd.hpp> +#include <boost/optional/optional.hpp> +#include <boost/signals2.hpp> -#include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Elements/JingleS5BTransportPayload.h> namespace Swift { - class TransportSession; - class ErrorPayload; - class ReadBytestream; - class WriteBytestream; - - class SWIFTEN_API FileTransferTransporter { - public: - virtual ~FileTransferTransporter(); - - virtual void startGeneratingLocalCandidates() = 0; - virtual void stopGeneratingLocalCandidates() = 0; - - virtual void addRemoteCandidates( - const std::vector<JingleS5BTransportPayload::Candidate>&) = 0; - virtual void startTryingRemoteCandidates() = 0; - virtual void stopTryingRemoteCandidates() = 0; - - virtual void startActivatingProxy(const JID& proxy) = 0; - virtual void stopActivatingProxy() = 0; - - virtual boost::shared_ptr<TransportSession> createIBBSendSession( - const std::string& sessionID, unsigned int blockSize, boost::shared_ptr<ReadBytestream>) = 0; - virtual boost::shared_ptr<TransportSession> createIBBReceiveSession( - const std::string& sessionID, unsigned long long size, boost::shared_ptr<WriteBytestream>) = 0; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<ReadBytestream>) = 0; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<WriteBytestream>) = 0; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<ReadBytestream>) = 0; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<WriteBytestream>) = 0; - - boost::signal<void (const std::string& /* sessionID */, const std::vector<JingleS5BTransportPayload::Candidate>&)> onLocalCandidatesGenerated; - boost::signal<void (const std::string& /* sessionID */, const boost::optional<JingleS5BTransportPayload::Candidate>&)> onRemoteCandidateSelectFinished; - boost::signal<void (const std::string& /* sessionID */, boost::shared_ptr<ErrorPayload>)> onProxyActivated; - }; + class TransportSession; + class ErrorPayload; + class ReadBytestream; + class WriteBytestream; + + /** + * @brief The FileTransferTransporter class is an abstract factory definition + * to generate SOCKS5 bytestream transports or IBB bytestreams for use in file + * transfers. + */ + class SWIFTEN_API FileTransferTransporter { + public: + virtual ~FileTransferTransporter(); + + virtual void startGeneratingLocalCandidates() = 0; + virtual void stopGeneratingLocalCandidates() = 0; + + virtual void addRemoteCandidates( + const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string&) = 0; + virtual void startTryingRemoteCandidates() = 0; + virtual void stopTryingRemoteCandidates() = 0; + + virtual void startActivatingProxy(const JID& proxy) = 0; + virtual void stopActivatingProxy() = 0; + + virtual std::shared_ptr<TransportSession> createIBBSendSession( + const std::string& sessionID, unsigned int blockSize, std::shared_ptr<ReadBytestream>) = 0; + virtual std::shared_ptr<TransportSession> createIBBReceiveSession( + const std::string& sessionID, unsigned long long size, std::shared_ptr<WriteBytestream>) = 0; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; + + boost::signals2::signal<void (const std::string& /* sessionID */, const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string& /* dstAddr */)> onLocalCandidatesGenerated; + boost::signals2::signal<void (const std::string& /* sessionID */, const boost::optional<JingleS5BTransportPayload::Candidate>&)> onRemoteCandidateSelectFinished; + boost::signals2::signal<void (const std::string& /* sessionID */, std::shared_ptr<ErrorPayload>)> onProxyActivated; + }; } diff --git a/Swiften/FileTransfer/FileTransferTransporterFactory.cpp b/Swiften/FileTransfer/FileTransferTransporterFactory.cpp index 0acc016..6bfdaaf 100644 --- a/Swiften/FileTransfer/FileTransferTransporterFactory.cpp +++ b/Swiften/FileTransfer/FileTransferTransporterFactory.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/FileTransfer/FileTransferTransporterFactory.h b/Swiften/FileTransfer/FileTransferTransporterFactory.h index f7f9acc..4adf32e 100644 --- a/Swiften/FileTransfer/FileTransferTransporterFactory.h +++ b/Swiften/FileTransfer/FileTransferTransporterFactory.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2015 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -11,19 +11,22 @@ #include <Swiften/Base/API.h> namespace Swift { - class JID; - class FileTransferTransporter; + class JID; + class FileTransferTransporter; + class FileTransferOptions; - class SWIFTEN_API FileTransferTransporterFactory { - public: - virtual ~FileTransferTransporterFactory(); + class SWIFTEN_API FileTransferTransporterFactory { + public: + virtual ~FileTransferTransporterFactory(); - virtual FileTransferTransporter* createInitiatorTransporter( - const JID& initiator, - const JID& responder) = 0; - virtual FileTransferTransporter* createResponderTransporter( - const JID& initiator, - const JID& responder, - const std::string& s5bSessionID) = 0; - }; + virtual FileTransferTransporter* createInitiatorTransporter( + const JID& initiator, + const JID& responder, + const FileTransferOptions& options) = 0; + virtual FileTransferTransporter* createResponderTransporter( + const JID& initiator, + const JID& responder, + const std::string& s5bSessionID, + const FileTransferOptions& options) = 0; + }; } diff --git a/Swiften/FileTransfer/FileWriteBytestream.cpp b/Swiften/FileTransfer/FileWriteBytestream.cpp index 6c11eb0..e7daa2c 100644 --- a/Swiften/FileTransfer/FileWriteBytestream.cpp +++ b/Swiften/FileTransfer/FileWriteBytestream.cpp @@ -1,44 +1,52 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/filesystem/fstream.hpp> +#include <Swiften/FileTransfer/FileWriteBytestream.h> + #include <cassert> -#include <boost/numeric/conversion/cast.hpp> -#include <Swiften/FileTransfer/FileWriteBytestream.h> +#include <boost/filesystem/fstream.hpp> +#include <boost/numeric/conversion/cast.hpp> namespace Swift { -FileWriteBytestream::FileWriteBytestream(const boost::filesystem::path& file) : file(file), stream(NULL) { +FileWriteBytestream::FileWriteBytestream(const boost::filesystem::path& file) : file(file), stream(nullptr) { } FileWriteBytestream::~FileWriteBytestream() { - if (stream) { - stream->close(); - stream = NULL; - } + if (stream) { + stream->close(); + delete stream; + stream = nullptr; + } } -void FileWriteBytestream::write(const std::vector<unsigned char>& data) { - if (data.empty()) { - return; - } - if (!stream) { - stream = new boost::filesystem::ofstream(file, std::ios_base::out|std::ios_base::binary); - } - assert(stream->good()); - stream->write(reinterpret_cast<const char*>(&data[0]), boost::numeric_cast<std::streamsize>(data.size())); - onWrite(data); +bool FileWriteBytestream::write(const std::vector<unsigned char>& data) { + if (data.empty()) { + return true; + } + if (!stream) { + stream = new boost::filesystem::ofstream(file, std::ios_base::out|std::ios_base::binary); + } + if (stream->good()) { + stream->write(reinterpret_cast<const char*>(&data[0]), boost::numeric_cast<std::streamsize>(data.size())); + if (stream->good()) { + onWrite(data); + return true; + } + } + return false; } void FileWriteBytestream::close() { - if (stream) { - stream->close(); - stream = NULL; - } + if (stream) { + stream->close(); + delete stream; + stream = nullptr; + } } } diff --git a/Swiften/FileTransfer/FileWriteBytestream.h b/Swiften/FileTransfer/FileWriteBytestream.h index f72ac17..26ab98e 100644 --- a/Swiften/FileTransfer/FileWriteBytestream.h +++ b/Swiften/FileTransfer/FileWriteBytestream.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/filesystem/path.hpp> #include <boost/filesystem/fstream.hpp> +#include <boost/filesystem/path.hpp> #include <Swiften/Base/API.h> #include <Swiften/FileTransfer/WriteBytestream.h> namespace Swift { - class SWIFTEN_API FileWriteBytestream : public WriteBytestream { - public: - FileWriteBytestream(const boost::filesystem::path& file); - ~FileWriteBytestream(); + class SWIFTEN_API FileWriteBytestream : public WriteBytestream { + public: + FileWriteBytestream(const boost::filesystem::path& file); + virtual ~FileWriteBytestream(); - virtual void write(const std::vector<unsigned char>&); - void close(); + virtual bool write(const std::vector<unsigned char>&); + virtual void close(); - private: - boost::filesystem::path file; - boost::filesystem::ofstream* stream; - }; + private: + boost::filesystem::path file; + boost::filesystem::ofstream* stream; + }; } diff --git a/Swiften/FileTransfer/IBBReceiveSession.cpp b/Swiften/FileTransfer/IBBReceiveSession.cpp index 3aa6fdc..24996ed 100644 --- a/Swiften/FileTransfer/IBBReceiveSession.cpp +++ b/Swiften/FileTransfer/IBBReceiveSession.cpp @@ -1,117 +1,118 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <cassert> + #include <boost/bind.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/FileTransfer/IBBRequest.h> #include <Swiften/FileTransfer/BytestreamException.h> +#include <Swiften/FileTransfer/IBBRequest.h> +#include <Swiften/Queries/IQRouter.h> #include <Swiften/Queries/SetResponder.h> -#include <cassert> - namespace Swift { class IBBReceiveSession::IBBResponder : public SetResponder<IBB> { - public: - IBBResponder(IBBReceiveSession* session, IQRouter* router) : SetResponder<IBB>(router), session(session), sequenceNumber(0), receivedSize(0) { - } + public: + IBBResponder(IBBReceiveSession* session, IQRouter* router) : SetResponder<IBB>(router), session(session), sequenceNumber(0), receivedSize(0) { + setFinal(false); + } - virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, IBB::ref ibb) { - if (from == session->from && ibb->getStreamID() == session->id) { - if (ibb->getAction() == IBB::Data) { - if (sequenceNumber == ibb->getSequenceNumber()) { - session->bytestream->write(ibb->getData()); - receivedSize += ibb->getData().size(); - sequenceNumber++; - sendResponse(from, id, IBB::ref()); - if (receivedSize >= session->size) { - if (receivedSize > session->size) { - std::cerr << "Warning: Received more data than expected" << std::endl; - } - session->finish(boost::optional<FileTransferError>()); - } - } - else { - SWIFT_LOG(warning) << "Received data out of order" << std::endl; - sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Cancel); - session->finish(FileTransferError(FileTransferError::ClosedError)); - } - } - else if (ibb->getAction() == IBB::Open) { - SWIFT_LOG(debug) << "IBB open received" << std::endl; - sendResponse(from, id, IBB::ref()); - } - else if (ibb->getAction() == IBB::Close) { - SWIFT_LOG(debug) << "IBB close received" << std::endl; - sendResponse(from, id, IBB::ref()); - session->finish(FileTransferError(FileTransferError::ClosedError)); - } - return true; - } - SWIFT_LOG(debug) << "wrong from/sessionID: " << from << " == " << session->from << " / " <<ibb->getStreamID() << " == " << session->id << std::endl; - return false; - } + virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, IBB::ref ibb) { + if (from == session->from && ibb->getStreamID() == session->id) { + if (ibb->getAction() == IBB::Data) { + if (sequenceNumber == ibb->getSequenceNumber()) { + session->bytestream->write(ibb->getData()); + receivedSize += ibb->getData().size(); + sequenceNumber++; + sendResponse(from, id, IBB::ref()); + if (receivedSize >= session->size) { + if (receivedSize > session->size) { + SWIFT_LOG(warning) << "Received more data than expected"; + } + session->finish(boost::optional<FileTransferError>()); + } + } + else { + SWIFT_LOG(warning) << "Received data out of order"; + sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Cancel); + session->finish(FileTransferError(FileTransferError::ClosedError)); + } + } + else if (ibb->getAction() == IBB::Open) { + SWIFT_LOG(debug) << "IBB open received"; + sendResponse(from, id, IBB::ref()); + } + else if (ibb->getAction() == IBB::Close) { + SWIFT_LOG(debug) << "IBB close received"; + sendResponse(from, id, IBB::ref()); + session->finish(FileTransferError(FileTransferError::ClosedError)); + } + return true; + } + SWIFT_LOG(debug) << "wrong from/sessionID: " << from << " == " << session->from << " / " <<ibb->getStreamID() << " == " << session->id; + return false; + } - private: - IBBReceiveSession* session; - int sequenceNumber; - unsigned long long receivedSize; + private: + IBBReceiveSession* session; + int sequenceNumber; + unsigned long long receivedSize; }; IBBReceiveSession::IBBReceiveSession( - const std::string& id, - const JID& from, - const JID& to, - unsigned long long size, - boost::shared_ptr<WriteBytestream> bytestream, - IQRouter* router) : - id(id), - from(from), - to(to), - size(size), - bytestream(bytestream), - router(router), - active(false) { - assert(!id.empty()); - assert(from.isValid()); - responder = new IBBResponder(this, router); + const std::string& id, + const JID& from, + const JID& to, + unsigned long long size, + std::shared_ptr<WriteBytestream> bytestream, + IQRouter* router) : + id(id), + from(from), + to(to), + size(size), + bytestream(bytestream), + router(router), + active(false) { + assert(!id.empty()); + assert(from.isValid()); + responder = new IBBResponder(this, router); } IBBReceiveSession::~IBBReceiveSession() { - if (active) { - SWIFT_LOG(warning) << "Session still active" << std::endl; - } - delete responder; + if (active) { + SWIFT_LOG(warning) << "Session still active"; + } + delete responder; } void IBBReceiveSession::start() { - SWIFT_LOG(debug) << "receive session started" << std::endl; - active = true; - responder->start(); + SWIFT_LOG(debug) << "receive session started"; + active = true; + responder->start(); } void IBBReceiveSession::stop() { - SWIFT_LOG(debug) << "receive session stopped" << std::endl; - responder->stop(); - if (active) { - if (router->isAvailable()) { - IBBRequest::create(to, from, IBB::createIBBClose(id), router)->send(); - } - finish(boost::optional<FileTransferError>()); - } + SWIFT_LOG(debug) << "receive session stopped"; + responder->stop(); + if (active) { + if (router->isAvailable()) { + IBBRequest::create(to, from, IBB::createIBBClose(id), router)->send(); + } + finish(boost::optional<FileTransferError>()); + } } void IBBReceiveSession::finish(boost::optional<FileTransferError> error) { - active = false; - onFinished(error); + active = false; + onFinished(error); } } diff --git a/Swiften/FileTransfer/IBBReceiveSession.h b/Swiften/FileTransfer/IBBReceiveSession.h index 23d9648..797394c 100644 --- a/Swiften/FileTransfer/IBBReceiveSession.h +++ b/Swiften/FileTransfer/IBBReceiveSession.h @@ -1,63 +1,64 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/optional/optional_fwd.hpp> +#include <memory> + +#include <boost/optional/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/FileTransfer/WriteBytestream.h> -#include <Swiften/JID/JID.h> #include <Swiften/Elements/IBB.h> #include <Swiften/FileTransfer/FileTransferError.h> +#include <Swiften/FileTransfer/WriteBytestream.h> +#include <Swiften/JID/JID.h> namespace Swift { - class IQRouter; - - class SWIFTEN_API IBBReceiveSession { - public: - IBBReceiveSession( - const std::string& id, - const JID& from, - const JID& to, - unsigned long long size, - boost::shared_ptr<WriteBytestream> bytestream, - IQRouter* router); - ~IBBReceiveSession(); - - void start(); - void stop(); - - const JID& getSender() const { - return from; - } - - const JID& getReceiver() const { - return to; - } - - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - - private: - bool handleSetRequest(const JID& from, const JID& to, const std::string& id, IBB::ref payload); - void finish(boost::optional<FileTransferError>); - - private: - class IBBResponder; - friend class IBBResponder; - - std::string id; - JID from; - JID to; - unsigned long long size; - boost::shared_ptr<WriteBytestream> bytestream; - IQRouter* router; - IBBResponder* responder; - bool active; - }; + class IQRouter; + + class SWIFTEN_API IBBReceiveSession { + public: + IBBReceiveSession( + const std::string& id, + const JID& from, + const JID& to, + unsigned long long size, + std::shared_ptr<WriteBytestream> bytestream, + IQRouter* router); + ~IBBReceiveSession(); + + void start(); + void stop(); + + const JID& getSender() const { + return from; + } + + const JID& getReceiver() const { + return to; + } + + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + + private: + bool handleSetRequest(const JID& from, const JID& to, const std::string& id, IBB::ref payload); + void finish(boost::optional<FileTransferError>); + + private: + class IBBResponder; + friend class IBBResponder; + + std::string id; + JID from; + JID to; + unsigned long long size; + std::shared_ptr<WriteBytestream> bytestream; + IQRouter* router; + IBBResponder* responder; + bool active; + }; } diff --git a/Swiften/FileTransfer/IBBReceiveTransportSession.cpp b/Swiften/FileTransfer/IBBReceiveTransportSession.cpp new file mode 100644 index 0000000..6e47ac6 --- /dev/null +++ b/Swiften/FileTransfer/IBBReceiveTransportSession.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/IBBReceiveTransportSession.h> + +#include <boost/bind.hpp> + +namespace Swift { + +IBBReceiveTransportSession::IBBReceiveTransportSession(std::shared_ptr<IBBReceiveSession> session) : session(session) { + finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); +} + +IBBReceiveTransportSession::~IBBReceiveTransportSession() { +} + +void IBBReceiveTransportSession::start() { + session->start(); +} + +void IBBReceiveTransportSession::stop() { + session->stop(); +} + +} diff --git a/Swiften/FileTransfer/IBBReceiveTransportSession.h b/Swiften/FileTransfer/IBBReceiveTransportSession.h new file mode 100644 index 0000000..5b1fd8d --- /dev/null +++ b/Swiften/FileTransfer/IBBReceiveTransportSession.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/FileTransfer/TransportSession.h> + +namespace Swift { + +class SWIFTEN_API IBBReceiveTransportSession : public TransportSession { + public: + IBBReceiveTransportSession(std::shared_ptr<IBBReceiveSession> session); + virtual ~IBBReceiveTransportSession() override; + + virtual void start() override; + virtual void stop() override; + + private: + std::shared_ptr<IBBReceiveSession> session; + boost::signals2::scoped_connection finishedConnection; + boost::signals2::scoped_connection bytesSentConnection; +}; + +} diff --git a/Swiften/FileTransfer/IBBRequest.h b/Swiften/FileTransfer/IBBRequest.h index 58be173..67bd33a 100644 --- a/Swiften/FileTransfer/IBBRequest.h +++ b/Swiften/FileTransfer/IBBRequest.h @@ -1,26 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/IBB.h> - +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class IBBRequest : public GenericRequest<IBB> { - public: - typedef boost::shared_ptr<IBBRequest> ref; + class SWIFTEN_API IBBRequest : public GenericRequest<IBB> { + public: + typedef std::shared_ptr<IBBRequest> ref; - static ref create(const JID& from, const JID& to, boost::shared_ptr<IBB> payload, IQRouter* router) { - return ref(new IBBRequest(from, to, payload, router)); - } + static ref create(const JID& from, const JID& to, std::shared_ptr<IBB> payload, IQRouter* router) { + return ref(new IBBRequest(from, to, payload, router)); + } - private: - IBBRequest(const JID& from, const JID& to, boost::shared_ptr<IBB> payload, IQRouter* router) : GenericRequest<IBB>(IQ::Set, from, to, payload, router) { - } - }; + private: + IBBRequest(const JID& from, const JID& to, std::shared_ptr<IBB> payload, IQRouter* router) : GenericRequest<IBB>(IQ::Set, from, to, payload, router) { + } + }; } diff --git a/Swiften/FileTransfer/IBBSendSession.cpp b/Swiften/FileTransfer/IBBSendSession.cpp index d8b7c7b..258412b 100644 --- a/Swiften/FileTransfer/IBBSendSession.cpp +++ b/Swiften/FileTransfer/IBBSendSession.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/IBBSendSession.h> @@ -10,92 +10,99 @@ #include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/ByteArray.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/FileTransfer/IBBRequest.h> #include <Swiften/FileTransfer/BytestreamException.h> +#include <Swiften/FileTransfer/IBBRequest.h> +#include <Swiften/Queries/IQRouter.h> namespace Swift { IBBSendSession::IBBSendSession( - const std::string& id, - const JID& from, - const JID& to, - boost::shared_ptr<ReadBytestream> bytestream, - IQRouter* router) : - id(id), - from(from), - to(to), - bytestream(bytestream), - router(router), - blockSize(4096), - sequenceNumber(0), - active(false), - waitingForData(false) { - bytestream->onDataAvailable.connect(boost::bind(&IBBSendSession::handleDataAvailable, this)); + const std::string& id, + const JID& from, + const JID& to, + std::shared_ptr<ReadBytestream> bytestream, + IQRouter* router) : + id(id), + from(from), + to(to), + bytestream(bytestream), + router(router), + blockSize(4096), + sequenceNumber(0), + active(false), + waitingForData(false) { + bytestream->onDataAvailable.connect(boost::bind(&IBBSendSession::handleDataAvailable, this)); } IBBSendSession::~IBBSendSession() { - bytestream->onDataAvailable.disconnect(boost::bind(&IBBSendSession::handleDataAvailable, this)); + bytestream->onDataAvailable.disconnect(boost::bind(&IBBSendSession::handleDataAvailable, this)); } void IBBSendSession::start() { - IBBRequest::ref request = IBBRequest::create( - from, to, IBB::createIBBOpen(id, boost::numeric_cast<int>(blockSize)), router); - request->onResponse.connect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); - active = true; - request->send(); + IBBRequest::ref request = IBBRequest::create( + from, to, IBB::createIBBOpen(id, blockSize), router); + request->onResponse.connect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); + active = true; + request->send(); + currentRequest = request; } void IBBSendSession::stop() { - if (active && router->isAvailable()) { - IBBRequest::create(from, to, IBB::createIBBClose(id), router)->send(); - } - finish(boost::optional<FileTransferError>()); + if (active && router->isAvailable()) { + IBBRequest::create(from, to, IBB::createIBBClose(id), router)->send(); + } + if (currentRequest) { + currentRequest->onResponse.disconnect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); + } + finish(boost::optional<FileTransferError>()); } void IBBSendSession::handleIBBResponse(IBB::ref, ErrorPayload::ref error) { - if (!error && active) { - if (!bytestream->isFinished()) { - sendMoreData(); - } - else { - finish(boost::optional<FileTransferError>()); - } - } - else { - finish(FileTransferError(FileTransferError::PeerError)); - } + currentRequest.reset(); + + if (!error && active) { + if (!bytestream->isFinished()) { + sendMoreData(); + } + else { + finish(boost::optional<FileTransferError>()); + } + } + else { + finish(FileTransferError(FileTransferError::PeerError)); + } } void IBBSendSession::sendMoreData() { - try { - boost::shared_ptr<ByteArray> data = bytestream->read(blockSize); - if (!data->empty()) { - waitingForData = false; - IBBRequest::ref request = IBBRequest::create(from, to, IBB::createIBBData(id, sequenceNumber, *data), router); - sequenceNumber++; - request->onResponse.connect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); - request->send(); - onBytesSent(data->size()); - } - else { - waitingForData = true; - } - } - catch (const BytestreamException&) { - finish(FileTransferError(FileTransferError::ReadError)); - } + try { + std::shared_ptr<ByteArray> data = bytestream->read(blockSize); + if (!data->empty()) { + waitingForData = false; + IBBRequest::ref request = IBBRequest::create(from, to, IBB::createIBBData(id, sequenceNumber, *data), router); + sequenceNumber++; + request->onResponse.connect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); + request->send(); + currentRequest = request; + onBytesSent(data->size()); + } + else { + waitingForData = true; + } + } + catch (const BytestreamException&) { + finish(FileTransferError(FileTransferError::ReadError)); + } } void IBBSendSession::finish(boost::optional<FileTransferError> error) { - active = false; - onFinished(error); + active = false; + onFinished(error); } void IBBSendSession::handleDataAvailable() { - if (waitingForData) { - sendMoreData(); - } + if (waitingForData) { + sendMoreData(); + } } } diff --git a/Swiften/FileTransfer/IBBSendSession.h b/Swiften/FileTransfer/IBBSendSession.h index f6ba7b3..e45532d 100644 --- a/Swiften/FileTransfer/IBBSendSession.h +++ b/Swiften/FileTransfer/IBBSendSession.h @@ -1,68 +1,71 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/FileTransfer/ReadBytestream.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/IBB.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/IBB.h> #include <Swiften/FileTransfer/FileTransferError.h> +#include <Swiften/FileTransfer/ReadBytestream.h> +#include <Swiften/JID/JID.h> namespace Swift { - class IQRouter; + class IQRouter; + class IBBRequest; - class SWIFTEN_API IBBSendSession { - public: - IBBSendSession( - const std::string& id, - const JID& from, - const JID& to, - boost::shared_ptr<ReadBytestream> bytestream, - IQRouter* router); - ~IBBSendSession(); + class SWIFTEN_API IBBSendSession { + public: + IBBSendSession( + const std::string& id, + const JID& from, + const JID& to, + std::shared_ptr<ReadBytestream> bytestream, + IQRouter* router); + ~IBBSendSession(); - void start(); - void stop(); + void start(); + void stop(); - const JID& getSender() const { - return from; - } + const JID& getSender() const { + return from; + } - const JID& getReceiver() const { - return to; - } + const JID& getReceiver() const { + return to; + } - void setBlockSize(unsigned int blockSize) { - this->blockSize = blockSize; - } + void setBlockSize(unsigned int blockSize) { + this->blockSize = blockSize; + } - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - boost::signal<void (size_t)> onBytesSent; + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + boost::signals2::signal<void (size_t)> onBytesSent; - private: - void handleIBBResponse(IBB::ref, ErrorPayload::ref); - void finish(boost::optional<FileTransferError>); - void sendMoreData(); - void handleDataAvailable(); + private: + void handleIBBResponse(IBB::ref, ErrorPayload::ref); + void finish(boost::optional<FileTransferError>); + void sendMoreData(); + void handleDataAvailable(); - private: - std::string id; - JID from; - JID to; - boost::shared_ptr<ReadBytestream> bytestream; - IQRouter* router; - unsigned int blockSize; - int sequenceNumber; - bool active; - bool waitingForData; - }; + private: + std::string id; + JID from; + JID to; + std::shared_ptr<ReadBytestream> bytestream; + IQRouter* router; + unsigned int blockSize; + int sequenceNumber; + bool active; + bool waitingForData; + std::shared_ptr<IBBRequest> currentRequest; + }; } diff --git a/Swiften/FileTransfer/IBBSendTransportSession.cpp b/Swiften/FileTransfer/IBBSendTransportSession.cpp new file mode 100644 index 0000000..81972c9 --- /dev/null +++ b/Swiften/FileTransfer/IBBSendTransportSession.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/IBBSendTransportSession.h> + +#include <boost/bind.hpp> + +namespace Swift { + +IBBSendTransportSession::IBBSendTransportSession(std::shared_ptr<IBBSendSession> session) : session(session) { + finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); + bytesSentConnection = session->onBytesSent.connect(boost::bind(boost::ref(onBytesSent), _1)); +} + +IBBSendTransportSession::~IBBSendTransportSession() { +} + + void IBBSendTransportSession::start() { + session->start(); +} + +void IBBSendTransportSession::stop() { + session->stop(); +} + +} diff --git a/Swiften/FileTransfer/IBBSendTransportSession.h b/Swiften/FileTransfer/IBBSendTransportSession.h new file mode 100644 index 0000000..7deaaac --- /dev/null +++ b/Swiften/FileTransfer/IBBSendTransportSession.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/FileTransfer/IBBSendSession.h> +#include <Swiften/FileTransfer/TransportSession.h> + +namespace Swift { + +class SWIFTEN_API IBBSendTransportSession : public TransportSession { + public: + IBBSendTransportSession(std::shared_ptr<IBBSendSession> session); + virtual ~IBBSendTransportSession() override; + + virtual void start() override; + virtual void stop() override; + + private: + std::shared_ptr<IBBSendSession> session; + boost::signals2::scoped_connection finishedConnection; + boost::signals2::scoped_connection bytesSentConnection; +}; + +} diff --git a/Swiften/FileTransfer/IncomingFileTransfer.cpp b/Swiften/FileTransfer/IncomingFileTransfer.cpp index 7c97e4d..9ae4767 100644 --- a/Swiften/FileTransfer/IncomingFileTransfer.cpp +++ b/Swiften/FileTransfer/IncomingFileTransfer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/IncomingFileTransfer.h> diff --git a/Swiften/FileTransfer/IncomingFileTransfer.h b/Swiften/FileTransfer/IncomingFileTransfer.h index 698a588..7236c35 100644 --- a/Swiften/FileTransfer/IncomingFileTransfer.h +++ b/Swiften/FileTransfer/IncomingFileTransfer.h @@ -1,32 +1,38 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/FileTransfer/FileTransfer.h> #include <Swiften/FileTransfer/FileTransferOptions.h> namespace Swift { - class WriteBytestream; - class JID; - - class IncomingFileTransfer : public FileTransfer { - public: - typedef boost::shared_ptr<IncomingFileTransfer> ref; - - virtual ~IncomingFileTransfer(); - - virtual void accept( - boost::shared_ptr<WriteBytestream>, - const FileTransferOptions& = FileTransferOptions()) = 0; - - virtual const JID& getSender() const = 0; - virtual const JID& getRecipient() const = 0; - }; + class WriteBytestream; + class JID; + + /** + * @brief The IncomingFileTransfer abstract class is the general interface in Swiften + * for incoming file transfers. + */ + class SWIFTEN_API IncomingFileTransfer : public FileTransfer { + public: + typedef std::shared_ptr<IncomingFileTransfer> ref; + + virtual ~IncomingFileTransfer(); + + virtual void accept( + std::shared_ptr<WriteBytestream>, + const FileTransferOptions& = FileTransferOptions()) = 0; + + virtual const JID& getSender() const = 0; + virtual const JID& getRecipient() const = 0; + }; } diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.cpp b/Swiften/FileTransfer/IncomingFileTransferManager.cpp index d40c5de..1c2b788 100644 --- a/Swiften/FileTransfer/IncomingFileTransferManager.cpp +++ b/Swiften/FileTransfer/IncomingFileTransferManager.cpp @@ -1,66 +1,65 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/IncomingFileTransferManager.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <Swiften/Base/Log.h> #include <Swiften/Elements/JingleDescription.h> #include <Swiften/Elements/JingleFileTransferDescription.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> -#include <Swiften/Jingle/JingleSessionManager.h> -#include <Swiften/Jingle/Jingle.h> #include <Swiften/FileTransfer/IncomingJingleFileTransfer.h> +#include <Swiften/Jingle/Jingle.h> +#include <Swiften/Jingle/JingleSessionManager.h> namespace Swift { IncomingFileTransferManager::IncomingFileTransferManager( - JingleSessionManager* jingleSessionManager, - IQRouter* router, - FileTransferTransporterFactory* transporterFactory, - TimerFactory* timerFactory, - CryptoProvider* crypto) : - jingleSessionManager(jingleSessionManager), - router(router), - transporterFactory(transporterFactory), - timerFactory(timerFactory), - crypto(crypto) { - jingleSessionManager->addIncomingSessionHandler(this); + JingleSessionManager* jingleSessionManager, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto) : + jingleSessionManager(jingleSessionManager), + transporterFactory(transporterFactory), + timerFactory(timerFactory), + crypto(crypto) { + jingleSessionManager->addIncomingSessionHandler(this); } IncomingFileTransferManager::~IncomingFileTransferManager() { - jingleSessionManager->removeIncomingSessionHandler(this); + jingleSessionManager->removeIncomingSessionHandler(this); } bool IncomingFileTransferManager::handleIncomingJingleSession( - JingleSession::ref session, - const std::vector<JingleContentPayload::ref>& contents, - const JID& recipient) { - if (JingleContentPayload::ref content = Jingle::getContentWithDescription<JingleFileTransferDescription>(contents)) { - if (content->getTransport<JingleS5BTransportPayload>()) { - JingleFileTransferDescription::ref description = content->getDescription<JingleFileTransferDescription>(); - if (description && description->getOffers().size() == 1) { - IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>( - recipient, session, content, transporterFactory, timerFactory, crypto); - onIncomingFileTransfer(transfer); - } - else { - std::cerr << "Received a file-transfer request with no description or more than one file!" << std::endl; - session->sendTerminate(JinglePayload::Reason::FailedApplication); - } - } - else { - session->sendTerminate(JinglePayload::Reason::UnsupportedTransports); - } - return true; - } - else { - return false; - } + JingleSession::ref session, + const std::vector<JingleContentPayload::ref>& contents, + const JID& recipient) { + if (JingleContentPayload::ref content = Jingle::getContentWithDescription<JingleFileTransferDescription>(contents)) { + if (content->getTransport<JingleS5BTransportPayload>() || content->getTransport<JingleIBBTransportPayload>()) { + JingleFileTransferDescription::ref description = content->getDescription<JingleFileTransferDescription>(); + if (description) { + IncomingJingleFileTransfer::ref transfer = std::make_shared<IncomingJingleFileTransfer>( + recipient, session, content, transporterFactory, timerFactory, crypto); + onIncomingFileTransfer(transfer); + } + else { + SWIFT_LOG(warning) << "Received a file-transfer request with no file description."; + session->sendTerminate(JinglePayload::Reason::FailedApplication); + } + } + else { + session->sendTerminate(JinglePayload::Reason::UnsupportedTransports); + } + return true; + } + else { + return false; + } } diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.h b/Swiften/FileTransfer/IncomingFileTransferManager.h index 9570def..a0cce10 100644 --- a/Swiften/FileTransfer/IncomingFileTransferManager.h +++ b/Swiften/FileTransfer/IncomingFileTransferManager.h @@ -1,47 +1,46 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/FileTransfer/IncomingFileTransfer.h> #include <Swiften/Jingle/IncomingJingleSessionHandler.h> namespace Swift { - class IQRouter; - class JingleSessionManager; - class FileTransferTransporterFactory; - class TimerFactory; - class CryptoProvider; - - class IncomingFileTransferManager : public IncomingJingleSessionHandler { - public: - IncomingFileTransferManager( - JingleSessionManager* jingleSessionManager, - IQRouter* router, - FileTransferTransporterFactory* transporterFactory, - TimerFactory* timerFactory, - CryptoProvider* crypto); - ~IncomingFileTransferManager(); - - boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer; - - private: - bool handleIncomingJingleSession( - JingleSession::ref session, - const std::vector<JingleContentPayload::ref>& contents, - const JID& recipient); - - private: - JingleSessionManager* jingleSessionManager; - IQRouter* router; - FileTransferTransporterFactory* transporterFactory; - TimerFactory* timerFactory; - CryptoProvider* crypto; - }; + class JingleSessionManager; + class FileTransferTransporterFactory; + class TimerFactory; + class CryptoProvider; + + class SWIFTEN_API IncomingFileTransferManager : public IncomingJingleSessionHandler { + public: + IncomingFileTransferManager( + JingleSessionManager* jingleSessionManager, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto); + virtual ~IncomingFileTransferManager(); + + boost::signals2::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer; + + private: + bool handleIncomingJingleSession( + JingleSession::ref session, + const std::vector<JingleContentPayload::ref>& contents, + const JID& recipient); + + private: + JingleSessionManager* jingleSessionManager; + FileTransferTransporterFactory* transporterFactory; + TimerFactory* timerFactory; + CryptoProvider* crypto; + }; } diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp index b64e333..7c46c60 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp @@ -1,394 +1,419 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/IncomingJingleFileTransfer.h> +#include <memory> +#include <set> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Jingle/JingleSession.h> +#include <Swiften/Elements/JingleFileTransferDescription.h> +#include <Swiften/Elements/JingleFileTransferHash.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> -#include <Swiften/Elements/JingleFileTransferHash.h> -#include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> #include <Swiften/FileTransfer/FileTransferTransporter.h> #include <Swiften/FileTransfer/FileTransferTransporterFactory.h> +#include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h> +#include <Swiften/FileTransfer/TransportSession.h> #include <Swiften/FileTransfer/WriteBytestream.h> -#include <Swiften/Elements/JingleFileTransferDescription.h> +#include <Swiften/Jingle/JingleSession.h> #include <Swiften/Network/TimerFactory.h> #include <Swiften/Queries/GenericRequest.h> -#include <Swiften/FileTransfer/TransportSession.h> +#include <Swiften/StringCodecs/Base64.h> using namespace Swift; // TODO: ALlow terminate when already terminated. IncomingJingleFileTransfer::IncomingJingleFileTransfer( - const JID& toJID, - JingleSession::ref session, - JingleContentPayload::ref content, - FileTransferTransporterFactory* transporterFactory, - TimerFactory* timerFactory, - CryptoProvider* crypto) : - JingleFileTransfer(session, toJID, transporterFactory), - initialContent(content), - crypto(crypto), - state(Initial), - receivedBytes(0), - hashCalculator(NULL) { - description = initialContent->getDescription<JingleFileTransferDescription>(); - assert(description); - assert(description->getOffers().size() == 1); - StreamInitiationFileInfo fileInfo = description->getOffers().front(); - setFileInfo(fileInfo.getName(), fileInfo.getSize()); - hash = fileInfo.getHash(); - hashAlgorithm = fileInfo.getAlgo(); - - waitOnHashTimer = timerFactory->createTimer(5000); - waitOnHashTimerTickedConnection = waitOnHashTimer->onTick.connect( - boost::bind(&IncomingJingleFileTransfer::handleWaitOnHashTimerTicked, this)); + const JID& toJID, + JingleSession::ref session, + JingleContentPayload::ref content, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto) : + JingleFileTransfer(session, toJID, transporterFactory), + initialContent(content), + crypto(crypto), + state(Initial), + receivedBytes(0), + hashCalculator(nullptr) { + description = initialContent->getDescription<JingleFileTransferDescription>(); + assert(description); + JingleFileTransferFileInfo fileInfo = description->getFileInfo(); + setFileInfo(fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription()); + hashes = fileInfo.getHashes(); + + waitOnHashTimer = timerFactory->createTimer(5000); + waitOnHashTimerTickedConnection = waitOnHashTimer->onTick.connect( + boost::bind(&IncomingJingleFileTransfer::handleWaitOnHashTimerTicked, this)); } IncomingJingleFileTransfer::~IncomingJingleFileTransfer() { + if (waitOnHashTimer) { + waitOnHashTimer->stop(); + } + + delete hashCalculator; + hashCalculator = nullptr; } void IncomingJingleFileTransfer::accept( - boost::shared_ptr<WriteBytestream> stream, - const FileTransferOptions& options) { - SWIFT_LOG(debug) << std::endl; - if (state != Initial) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - assert(!this->stream); - this->stream = stream; - this->options = options; - - assert(!hashCalculator); - hashCalculator = new IncrementalBytestreamHashCalculator( - hashAlgorithm == "md5" || hash.empty(), hashAlgorithm == "sha-1" || hash.empty(), crypto); - - writeStreamDataReceivedConnection = stream->onWrite.connect( - boost::bind(&IncomingJingleFileTransfer::handleWriteStreamDataReceived, this, _1)); - - if (JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>()) { - SWIFT_LOG(debug) << "Got S5B transport payload!" << std::endl; - setTransporter(transporterFactory->createResponderTransporter( - getInitiator(), getResponder(), s5bTransport->getSessionID())); - transporter->addRemoteCandidates(s5bTransport->getCandidates()); - setState(GeneratingInitialLocalCandidates); - transporter->startGeneratingLocalCandidates(); - } - else { - // Can't happen, because the transfer would have been rejected automatically - assert(false); - } + std::shared_ptr<WriteBytestream> stream, + const FileTransferOptions& options) { + SWIFT_LOG(debug); + if (state != Initial) { SWIFT_LOG(warning) << "Incorrect state"; return; } + + assert(!this->stream); + this->stream = stream; + this->options = options; + + assert(!hashCalculator); + + hashCalculator = new IncrementalBytestreamHashCalculator( + hashes.find("md5") != hashes.end(), hashes.find("sha-1") != hashes.end(), crypto); + + writeStreamDataReceivedConnection = stream->onWrite.connect( + boost::bind(&IncomingJingleFileTransfer::handleWriteStreamDataReceived, this, _1)); + + JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>(); + JingleIBBTransportPayload::ref ibbTransport = initialContent->getTransport<JingleIBBTransportPayload>(); + if (s5bTransport) { + SWIFT_LOG(debug) << "Got S5B transport as initial payload."; + setTransporter(transporterFactory->createResponderTransporter( + getInitiator(), getResponder(), s5bTransport->getSessionID(), options)); + transporter->addRemoteCandidates(s5bTransport->getCandidates(), s5bTransport->getDstAddr()); + setState(GeneratingInitialLocalCandidates); + transporter->startGeneratingLocalCandidates(); + } + else if (ibbTransport && options.isInBandAllowed()) { + SWIFT_LOG(debug) << "Got IBB transport as initial payload."; + setTransporter(transporterFactory->createResponderTransporter( + getInitiator(), getResponder(), ibbTransport->getSessionID(), options)); + + startTransferring(transporter->createIBBReceiveSession( + ibbTransport->getSessionID(), + description->getFileInfo().getSize(), + stream)); + + session->sendAccept(getContentID(), initialContent->getDescriptions()[0], ibbTransport); + } + else { + // This might happen on incoming transfer which only list transport methods we are not allowed to use due to file-transfer options. + session->sendTerminate(JinglePayload::Reason::UnsupportedTransports); + setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); + } } void IncomingJingleFileTransfer::cancel() { - SWIFT_LOG(debug) << std::endl; - terminate(state == Initial ? JinglePayload::Reason::Decline : JinglePayload::Reason::Cancel); + SWIFT_LOG(debug); + terminate(state == Initial ? JinglePayload::Reason::Decline : JinglePayload::Reason::Cancel); } void IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated( - const std::string& s5bSessionID, - const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - SWIFT_LOG(debug) << std::endl; - if (state != GeneratingInitialLocalCandidates) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } + const std::string& s5bSessionID, + const std::vector<JingleS5BTransportPayload::Candidate>& candidates, + const std::string& dstAddr) { + SWIFT_LOG(debug); + if (state != GeneratingInitialLocalCandidates) { SWIFT_LOG(warning) << "Incorrect state"; return; } - fillCandidateMap(localCandidates, candidates); + fillCandidateMap(localCandidates, candidates); - JingleS5BTransportPayload::ref transport = boost::make_shared<JingleS5BTransportPayload>(); - transport->setSessionID(s5bSessionID); - transport->setMode(JingleS5BTransportPayload::TCPMode); - foreach(JingleS5BTransportPayload::Candidate candidate, candidates) { - transport->addCandidate(candidate); - } - session->sendAccept(getContentID(), initialContent->getDescriptions()[0], transport); + JingleS5BTransportPayload::ref transport = std::make_shared<JingleS5BTransportPayload>(); + transport->setSessionID(s5bSessionID); + transport->setMode(JingleS5BTransportPayload::TCPMode); + transport->setDstAddr(dstAddr); + for (auto&& candidate : candidates) { + transport->addCandidate(candidate); + } + session->sendAccept(getContentID(), initialContent->getDescriptions()[0], transport); - setState(TryingCandidates); - transporter->startTryingRemoteCandidates(); + setState(TryingCandidates); + transporter->startTryingRemoteCandidates(); } void IncomingJingleFileTransfer::handleSessionInfoReceived(JinglePayload::ref jinglePayload) { - SWIFT_LOG(debug) << std::endl; - - JingleFileTransferHash::ref transferHash = jinglePayload->getPayload<JingleFileTransferHash>(); - if (transferHash) { - SWIFT_LOG(debug) << "Received hash information." << std::endl; - waitOnHashTimer->stop(); - if (transferHash->getHashes().find("sha-1") != transferHash->getHashes().end()) { - hashAlgorithm = "sha-1"; - hash = transferHash->getHashes().find("sha-1")->second; - } - else if (transferHash->getHashes().find("md5") != transferHash->getHashes().end()) { - hashAlgorithm = "md5"; - hash = transferHash->getHashes().find("md5")->second; - } - if (state == WaitingForHash) { - checkHashAndTerminate(); - } - } - else { - SWIFT_LOG(debug) << "Ignoring unknown session info" << std::endl; - } + SWIFT_LOG(debug); + + JingleFileTransferHash::ref transferHash = jinglePayload->getPayload<JingleFileTransferHash>(); + if (transferHash) { + SWIFT_LOG(debug) << "Received hash information."; + waitOnHashTimer->stop(); + if (transferHash->getFileInfo().getHashes().find("sha-1") != transferHash->getFileInfo().getHashes().end()) { + hashes["sha-1"] = transferHash->getFileInfo().getHash("sha-1").get(); + } + if (transferHash->getFileInfo().getHashes().find("md5") != transferHash->getFileInfo().getHashes().end()) { + hashes["md5"] = transferHash->getFileInfo().getHash("md5").get(); + } + if (state == WaitingForHash) { + checkHashAndTerminate(); + } + } + else { + SWIFT_LOG(debug) << "Ignoring unknown session info"; + } } void IncomingJingleFileTransfer::handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason) { - SWIFT_LOG(debug) << std::endl; - if (state == Finished) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - if (state == Finished) { - SWIFT_LOG(debug) << "Already terminated" << std::endl; - return; - } - - stopAll(); - if (reason && reason->type == JinglePayload::Reason::Cancel) { - setFinishedState(FileTransfer::State::Canceled, FileTransferError(FileTransferError::PeerError)); - } - else if (reason && reason->type == JinglePayload::Reason::Success) { - setFinishedState(FileTransfer::State::Finished, boost::optional<FileTransferError>()); - } - else { - setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); - } + SWIFT_LOG(debug); + if (state == Finished) { SWIFT_LOG(warning) << "Incorrect state"; return; } + + if (state == Finished) { + SWIFT_LOG(debug) << "Already terminated"; + return; + } + + stopAll(); + if (reason && reason->type == JinglePayload::Reason::Cancel) { + setFinishedState(FileTransfer::State::Canceled, FileTransferError(FileTransferError::PeerError)); + } + else if (reason && reason->type == JinglePayload::Reason::Success) { + setFinishedState(FileTransfer::State::Finished, boost::optional<FileTransferError>()); + } + else { + setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); + } } void IncomingJingleFileTransfer::checkHashAndTerminate() { - if (verifyData()) { - terminate(JinglePayload::Reason::Success); - } - else { - SWIFT_LOG(warning) << "Hash verification failed" << std::endl; - terminate(JinglePayload::Reason::MediaError); - } + if (verifyData()) { + terminate(JinglePayload::Reason::Success); + } + else { + SWIFT_LOG(warning) << "Hash verification failed"; + terminate(JinglePayload::Reason::MediaError); + } } void IncomingJingleFileTransfer::checkIfAllDataReceived() { - if (receivedBytes == getFileSizeInBytes()) { - SWIFT_LOG(debug) << "All data received." << std::endl; - if (hash.empty()) { - SWIFT_LOG(debug) << "No hash information yet. Waiting a while on hash info." << std::endl; - setState(WaitingForHash); - waitOnHashTimer->start(); - } - else { - checkHashAndTerminate(); - } - } - else if (receivedBytes > getFileSizeInBytes()) { - SWIFT_LOG(debug) << "We got more than we could handle!" << std::endl; - terminate(JinglePayload::Reason::MediaError); - } + if (receivedBytes == getFileSizeInBytes()) { + SWIFT_LOG(debug) << "All data received."; + bool hashInfoAvailable = false; + for (const auto& hashElement : hashes) { + hashInfoAvailable |= !hashElement.second.empty(); + } + + if (!hashInfoAvailable) { + SWIFT_LOG(debug) << "No hash information yet. Waiting a while on hash info."; + setState(WaitingForHash); + waitOnHashTimer->start(); + } + else { + checkHashAndTerminate(); + } + } + else if (receivedBytes > getFileSizeInBytes()) { + SWIFT_LOG(debug) << "We got more than we could handle!"; + terminate(JinglePayload::Reason::MediaError); + } } void IncomingJingleFileTransfer::handleWriteStreamDataReceived( - const std::vector<unsigned char>& data) { - hashCalculator->feedData(data); - receivedBytes += data.size(); - checkIfAllDataReceived(); + const std::vector<unsigned char>& data) { + hashCalculator->feedData(data); + receivedBytes += data.size(); + onProcessedBytes(data.size()); + checkIfAllDataReceived(); } void IncomingJingleFileTransfer::handleTransportReplaceReceived( - const JingleContentID& content, JingleTransportPayload::ref transport) { - SWIFT_LOG(debug) << std::endl; - if (state != WaitingForFallbackOrTerminate) { - SWIFT_LOG(warning) << "Incorrect state" << std::endl; - return; - } - - if (JingleIBBTransportPayload::ref ibbTransport = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transport)) { - SWIFT_LOG(debug) << "transport replaced with IBB" << std::endl; - - startTransferring(transporter->createIBBReceiveSession( - ibbTransport->getSessionID(), - description->getOffers()[0].getSize(), - stream)); - session->sendTransportAccept(content, ibbTransport); - } - else { - SWIFT_LOG(debug) << "Unknown replace transport" << std::endl; - session->sendTransportReject(content, transport); - } + const JingleContentID& content, JingleTransportPayload::ref transport) { + SWIFT_LOG(debug); + if (state != WaitingForFallbackOrTerminate) { + SWIFT_LOG(warning) << "Incorrect state"; + return; + } + + JingleIBBTransportPayload::ref ibbTransport; + if (options.isInBandAllowed() && (ibbTransport = std::dynamic_pointer_cast<JingleIBBTransportPayload>(transport))) { + SWIFT_LOG(debug) << "transport replaced with IBB"; + + startTransferring(transporter->createIBBReceiveSession( + ibbTransport->getSessionID(), + description->getFileInfo().getSize(), + stream)); + session->sendTransportAccept(content, ibbTransport); + } + else { + SWIFT_LOG(debug) << "Unknown replace transport"; + session->sendTransportReject(content, transport); + } } JingleContentID IncomingJingleFileTransfer::getContentID() const { - return JingleContentID(initialContent->getName(), initialContent->getCreator()); + return JingleContentID(initialContent->getName(), initialContent->getCreator()); } bool IncomingJingleFileTransfer::verifyData() { - if (hashAlgorithm.empty() || hash.empty()) { - SWIFT_LOG(debug) << "no verification possible, skipping" << std::endl; - return true; - } - if (hashAlgorithm == "sha-1") { - SWIFT_LOG(debug) << "Verify SHA-1 hash: " << (hash == hashCalculator->getSHA1String()) << std::endl; - return hash == hashCalculator->getSHA1String(); - } - else if (hashAlgorithm == "md5") { - SWIFT_LOG(debug) << "Verify MD5 hash: " << (hash == hashCalculator->getMD5String()) << std::endl; - return hash == hashCalculator->getMD5String(); - } - else { - SWIFT_LOG(debug) << "Unknown hash, skipping" << std::endl; - return true; - } + if (hashes.empty()) { + SWIFT_LOG(debug) << "no verification possible, skipping"; + return true; + } + if (hashes.find("sha-1") != hashes.end()) { + SWIFT_LOG(debug) << "Verify SHA-1 hash: " << (hashes["sha-1"] == hashCalculator->getSHA1Hash()); + return hashes["sha-1"] == hashCalculator->getSHA1Hash(); + } + else if (hashes.find("md5") != hashes.end()) { + SWIFT_LOG(debug) << "Verify MD5 hash: " << (hashes["md5"] == hashCalculator->getMD5Hash()); + return hashes["md5"] == hashCalculator->getMD5Hash(); + } + else { + SWIFT_LOG(debug) << "Unknown hash, skipping"; + return true; + } } void IncomingJingleFileTransfer::handleWaitOnHashTimerTicked() { - SWIFT_LOG(debug) << std::endl; - waitOnHashTimer->stop(); - terminate(JinglePayload::Reason::Success); + SWIFT_LOG(debug); + waitOnHashTimer->stop(); + terminate(JinglePayload::Reason::Success); } const JID& IncomingJingleFileTransfer::getSender() const { - return getInitiator(); + return getInitiator(); } const JID& IncomingJingleFileTransfer::getRecipient() const { - return getResponder(); + return getResponder(); } void IncomingJingleFileTransfer::setState(State state) { - SWIFT_LOG(debug) << state << std::endl; - this->state = state; - onStateChanged(FileTransfer::State(getExternalState(state))); + SWIFT_LOG(debug) << state; + this->state = state; + onStateChanged(FileTransfer::State(getExternalState(state))); } void IncomingJingleFileTransfer::setFinishedState( - FileTransfer::State::Type type, const boost::optional<FileTransferError>& error) { - SWIFT_LOG(debug) << std::endl; - this->state = Finished; - onStateChanged(type); - onFinished(error); + FileTransfer::State::Type type, const boost::optional<FileTransferError>& error) { + SWIFT_LOG(debug); + this->state = Finished; + onStateChanged(type); + onFinished(error); } void IncomingJingleFileTransfer::handleTransferFinished(boost::optional<FileTransferError> error) { - if (error && state != WaitingForHash) { - terminate(JinglePayload::Reason::MediaError); - } + if (error && state != WaitingForHash) { + terminate(JinglePayload::Reason::MediaError); + } } FileTransfer::State::Type IncomingJingleFileTransfer::getExternalState(State state) { - switch (state) { - case Initial: return FileTransfer::State::Initial; - case GeneratingInitialLocalCandidates: return FileTransfer::State::WaitingForStart; - case TryingCandidates: return FileTransfer::State::Negotiating; - case WaitingForPeerProxyActivate: return FileTransfer::State::Negotiating; - case WaitingForLocalProxyActivate: return FileTransfer::State::Negotiating; - case WaitingForFallbackOrTerminate: return FileTransfer::State::Negotiating; - case Transferring: return FileTransfer::State::Transferring; - case WaitingForHash: return FileTransfer::State::Transferring; - case Finished: return FileTransfer::State::Finished; - } - assert(false); - return FileTransfer::State::Initial; + switch (state) { + case Initial: return FileTransfer::State::Initial; + case GeneratingInitialLocalCandidates: return FileTransfer::State::WaitingForStart; + case TryingCandidates: return FileTransfer::State::Negotiating; + case WaitingForPeerProxyActivate: return FileTransfer::State::Negotiating; + case WaitingForLocalProxyActivate: return FileTransfer::State::Negotiating; + case WaitingForFallbackOrTerminate: return FileTransfer::State::Negotiating; + case Transferring: return FileTransfer::State::Transferring; + case WaitingForHash: return FileTransfer::State::Transferring; + case Finished: return FileTransfer::State::Finished; + } + assert(false); + return FileTransfer::State::Initial; } void IncomingJingleFileTransfer::stopAll() { - if (state != Initial) { - writeStreamDataReceivedConnection.disconnect(); - delete hashCalculator; - } - switch (state) { - case Initial: break; - case GeneratingInitialLocalCandidates: transporter->stopGeneratingLocalCandidates(); break; - case TryingCandidates: transporter->stopTryingRemoteCandidates(); break; - case WaitingForFallbackOrTerminate: break; - case WaitingForPeerProxyActivate: break; - case WaitingForLocalProxyActivate: transporter->stopActivatingProxy(); break; - case WaitingForHash: // Fallthrough - case Transferring: - assert(transportSession); - transferFinishedConnection.disconnect(); - transportSession->stop(); - transportSession.reset(); - break; - case Finished: SWIFT_LOG(warning) << "Already finished" << std::endl; break; - } - if (state != Initial) { - delete transporter; - } + if (state != Initial) { + writeStreamDataReceivedConnection.disconnect(); + delete hashCalculator; + hashCalculator = nullptr; + } + switch (state) { + case Initial: break; + case GeneratingInitialLocalCandidates: transporter->stopGeneratingLocalCandidates(); break; + case TryingCandidates: transporter->stopTryingRemoteCandidates(); break; + case WaitingForFallbackOrTerminate: break; + case WaitingForPeerProxyActivate: break; + case WaitingForLocalProxyActivate: transporter->stopActivatingProxy(); break; + case WaitingForHash: // Fallthrough + case Transferring: + assert(transportSession); + transferFinishedConnection.disconnect(); + transportSession->stop(); + transportSession.reset(); + break; + case Finished: SWIFT_LOG(warning) << "Already finished"; break; + } + if (state != Initial) { + removeTransporter(); + } } bool IncomingJingleFileTransfer::hasPriorityOnCandidateTie() const { - return false; + return false; } void IncomingJingleFileTransfer::fallback() { - if (options.isInBandAllowed()) { - setState(WaitingForFallbackOrTerminate); - } - else { - terminate(JinglePayload::Reason::ConnectivityError); - } + setState(WaitingForFallbackOrTerminate); } void IncomingJingleFileTransfer::startTransferViaRemoteCandidate() { - SWIFT_LOG(debug) << std::endl; + SWIFT_LOG(debug); - if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { - setState(WaitingForPeerProxyActivate); - } - else { - startTransferring(createRemoteCandidateSession()); - } + if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setState(WaitingForPeerProxyActivate); + } + else { + startTransferring(createRemoteCandidateSession()); + } } void IncomingJingleFileTransfer::startTransferViaLocalCandidate() { - SWIFT_LOG(debug) << std::endl; + SWIFT_LOG(debug); - if (theirCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { - setState(WaitingForLocalProxyActivate); - transporter->startActivatingProxy(theirCandidateChoice->jid); - } - else { - startTransferring(createLocalCandidateSession()); - } + if (theirCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setState(WaitingForLocalProxyActivate); + transporter->startActivatingProxy(theirCandidateChoice->jid); + } + else { + startTransferring(createLocalCandidateSession()); + } } +void IncomingJingleFileTransfer::startTransferring(std::shared_ptr<TransportSession> transportSession) { + SWIFT_LOG(debug); -void IncomingJingleFileTransfer::startTransferring(boost::shared_ptr<TransportSession> transportSession) { - SWIFT_LOG(debug) << std::endl; - - this->transportSession = transportSession; - transferFinishedConnection = transportSession->onFinished.connect( - boost::bind(&IncomingJingleFileTransfer::handleTransferFinished, this, _1)); - setState(Transferring); - transportSession->start(); + this->transportSession = transportSession; + transferFinishedConnection = transportSession->onFinished.connect( + boost::bind(&IncomingJingleFileTransfer::handleTransferFinished, this, _1)); + setState(Transferring); + transportSession->start(); } bool IncomingJingleFileTransfer::isWaitingForPeerProxyActivate() const { - return state == WaitingForPeerProxyActivate; + return state == WaitingForPeerProxyActivate; } bool IncomingJingleFileTransfer::isWaitingForLocalProxyActivate() const { - return state == WaitingForLocalProxyActivate; + return state == WaitingForLocalProxyActivate; } bool IncomingJingleFileTransfer::isTryingCandidates() const { - return state == TryingCandidates; + return state == TryingCandidates; } -boost::shared_ptr<TransportSession> IncomingJingleFileTransfer::createLocalCandidateSession() { - return transporter->createLocalCandidateSession(stream); +std::shared_ptr<TransportSession> IncomingJingleFileTransfer::createLocalCandidateSession() { + return transporter->createLocalCandidateSession(stream, theirCandidateChoice.get()); } -boost::shared_ptr<TransportSession> IncomingJingleFileTransfer::createRemoteCandidateSession() { - return transporter->createRemoteCandidateSession(stream); +std::shared_ptr<TransportSession> IncomingJingleFileTransfer::createRemoteCandidateSession() { + return transporter->createRemoteCandidateSession(stream, ourCandidateChoice.get()); } void IncomingJingleFileTransfer::terminate(JinglePayload::Reason::Type reason) { - SWIFT_LOG(debug) << reason << std::endl; + SWIFT_LOG(debug) << reason; - if (state != Finished) { - session->sendTerminate(reason); - } - stopAll(); - setFinishedState(getExternalFinishedState(reason), getFileTransferError(reason)); + if (state != Finished) { + session->sendTerminate(reason); + } + stopAll(); + setFinishedState(getExternalFinishedState(reason), getFileTransferError(reason)); } diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.h b/Swiften/FileTransfer/IncomingJingleFileTransfer.h index a691d5b..f42004d 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.h +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.h @@ -1,119 +1,126 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/cstdint.hpp> +#include <memory> #include <string> +#include <boost/cstdint.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/Override.h> -#include <Swiften/Jingle/JingleContentID.h> -#include <Swiften/FileTransfer/IncomingFileTransfer.h> -#include <Swiften/FileTransfer/JingleFileTransfer.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/FileTransfer/FileTransferOptions.h> +#include <Swiften/FileTransfer/IncomingFileTransfer.h> +#include <Swiften/FileTransfer/JingleFileTransfer.h> +#include <Swiften/Jingle/JingleContentID.h> namespace Swift { - class JID; - class JingleSession; - class JingleContentPayload; - class FileTransferTransporter; - class FileTransferTransporterFactory; - class TimerFactory; - class Timer; - class CryptoProvider; - class IncrementalBytestreamHashCalculator; - class JingleFileTransferDescription; - - class SWIFTEN_API IncomingJingleFileTransfer : public IncomingFileTransfer, public JingleFileTransfer { - public: - typedef boost::shared_ptr<IncomingJingleFileTransfer> ref; - - IncomingJingleFileTransfer( - const JID& recipient, - boost::shared_ptr<JingleSession>, - boost::shared_ptr<JingleContentPayload> content, - FileTransferTransporterFactory*, - TimerFactory*, - CryptoProvider*); - ~IncomingJingleFileTransfer(); - - virtual void accept(boost::shared_ptr<WriteBytestream>, const FileTransferOptions&) SWIFTEN_OVERRIDE; - void cancel(); - - private: - enum State { - Initial, - GeneratingInitialLocalCandidates, - TryingCandidates, - WaitingForPeerProxyActivate, - WaitingForLocalProxyActivate, - WaitingForFallbackOrTerminate, - Transferring, - WaitingForHash, - Finished - }; - - virtual void handleSessionTerminateReceived( - boost::optional<JinglePayload::Reason> reason) SWIFTEN_OVERRIDE; - virtual void handleSessionInfoReceived(boost::shared_ptr<JinglePayload>) SWIFTEN_OVERRIDE; - virtual void handleTransportReplaceReceived( - const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; - - virtual void handleLocalTransportCandidatesGenerated( - const std::string& s5bSessionID, - const std::vector<JingleS5BTransportPayload::Candidate>&) SWIFTEN_OVERRIDE; - - void handleWriteStreamDataReceived(const std::vector<unsigned char>& data); - void stopActiveTransport(); - void checkCandidateSelected(); - virtual JingleContentID getContentID() const SWIFTEN_OVERRIDE; - void checkIfAllDataReceived(); - bool verifyData(); - void handleWaitOnHashTimerTicked(); - void handleTransferFinished(boost::optional<FileTransferError>); - - private: - void startTransferViaRemoteCandidate(); - void startTransferViaLocalCandidate(); - void checkHashAndTerminate(); - void stopAll(); - void setState(State state); - void setFinishedState(FileTransfer::State::Type, const boost::optional<FileTransferError>& error); - const JID& getSender() const SWIFTEN_OVERRIDE; - const JID& getRecipient() const SWIFTEN_OVERRIDE; - static FileTransfer::State::Type getExternalState(State state); - virtual bool hasPriorityOnCandidateTie() const SWIFTEN_OVERRIDE; - virtual void fallback() SWIFTEN_OVERRIDE; - virtual void startTransferring(boost::shared_ptr<TransportSession>) SWIFTEN_OVERRIDE; - virtual bool isWaitingForPeerProxyActivate() const SWIFTEN_OVERRIDE; - virtual bool isWaitingForLocalProxyActivate() const SWIFTEN_OVERRIDE; - virtual bool isTryingCandidates() const SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession() SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession() SWIFTEN_OVERRIDE; - virtual void terminate(JinglePayload::Reason::Type reason) SWIFTEN_OVERRIDE; - - - private: - boost::shared_ptr<JingleContentPayload> initialContent; - CryptoProvider* crypto; - State state; - boost::shared_ptr<JingleFileTransferDescription> description; - boost::shared_ptr<WriteBytestream> stream; - boost::uintmax_t receivedBytes; - IncrementalBytestreamHashCalculator* hashCalculator; - boost::shared_ptr<Timer> waitOnHashTimer; - std::string hashAlgorithm; - std::string hash; - FileTransferOptions options; - - boost::bsignals::scoped_connection writeStreamDataReceivedConnection; - boost::bsignals::scoped_connection waitOnHashTimerTickedConnection; - boost::bsignals::connection transferFinishedConnection; - }; + class CryptoProvider; + class FileTransferTransporterFactory; + class IncrementalBytestreamHashCalculator; + class JID; + class JingleContentPayload; + class JingleFileTransferDescription; + class JingleSession; + class Timer; + class TimerFactory; + + /** + * @brief The IncomingJingleFileTransfer class contains the business logic for managing incoming + * Jingle file transfers. + * + * Calling IncomingJingleFileTransfer::accept will start to negotiate possible transfer + * methods and after a working method has been decided among peers the trasnfer is started. + */ + class SWIFTEN_API IncomingJingleFileTransfer : public IncomingFileTransfer, public JingleFileTransfer { + public: + typedef std::shared_ptr<IncomingJingleFileTransfer> ref; + + IncomingJingleFileTransfer( + const JID& recipient, + std::shared_ptr<JingleSession>, + std::shared_ptr<JingleContentPayload> content, + FileTransferTransporterFactory*, + TimerFactory*, + CryptoProvider*); + virtual ~IncomingJingleFileTransfer() override; + + virtual void accept(std::shared_ptr<WriteBytestream>, const FileTransferOptions& = FileTransferOptions()) override; + virtual void cancel() override; + + private: + enum State { + Initial, + GeneratingInitialLocalCandidates, + TryingCandidates, + WaitingForPeerProxyActivate, + WaitingForLocalProxyActivate, + WaitingForFallbackOrTerminate, + Transferring, + WaitingForHash, + Finished + }; + + virtual void handleSessionTerminateReceived( + boost::optional<JinglePayload::Reason> reason) override; + virtual void handleSessionInfoReceived(std::shared_ptr<JinglePayload>) override; + virtual void handleTransportReplaceReceived( + const JingleContentID&, std::shared_ptr<JingleTransportPayload>) override; + + virtual void handleLocalTransportCandidatesGenerated( + const std::string& s5bSessionID, + const std::vector<JingleS5BTransportPayload::Candidate>&, + const std::string& dstAddr) override; + + void handleWriteStreamDataReceived(const std::vector<unsigned char>& data); + void stopActiveTransport(); + void checkCandidateSelected(); + virtual JingleContentID getContentID() const override; + void checkIfAllDataReceived(); + bool verifyData(); + void handleWaitOnHashTimerTicked(); + void handleTransferFinished(boost::optional<FileTransferError>); + + private: + virtual void startTransferViaRemoteCandidate() override; + virtual void startTransferViaLocalCandidate() override; + void checkHashAndTerminate(); + void stopAll(); + void setState(State state); + void setFinishedState(FileTransfer::State::Type, const boost::optional<FileTransferError>& error); + const JID& getSender() const override; + const JID& getRecipient() const override; + static FileTransfer::State::Type getExternalState(State state); + virtual bool hasPriorityOnCandidateTie() const override; + virtual void fallback() override; + virtual void startTransferring(std::shared_ptr<TransportSession>) override; + virtual bool isWaitingForPeerProxyActivate() const override; + virtual bool isWaitingForLocalProxyActivate() const override; + virtual bool isTryingCandidates() const override; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession() override; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession() override; + virtual void terminate(JinglePayload::Reason::Type reason) override; + + + private: + std::shared_ptr<JingleContentPayload> initialContent; + CryptoProvider* crypto; + State state; + std::shared_ptr<JingleFileTransferDescription> description; + std::shared_ptr<WriteBytestream> stream; + boost::uintmax_t receivedBytes; + IncrementalBytestreamHashCalculator* hashCalculator; + std::shared_ptr<Timer> waitOnHashTimer; + std::map<std::string, ByteArray> hashes; + FileTransferOptions options; + + boost::signals2::scoped_connection writeStreamDataReceivedConnection; + boost::signals2::scoped_connection waitOnHashTimerTickedConnection; + boost::signals2::connection transferFinishedConnection; + }; } diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp index 601a97f..faddcb9 100644 --- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp +++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp @@ -5,61 +5,71 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h> -#include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/StringCodecs/Hexify.h> namespace Swift { IncrementalBytestreamHashCalculator::IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1, CryptoProvider* crypto) { - md5Hasher = doMD5 ? crypto->createMD5() : NULL; - sha1Hasher = doSHA1 ? crypto->createSHA1() : NULL; + md5Hasher = doMD5 ? crypto->createMD5() : nullptr; + sha1Hasher = doSHA1 ? crypto->createSHA1() : nullptr; } IncrementalBytestreamHashCalculator::~IncrementalBytestreamHashCalculator() { - delete md5Hasher; - delete sha1Hasher; + delete md5Hasher; + delete sha1Hasher; } void IncrementalBytestreamHashCalculator::feedData(const ByteArray& data) { - if (md5Hasher) { - md5Hasher->update(data); - } - if (sha1Hasher) { - sha1Hasher->update(data); - } + if (md5Hasher) { + md5Hasher->update(data); + } + if (sha1Hasher) { + sha1Hasher->update(data); + } } /* void IncrementalBytestreamHashCalculator::feedData(const SafeByteArray& data) { - if (md5Hasher) { - md5Hasher->update(createByteArray(data.data(), data.size())); - } - if (sha1Hasher) { - sha1Hasher->update(createByteArray(data.data(), data.size())); - } + if (md5Hasher) { + md5Hasher->update(createByteArray(data.data(), data.size())); + } + if (sha1Hasher) { + sha1Hasher->update(createByteArray(data.data(), data.size())); + } }*/ +ByteArray IncrementalBytestreamHashCalculator::getSHA1Hash() { + assert(sha1Hasher); + if (!sha1Hash) { + sha1Hash = sha1Hasher->getHash(); + } + return *sha1Hash; +} + +ByteArray IncrementalBytestreamHashCalculator::getMD5Hash() { + assert(md5Hasher); + if (!md5Hash) { + md5Hash = md5Hasher->getHash(); + } + return *md5Hash; +} + std::string IncrementalBytestreamHashCalculator::getSHA1String() { - assert(sha1Hasher); - if (!sha1Hash) { - sha1Hash = Hexify::hexify(sha1Hasher->getHash()); - } - return *sha1Hash; + assert(sha1Hasher); + return Hexify::hexify(getSHA1Hash()); } std::string IncrementalBytestreamHashCalculator::getMD5String() { - assert(md5Hasher); - if (!md5Hash) { - md5Hash = Hexify::hexify(md5Hasher->getHash()); - } - return *md5Hash; + assert(md5Hasher); + return Hexify::hexify(getMD5Hash()); } } diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h index 7b4e124..4477ec1 100644 --- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h +++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h @@ -5,8 +5,8 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -14,30 +14,34 @@ #include <string> +#include <boost/optional.hpp> + #include <Swiften/Base/ByteArray.h> #include <Swiften/Base/SafeByteArray.h> -#include <boost/optional.hpp> namespace Swift { - class Hash; - class CryptoProvider; - - class IncrementalBytestreamHashCalculator { - public: - IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1, CryptoProvider* crypto); - ~IncrementalBytestreamHashCalculator(); - - void feedData(const ByteArray& data); - //void feedData(const SafeByteArray& data); - - std::string getSHA1String(); - std::string getMD5String(); - - private: - Hash* md5Hasher; - Hash* sha1Hasher; - boost::optional<std::string> md5Hash; - boost::optional<std::string> sha1Hash; - }; + class Hash; + class CryptoProvider; + + class IncrementalBytestreamHashCalculator { + public: + IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1, CryptoProvider* crypto); + ~IncrementalBytestreamHashCalculator(); + + void feedData(const ByteArray& data); + //void feedData(const SafeByteArray& data); + + ByteArray getSHA1Hash(); + ByteArray getMD5Hash(); + + std::string getSHA1String(); + std::string getMD5String(); + + private: + Hash* md5Hasher; + Hash* sha1Hasher; + boost::optional<ByteArray> md5Hash; + boost::optional<ByteArray> sha1Hash; + }; } diff --git a/Swiften/FileTransfer/JingleFileTransfer.cpp b/Swiften/FileTransfer/JingleFileTransfer.cpp index 6eecaa2..3d05db9 100644 --- a/Swiften/FileTransfer/JingleFileTransfer.cpp +++ b/Swiften/FileTransfer/JingleFileTransfer.cpp @@ -1,214 +1,230 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2019 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/JingleFileTransfer.h> -#include <boost/typeof/typeof.hpp> - -#include <Swiften/Base/foreach.h> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/Log.h> #include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/Jingle/JingleSession.h> #include <Swiften/FileTransfer/FileTransferTransporter.h> -#include <Swiften/Base/Log.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Jingle/JingleSession.h> +#include <Swiften/StringCodecs/Hexify.h> using namespace Swift; JingleFileTransfer::JingleFileTransfer( - boost::shared_ptr<JingleSession> session, - const JID& target, - FileTransferTransporterFactory* transporterFactory) : - session(session), - target(target), - transporterFactory(transporterFactory), - transporter(NULL), - ourCandidateSelectFinished(false), - theirCandidateSelectFinished(false) { - - session->addListener(this); - + std::shared_ptr<JingleSession> session, + const JID& target, + FileTransferTransporterFactory* transporterFactory) : + session(session), + target(target), + transporterFactory(transporterFactory), + transporter(nullptr), + ourCandidateSelectFinished(false), + theirCandidateSelectFinished(false) { + + session->addListener(this); } JingleFileTransfer::~JingleFileTransfer() { - session->removeListener(this); + session->removeListener(this); } void JingleFileTransfer::fillCandidateMap(CandidateMap& map, const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - map.clear(); - foreach (JingleS5BTransportPayload::Candidate candidate, candidates) { - map[candidate.cid] = candidate; - } + map.clear(); + for (auto&& candidate : candidates) { + map[candidate.cid] = candidate; + } } /* std::string JingleFileTransfer::getS5BDstAddr(const JID& requester, const JID& target) const { - return Hexify::hexify(crypto->getSHA1Hash( - createSafeByteArray(s5bSessionID + requester.toString() + target.toString()))); + return Hexify::hexify(crypto->getSHA1Hash( + createSafeByteArray(s5bSessionID + requester.toString() + target.toString()))); } */ const JID& JingleFileTransfer::getInitiator() const { - return session->getInitiator(); + return session->getInitiator(); } const JID& JingleFileTransfer::getResponder() const { - return target; + return target; } FileTransfer::State::Type JingleFileTransfer::getExternalFinishedState(JinglePayload::Reason::Type reason) { - if (reason == JinglePayload::Reason::Cancel || reason == JinglePayload::Reason::Decline) { - return FileTransfer::State::Canceled; - } - else if (reason == JinglePayload::Reason::Success) { - return FileTransfer::State::Finished; - } - else { - return FileTransfer::State::Failed; - } + if (reason == JinglePayload::Reason::Cancel || reason == JinglePayload::Reason::Decline) { + return FileTransfer::State::Canceled; + } + else if (reason == JinglePayload::Reason::Success) { + return FileTransfer::State::Finished; + } + else { + return FileTransfer::State::Failed; + } } boost::optional<FileTransferError> JingleFileTransfer::getFileTransferError(JinglePayload::Reason::Type reason) { - if (reason == JinglePayload::Reason::Success) { - return boost::optional<FileTransferError>(); - } - else { - return boost::optional<FileTransferError>(FileTransferError::UnknownError); - } + if (reason == JinglePayload::Reason::Success) { + return boost::optional<FileTransferError>(); + } + else { + return boost::optional<FileTransferError>(FileTransferError::UnknownError); + } } void JingleFileTransfer::handleRemoteTransportCandidateSelectFinished( - const std::string& s5bSessionID, const boost::optional<JingleS5BTransportPayload::Candidate>& candidate) { - SWIFT_LOG(debug) << std::endl; - - ourCandidateChoice = candidate; - ourCandidateSelectFinished = true; - - JingleS5BTransportPayload::ref s5bPayload = boost::make_shared<JingleS5BTransportPayload>(); - s5bPayload->setSessionID(s5bSessionID); - if (candidate) { - s5bPayload->setCandidateUsed(candidate->cid); - } - else { - s5bPayload->setCandidateError(true); - } - candidateSelectRequestID = session->sendTransportInfo(getContentID(), s5bPayload); - - decideOnCandidates(); + const std::string& s5bSessionID, const boost::optional<JingleS5BTransportPayload::Candidate>& candidate) { + SWIFT_LOG(debug); + + ourCandidateChoice = candidate; + ourCandidateSelectFinished = true; + + JingleS5BTransportPayload::ref s5bPayload = std::make_shared<JingleS5BTransportPayload>(); + s5bPayload->setSessionID(s5bSessionID); + if (candidate) { + s5bPayload->setCandidateUsed(candidate->cid); + } + else { + s5bPayload->setCandidateError(true); + } + candidateSelectRequestID = session->sendTransportInfo(getContentID(), s5bPayload); + + decideOnCandidates(); } // decide on candidates according to http://xmpp.org/extensions/xep-0260.html#complete void JingleFileTransfer::decideOnCandidates() { - SWIFT_LOG(debug) << std::endl; - if (!ourCandidateSelectFinished || !theirCandidateSelectFinished) { - SWIFT_LOG(debug) << "Can't make a decision yet!" << std::endl; - return; - } - if (!ourCandidateChoice && !theirCandidateChoice) { - SWIFT_LOG(debug) << "No candidates succeeded." << std::endl; - fallback(); - } - else if (ourCandidateChoice && !theirCandidateChoice) { - startTransferViaRemoteCandidate(); - } - else if (theirCandidateChoice && !ourCandidateChoice) { - startTransferViaLocalCandidate(); - } - else { - SWIFT_LOG(debug) << "Choosing between candidates " - << ourCandidateChoice->cid << "(" << ourCandidateChoice->priority << ")" << " and " - << theirCandidateChoice->cid << "(" << theirCandidateChoice->priority << ")" << std::endl; - if (ourCandidateChoice->priority > theirCandidateChoice->priority) { - startTransferViaRemoteCandidate(); - } - else if (ourCandidateChoice->priority < theirCandidateChoice->priority) { - startTransferViaLocalCandidate(); - } - else { - if (hasPriorityOnCandidateTie()) { - startTransferViaRemoteCandidate(); - } - else { - startTransferViaLocalCandidate(); - } - } - } + SWIFT_LOG(debug); + if (!ourCandidateSelectFinished || !theirCandidateSelectFinished) { + SWIFT_LOG(debug) << "Can't make a decision yet!"; + return; + } + if (!ourCandidateChoice && !theirCandidateChoice) { + SWIFT_LOG(debug) << "No candidates succeeded."; + fallback(); + } + else if (ourCandidateChoice && !theirCandidateChoice) { + SWIFT_LOG(debug) << "Start transfer using remote candidate: " << ourCandidateChoice.get().cid << "."; + startTransferViaRemoteCandidate(); + } + else if (theirCandidateChoice && !ourCandidateChoice) { + SWIFT_LOG(debug) << "Start transfer using local candidate: " << theirCandidateChoice.get().cid << "."; + startTransferViaLocalCandidate(); + } + else { + SWIFT_LOG(debug) << "Choosing between candidates " + << ourCandidateChoice->cid << "(" << ourCandidateChoice->priority << ")" << " and " + << theirCandidateChoice->cid << "(" << theirCandidateChoice->priority << ")"; + if (ourCandidateChoice->priority > theirCandidateChoice->priority) { + SWIFT_LOG(debug) << "Start transfer using remote candidate: " << ourCandidateChoice.get().cid << "."; + startTransferViaRemoteCandidate(); + } + else if (ourCandidateChoice->priority < theirCandidateChoice->priority) { + SWIFT_LOG(debug) << "Start transfer using local candidate:" << theirCandidateChoice.get().cid << "."; + startTransferViaLocalCandidate(); + } + else { + if (hasPriorityOnCandidateTie()) { + SWIFT_LOG(debug) << "Start transfer using remote candidate: " << ourCandidateChoice.get().cid; + startTransferViaRemoteCandidate(); + } + else { + SWIFT_LOG(debug) << "Start transfer using local candidate: " << theirCandidateChoice.get().cid; + startTransferViaLocalCandidate(); + } + } + } } void JingleFileTransfer::handleProxyActivateFinished( - const std::string& s5bSessionID, ErrorPayload::ref error) { - SWIFT_LOG(debug) << std::endl; - if (!isWaitingForLocalProxyActivate()) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - if (error) { - SWIFT_LOG(debug) << "Error activating proxy" << std::endl; - JingleS5BTransportPayload::ref proxyError = boost::make_shared<JingleS5BTransportPayload>(); - proxyError->setSessionID(s5bSessionID); - proxyError->setProxyError(true); - session->sendTransportInfo(getContentID(), proxyError); - fallback(); - } - else { - JingleS5BTransportPayload::ref proxyActivate = boost::make_shared<JingleS5BTransportPayload>(); - proxyActivate->setSessionID(s5bSessionID); - proxyActivate->setActivated(theirCandidateChoice->cid); - session->sendTransportInfo(getContentID(), proxyActivate); - startTransferring(createRemoteCandidateSession()); - } + const std::string& s5bSessionID, ErrorPayload::ref error) { + SWIFT_LOG(debug); + if (!isWaitingForLocalProxyActivate()) { SWIFT_LOG(warning) << "Incorrect state"; return; } + + if (error) { + SWIFT_LOG(debug) << "Error activating proxy"; + JingleS5BTransportPayload::ref proxyError = std::make_shared<JingleS5BTransportPayload>(); + proxyError->setSessionID(s5bSessionID); + proxyError->setProxyError(true); + session->sendTransportInfo(getContentID(), proxyError); + fallback(); + } + else { + JingleS5BTransportPayload::ref proxyActivate = std::make_shared<JingleS5BTransportPayload>(); + proxyActivate->setSessionID(s5bSessionID); + proxyActivate->setActivated(theirCandidateChoice->cid); + session->sendTransportInfo(getContentID(), proxyActivate); + startTransferring(createLocalCandidateSession()); + } } void JingleFileTransfer::handleTransportInfoReceived( - const JingleContentID& /* contentID */, JingleTransportPayload::ref transport) { - SWIFT_LOG(debug) << std::endl; - - if (JingleS5BTransportPayload::ref s5bPayload = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transport)) { - if (s5bPayload->hasCandidateError() || !s5bPayload->getCandidateUsed().empty()) { - SWIFT_LOG(debug) << "Received candidate decision from peer" << std::endl; - if (!isTryingCandidates()) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - theirCandidateSelectFinished = true; - if (!s5bPayload->hasCandidateError()) { - BOOST_AUTO(theirCandidate, localCandidates.find(s5bPayload->getCandidateUsed())); - if (theirCandidate == localCandidates.end()) { - SWIFT_LOG(warning) << "Got invalid candidate" << std::endl; - terminate(JinglePayload::Reason::GeneralError); - return; - } - theirCandidateChoice = theirCandidate->second; - } - decideOnCandidates(); - } - else if (!s5bPayload->getActivated().empty()) { - SWIFT_LOG(debug) << "Received peer activate from peer" << std::endl; - if (!isWaitingForPeerProxyActivate()) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - if (ourCandidateChoice->cid == s5bPayload->getActivated()) { - startTransferring(createRemoteCandidateSession()); - } - else { - SWIFT_LOG(warning) << "ourCandidateChoice doesn't match activated proxy candidate!" << std::endl; - terminate(JinglePayload::Reason::GeneralError); - } - } - else { - SWIFT_LOG(debug) << "Ignoring unknown info" << std::endl; - } - } - else { - SWIFT_LOG(debug) << "Ignoring unknown info" << std::endl; - } + const JingleContentID& /* contentID */, JingleTransportPayload::ref transport) { + SWIFT_LOG(debug); + + if (JingleS5BTransportPayload::ref s5bPayload = std::dynamic_pointer_cast<JingleS5BTransportPayload>(transport)) { + if (s5bPayload->hasCandidateError() || !s5bPayload->getCandidateUsed().empty()) { + SWIFT_LOG(debug) << "Received candidate decision from peer"; + if (!isTryingCandidates()) { SWIFT_LOG(warning) << "Incorrect state"; return; } + + theirCandidateSelectFinished = true; + if (!s5bPayload->hasCandidateError()) { + auto theirCandidate = localCandidates.find(s5bPayload->getCandidateUsed()); + if (theirCandidate == localCandidates.end()) { + SWIFT_LOG(warning) << "Got invalid candidate"; + terminate(JinglePayload::Reason::GeneralError); + return; + } + theirCandidateChoice = theirCandidate->second; + } + decideOnCandidates(); + } + else if (!s5bPayload->getActivated().empty()) { + SWIFT_LOG(debug) << "Received peer activate from peer"; + if (!isWaitingForPeerProxyActivate()) { SWIFT_LOG(warning) << "Incorrect state"; return; } + + if (ourCandidateChoice->cid == s5bPayload->getActivated()) { + startTransferring(createRemoteCandidateSession()); + } + else { + SWIFT_LOG(warning) << "ourCandidateChoice doesn't match activated proxy candidate!"; + terminate(JinglePayload::Reason::GeneralError); + } + } + else if (s5bPayload->hasProxyError()) { + SWIFT_LOG(debug) << "Received proxy error. Trying to fall back to IBB."; + fallback(); + } + else { + SWIFT_LOG(debug) << "Ignoring unknown info"; + } + } + else { + SWIFT_LOG(debug) << "Ignoring unknown info"; + } } void JingleFileTransfer::setTransporter(FileTransferTransporter* transporter) { - this->transporter = transporter; - localTransportCandidatesGeneratedConnection = transporter->onLocalCandidatesGenerated.connect( - boost::bind(&JingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1, _2)); - remoteTransportCandidateSelectFinishedConnection = transporter->onRemoteCandidateSelectFinished.connect( - boost::bind(&JingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1, _2)); - proxyActivatedConnection = transporter->onProxyActivated.connect( - boost::bind(&JingleFileTransfer::handleProxyActivateFinished, this, _1, _2)); + SWIFT_LOG_ASSERT(!this->transporter, error); + this->transporter = transporter; + localTransportCandidatesGeneratedConnection = transporter->onLocalCandidatesGenerated.connect( + boost::bind(&JingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1, _2, _3)); + remoteTransportCandidateSelectFinishedConnection = transporter->onRemoteCandidateSelectFinished.connect( + boost::bind(&JingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1, _2)); + proxyActivatedConnection = transporter->onProxyActivated.connect( + boost::bind(&JingleFileTransfer::handleProxyActivateFinished, this, _1, _2)); } +void JingleFileTransfer::removeTransporter() { + if (transporter) { + localTransportCandidatesGeneratedConnection.release(); + remoteTransportCandidateSelectFinishedConnection.release(); + proxyActivatedConnection.release(); + delete transporter; + transporter = nullptr; + } +} diff --git a/Swiften/FileTransfer/JingleFileTransfer.h b/Swiften/FileTransfer/JingleFileTransfer.h index ee646c1..dd9bcb9 100644 --- a/Swiften/FileTransfer/JingleFileTransfer.h +++ b/Swiften/FileTransfer/JingleFileTransfer.h @@ -1,16 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> - -#include <boost/shared_ptr.hpp> +#include <memory> #include <vector> -#include <Swiften/Base/boost_bsignals.h> + +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/ErrorPayload.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/FileTransfer/FileTransfer.h> @@ -18,76 +19,74 @@ #include <Swiften/Jingle/JingleContentID.h> namespace Swift { - class CryptoProvider; - class IQRouter; - class RemoteJingleTransportCandidateSelector; - class LocalJingleTransportCandidateGenerator; - class JingleSession; - class FileTransferTransporter; - class FileTransferTransporterFactory; - class TransportSession; + class JingleSession; + class FileTransferTransporter; + class FileTransferTransporterFactory; + class TransportSession; - class SWIFTEN_API JingleFileTransfer : public AbstractJingleSessionListener { - public: - JingleFileTransfer( - boost::shared_ptr<JingleSession>, - const JID& target, - FileTransferTransporterFactory*); - virtual ~JingleFileTransfer(); + class SWIFTEN_API JingleFileTransfer : public AbstractJingleSessionListener { + public: + JingleFileTransfer( + std::shared_ptr<JingleSession>, + const JID& target, + FileTransferTransporterFactory*); + virtual ~JingleFileTransfer(); - protected: - virtual void handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref); - virtual void handleLocalTransportCandidatesGenerated( - const std::string& s5bSessionID, - const std::vector<JingleS5BTransportPayload::Candidate>&) = 0; - virtual void handleProxyActivateFinished( - const std::string& s5bSessionID, - ErrorPayload::ref error); - virtual void decideOnCandidates(); - void handleRemoteTransportCandidateSelectFinished( - const std::string& s5bSessionID, const boost::optional<JingleS5BTransportPayload::Candidate>&); - virtual JingleContentID getContentID() const = 0; - virtual void startTransferring(boost::shared_ptr<TransportSession>) = 0; - virtual void terminate(JinglePayload::Reason::Type reason) = 0; - virtual void fallback() = 0; - virtual bool hasPriorityOnCandidateTie() const = 0; - virtual bool isWaitingForPeerProxyActivate() const = 0; - virtual bool isWaitingForLocalProxyActivate() const = 0; - virtual bool isTryingCandidates() const = 0; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession() = 0; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession() = 0; - virtual void startTransferViaLocalCandidate() = 0; - virtual void startTransferViaRemoteCandidate() = 0; + protected: + virtual void handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref); + virtual void handleLocalTransportCandidatesGenerated( + const std::string& s5bSessionID, + const std::vector<JingleS5BTransportPayload::Candidate>&, + const std::string& dstAddr) = 0; + virtual void handleProxyActivateFinished( + const std::string& s5bSessionID, + ErrorPayload::ref error); + virtual void decideOnCandidates(); + void handleRemoteTransportCandidateSelectFinished( + const std::string& s5bSessionID, const boost::optional<JingleS5BTransportPayload::Candidate>&); + virtual JingleContentID getContentID() const = 0; + virtual void startTransferring(std::shared_ptr<TransportSession>) = 0; + virtual void terminate(JinglePayload::Reason::Type reason) = 0; + virtual void fallback() = 0; + virtual bool hasPriorityOnCandidateTie() const = 0; + virtual bool isWaitingForPeerProxyActivate() const = 0; + virtual bool isWaitingForLocalProxyActivate() const = 0; + virtual bool isTryingCandidates() const = 0; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession() = 0; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession() = 0; + virtual void startTransferViaLocalCandidate() = 0; + virtual void startTransferViaRemoteCandidate() = 0; - protected: - typedef std::map<std::string, JingleS5BTransportPayload::Candidate> CandidateMap; + protected: + typedef std::map<std::string, JingleS5BTransportPayload::Candidate> CandidateMap; - void setTransporter(FileTransferTransporter* transporter); - void fillCandidateMap( - CandidateMap& map, - const std::vector<JingleS5BTransportPayload::Candidate>&); - const JID& getInitiator() const; - const JID& getResponder() const; + void setTransporter(FileTransferTransporter* transporter); + void removeTransporter(); + void fillCandidateMap( + CandidateMap& map, + const std::vector<JingleS5BTransportPayload::Candidate>&); + const JID& getInitiator() const; + const JID& getResponder() const; - static FileTransfer::State::Type getExternalFinishedState(JinglePayload::Reason::Type); - static boost::optional<FileTransferError> getFileTransferError(JinglePayload::Reason::Type); + static FileTransfer::State::Type getExternalFinishedState(JinglePayload::Reason::Type); + static boost::optional<FileTransferError> getFileTransferError(JinglePayload::Reason::Type); - boost::shared_ptr<JingleSession> session; - JID target; - FileTransferTransporterFactory* transporterFactory; - FileTransferTransporter* transporter; + std::shared_ptr<JingleSession> session; + JID target; + FileTransferTransporterFactory* transporterFactory; + FileTransferTransporter* transporter; - std::string candidateSelectRequestID; - bool ourCandidateSelectFinished; - boost::optional<JingleS5BTransportPayload::Candidate> ourCandidateChoice; - bool theirCandidateSelectFinished; - boost::optional<JingleS5BTransportPayload::Candidate> theirCandidateChoice; - CandidateMap localCandidates; + std::string candidateSelectRequestID; + bool ourCandidateSelectFinished; + boost::optional<JingleS5BTransportPayload::Candidate> ourCandidateChoice; + bool theirCandidateSelectFinished; + boost::optional<JingleS5BTransportPayload::Candidate> theirCandidateChoice; + CandidateMap localCandidates; - boost::shared_ptr<TransportSession> transportSession; + std::shared_ptr<TransportSession> transportSession; - boost::bsignals::scoped_connection localTransportCandidatesGeneratedConnection; - boost::bsignals::scoped_connection remoteTransportCandidateSelectFinishedConnection; - boost::bsignals::scoped_connection proxyActivatedConnection; - }; + boost::signals2::scoped_connection localTransportCandidatesGeneratedConnection; + boost::signals2::scoped_connection remoteTransportCandidateSelectFinishedConnection; + boost::signals2::scoped_connection proxyActivatedConnection; + }; } diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp index 53ad53a..7cb4cbb 100644 --- a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp +++ b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp @@ -5,116 +5,187 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2019 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> +#include <memory> #include <vector> -#include <boost/shared_ptr.hpp> #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/Base/Log.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h> static const unsigned int LOCAL_PREFERENCE = 0; namespace Swift { LocalJingleTransportCandidateGenerator::LocalJingleTransportCandidateGenerator( - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - const JID& ownJID, - IDGenerator* idGenerator) : - s5bServerManager(s5bServerManager), - s5bProxy(s5bProxy), - ownJID(ownJID), - idGenerator(idGenerator) { + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + const JID& ownJID, + IDGenerator* idGenerator, + const FileTransferOptions& options) : + s5bServerManager(s5bServerManager), + s5bProxy(s5bProxy), + ownJID(ownJID), + idGenerator(idGenerator), + triedServerInit_(false), + triedForwarding_(false), + triedProxyDiscovery_(false), + options_(options) { } LocalJingleTransportCandidateGenerator::~LocalJingleTransportCandidateGenerator() { - SWIFT_LOG_ASSERT(!s5bServerInitializeRequest, warning) << std::endl; + SWIFT_LOG_ASSERT(!s5bServerInitializeRequest, warning); } void LocalJingleTransportCandidateGenerator::start() { - assert(!s5bServerInitializeRequest); - s5bServerInitializeRequest = s5bServerManager->createInitializeRequest(); - s5bServerInitializeRequest->onFinished.connect( - boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); - - s5bServerInitializeRequest->start(); + assert(!s5bServerInitializeRequest); + if (options_.isDirectAllowed() || options_.isAssistedAllowed()) { + s5bServerResourceUser_ = s5bServerManager->aquireResourceUser(); + if (s5bServerResourceUser_->isInitialized()) { + handleS5BServerInitialized(true); + } + else { + s5bServerResourceUser_->onSuccessfulInitialized.connect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); + } + } else { + handleS5BServerInitialized(false); + } + + if (options_.isProxiedAllowed()) { + s5bProxy->onDiscoveredProxiesChanged.connect(boost::bind(&LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged, this)); + if (s5bProxy->getOrDiscoverS5BProxies().is_initialized()) { + handleDiscoveredProxiesChanged(); + } + } } void LocalJingleTransportCandidateGenerator::stop() { - if (s5bServerInitializeRequest) { - s5bServerInitializeRequest->stop(); - s5bServerInitializeRequest.reset(); - } + s5bProxy->onDiscoveredProxiesChanged.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged, this)); + if (s5bServerPortForwardingUser_) { + s5bServerPortForwardingUser_->onSetup.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handlePortForwardingSetup, this, _1)); + s5bServerPortForwardingUser_.reset(); + } + if (s5bServerResourceUser_) { + s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); + s5bServerResourceUser_.reset(); + } } void LocalJingleTransportCandidateGenerator::handleS5BServerInitialized(bool success) { - std::vector<JingleS5BTransportPayload::Candidate> candidates; - if (success) { - // get direct candidates - std::vector<HostAddressPort> directCandidates = s5bServerManager->getHostAddressPorts(); - foreach(HostAddressPort addressPort, directCandidates) { - JingleS5BTransportPayload::Candidate candidate; - candidate.type = JingleS5BTransportPayload::Candidate::DirectType; - candidate.jid = ownJID; - candidate.hostPort = addressPort; - candidate.priority = 65536 * 126 + LOCAL_PREFERENCE; - candidate.cid = idGenerator->generateID(); - candidates.push_back(candidate); - } - - // get assissted candidates - std::vector<HostAddressPort> assisstedCandidates = s5bServerManager->getAssistedHostAddressPorts(); - foreach(HostAddressPort addressPort, assisstedCandidates) { - JingleS5BTransportPayload::Candidate candidate; - candidate.type = JingleS5BTransportPayload::Candidate::AssistedType; - candidate.jid = ownJID; - candidate.hostPort = addressPort; - candidate.priority = 65536 * 120 + LOCAL_PREFERENCE; - candidate.cid = idGenerator->generateID(); - candidates.push_back(candidate); - } - } - else { - SWIFT_LOG(warning) << "Unable to start SOCKS5 server" << std::endl; - } - - s5bServerInitializeRequest->stop(); - s5bServerInitializeRequest.reset(); - - onLocalTransportCandidatesGenerated(candidates); + if (s5bServerResourceUser_) { + s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); + } + triedServerInit_ = true; + if (success) { + if (options_.isAssistedAllowed()) { + // try to setup port forwarding + s5bServerPortForwardingUser_ = s5bServerManager->aquirePortForwardingUser(); + s5bServerPortForwardingUser_->onSetup.connect(boost::bind(&LocalJingleTransportCandidateGenerator::handlePortForwardingSetup, this, _1)); + if (s5bServerPortForwardingUser_->isForwardingSetup()) { + handlePortForwardingSetup(true); + } + } + } + else { + SWIFT_LOG(warning) << "Unable to start SOCKS5 server"; + if (s5bServerResourceUser_) { + s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); + } + s5bServerResourceUser_.reset(); + handlePortForwardingSetup(false); + } + checkS5BCandidatesReady(); +} + +void LocalJingleTransportCandidateGenerator::handlePortForwardingSetup(bool /* success */) { + if (s5bServerPortForwardingUser_) { + s5bServerPortForwardingUser_->onSetup.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handlePortForwardingSetup, this, _1)); + } + triedForwarding_ = true; + checkS5BCandidatesReady(); +} + +void LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged() { + if (s5bProxy) { + s5bProxy->onDiscoveredProxiesChanged.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged, this)); + } + triedProxyDiscovery_ = true; + checkS5BCandidatesReady(); } -/*void LocalJingleTransportCandidateGenerator::handleS5BProxiesDiscovered() { - foreach(S5BProxyRequest::ref proxy, s5bProxiesDiscoverRequest->getS5BProxies()) { - if (proxy->getStreamHost()) { // FIXME: Added this test, because there were cases where this wasn't initialized. Investigate this. (Remko) - JingleS5BTransportPayload::Candidate candidate; - candidate.type = JingleS5BTransportPayload::Candidate::ProxyType; - candidate.jid = (*proxy->getStreamHost()).jid; - candidate.hostPort = (*proxy->getStreamHost()).addressPort; - candidate.priority = 65536 * 10 + LOCAL_PREFERENCE; - candidate.cid = idGenerator.generateID(); - s5bCandidatesPayload->addCandidate(candidate); - } - } - - haveS5BProxyCandidates = true; - s5bProxiesDiscoverRequest->stop(); - s5bProxiesDiscoverRequest.reset(); - - checkS5BCandidatesReady(); -}*/ +void LocalJingleTransportCandidateGenerator::checkS5BCandidatesReady() { + if ((!options_.isDirectAllowed() || (options_.isDirectAllowed() && triedServerInit_)) && + (!options_.isProxiedAllowed() || (options_.isProxiedAllowed() && triedProxyDiscovery_)) && + (!options_.isAssistedAllowed() || (options_.isAssistedAllowed() && triedForwarding_))) { + emitOnLocalTransportCandidatesGenerated(); + } +} + + +void LocalJingleTransportCandidateGenerator::emitOnLocalTransportCandidatesGenerated() { + std::vector<JingleS5BTransportPayload::Candidate> candidates; + + if (options_.isDirectAllowed()) { + // get direct candidates + std::vector<HostAddressPort> directCandidates = s5bServerManager->getHostAddressPorts(); + for(auto&& addressPort : directCandidates) { + if (addressPort.getAddress().getRawAddress().is_v6() && + addressPort.getAddress().getRawAddress().to_v6().is_link_local()) { + continue; + } + JingleS5BTransportPayload::Candidate candidate; + candidate.type = JingleS5BTransportPayload::Candidate::DirectType; + candidate.jid = ownJID; + candidate.hostPort = addressPort; + candidate.priority = 65536 * 126 + LOCAL_PREFERENCE; + candidate.cid = idGenerator->generateID(); + candidates.push_back(candidate); + } + } + + if (options_.isAssistedAllowed()) { + // get assissted candidates + std::vector<HostAddressPort> assisstedCandidates = s5bServerManager->getAssistedHostAddressPorts(); + for (auto&& addressPort : assisstedCandidates) { + JingleS5BTransportPayload::Candidate candidate; + candidate.type = JingleS5BTransportPayload::Candidate::AssistedType; + candidate.jid = ownJID; + candidate.hostPort = addressPort; + candidate.priority = 65536 * 120 + LOCAL_PREFERENCE; + candidate.cid = idGenerator->generateID(); + candidates.push_back(candidate); + } + } + + if (options_.isProxiedAllowed() && s5bProxy && s5bProxy->getOrDiscoverS5BProxies().is_initialized()) { + for (auto&& proxy : s5bProxy->getOrDiscoverS5BProxies().get()) { + if (proxy->getStreamHost()) { // FIXME: Added this test, because there were cases where this wasn't initialized. Investigate this. (Remko) + JingleS5BTransportPayload::Candidate candidate; + candidate.type = JingleS5BTransportPayload::Candidate::ProxyType; + candidate.jid = (*proxy->getStreamHost()).jid; + auto address = HostAddress::fromString((*proxy->getStreamHost()).host); + if (address) { + candidate.hostPort = HostAddressPort(address.get(), (*proxy->getStreamHost()).port); + candidate.priority = 65536 * 10 + LOCAL_PREFERENCE; + candidate.cid = idGenerator->generateID(); + candidates.push_back(candidate); + } + } + } + } + + onLocalTransportCandidatesGenerated(candidates); +} } diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h index 02dfef5..8c53d16 100644 --- a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h +++ b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h @@ -5,50 +5,65 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> +#include <boost/signals2.hpp> + #include <Swiften/Base/IDGenerator.h> -#include <Swiften/Base/Override.h> -#include <Swiften/JID/JID.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h> +#include <Swiften/JID/JID.h> namespace Swift { - class SOCKS5BytestreamServerManager; - class SOCKS5BytestreamProxiesManager; - class SOCKS5BytestreamServerInitializeRequest; - class JingleS5BTransportPayload; - - class LocalJingleTransportCandidateGenerator { - public: - LocalJingleTransportCandidateGenerator( - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - const JID& ownJID, - IDGenerator* idGenerator); - virtual ~LocalJingleTransportCandidateGenerator(); - - virtual void start(); - virtual void stop(); - - boost::signal<void (const std::vector<JingleS5BTransportPayload::Candidate>&)> onLocalTransportCandidatesGenerated; - - private: - void handleS5BServerInitialized(bool success); - void checkS5BCandidatesReady(); - - private: - SOCKS5BytestreamServerManager* s5bServerManager; - SOCKS5BytestreamProxiesManager* s5bProxy; - JID ownJID; - IDGenerator* idGenerator; - boost::shared_ptr<SOCKS5BytestreamServerInitializeRequest> s5bServerInitializeRequest; - }; + class SOCKS5BytestreamServerManager; + class SOCKS5BytestreamProxiesManager; + class SOCKS5BytestreamServerInitializeRequest; + class SOCKS5BytestreamServerResourceUser; + class SOCKS5BytestreamServerPortForwardingUser; + class JingleS5BTransportPayload; + + class LocalJingleTransportCandidateGenerator { + public: + LocalJingleTransportCandidateGenerator( + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + const JID& ownJID, + IDGenerator* idGenerator, + const FileTransferOptions& options); + virtual ~LocalJingleTransportCandidateGenerator(); + + virtual void start(); + virtual void stop(); + + boost::signals2::signal<void (const std::vector<JingleS5BTransportPayload::Candidate>&)> onLocalTransportCandidatesGenerated; + + private: + void handleS5BServerInitialized(bool success); + void handlePortForwardingSetup(bool success); + void handleDiscoveredProxiesChanged(); + + void checkS5BCandidatesReady(); + void emitOnLocalTransportCandidatesGenerated(); + + private: + SOCKS5BytestreamServerManager* s5bServerManager; + SOCKS5BytestreamProxiesManager* s5bProxy; + JID ownJID; + IDGenerator* idGenerator; + std::shared_ptr<SOCKS5BytestreamServerInitializeRequest> s5bServerInitializeRequest; + std::shared_ptr<SOCKS5BytestreamServerResourceUser> s5bServerResourceUser_; + std::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> s5bServerPortForwardingUser_; + bool triedServerInit_; + bool triedForwarding_; + bool triedProxyDiscovery_; + FileTransferOptions options_; + }; } diff --git a/Swiften/FileTransfer/OutgoingFileTransfer.cpp b/Swiften/FileTransfer/OutgoingFileTransfer.cpp index 94d4348..e11c269 100644 --- a/Swiften/FileTransfer/OutgoingFileTransfer.cpp +++ b/Swiften/FileTransfer/OutgoingFileTransfer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/OutgoingFileTransfer.h> diff --git a/Swiften/FileTransfer/OutgoingFileTransfer.h b/Swiften/FileTransfer/OutgoingFileTransfer.h index 59dc718..07fc6d2 100644 --- a/Swiften/FileTransfer/OutgoingFileTransfer.h +++ b/Swiften/FileTransfer/OutgoingFileTransfer.h @@ -1,22 +1,23 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/FileTransfer/FileTransfer.h> namespace Swift { - class OutgoingFileTransfer : public FileTransfer { - public: - typedef boost::shared_ptr<OutgoingFileTransfer> ref; - public: - virtual ~OutgoingFileTransfer(); + class SWIFTEN_API OutgoingFileTransfer : public FileTransfer { + public: + typedef std::shared_ptr<OutgoingFileTransfer> ref; + public: + virtual ~OutgoingFileTransfer(); - virtual void start() = 0; - }; + virtual void start() = 0; + }; } diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp index 4b3c6b5..c74aefb 100644 --- a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp +++ b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp @@ -5,58 +5,61 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/OutgoingFileTransferManager.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <Swiften/Base/IDGenerator.h> +#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> #include <Swiften/JID/JID.h> -#include <Swiften/Jingle/JingleSessionManager.h> -#include <Swiften/Jingle/JingleSessionImpl.h> #include <Swiften/Jingle/JingleContentID.h> -#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> -#include <Swiften/Base/IDGenerator.h> +#include <Swiften/Jingle/JingleSessionImpl.h> +#include <Swiften/Jingle/JingleSessionManager.h> namespace Swift { OutgoingFileTransferManager::OutgoingFileTransferManager( - JingleSessionManager* jingleSessionManager, - IQRouter* router, - FileTransferTransporterFactory* transporterFactory, - CryptoProvider* crypto) : - jingleSessionManager(jingleSessionManager), - iqRouter(router), - transporterFactory(transporterFactory), - crypto(crypto) { - idGenerator = new IDGenerator(); + JingleSessionManager* jingleSessionManager, + IQRouter* router, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto) : + jingleSessionManager(jingleSessionManager), + iqRouter(router), + transporterFactory(transporterFactory), + timerFactory(timerFactory), + crypto(crypto) { + idGenerator = new IDGenerator(); } OutgoingFileTransferManager::~OutgoingFileTransferManager() { - delete idGenerator; + delete idGenerator; } -boost::shared_ptr<OutgoingFileTransfer> OutgoingFileTransferManager::createOutgoingFileTransfer( - const JID& from, - const JID& recipient, - boost::shared_ptr<ReadBytestream> readBytestream, - const StreamInitiationFileInfo& fileInfo, - const FileTransferOptions& config) { - JingleSessionImpl::ref jingleSession = boost::make_shared<JingleSessionImpl>( - from, recipient, idGenerator->generateID(), iqRouter); - jingleSessionManager->registerOutgoingSession(from, jingleSession); - return boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer( - recipient, - jingleSession, - readBytestream, - transporterFactory, - idGenerator, - fileInfo, - config, - crypto)); +std::shared_ptr<OutgoingFileTransfer> OutgoingFileTransferManager::createOutgoingFileTransfer( + const JID& from, + const JID& recipient, + std::shared_ptr<ReadBytestream> readBytestream, + const JingleFileTransferFileInfo& fileInfo, + const FileTransferOptions& config) { + JingleSessionImpl::ref jingleSession = std::make_shared<JingleSessionImpl>( + from, recipient, idGenerator->generateID(), iqRouter); + jingleSessionManager->registerOutgoingSession(from, jingleSession); + return std::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer( + recipient, + jingleSession, + readBytestream, + transporterFactory, + timerFactory, + idGenerator, + fileInfo, + config, + crypto)); } } diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.h b/Swiften/FileTransfer/OutgoingFileTransferManager.h index 17a489d..48a6e5a 100644 --- a/Swiften/FileTransfer/OutgoingFileTransferManager.h +++ b/Swiften/FileTransfer/OutgoingFileTransferManager.h @@ -5,48 +5,53 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <Swiften/Base/API.h> namespace Swift { - class JingleSessionManager; - class IQRouter; - class FileTransferTransporterFactory; - class OutgoingFileTransfer; - class JID; - class IDGenerator; - class ReadBytestream; - class StreamInitiationFileInfo; - class CryptoProvider; - class FileTransferOptions; - - class OutgoingFileTransferManager { - public: - OutgoingFileTransferManager( - JingleSessionManager* jingleSessionManager, - IQRouter* router, - FileTransferTransporterFactory* transporterFactory, - CryptoProvider* crypto); - ~OutgoingFileTransferManager(); - - boost::shared_ptr<OutgoingFileTransfer> createOutgoingFileTransfer( - const JID& from, - const JID& to, - boost::shared_ptr<ReadBytestream>, - const StreamInitiationFileInfo&, - const FileTransferOptions&); - - private: - JingleSessionManager* jingleSessionManager; - IQRouter* iqRouter; - FileTransferTransporterFactory* transporterFactory; - IDGenerator* idGenerator; - CryptoProvider* crypto; - }; + class JingleSessionManager; + class IQRouter; + class FileTransferTransporterFactory; + class OutgoingFileTransfer; + class JID; + class IDGenerator; + class ReadBytestream; + class JingleFileTransferFileInfo; + class CryptoProvider; + class FileTransferOptions; + class TimerFactory; + + class SWIFTEN_API OutgoingFileTransferManager { + public: + OutgoingFileTransferManager( + JingleSessionManager* jingleSessionManager, + IQRouter* router, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto); + ~OutgoingFileTransferManager(); + + std::shared_ptr<OutgoingFileTransfer> createOutgoingFileTransfer( + const JID& from, + const JID& to, + std::shared_ptr<ReadBytestream>, + const JingleFileTransferFileInfo&, + const FileTransferOptions&); + + private: + JingleSessionManager* jingleSessionManager; + IQRouter* iqRouter; + FileTransferTransporterFactory* transporterFactory; + TimerFactory* timerFactory; + IDGenerator* idGenerator; + CryptoProvider* crypto; + }; } diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp index 7bcee4b..57a18a8 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp @@ -5,339 +5,403 @@ */ /* - * Copyright (C) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2019 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -// TODO: +// TODO: // - We should handle incoming terminates after we have terminated, so the other // side can warn that he didn't receive all bytes correctly. // - Should the proby stuff also wait for candidate used acknowledgement? #include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <boost/typeof/typeof.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/Base/IDGenerator.h> -#include <Swiften/Jingle/JingleContentID.h> -#include <Swiften/Jingle/JingleSession.h> +#include <Swiften/Base/Log.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Elements/JingleFileTransferDescription.h> #include <Swiften/Elements/JingleFileTransferHash.h> -#include <Swiften/Elements/JingleTransportPayload.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> -#include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h> +#include <Swiften/Elements/JingleTransportPayload.h> #include <Swiften/FileTransfer/FileTransferTransporter.h> #include <Swiften/FileTransfer/FileTransferTransporterFactory.h> +#include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h> #include <Swiften/FileTransfer/ReadBytestream.h> #include <Swiften/FileTransfer/TransportSession.h> -#include <Swiften/Crypto/CryptoProvider.h> - -#include <Swiften/Base/Log.h> +#include <Swiften/Jingle/JingleContentID.h> +#include <Swiften/Jingle/JingleSession.h> +#include <Swiften/Network/TimerFactory.h> using namespace Swift; static const int DEFAULT_BLOCK_SIZE = 4096; OutgoingJingleFileTransfer::OutgoingJingleFileTransfer( - const JID& toJID, - JingleSession::ref session, - boost::shared_ptr<ReadBytestream> stream, - FileTransferTransporterFactory* transporterFactory, - IDGenerator* idGenerator, - const StreamInitiationFileInfo& fileInfo, - const FileTransferOptions& options, - CryptoProvider* crypto) : - JingleFileTransfer(session, toJID, transporterFactory), - idGenerator(idGenerator), - stream(stream), - fileInfo(fileInfo), - options(options), - contentID(idGenerator->generateID(), JingleContentPayload::InitiatorCreator), - state(Initial), - candidateAcknowledged(false) { - - setFileInfo(fileInfo.getName(), fileInfo.getSize()); - - // calculate both, MD5 and SHA-1 since we don't know which one the other side supports - hashCalculator = new IncrementalBytestreamHashCalculator(true, true, crypto); - stream->onRead.connect( - boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); + const JID& toJID, + JingleSession::ref session, + std::shared_ptr<ReadBytestream> stream, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + IDGenerator* idGenerator, + const JingleFileTransferFileInfo& fileInfo, + const FileTransferOptions& options, + CryptoProvider* crypto) : + JingleFileTransfer(session, toJID, transporterFactory), + idGenerator(idGenerator), + stream(stream), + fileInfo(fileInfo), + options(options), + contentID(idGenerator->generateID(), JingleContentPayload::InitiatorCreator), + state(Initial), + candidateAcknowledged(false) { + + setFileInfo(fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription()); + + // calculate both, MD5 and SHA-1 since we don't know which one the other side supports + hashCalculator = new IncrementalBytestreamHashCalculator(true, true, crypto); + stream->onRead.connect( + boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); + + waitForRemoteTermination = timerFactory->createTimer(5000); + waitForRemoteTermination->onTick.connect(boost::bind(&OutgoingJingleFileTransfer::handleWaitForRemoteTerminationTimeout, this)); } OutgoingJingleFileTransfer::~OutgoingJingleFileTransfer() { - stream->onRead.disconnect( - boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); - delete hashCalculator; + if (waitForRemoteTermination) { + waitForRemoteTermination->onTick.disconnect(boost::bind(&OutgoingJingleFileTransfer::handleWaitForRemoteTerminationTimeout, this)); + waitForRemoteTermination->stop(); + } + + stream->onRead.disconnect( + boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); + delete hashCalculator; + hashCalculator = nullptr; + removeTransporter(); } - -void OutgoingJingleFileTransfer::start() { - SWIFT_LOG(debug) << std::endl; - if (state != Initial) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - setTransporter(transporterFactory->createInitiatorTransporter(getInitiator(), getResponder())); - setState(GeneratingInitialLocalCandidates); - transporter->startGeneratingLocalCandidates(); +void OutgoingJingleFileTransfer::start() { + SWIFT_LOG(debug); + if (state != Initial) { + SWIFT_LOG(warning) << "Incorrect state"; + return; + } + + if (!options.isInBandAllowed() && !options.isDirectAllowed() && !options.isAssistedAllowed() && !options.isProxiedAllowed()) { + // Started outgoing file transfer while not supporting transport methods. + setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::UnknownError)); + } + else { + setTransporter(transporterFactory->createInitiatorTransporter(getInitiator(), getResponder(), options)); + setInternalState(GeneratingInitialLocalCandidates); + transporter->startGeneratingLocalCandidates(); + } } void OutgoingJingleFileTransfer::cancel() { - terminate(JinglePayload::Reason::Cancel); + terminate(JinglePayload::Reason::Cancel); } void OutgoingJingleFileTransfer::terminate(JinglePayload::Reason::Type reason) { - SWIFT_LOG(debug) << reason << std::endl; + SWIFT_LOG(debug) << reason; - if (state != Initial && state != GeneratingInitialLocalCandidates && state != Finished) { - session->sendTerminate(reason); - } - stopAll(); - setFinishedState(getExternalFinishedState(reason), getFileTransferError(reason)); + if (state != Initial && state != GeneratingInitialLocalCandidates && state != Finished) { + session->sendTerminate(reason); + } + stopAll(); + setFinishedState(getExternalFinishedState(reason), getFileTransferError(reason)); } void OutgoingJingleFileTransfer::handleSessionAcceptReceived( - const JingleContentID&, - JingleDescription::ref, - JingleTransportPayload::ref transportPayload) { - SWIFT_LOG(debug) << std::endl; - if (state != WaitingForAccept) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - if (JingleS5BTransportPayload::ref s5bPayload = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transportPayload)) { - transporter->addRemoteCandidates(s5bPayload->getCandidates()); - setState(TryingCandidates); - transporter->startTryingRemoteCandidates(); - } - else { - SWIFT_LOG(debug) << "Unknown transport payload. Falling back." << std::endl; - fallback(); - } + const JingleContentID&, + JingleDescription::ref, + JingleTransportPayload::ref transportPayload) { + SWIFT_LOG(debug); + if (state != WaitingForAccept) { SWIFT_LOG(warning) << "Incorrect state"; return; } + + if (JingleS5BTransportPayload::ref s5bPayload = std::dynamic_pointer_cast<JingleS5BTransportPayload>(transportPayload)) { + transporter->addRemoteCandidates(s5bPayload->getCandidates(), s5bPayload->getDstAddr()); + setInternalState(TryingCandidates); + transporter->startTryingRemoteCandidates(); + } + else if (JingleIBBTransportPayload::ref ibbPayload = std::dynamic_pointer_cast<JingleIBBTransportPayload>(transportPayload)) { + startTransferring(transporter->createIBBSendSession(ibbPayload->getSessionID(), ibbPayload->getBlockSize().get_value_or(DEFAULT_BLOCK_SIZE), stream)); + } + else { + SWIFT_LOG(debug) << "Unknown transport payload. Falling back."; + fallback(); + } } void OutgoingJingleFileTransfer::handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason) { - SWIFT_LOG(debug) << std::endl; - if (state == Finished) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - stopAll(); - if (reason && reason->type == JinglePayload::Reason::Cancel) { - setFinishedState(FileTransfer::State::Canceled, FileTransferError(FileTransferError::PeerError)); - } - else if (reason && reason->type == JinglePayload::Reason::Success) { - setFinishedState(FileTransfer::State::Finished, boost::optional<FileTransferError>()); - } - else { - setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); - } + SWIFT_LOG(debug); + if (state == Finished) { SWIFT_LOG(warning) << "Incorrect state: " << state; return; } + + stopAll(); + if (state == WaitForTermination) { + waitForRemoteTermination->stop(); + } + if (reason && reason->type == JinglePayload::Reason::Cancel) { + setFinishedState(FileTransfer::State::Canceled, FileTransferError(FileTransferError::PeerError)); + } + else if (reason && reason->type == JinglePayload::Reason::Decline) { + setFinishedState(FileTransfer::State::Canceled, boost::optional<FileTransferError>()); + } + else if (reason && reason->type == JinglePayload::Reason::Success) { + setFinishedState(FileTransfer::State::Finished, boost::optional<FileTransferError>()); + } + else { + setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); + } } void OutgoingJingleFileTransfer::handleTransportAcceptReceived(const JingleContentID&, JingleTransportPayload::ref transport) { - SWIFT_LOG(debug) << std::endl; - if (state != FallbackRequested) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - if (JingleIBBTransportPayload::ref ibbPayload = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transport)) { - startTransferring(transporter->createIBBSendSession(ibbPayload->getSessionID(), ibbPayload->getBlockSize().get_value_or(DEFAULT_BLOCK_SIZE), stream)); - } - else { - SWIFT_LOG(debug) << "Unknown transport replacement" << std::endl; - terminate(JinglePayload::Reason::FailedTransport); - } + SWIFT_LOG(debug); + if (state != FallbackRequested) { SWIFT_LOG(warning) << "Incorrect state"; return; } + + if (JingleIBBTransportPayload::ref ibbPayload = std::dynamic_pointer_cast<JingleIBBTransportPayload>(transport)) { + startTransferring(transporter->createIBBSendSession(ibbPayload->getSessionID(), ibbPayload->getBlockSize().get_value_or(DEFAULT_BLOCK_SIZE), stream)); + } + else { + SWIFT_LOG(debug) << "Unknown transport replacement"; + terminate(JinglePayload::Reason::FailedTransport); + } +} + +void OutgoingJingleFileTransfer::handleTransportRejectReceived(const JingleContentID &, std::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(debug); + + terminate(JinglePayload::Reason::UnsupportedTransports); } void OutgoingJingleFileTransfer::sendSessionInfoHash() { - SWIFT_LOG(debug) << std::endl; + SWIFT_LOG(debug); - JingleFileTransferHash::ref hashElement = boost::make_shared<JingleFileTransferHash>(); - hashElement->setHash("sha-1", hashCalculator->getSHA1String()); - hashElement->setHash("md5", hashCalculator->getMD5String()); - session->sendInfo(hashElement); + JingleFileTransferHash::ref hashElement = std::make_shared<JingleFileTransferHash>(); + hashElement->getFileInfo().addHash(HashElement("sha-1", hashCalculator->getSHA1Hash())); + hashElement->getFileInfo().addHash(HashElement("md5", hashCalculator->getMD5Hash())); + session->sendInfo(hashElement); } void OutgoingJingleFileTransfer::handleLocalTransportCandidatesGenerated( - const std::string& s5bSessionID, const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - SWIFT_LOG(debug) << std::endl; - if (state != GeneratingInitialLocalCandidates) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - fillCandidateMap(localCandidates, candidates); - - JingleFileTransferDescription::ref description = boost::make_shared<JingleFileTransferDescription>(); - description->addOffer(fileInfo); - - JingleS5BTransportPayload::ref transport = boost::make_shared<JingleS5BTransportPayload>(); - transport->setSessionID(s5bSessionID); - transport->setMode(JingleS5BTransportPayload::TCPMode); - foreach(JingleS5BTransportPayload::Candidate candidate, candidates) { - transport->addCandidate(candidate); - } - setState(WaitingForAccept); - session->sendInitiate(contentID, description, transport); + const std::string& s5bSessionID, const std::vector<JingleS5BTransportPayload::Candidate>& candidates, const std::string& dstAddr) { + SWIFT_LOG(debug); + if (state != GeneratingInitialLocalCandidates) { SWIFT_LOG(warning) << "Incorrect state: " << state; return; } + + fillCandidateMap(localCandidates, candidates); + + JingleFileTransferDescription::ref description = std::make_shared<JingleFileTransferDescription>(); + fileInfo.addHash(HashElement("sha-1", ByteArray())); + fileInfo.addHash(HashElement("md5", ByteArray())); + description->setFileInfo(fileInfo); + + JingleTransportPayload::ref transport; + if (candidates.empty()) { + SWIFT_LOG(debug) << "no S5B candidates generated. Send IBB transport candidate."; + JingleIBBTransportPayload::ref ibbTransport = std::make_shared<JingleIBBTransportPayload>(); + ibbTransport->setBlockSize(DEFAULT_BLOCK_SIZE); + ibbTransport->setSessionID(idGenerator->generateID()); + transport = ibbTransport; + } + else { + JingleS5BTransportPayload::ref s5bTransport = std::make_shared<JingleS5BTransportPayload>(); + s5bTransport->setSessionID(s5bSessionID); + s5bTransport->setMode(JingleS5BTransportPayload::TCPMode); + s5bTransport->setDstAddr(dstAddr); + for (auto&& candidate : candidates) { + s5bTransport->addCandidate(candidate); + SWIFT_LOG(debug) << "\t" << "S5B candidate: " << candidate.hostPort.toString(); + } + transport = s5bTransport; + } + setInternalState(WaitingForAccept); + session->sendInitiate(contentID, description, transport); } void OutgoingJingleFileTransfer::fallback() { - SWIFT_LOG(debug) << std::endl; - if (options.isInBandAllowed()) { - JingleIBBTransportPayload::ref ibbTransport = boost::make_shared<JingleIBBTransportPayload>(); - ibbTransport->setBlockSize(DEFAULT_BLOCK_SIZE); - ibbTransport->setSessionID(idGenerator->generateID()); - setState(FallbackRequested); - session->sendTransportReplace(contentID, ibbTransport); - } - else { - terminate(JinglePayload::Reason::ConnectivityError); - } + if (options.isInBandAllowed()) { + SWIFT_LOG(debug) << "Trying to fallback to IBB transport."; + JingleIBBTransportPayload::ref ibbTransport = std::make_shared<JingleIBBTransportPayload>(); + ibbTransport->setBlockSize(DEFAULT_BLOCK_SIZE); + ibbTransport->setSessionID(idGenerator->generateID()); + setInternalState(FallbackRequested); + session->sendTransportReplace(contentID, ibbTransport); + } + else { + SWIFT_LOG(debug) << "Fallback to IBB transport not allowed."; + terminate(JinglePayload::Reason::ConnectivityError); + } } void OutgoingJingleFileTransfer::handleTransferFinished(boost::optional<FileTransferError> error) { - SWIFT_LOG(debug) << std::endl; - if (state != Transferring) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - if (error) { - terminate(JinglePayload::Reason::ConnectivityError); - } - else { - sendSessionInfoHash(); - terminate(JinglePayload::Reason::Success); - } + SWIFT_LOG(debug); + if (state != Transferring) { SWIFT_LOG(warning) << "Incorrect state: " << state; return; } + + if (error) { + terminate(JinglePayload::Reason::ConnectivityError); + } + else { + sendSessionInfoHash(); + + // wait for other party to terminate session after they have verified the hash + setInternalState(WaitForTermination); + waitForRemoteTermination->start(); + } } -void OutgoingJingleFileTransfer::startTransferring(boost::shared_ptr<TransportSession> transportSession) { - SWIFT_LOG(debug) << std::endl; +void OutgoingJingleFileTransfer::startTransferring(std::shared_ptr<TransportSession> transportSession) { + SWIFT_LOG(debug); - this->transportSession = transportSession; - processedBytesConnection = transportSession->onBytesSent.connect( - boost::bind(boost::ref(onProcessedBytes), _1)); - transferFinishedConnection = transportSession->onFinished.connect( - boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1)); - setState(Transferring); - transportSession->start(); + this->transportSession = transportSession; + processedBytesConnection = transportSession->onBytesSent.connect( + boost::bind(boost::ref(onProcessedBytes), _1)); + transferFinishedConnection = transportSession->onFinished.connect( + boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1)); + setInternalState(Transferring); + transportSession->start(); } -void OutgoingJingleFileTransfer::setState(State state) { - SWIFT_LOG(debug) << state << std::endl; - this->state = state; - onStateChanged(FileTransfer::State(getExternalState(state))); +void OutgoingJingleFileTransfer::setInternalState(State state) { + SWIFT_LOG(debug) << state; + this->state = state; + setState(FileTransfer::State(getExternalState(state))); } void OutgoingJingleFileTransfer::setFinishedState( - FileTransfer::State::Type type, const boost::optional<FileTransferError>& error) { - SWIFT_LOG(debug) << std::endl; - this->state = Finished; - onStateChanged(type); - onFinished(error); + FileTransfer::State::Type type, const boost::optional<FileTransferError>& error) { + SWIFT_LOG(debug); + this->state = Finished; + onStateChanged(type); + onFinished(error); } FileTransfer::State::Type OutgoingJingleFileTransfer::getExternalState(State state) { - switch (state) { - case Initial: return FileTransfer::State::Initial; - case GeneratingInitialLocalCandidates: return FileTransfer::State::WaitingForStart; - case WaitingForAccept: return FileTransfer::State::WaitingForAccept; - case TryingCandidates: return FileTransfer::State::Negotiating; - case WaitingForPeerProxyActivate: return FileTransfer::State::Negotiating; - case WaitingForLocalProxyActivate: return FileTransfer::State::Negotiating; - case WaitingForCandidateAcknowledge: return FileTransfer::State::Negotiating; - case FallbackRequested: return FileTransfer::State::Negotiating; - case Transferring: return FileTransfer::State::Transferring; - case Finished: return FileTransfer::State::Finished; - } - assert(false); - return FileTransfer::State::Initial; + switch (state) { + case Initial: return FileTransfer::State::Initial; + case GeneratingInitialLocalCandidates: return FileTransfer::State::WaitingForStart; + case WaitingForAccept: return FileTransfer::State::WaitingForAccept; + case TryingCandidates: return FileTransfer::State::Negotiating; + case WaitingForPeerProxyActivate: return FileTransfer::State::Negotiating; + case WaitingForLocalProxyActivate: return FileTransfer::State::Negotiating; + case WaitingForCandidateAcknowledge: return FileTransfer::State::Negotiating; + case FallbackRequested: return FileTransfer::State::Negotiating; + case Transferring: return FileTransfer::State::Transferring; + case WaitForTermination: return FileTransfer::State::Transferring; + case Finished: return FileTransfer::State::Finished; + } + assert(false); + return FileTransfer::State::Initial; } void OutgoingJingleFileTransfer::stopAll() { - SWIFT_LOG(debug) << state << std::endl; - switch (state) { - case Initial: SWIFT_LOG(warning) << "Not yet started" << std::endl; break; - case GeneratingInitialLocalCandidates: transporter->stopGeneratingLocalCandidates(); break; - case WaitingForAccept: break; - case TryingCandidates: transporter->stopTryingRemoteCandidates(); break; - case FallbackRequested: break; - case WaitingForPeerProxyActivate: break; - case WaitingForLocalProxyActivate: transporter->stopActivatingProxy(); break; - case WaitingForCandidateAcknowledge: // Fallthrough - case Transferring: - assert(transportSession); - processedBytesConnection.disconnect(); - transferFinishedConnection.disconnect(); - transportSession->stop(); - transportSession.reset(); - break; - case Finished: SWIFT_LOG(warning) << "Already finished" << std::endl; break; - } - if (state != Initial) { - delete transporter; - } + SWIFT_LOG(debug) << state; + switch (state) { + case Initial: SWIFT_LOG(warning) << "Not yet started"; break; + case GeneratingInitialLocalCandidates: transporter->stopGeneratingLocalCandidates(); break; + case WaitingForAccept: break; + case TryingCandidates: transporter->stopTryingRemoteCandidates(); break; + case FallbackRequested: break; + case WaitingForPeerProxyActivate: break; + case WaitingForLocalProxyActivate: transporter->stopActivatingProxy(); break; + case WaitingForCandidateAcknowledge: // Fallthrough + case Transferring: + assert(transportSession); + processedBytesConnection.disconnect(); + transferFinishedConnection.disconnect(); + transportSession->stop(); + transportSession.reset(); + break; + case WaitForTermination: + break; + case Finished: SWIFT_LOG(warning) << "Already finished"; break; + } + if (state != Initial) { + removeTransporter(); + } } void OutgoingJingleFileTransfer::startTransferViaRemoteCandidate() { - SWIFT_LOG(debug) << std::endl; - - if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { - setState(WaitingForPeerProxyActivate); - } - else { - transportSession = createRemoteCandidateSession(); - startTransferringIfCandidateAcknowledged(); - } + SWIFT_LOG(debug); + + if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setInternalState(WaitingForPeerProxyActivate); + } + else { + transportSession = createRemoteCandidateSession(); + startTransferringIfCandidateAcknowledged(); + } } void OutgoingJingleFileTransfer::startTransferViaLocalCandidate() { - SWIFT_LOG(debug) << std::endl; - - if (theirCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { - setState(WaitingForLocalProxyActivate); - transporter->startActivatingProxy(theirCandidateChoice->jid); - } - else { - transportSession = createLocalCandidateSession(); - startTransferringIfCandidateAcknowledged(); - } + SWIFT_LOG(debug); + + if (theirCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setInternalState(WaitingForLocalProxyActivate); + transporter->startActivatingProxy(theirCandidateChoice->jid); + } + else { + transportSession = createLocalCandidateSession(); + startTransferringIfCandidateAcknowledged(); + } } void OutgoingJingleFileTransfer::startTransferringIfCandidateAcknowledged() { - if (candidateAcknowledged) { - startTransferring(transportSession); - } - else { - setState(WaitingForCandidateAcknowledge); - } + if (candidateAcknowledged) { + startTransferring(transportSession); + } + else { + setInternalState(WaitingForCandidateAcknowledge); + } } void OutgoingJingleFileTransfer::handleTransportInfoAcknowledged(const std::string& id) { - if (id == candidateSelectRequestID) { - candidateAcknowledged = true; - } - if (state == WaitingForCandidateAcknowledge) { - startTransferring(transportSession); - } + if (id == candidateSelectRequestID) { + candidateAcknowledged = true; + } + if (state == WaitingForCandidateAcknowledge) { + startTransferring(transportSession); + } } JingleContentID OutgoingJingleFileTransfer::getContentID() const { - return contentID; + return contentID; } bool OutgoingJingleFileTransfer::hasPriorityOnCandidateTie() const { - return true; + return true; } bool OutgoingJingleFileTransfer::isWaitingForPeerProxyActivate() const { - return state == WaitingForPeerProxyActivate; + return state == WaitingForPeerProxyActivate; } bool OutgoingJingleFileTransfer::isWaitingForLocalProxyActivate() const { - return state == WaitingForLocalProxyActivate; + return state == WaitingForLocalProxyActivate; } bool OutgoingJingleFileTransfer::isTryingCandidates() const { - return state == TryingCandidates; + return state == TryingCandidates; +} + +std::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createLocalCandidateSession() { + return transporter->createLocalCandidateSession(stream, theirCandidateChoice.get()); } -boost::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createLocalCandidateSession() { - return transporter->createLocalCandidateSession(stream); +std::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createRemoteCandidateSession() { + return transporter->createRemoteCandidateSession(stream, ourCandidateChoice.get()); } -boost::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createRemoteCandidateSession() { - return transporter->createRemoteCandidateSession(stream); +void OutgoingJingleFileTransfer::handleWaitForRemoteTerminationTimeout() { + assert(state == WaitForTermination); + SWIFT_LOG(warning) << "Other party did not terminate session. Terminate it now."; + waitForRemoteTermination->stop(); + terminate(JinglePayload::Reason::MediaError); } diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h index d1f4dc4..6db4e40 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h @@ -5,109 +5,117 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/optional/optional.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/Override.h> -#include <Swiften/Jingle/JingleContentID.h> -#include <Swiften/Elements/StreamInitiationFileInfo.h> -#include <Swiften/FileTransfer/OutgoingFileTransfer.h> -#include <Swiften/FileTransfer/JingleFileTransfer.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h> #include <Swiften/FileTransfer/FileTransferOptions.h> +#include <Swiften/FileTransfer/JingleFileTransfer.h> +#include <Swiften/FileTransfer/OutgoingFileTransfer.h> +#include <Swiften/Jingle/JingleContentID.h> +#include <Swiften/Network/Timer.h> namespace Swift { - class ReadBytestream; - class IDGenerator; - class IncrementalBytestreamHashCalculator; - class CryptoProvider; - class FileTransferTransporter; - class FileTransferTransporterFactory; - class TransportSession; - - class SWIFTEN_API OutgoingJingleFileTransfer : public OutgoingFileTransfer, public JingleFileTransfer { - public: - OutgoingJingleFileTransfer( - const JID& to, - boost::shared_ptr<JingleSession>, - boost::shared_ptr<ReadBytestream>, - FileTransferTransporterFactory*, - IDGenerator*, - const StreamInitiationFileInfo&, - const FileTransferOptions&, - CryptoProvider*); - virtual ~OutgoingJingleFileTransfer(); - - void start(); - void cancel(); - - private: - enum State { - Initial, - GeneratingInitialLocalCandidates, - WaitingForAccept, - TryingCandidates, - WaitingForPeerProxyActivate, - WaitingForLocalProxyActivate, - WaitingForCandidateAcknowledge, - FallbackRequested, - Transferring, - Finished - }; - - virtual void handleSessionAcceptReceived(const JingleContentID&, boost::shared_ptr<JingleDescription>, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; - virtual void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason) SWIFTEN_OVERRIDE; - virtual void handleTransportAcceptReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; - void startTransferViaRemoteCandidate(); - void startTransferViaLocalCandidate(); - void startTransferringIfCandidateAcknowledged(); - - virtual void handleLocalTransportCandidatesGenerated(const std::string& s5bSessionID, const std::vector<JingleS5BTransportPayload::Candidate>&) SWIFTEN_OVERRIDE; - virtual void handleTransportInfoAcknowledged(const std::string& id) SWIFTEN_OVERRIDE; - - virtual JingleContentID getContentID() const SWIFTEN_OVERRIDE; - - virtual void terminate(JinglePayload::Reason::Type reason) SWIFTEN_OVERRIDE; - - virtual void fallback() SWIFTEN_OVERRIDE; - void handleTransferFinished(boost::optional<FileTransferError>); - - void sendSessionInfoHash(); - - virtual void startTransferring(boost::shared_ptr<TransportSession>) SWIFTEN_OVERRIDE; - - virtual bool hasPriorityOnCandidateTie() const SWIFTEN_OVERRIDE; - virtual bool isWaitingForPeerProxyActivate() const SWIFTEN_OVERRIDE; - virtual bool isWaitingForLocalProxyActivate() const SWIFTEN_OVERRIDE; - virtual bool isTryingCandidates() const SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession() SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession() SWIFTEN_OVERRIDE; - - void stopAll(); - void setState(State state); - void setFinishedState(FileTransfer::State::Type, const boost::optional<FileTransferError>& error); - - static FileTransfer::State::Type getExternalState(State state); - - private: - IDGenerator* idGenerator; - boost::shared_ptr<ReadBytestream> stream; - StreamInitiationFileInfo fileInfo; - FileTransferOptions options; - JingleContentID contentID; - IncrementalBytestreamHashCalculator* hashCalculator; - State state; - bool candidateAcknowledged; - - boost::bsignals::connection processedBytesConnection; - boost::bsignals::connection transferFinishedConnection; - }; + class CryptoProvider; + class FileTransferTransporterFactory; + class IDGenerator; + class IncrementalBytestreamHashCalculator; + class ReadBytestream; + class TimerFactory; + class TransportSession; + + class SWIFTEN_API OutgoingJingleFileTransfer : public OutgoingFileTransfer, public JingleFileTransfer { + public: + OutgoingJingleFileTransfer( + const JID& to, + std::shared_ptr<JingleSession>, + std::shared_ptr<ReadBytestream>, + FileTransferTransporterFactory*, + TimerFactory*, + IDGenerator*, + const JingleFileTransferFileInfo&, + const FileTransferOptions&, + CryptoProvider*); + virtual ~OutgoingJingleFileTransfer() override; + + virtual void start() override; + virtual void cancel() override; + + private: + enum State { + Initial, + GeneratingInitialLocalCandidates, + WaitingForAccept, + TryingCandidates, + WaitingForPeerProxyActivate, + WaitingForLocalProxyActivate, + WaitingForCandidateAcknowledge, + FallbackRequested, + Transferring, + WaitForTermination, + Finished + }; + + virtual void handleSessionAcceptReceived(const JingleContentID&, std::shared_ptr<JingleDescription>, std::shared_ptr<JingleTransportPayload>) override; + virtual void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason) override; + virtual void handleTransportAcceptReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>) override; + virtual void handleTransportRejectReceived(const JingleContentID &, std::shared_ptr<JingleTransportPayload>) override; + virtual void startTransferViaRemoteCandidate() override; + virtual void startTransferViaLocalCandidate() override; + void startTransferringIfCandidateAcknowledged(); + + virtual void handleLocalTransportCandidatesGenerated(const std::string& s5bSessionID, const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string& dstAddr) override; + virtual void handleTransportInfoAcknowledged(const std::string& id) override; + + virtual JingleContentID getContentID() const override; + + virtual void terminate(JinglePayload::Reason::Type reason) override; + + virtual void fallback() override; + void handleTransferFinished(boost::optional<FileTransferError>); + + void sendSessionInfoHash(); + + virtual void startTransferring(std::shared_ptr<TransportSession>) override; + + virtual bool hasPriorityOnCandidateTie() const override; + virtual bool isWaitingForPeerProxyActivate() const override; + virtual bool isWaitingForLocalProxyActivate() const override; + virtual bool isTryingCandidates() const override; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession() override; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession() override; + + void handleWaitForRemoteTerminationTimeout(); + + void stopAll(); + void setInternalState(State state); + void setFinishedState(FileTransfer::State::Type, const boost::optional<FileTransferError>& error); + + static FileTransfer::State::Type getExternalState(State state); + + private: + IDGenerator* idGenerator; + std::shared_ptr<ReadBytestream> stream; + JingleFileTransferFileInfo fileInfo; + FileTransferOptions options; + JingleContentID contentID; + IncrementalBytestreamHashCalculator* hashCalculator; + State state; + bool candidateAcknowledged; + + Timer::ref waitForRemoteTermination; + + boost::signals2::connection processedBytesConnection; + boost::signals2::connection transferFinishedConnection; + }; } diff --git a/Swiften/FileTransfer/OutgoingSIFileTransfer.cpp b/Swiften/FileTransfer/OutgoingSIFileTransfer.cpp deleted file mode 100644 index 1c60469..0000000 --- a/Swiften/FileTransfer/OutgoingSIFileTransfer.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/FileTransfer/OutgoingSIFileTransfer.h> - -#include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> - -#include <Swiften/FileTransfer/StreamInitiationRequest.h> -#include <Swiften/FileTransfer/BytestreamsRequest.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> -#include <Swiften/FileTransfer/IBBSendSession.h> - -namespace Swift { - -OutgoingSIFileTransfer::OutgoingSIFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, unsigned long long size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer) : id(id), from(from), to(to), name(name), size(size), description(description), bytestream(bytestream), iqRouter(iqRouter), socksServer(socksServer) { -} - -void OutgoingSIFileTransfer::start() { - /* - StreamInitiation::ref streamInitiation(new StreamInitiation()); - streamInitiation->setID(id); - streamInitiation->setFileInfo(StreamInitiationFileInfo(name, description, size)); - //streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams"); - streamInitiation->addProvidedMethod("http://jabber.org/protocol/ibb"); - StreamInitiationRequest::ref request = StreamInitiationRequest::create(to, streamInitiation, iqRouter); - request->onResponse.connect(boost::bind(&OutgoingSIFileTransfer::handleStreamInitiationRequestResponse, this, _1, _2)); - request->send(); - */ -} - -void OutgoingSIFileTransfer::stop() { -} - -void OutgoingSIFileTransfer::handleStreamInitiationRequestResponse(StreamInitiation::ref, ErrorPayload::ref) { - /* - if (error) { - finish(FileTransferError()); - } - else { - if (response->getRequestedMethod() == "http://jabber.org/protocol/bytestreams") { - socksServer->addReadBytestream(id, from, to, bytestream); - Bytestreams::ref bytestreams(new Bytestreams()); - bytestreams->setStreamID(id); - HostAddressPort addressPort = socksServer->getAddressPort(); - bytestreams->addStreamHost(Bytestreams::StreamHost(addressPort.getAddress().toString(), from, addressPort.getPort())); - BytestreamsRequest::ref request = BytestreamsRequest::create(to, bytestreams, iqRouter); - request->onResponse.connect(boost::bind(&OutgoingSIFileTransfer::handleBytestreamsRequestResponse, this, _1, _2)); - request->send(); - } - else if (response->getRequestedMethod() == "http://jabber.org/protocol/ibb") { - ibbSession = boost::make_shared<IBBSendSession>(id, from, to, bytestream, iqRouter); - ibbSession->onFinished.connect(boost::bind(&OutgoingSIFileTransfer::handleIBBSessionFinished, this, _1)); - ibbSession->start(); - } - } - */ -} - -void OutgoingSIFileTransfer::handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref) { - /* - if (error) { - finish(FileTransferError()); - } - */ - //socksServer->onTransferFinished.connect(); -} - -void OutgoingSIFileTransfer::finish(boost::optional<FileTransferError>) { - /* - if (ibbSession) { - ibbSession->onFinished.disconnect(boost::bind(&OutgoingSIFileTransfer::handleIBBSessionFinished, this, _1)); - ibbSession.reset(); - } - socksServer->removeReadBytestream(id, from, to); - onFinished(error); - */ -} - -void OutgoingSIFileTransfer::handleIBBSessionFinished(boost::optional<FileTransferError>) { - //finish(error); -} - -} diff --git a/Swiften/FileTransfer/OutgoingSIFileTransfer.h b/Swiften/FileTransfer/OutgoingSIFileTransfer.h deleted file mode 100644 index 79da339..0000000 --- a/Swiften/FileTransfer/OutgoingSIFileTransfer.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2010-2013 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/FileTransfer/OutgoingFileTransfer.h> -#include <Swiften/FileTransfer/ReadBytestream.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/FileTransfer/FileTransferError.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/StreamInitiation.h> -#include <Swiften/Elements/Bytestreams.h> -#include <Swiften/Elements/ErrorPayload.h> -#include <Swiften/FileTransfer/IBBSendSession.h> - -namespace Swift { - class IQRouter; - class SOCKS5BytestreamServer; - - class OutgoingSIFileTransfer : public OutgoingFileTransfer { - public: - OutgoingSIFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, unsigned long long size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer); - - virtual void start(); - virtual void stop(); - - boost::signal<void (const boost::optional<FileTransferError>&)> onFinished; - - private: - void handleStreamInitiationRequestResponse(StreamInitiation::ref, ErrorPayload::ref); - void handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref); - void finish(boost::optional<FileTransferError> error); - void handleIBBSessionFinished(boost::optional<FileTransferError> error); - - private: - std::string id; - JID from; - JID to; - std::string name; - unsigned long long size; - std::string description; - boost::shared_ptr<ReadBytestream> bytestream; - IQRouter* iqRouter; - SOCKS5BytestreamServer* socksServer; - boost::shared_ptr<IBBSendSession> ibbSession; - }; -} diff --git a/Swiften/FileTransfer/ReadBytestream.cpp b/Swiften/FileTransfer/ReadBytestream.cpp index 5fa10d8..9e67eae 100644 --- a/Swiften/FileTransfer/ReadBytestream.cpp +++ b/Swiften/FileTransfer/ReadBytestream.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/ReadBytestream.h> diff --git a/Swiften/FileTransfer/ReadBytestream.h b/Swiften/FileTransfer/ReadBytestream.h index b0663ab..f146c04 100644 --- a/Swiften/FileTransfer/ReadBytestream.h +++ b/Swiften/FileTransfer/ReadBytestream.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <vector> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class SWIFTEN_API ReadBytestream { - public: - virtual ~ReadBytestream(); - - /** - * Return an empty vector if no more data is available. - * Use onDataAvailable signal for signaling there is data available again. - */ - virtual boost::shared_ptr< std::vector<unsigned char> > read(size_t size) = 0; - - virtual bool isFinished() const = 0; - - public: - boost::signal<void ()> onDataAvailable; - boost::signal<void (const std::vector<unsigned char>&)> onRead; - }; + class SWIFTEN_API ReadBytestream { + public: + virtual ~ReadBytestream(); + + /** + * Return an empty vector if no more data is available. + * Use onDataAvailable signal for signaling there is data available again. + */ + virtual std::shared_ptr< std::vector<unsigned char> > read(size_t size) = 0; + + virtual bool isFinished() const = 0; + + public: + boost::signals2::signal<void ()> onDataAvailable; + boost::signals2::signal<void (const std::vector<unsigned char>&)> onRead; + }; } diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp index 1e96b22..4023be3 100644 --- a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp +++ b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp @@ -5,91 +5,93 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2019 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/bind.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> -#include <Swiften/Network/ConnectionFactory.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/Network/ConnectionFactory.h> using namespace Swift; RemoteJingleTransportCandidateSelector::RemoteJingleTransportCandidateSelector( - ConnectionFactory* connectionFactory, - TimerFactory* timerFactory) : - connectionFactory(connectionFactory), - timerFactory(timerFactory) { + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + const FileTransferOptions& options) : + connectionFactory(connectionFactory), + timerFactory(timerFactory), + options(options) { } RemoteJingleTransportCandidateSelector::~RemoteJingleTransportCandidateSelector() { } void RemoteJingleTransportCandidateSelector::addCandidates( - const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - foreach(JingleS5BTransportPayload::Candidate c, candidates) { - this->candidates.push(c); - } + const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { + for (auto&& c : candidates) { + this->candidates.push(c); + } } void RemoteJingleTransportCandidateSelector::startSelectingCandidate() { - tryNextCandidate(); + tryNextCandidate(); } void RemoteJingleTransportCandidateSelector::stopSelectingCandidate() { - if (s5bSession) { - sessionReadyConnection.disconnect(); - s5bSession->stop(); - } + if (s5bSession) { + sessionReadyConnection.disconnect(); + s5bSession->stop(); + } } void RemoteJingleTransportCandidateSelector::tryNextCandidate() { - if (candidates.empty()) { - SWIFT_LOG(debug) << "No more candidates" << std::endl; - onCandidateSelectFinished( - boost::optional<JingleS5BTransportPayload::Candidate>(), boost::shared_ptr<SOCKS5BytestreamClientSession>()); - } - else { - lastCandidate = candidates.top(); - candidates.pop(); - SWIFT_LOG(debug) << "Trying candidate " << lastCandidate.cid << std::endl; - if (lastCandidate.type == JingleS5BTransportPayload::Candidate::DirectType - || lastCandidate.type == JingleS5BTransportPayload::Candidate::AssistedType - || lastCandidate.type == JingleS5BTransportPayload::Candidate::ProxyType ) { - boost::shared_ptr<Connection> connection = connectionFactory->createConnection(); - s5bSession = boost::make_shared<SOCKS5BytestreamClientSession>( - connection, lastCandidate.hostPort, socks5DstAddr, timerFactory); - sessionReadyConnection = s5bSession->onSessionReady.connect( - boost::bind(&RemoteJingleTransportCandidateSelector::handleSessionReady, this, _1)); - s5bSession->start(); - } - else { - SWIFT_LOG(debug) << "Can't handle this type of candidate" << std::endl; - tryNextCandidate(); - } - } + if (candidates.empty()) { + SWIFT_LOG(debug) << "No more candidates"; + onCandidateSelectFinished( + boost::optional<JingleS5BTransportPayload::Candidate>(), std::shared_ptr<SOCKS5BytestreamClientSession>()); + } + else { + lastCandidate = candidates.top(); + candidates.pop(); + SWIFT_LOG(debug) << "Trying candidate " << lastCandidate.cid; + if ((lastCandidate.type == JingleS5BTransportPayload::Candidate::DirectType && options.isDirectAllowed()) || + (lastCandidate.type == JingleS5BTransportPayload::Candidate::AssistedType && options.isAssistedAllowed()) || + (lastCandidate.type == JingleS5BTransportPayload::Candidate::ProxyType && options.isProxiedAllowed())) { + std::shared_ptr<Connection> connection = connectionFactory->createConnection(); + s5bSession = std::make_shared<SOCKS5BytestreamClientSession>( + connection, lastCandidate.hostPort, socks5DstAddr, timerFactory); + sessionReadyConnection = s5bSession->onSessionReady.connect( + boost::bind(&RemoteJingleTransportCandidateSelector::handleSessionReady, this, _1)); + s5bSession->start(); + } + else { + SWIFT_LOG(debug) << "Can't handle this type of candidate"; + tryNextCandidate(); + } + } } void RemoteJingleTransportCandidateSelector::handleSessionReady(bool error) { - sessionReadyConnection.disconnect(); - if (error) { - s5bSession.reset(); - tryNextCandidate(); - } - else { - onCandidateSelectFinished(lastCandidate, s5bSession); - } + sessionReadyConnection.disconnect(); + if (error) { + s5bSession.reset(); + tryNextCandidate(); + } + else { + onCandidateSelectFinished(lastCandidate, s5bSession); + } } void RemoteJingleTransportCandidateSelector::setSOCKS5DstAddr(const std::string& socks5DstAddr) { - this->socks5DstAddr = socks5DstAddr; + this->socks5DstAddr = socks5DstAddr; } diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h index 66ab4b2..c205516 100644 --- a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h +++ b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h @@ -5,57 +5,57 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> + +#include <memory> #include <queue> #include <vector> -#include <boost/shared_ptr.hpp> - -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> #include <Swiften/JID/JID.h> #include <Swiften/Network/Connection.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> -#include <Swiften/Elements/JingleS5BTransportPayload.h> - namespace Swift { - class ConnectionFactory; - class TimerFactory; - - class RemoteJingleTransportCandidateSelector { - public: - RemoteJingleTransportCandidateSelector(ConnectionFactory*, TimerFactory*); - virtual ~RemoteJingleTransportCandidateSelector(); - - virtual void addCandidates(const std::vector<JingleS5BTransportPayload::Candidate>&); - virtual void setSOCKS5DstAddr(const std::string&); - virtual void startSelectingCandidate(); - virtual void stopSelectingCandidate(); - - boost::signal<void (const boost::optional<JingleS5BTransportPayload::Candidate>&, boost::shared_ptr<SOCKS5BytestreamClientSession>)> onCandidateSelectFinished; - - private: - void tryNextCandidate(); - void handleSessionReady(bool error); - - private: - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; - - std::priority_queue< - JingleS5BTransportPayload::Candidate, - std::vector<JingleS5BTransportPayload::Candidate>, - JingleS5BTransportPayload::CompareCandidate> candidates; - boost::shared_ptr<SOCKS5BytestreamClientSession> s5bSession; - boost::bsignals::connection sessionReadyConnection; - JingleS5BTransportPayload::Candidate lastCandidate; - std::string socks5DstAddr; - }; + class ConnectionFactory; + class TimerFactory; + + class RemoteJingleTransportCandidateSelector { + public: + RemoteJingleTransportCandidateSelector(ConnectionFactory*, TimerFactory*, const FileTransferOptions&); + virtual ~RemoteJingleTransportCandidateSelector(); + + virtual void addCandidates(const std::vector<JingleS5BTransportPayload::Candidate>&); + virtual void setSOCKS5DstAddr(const std::string&); + virtual void startSelectingCandidate(); + virtual void stopSelectingCandidate(); + + boost::signals2::signal<void (const boost::optional<JingleS5BTransportPayload::Candidate>&, std::shared_ptr<SOCKS5BytestreamClientSession>)> onCandidateSelectFinished; + + private: + void tryNextCandidate(); + void handleSessionReady(bool error); + + private: + ConnectionFactory* connectionFactory; + TimerFactory* timerFactory; + + std::priority_queue< + JingleS5BTransportPayload::Candidate, + std::vector<JingleS5BTransportPayload::Candidate>, + JingleS5BTransportPayload::CompareCandidate> candidates; + std::shared_ptr<SOCKS5BytestreamClientSession> s5bSession; + boost::signals2::connection sessionReadyConnection; + JingleS5BTransportPayload::Candidate lastCandidate; + std::string socks5DstAddr; + FileTransferOptions options; + }; } diff --git a/Swiften/FileTransfer/S5BTransportSession.h b/Swiften/FileTransfer/S5BTransportSession.h new file mode 100644 index 0000000..fd92f2e --- /dev/null +++ b/Swiften/FileTransfer/S5BTransportSession.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/bind.hpp> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/FileTransfer/ReadBytestream.h> +#include <Swiften/FileTransfer/TransportSession.h> +#include <Swiften/FileTransfer/WriteBytestream.h> + +namespace Swift { + +template <typename T> +class SWIFTEN_API S5BTransportSession : public TransportSession { + public: + S5BTransportSession( + std::shared_ptr<T> session, + std::shared_ptr<ReadBytestream> readStream) : + session(session), + readStream(readStream) { + initialize(); + } + + S5BTransportSession( + std::shared_ptr<T> session, + std::shared_ptr<WriteBytestream> writeStream) : + session(session), + writeStream(writeStream) { + initialize(); + } + + virtual ~S5BTransportSession() override { + } + + virtual void start() override { + if (readStream) { + session->startSending(readStream); + } + else { + session->startReceiving(writeStream); + } + } + + virtual void stop() override { + session->stop(); + } + + private: + void initialize() { + finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); + bytesSentConnection = session->onBytesSent.connect(boost::bind(boost::ref(onBytesSent), _1)); + } + + private: + std::shared_ptr<T> session; + std::shared_ptr<ReadBytestream> readStream; + std::shared_ptr<WriteBytestream> writeStream; + + boost::signals2::scoped_connection finishedConnection; + boost::signals2::scoped_connection bytesSentConnection; +}; + +} diff --git a/Swiften/FileTransfer/SConscript b/Swiften/FileTransfer/SConscript index 6c29ea6..d49b596 100644 --- a/Swiften/FileTransfer/SConscript +++ b/Swiften/FileTransfer/SConscript @@ -1,50 +1,53 @@ Import("swiften_env", "env") sources = [ - "ByteArrayReadBytestream.cpp", - "OutgoingFileTransfer.cpp", - "OutgoingSIFileTransfer.cpp", - "OutgoingJingleFileTransfer.cpp", - "OutgoingFileTransferManager.cpp", - "IncomingFileTransfer.cpp", - "IncomingJingleFileTransfer.cpp", - "IncomingFileTransferManager.cpp", - "JingleFileTransfer.cpp", - "FileTransferOptions.cpp", - "FileTransferTransporter.cpp", - "FileTransferTransporterFactory.cpp", - "DefaultFileTransferTransporter.cpp", - "DefaultFileTransferTransporterFactory.cpp", - "RemoteJingleTransportCandidateSelector.cpp", - "LocalJingleTransportCandidateGenerator.cpp", - "ReadBytestream.cpp", - "WriteBytestream.cpp", - "FileReadBytestream.cpp", - "FileWriteBytestream.cpp", - "FileTransfer.cpp", - "TransportSession.cpp", - "SOCKS5BytestreamClientSession.cpp", - "SOCKS5BytestreamServerInitializeRequest.cpp", - "SOCKS5BytestreamServerManager.cpp", - "SOCKS5BytestreamServer.cpp", - "SOCKS5BytestreamServerSession.cpp", - "SOCKS5BytestreamRegistry.cpp", - "SOCKS5BytestreamProxiesManager.cpp", - "SOCKS5BytestreamProxyFinder.cpp", - "IBBSendSession.cpp", - "IBBReceiveSession.cpp", - "FileTransferManager.cpp", - "FileTransferManagerImpl.cpp", - "IncrementalBytestreamHashCalculator.cpp", - ] + "ByteArrayReadBytestream.cpp", + "DefaultFileTransferTransporter.cpp", + "DefaultFileTransferTransporterFactory.cpp", + "FailingTransportSession.cpp", + "FileReadBytestream.cpp", + "FileTransfer.cpp", + "FileTransferManager.cpp", + "FileTransferManagerImpl.cpp", + "FileTransferOptions.cpp", + "FileTransferTransporter.cpp", + "FileTransferTransporterFactory.cpp", + "FileWriteBytestream.cpp", + "IBBReceiveSession.cpp", + "IBBReceiveTransportSession.cpp", + "IBBSendSession.cpp", + "IBBSendTransportSession.cpp", + "IncomingFileTransfer.cpp", + "IncomingFileTransferManager.cpp", + "IncomingJingleFileTransfer.cpp", + "IncrementalBytestreamHashCalculator.cpp", + "JingleFileTransfer.cpp", + "LocalJingleTransportCandidateGenerator.cpp", + "OutgoingFileTransfer.cpp", + "OutgoingFileTransferManager.cpp", + "OutgoingJingleFileTransfer.cpp", + "ReadBytestream.cpp", + "RemoteJingleTransportCandidateSelector.cpp", + "SOCKS5BytestreamClientSession.cpp", + "SOCKS5BytestreamProxiesManager.cpp", + "SOCKS5BytestreamProxyFinder.cpp", + "SOCKS5BytestreamRegistry.cpp", + "SOCKS5BytestreamServer.cpp", + "SOCKS5BytestreamServerManager.cpp", + "SOCKS5BytestreamServerPortForwardingUser.cpp", + "SOCKS5BytestreamServerResourceUser.cpp", + "SOCKS5BytestreamServerSession.cpp", + "TransportSession.cpp", + "WriteBytestream.cpp", + ] swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources)) env.Append(UNITTEST_SOURCES = [ - File("UnitTest/SOCKS5BytestreamServerSessionTest.cpp"), - File("UnitTest/SOCKS5BytestreamClientSessionTest.cpp"), - File("UnitTest/IBBSendSessionTest.cpp"), - File("UnitTest/IBBReceiveSessionTest.cpp"), - File("UnitTest/IncomingJingleFileTransferTest.cpp"), - File("UnitTest/OutgoingJingleFileTransferTest.cpp"), - ]) + File("UnitTest/IBBReceiveSessionTest.cpp"), + File("UnitTest/IBBSendSessionTest.cpp"), + File("UnitTest/IncomingJingleFileTransferTest.cpp"), + File("UnitTest/OutgoingJingleFileTransferTest.cpp"), + File("UnitTest/SOCKS5BytestreamClientSessionTest.cpp"), + File("UnitTest/SOCKS5BytestreamServerSessionTest.cpp"), + ]) diff --git a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp index b371078..a3f0dab 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp @@ -5,264 +5,272 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2019 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#include "SOCKS5BytestreamClientSession.h" +#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> #include <boost/bind.hpp> #include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/Algorithm.h> -#include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Concat.h> #include <Swiften/Base/Log.h> -#include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/FileTransfer/BytestreamException.h> #include <Swiften/Network/TimerFactory.h> -#include <Swiften/Base/ByteArray.h> +#include <Swiften/StringCodecs/Hexify.h> namespace Swift { SOCKS5BytestreamClientSession::SOCKS5BytestreamClientSession( - boost::shared_ptr<Connection> connection, - const HostAddressPort& addressPort, - const std::string& destination, - TimerFactory* timerFactory) : - connection(connection), - addressPort(addressPort), - destination(destination), - state(Initial), - chunkSize(131072) { - weFailedTimeout = timerFactory->createTimer(2000); - weFailedTimeout->onTick.connect( - boost::bind(&SOCKS5BytestreamClientSession::handleWeFailedTimeout, this)); + std::shared_ptr<Connection> connection, + const HostAddressPort& addressPort, + const std::string& destination, + TimerFactory* timerFactory) : + connection(connection), + addressPort(addressPort), + destination(destination), + state(Initial), + chunkSize(131072) { + weFailedTimeout = timerFactory->createTimer(3000); + weFailedTimeout->onTick.connect( + boost::bind(&SOCKS5BytestreamClientSession::handleWeFailedTimeout, this)); } SOCKS5BytestreamClientSession::~SOCKS5BytestreamClientSession() { + weFailedTimeout->onTick.disconnect( + boost::bind(&SOCKS5BytestreamClientSession::handleWeFailedTimeout, this)); + weFailedTimeout->stop(); } void SOCKS5BytestreamClientSession::start() { - assert(state == Initial); - SWIFT_LOG(debug) << "Trying to connect via TCP to " << addressPort.toString() << "." << std::endl; - weFailedTimeout->start(); - connectFinishedConnection = connection->onConnectFinished.connect( - boost::bind(&SOCKS5BytestreamClientSession::handleConnectFinished, this, _1)); - connection->connect(addressPort); + assert(state == Initial); + SWIFT_LOG(debug) << "Trying to connect via TCP to " << addressPort.toString() << "."; + weFailedTimeout->start(); + connectFinishedConnection = connection->onConnectFinished.connect( + boost::bind(&SOCKS5BytestreamClientSession::handleConnectFinished, this, _1)); + connection->connect(addressPort); } void SOCKS5BytestreamClientSession::stop() { - SWIFT_LOG(debug) << std::endl; - if (state == Finished) { - return; - } - closeConnection(); - readBytestream.reset(); - state = Finished; + SWIFT_LOG(debug); + if (state < Ready) { + weFailedTimeout->stop(); + } + if (state == Finished) { + return; + } + closeConnection(); + readBytestream.reset(); + state = Finished; } void SOCKS5BytestreamClientSession::process() { - SWIFT_LOG(debug) << "unprocessedData.size(): " << unprocessedData.size() << std::endl; - ByteArray bndAddress; - switch(state) { - case Initial: - hello(); - break; - case Hello: - if (unprocessedData.size() > 1) { - unsigned char version = unprocessedData[0]; - unsigned char authMethod = unprocessedData[1]; - if (version != 5 || authMethod != 0) { - // signal failure to upper level - finish(true); - return; - } - unprocessedData.clear(); - authenticate(); - } - break; - case Authenticating: - if (unprocessedData.size() < 5) { - // need more data to start progressing - break; - } - if (unprocessedData[0] != '\x05') { - // wrong version - // disconnect & signal failure - finish(true); - break; - } - if (unprocessedData[1] != '\x00') { - // no success - // disconnect & signal failure - finish(true); - break; - } - if (unprocessedData[3] != '\x03') { - // we expect x'03' = DOMAINNAME here - // discconect & signal failure - finish(true); - break; - } - if (static_cast<size_t>(unprocessedData[4]) + 1 > unprocessedData.size() + 5) { - // complete domainname and port not available yet - break; - } - bndAddress = createByteArray(&vecptr(unprocessedData)[5], unprocessedData[4]); - if (unprocessedData[unprocessedData[4] + 5] != 0 && bndAddress == createByteArray(destination)) { - // we expect a 0 as port - // disconnect and fail - finish(true); - } - unprocessedData.clear(); - state = Ready; - SWIFT_LOG(debug) << "session ready" << std::endl; - // issue ready signal so the bytestream can be used for reading or writing - weFailedTimeout->stop(); - onSessionReady(false); - break; - case Ready: - SWIFT_LOG(debug) << "Received further data in Ready state." << std::endl; - break; - case Reading: - case Writing: - case Finished: - SWIFT_LOG(debug) << "Unexpected receive of data. Current state: " << state << std::endl; - SWIFT_LOG(debug) << "Data: " << Hexify::hexify(unprocessedData) << std::endl; - unprocessedData.clear(); - //assert(false); - } + SWIFT_LOG(debug) << "unprocessedData.size(): " << unprocessedData.size(); + ByteArray bndAddress; + switch(state) { + case Initial: + hello(); + break; + case Hello: + if (unprocessedData.size() > 1) { + unsigned char version = unprocessedData[0]; + unsigned char authMethod = unprocessedData[1]; + if (version != 5 || authMethod != 0) { + // signal failure to upper level + finish(true); + return; + } + unprocessedData.clear(); + authenticate(); + } + break; + case Authenticating: + if (unprocessedData.size() < 5) { + // need more data to start progressing + break; + } + if (unprocessedData[0] != '\x05') { + // wrong version + // disconnect & signal failure + finish(true); + break; + } + if (unprocessedData[1] != '\x00') { + // no success + // disconnect & signal failure + finish(true); + break; + } + if (unprocessedData[3] != '\x03') { + // we expect x'03' = DOMAINNAME here + // disconnect & signal failure + finish(true); + break; + } + if (static_cast<size_t>(unprocessedData[4]) + 1 > unprocessedData.size() + 5) { + // complete domainname and port not available yet + break; + } + bndAddress = createByteArray(&vecptr(unprocessedData)[5], unprocessedData[4]); + if (unprocessedData[unprocessedData[4] + 5] != 0 && bndAddress == createByteArray(destination)) { + // we expect a 0 as port + // disconnect and fail + finish(true); + } + unprocessedData.clear(); + state = Ready; + SWIFT_LOG(debug) << "session ready"; + // issue ready signal so the bytestream can be used for reading or writing + weFailedTimeout->stop(); + onSessionReady(false); + break; + case Ready: + SWIFT_LOG(debug) << "Received further data in Ready state."; + break; + case Reading: + case Writing: + case Finished: + SWIFT_LOG(debug) << "Unexpected receive of data. Current state: " << state; + SWIFT_LOG(debug) << "Data: " << Hexify::hexify(unprocessedData); + unprocessedData.clear(); + //assert(false); + } } void SOCKS5BytestreamClientSession::hello() { - // Version 5, 1 auth method, No authentication - const SafeByteArray hello = createSafeByteArray("\x05\x01\x00", 3); - connection->write(hello); - state = Hello; + // Version 5, 1 auth method, No authentication + const SafeByteArray hello = createSafeByteArray("\x05\x01\x00", 3); + connection->write(hello); + state = Hello; } void SOCKS5BytestreamClientSession::authenticate() { - SWIFT_LOG(debug) << std::endl; - SafeByteArray header = createSafeByteArray("\x05\x01\x00\x03", 4); - SafeByteArray message = header; - append(message, createSafeByteArray(boost::numeric_cast<char>(destination.size()))); - authenticateAddress = createByteArray(destination); - append(message, authenticateAddress); - append(message, createSafeByteArray("\x00\x00", 2)); // 2 byte for port - connection->write(message); - state = Authenticating; + SWIFT_LOG(debug); + SafeByteArray header = createSafeByteArray("\x05\x01\x00\x03", 4); + SafeByteArray message = header; + append(message, createSafeByteArray(boost::numeric_cast<char>(destination.size()))); + authenticateAddress = createByteArray(destination); + append(message, authenticateAddress); + append(message, createSafeByteArray("\x00\x00", 2)); // 2 byte for port + connection->write(message); + state = Authenticating; } -void SOCKS5BytestreamClientSession::startReceiving(boost::shared_ptr<WriteBytestream> writeStream) { - if (state == Ready) { - state = Reading; - writeBytestream = writeStream; - writeBytestream->write(unprocessedData); - onBytesReceived(unprocessedData.size()); - unprocessedData.clear(); - } else { - SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl; - } +void SOCKS5BytestreamClientSession::startReceiving(std::shared_ptr<WriteBytestream> writeStream) { + if (state == Ready) { + state = Reading; + writeBytestream = writeStream; + writeBytestream->write(unprocessedData); + unprocessedData.clear(); + } else { + SWIFT_LOG(debug) << "Session isn't ready for transfer yet!"; + } } -void SOCKS5BytestreamClientSession::startSending(boost::shared_ptr<ReadBytestream> readStream) { - if (state == Ready) { - state = Writing; - readBytestream = readStream; - dataWrittenConnection = connection->onDataWritten.connect( - boost::bind(&SOCKS5BytestreamClientSession::sendData, this)); - sendData(); - } else { - SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl; - } +void SOCKS5BytestreamClientSession::startSending(std::shared_ptr<ReadBytestream> readStream) { + if (state == Ready) { + state = Writing; + readBytestream = readStream; + dataWrittenConnection = connection->onDataWritten.connect( + boost::bind(&SOCKS5BytestreamClientSession::sendData, this)); + sendData(); + } else { + SWIFT_LOG(debug) << "Session isn't ready for transfer yet!"; + } } HostAddressPort SOCKS5BytestreamClientSession::getAddressPort() const { - return addressPort; + return addressPort; } void SOCKS5BytestreamClientSession::sendData() { - if (!readBytestream->isFinished()) { - try { - boost::shared_ptr<ByteArray> dataToSend = readBytestream->read(boost::numeric_cast<size_t>(chunkSize)); - connection->write(createSafeByteArray(*dataToSend)); - onBytesSent(dataToSend->size()); - } - catch (const BytestreamException&) { - finish(true); - } - } - else { - finish(false); - } + if (!readBytestream->isFinished()) { + try { + std::shared_ptr<ByteArray> dataToSend = readBytestream->read(boost::numeric_cast<size_t>(chunkSize)); + connection->write(createSafeByteArray(*dataToSend)); + onBytesSent(dataToSend->size()); + } + catch (const BytestreamException&) { + finish(true); + } + } + else { + finish(false); + } } void SOCKS5BytestreamClientSession::finish(bool error) { - SWIFT_LOG(debug) << std::endl; - weFailedTimeout->stop(); - closeConnection(); - readBytestream.reset(); - if (state == Initial || state == Hello || state == Authenticating) { - onSessionReady(true); - } - else { - state = Finished; - if (error) { - onFinished(boost::optional<FileTransferError>(FileTransferError::ReadError)); - } else { - onFinished(boost::optional<FileTransferError>()); - } - } + SWIFT_LOG(debug); + if (state < Ready) { + weFailedTimeout->stop(); + } + closeConnection(); + readBytestream.reset(); + if (state == Initial || state == Hello || state == Authenticating) { + onSessionReady(true); + } + else { + state = Finished; + if (error) { + onFinished(boost::optional<FileTransferError>(FileTransferError::ReadError)); + } else { + onFinished(boost::optional<FileTransferError>()); + } + } } void SOCKS5BytestreamClientSession::handleConnectFinished(bool error) { - connectFinishedConnection.disconnect(); - if (error) { - SWIFT_LOG(debug) << "Failed to connect via TCP to " << addressPort.toString() << "." << std::endl; - finish(true); - } else { - SWIFT_LOG(debug) << "Successfully connected via TCP" << addressPort.toString() << "." << std::endl; - disconnectedConnection = connection->onDisconnected.connect( - boost::bind(&SOCKS5BytestreamClientSession::handleDisconnected, this, _1)); - dataReadConnection = connection->onDataRead.connect( - boost::bind(&SOCKS5BytestreamClientSession::handleDataRead, this, _1)); - weFailedTimeout->start(); - process(); - } + connectFinishedConnection.disconnect(); + if (error) { + SWIFT_LOG(debug) << "Failed to connect via TCP to " << addressPort.toString() << "."; + finish(true); + } else { + SWIFT_LOG(debug) << "Successfully connected via TCP" << addressPort.toString() << "."; + disconnectedConnection = connection->onDisconnected.connect( + boost::bind(&SOCKS5BytestreamClientSession::handleDisconnected, this, _1)); + dataReadConnection = connection->onDataRead.connect( + boost::bind(&SOCKS5BytestreamClientSession::handleDataRead, this, _1)); + weFailedTimeout->stop(); + weFailedTimeout->start(); + process(); + } } -void SOCKS5BytestreamClientSession::handleDataRead(boost::shared_ptr<SafeByteArray> data) { - SWIFT_LOG(debug) << "state: " << state << " data.size() = " << data->size() << std::endl; - if (state != Reading) { - append(unprocessedData, *data); - process(); - } - else { - writeBytestream->write(createByteArray(vecptr(*data), data->size())); - onBytesReceived(data->size()); - } +void SOCKS5BytestreamClientSession::handleDataRead(std::shared_ptr<SafeByteArray> data) { + SWIFT_LOG(debug) << "state: " << state << " data.size() = " << data->size(); + if (state != Reading) { + append(unprocessedData, *data); + process(); + } + else { + writeBytestream->write(createByteArray(vecptr(*data), data->size())); + //onBytesReceived(data->size()); + } } void SOCKS5BytestreamClientSession::handleDisconnected(const boost::optional<Connection::Error>& error) { - SWIFT_LOG(debug) << (error ? (error == Connection::ReadError ? "Read Error" : "Write Error") : "No Error") << std::endl; - if (error) { - finish(true); - } + SWIFT_LOG(debug) << (error ? (error == Connection::ReadError ? "Read Error" : "Write Error") : "No Error"); + if (error) { + finish(true); + } } void SOCKS5BytestreamClientSession::handleWeFailedTimeout() { - SWIFT_LOG(debug) << "Failed due to timeout!" << std::endl; - finish(true); + SWIFT_LOG(debug) << "Failed due to timeout!"; + finish(true); } void SOCKS5BytestreamClientSession::closeConnection() { - connectFinishedConnection.disconnect(); - dataWrittenConnection.disconnect(); - dataReadConnection.disconnect(); - disconnectedConnection.disconnect(); - connection->disconnect(); + connectFinishedConnection.disconnect(); + dataWrittenConnection.disconnect(); + dataReadConnection.disconnect(); + disconnectedConnection.disconnect(); + connection->disconnect(); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h index 287cf3b..70a7c9c 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h @@ -4,16 +4,23 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/optional.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/FileTransfer/FileTransferError.h> -#include <Swiften/FileTransfer/WriteBytestream.h> #include <Swiften/FileTransfer/ReadBytestream.h> +#include <Swiften/FileTransfer/WriteBytestream.h> #include <Swiften/JID/JID.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/HostAddressPort.h> @@ -21,7 +28,6 @@ namespace Swift { -class SOCKS5BytestreamRegistry; class Connection; class TimerFactory; @@ -31,75 +37,75 @@ class TimerFactory; */ class SWIFTEN_API SOCKS5BytestreamClientSession { public: - enum State { - Initial, - Hello, - Authenticating, - Ready, - Writing, - Reading, - Finished - }; + enum State { + Initial, + Hello, + Authenticating, + Ready, + Writing, + Reading, + Finished + }; public: - typedef boost::shared_ptr<SOCKS5BytestreamClientSession> ref; + typedef std::shared_ptr<SOCKS5BytestreamClientSession> ref; public: - SOCKS5BytestreamClientSession( - boost::shared_ptr<Connection> connection, - const HostAddressPort&, - const std::string&, - TimerFactory*); - ~SOCKS5BytestreamClientSession(); + SOCKS5BytestreamClientSession( + std::shared_ptr<Connection> connection, + const HostAddressPort&, + const std::string&, + TimerFactory*); + ~SOCKS5BytestreamClientSession(); - void start(); - void stop(); + void start(); + void stop(); - void startReceiving(boost::shared_ptr<WriteBytestream>); - void startSending(boost::shared_ptr<ReadBytestream>); + void startReceiving(std::shared_ptr<WriteBytestream>); + void startSending(std::shared_ptr<ReadBytestream>); - HostAddressPort getAddressPort() const; + HostAddressPort getAddressPort() const; - boost::signal<void (bool /*error*/)> onSessionReady; + boost::signals2::signal<void (bool /*error*/)> onSessionReady; - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - boost::signal<void (size_t)> onBytesSent; - boost::signal<void (size_t)> onBytesReceived; + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + boost::signals2::signal<void (size_t)> onBytesSent; + // boost::signals2::signal<void (size_t)> onBytesReceived; private: - void process(); - void hello(); - void authenticate(); + void process(); + void hello(); + void authenticate(); - void handleConnectFinished(bool error); - void handleDataRead(boost::shared_ptr<SafeByteArray>); - void handleDisconnected(const boost::optional<Connection::Error>&); - void handleWeFailedTimeout(); + void handleConnectFinished(bool error); + void handleDataRead(std::shared_ptr<SafeByteArray>); + void handleDisconnected(const boost::optional<Connection::Error>&); + void handleWeFailedTimeout(); - void finish(bool error); - void sendData(); - void closeConnection(); + void finish(bool error); + void sendData(); + void closeConnection(); private: - boost::shared_ptr<Connection> connection; - HostAddressPort addressPort; - std::string destination; // hexify(SHA1(sessionID + requester + target)) + std::shared_ptr<Connection> connection; + HostAddressPort addressPort; + std::string destination; // hexify(SHA1(sessionID + requester + target)) - State state; + State state; - ByteArray unprocessedData; - ByteArray authenticateAddress; + ByteArray unprocessedData; + ByteArray authenticateAddress; - int chunkSize; - boost::shared_ptr<WriteBytestream> writeBytestream; - boost::shared_ptr<ReadBytestream> readBytestream; + int chunkSize; + std::shared_ptr<WriteBytestream> writeBytestream; + std::shared_ptr<ReadBytestream> readBytestream; - Timer::ref weFailedTimeout; + Timer::ref weFailedTimeout; - boost::bsignals::connection connectFinishedConnection; - boost::bsignals::connection dataWrittenConnection; - boost::bsignals::connection dataReadConnection; - boost::bsignals::connection disconnectedConnection; + boost::signals2::scoped_connection connectFinishedConnection; + boost::signals2::scoped_connection dataWrittenConnection; + boost::signals2::scoped_connection dataReadConnection; + boost::signals2::scoped_connection disconnectedConnection; }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp index 0b94763..72c4d41 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp @@ -4,69 +4,204 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + + #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + +#include <boost/bind.hpp> -#include <Swiften/Base/foreach.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> #include <Swiften/Base/Log.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> +#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/Network/DomainNameResolveError.h> +#include <Swiften/Network/DomainNameResolver.h> +#include <Swiften/Network/TimerFactory.h> namespace Swift { -SOCKS5BytestreamProxiesManager::SOCKS5BytestreamProxiesManager(ConnectionFactory *connFactory, TimerFactory *timeFactory) : connectionFactory(connFactory), timerFactory(timeFactory) { +SOCKS5BytestreamProxiesManager::SOCKS5BytestreamProxiesManager(ConnectionFactory *connFactory, TimerFactory *timeFactory, DomainNameResolver* resolver, IQRouter* iqRouter, const JID& serviceRoot) : connectionFactory_(connFactory), timerFactory_(timeFactory), resolver_(resolver), iqRouter_(iqRouter), serviceRoot_(serviceRoot) { } +SOCKS5BytestreamProxiesManager::~SOCKS5BytestreamProxiesManager() { + if (proxyFinder_) { + proxyFinder_->stop(); + } + + for (const auto& sessionsForID : proxySessions_) { + for (const auto& session : sessionsForID.second) { + session.second->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this,sessionsForID.first, session.first, session.second, _1)); + session.second->onFinished.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionsForID.first, session.first, session.second, _1)); + } + } +} + void SOCKS5BytestreamProxiesManager::addS5BProxy(S5BProxyRequest::ref proxy) { - localS5BProxies.push_back(proxy); + if (proxy) { + SWIFT_LOG_ASSERT(HostAddress::fromString(proxy->getStreamHost().get().host), warning); + if (!localS5BProxies_) { + localS5BProxies_ = std::vector<S5BProxyRequest::ref>(); + } + localS5BProxies_->push_back(proxy); + } } -const std::vector<S5BProxyRequest::ref>& SOCKS5BytestreamProxiesManager::getS5BProxies() const { - return localS5BProxies; +const boost::optional<std::vector<S5BProxyRequest::ref> >& SOCKS5BytestreamProxiesManager::getOrDiscoverS5BProxies() { + if (!localS5BProxies_ && !proxyFinder_) { + queryForProxies(); + } + return localS5BProxies_; } void SOCKS5BytestreamProxiesManager::connectToProxies(const std::string& sessionID) { - SWIFT_LOG(debug) << "session ID: " << sessionID << std::endl; - ProxyJIDClientSessionMap clientSessions; - - foreach(S5BProxyRequest::ref proxy, localS5BProxies) { - boost::shared_ptr<Connection> conn = connectionFactory->createConnection(); + SWIFT_LOG(debug) << "session ID: " << sessionID; + ProxyJIDClientSessionVector clientSessions; + + if (localS5BProxies_) { + for (auto&& proxy : localS5BProxies_.get()) { + auto proxyHostAddress = HostAddress::fromString(proxy->getStreamHost().get().host); + if (proxyHostAddress) { + std::shared_ptr<Connection> conn = connectionFactory_->createConnection(); + HostAddressPort addressPort = HostAddressPort(proxyHostAddress.get(), proxy->getStreamHost().get().port); + SWIFT_LOG_ASSERT(addressPort.isValid(), warning); + std::shared_ptr<SOCKS5BytestreamClientSession> session = std::make_shared<SOCKS5BytestreamClientSession>(conn, addressPort, sessionID, timerFactory_); + JID proxyJid = proxy->getStreamHost().get().jid; + clientSessions.push_back(std::pair<JID, std::shared_ptr<SOCKS5BytestreamClientSession> >(proxyJid, session)); + session->onSessionReady.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this,sessionID, proxyJid, session, _1)); + session->onFinished.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionID, proxyJid, session, _1)); + session->start(); + } + } + } + + proxySessions_[sessionID] = clientSessions; +} - boost::shared_ptr<SOCKS5BytestreamClientSession> session = boost::make_shared<SOCKS5BytestreamClientSession>(conn, proxy->getStreamHost().get().addressPort, sessionID, timerFactory); - clientSessions[proxy->getStreamHost().get().jid] = session; - session->start(); - } +std::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID) { + // checking parameters + if (proxySessions_.find(sessionID) == proxySessions_.end()) { + return std::shared_ptr<SOCKS5BytestreamClientSession>(); + } + + // get active session + std::shared_ptr<SOCKS5BytestreamClientSession> activeSession; + for (ProxyJIDClientSessionVector::iterator i = proxySessions_[sessionID].begin(); i != proxySessions_[sessionID].end(); i++) { + i->second->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this,sessionID, proxyJID, i->second, _1)); + i->second->onFinished.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionID, proxyJID, i->second, _1)); + if (i->first == proxyJID && !activeSession) { + activeSession = i->second; + } + else { + i->second->stop(); + } + } + SWIFT_LOG_ASSERT(activeSession, warning) << "No active session with matching ID found."; + + proxySessions_.erase(sessionID); + + return activeSession; +} - proxySessions[sessionID] = clientSessions; +std::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr) { + SOCKS5BytestreamClientSession::ref connection = std::make_shared<SOCKS5BytestreamClientSession>(connectionFactory_->createConnection(), addressPort, destAddr, timerFactory_); + return connection; } -boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID) { - // checking parameters - if (proxySessions.find(sessionID) == proxySessions.end()) { - return boost::shared_ptr<SOCKS5BytestreamClientSession>(); - } - if (proxySessions[sessionID].find(proxyJID) == proxySessions[sessionID].end()) { - return boost::shared_ptr<SOCKS5BytestreamClientSession>(); - } +void SOCKS5BytestreamProxiesManager::handleProxiesFound(std::vector<S5BProxyRequest::ref> proxyHosts) { + proxyFinder_->onProxiesFound.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxiesFound, this, _1)); + for (auto&& proxy : proxyHosts) { + if (proxy) { + auto proxyHostAddress = HostAddress::fromString(proxy->getStreamHost().get().host); + if (proxyHostAddress) { + addS5BProxy(proxy); + onDiscoveredProxiesChanged(); + } + else { + DomainNameAddressQuery::ref resolveRequest = resolver_->createAddressQuery(proxy->getStreamHost().get().host); + resolveRequest->onResult.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleNameLookupResult, this, _1, _2, proxy)); + resolveRequest->run(); + } + } + } + proxyFinder_->stop(); + proxyFinder_.reset(); + if (proxyHosts.empty()) { + onDiscoveredProxiesChanged(); + } +} - // get active session - boost::shared_ptr<SOCKS5BytestreamClientSession> activeSession = proxySessions[sessionID][proxyJID]; - proxySessions[sessionID].erase(proxyJID); +void SOCKS5BytestreamProxiesManager::handleNameLookupResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error, S5BProxyRequest::ref proxy) { + if (error) { + onDiscoveredProxiesChanged(); + } + else { + if (addresses.empty()) { + SWIFT_LOG(warning) << "S5B proxy hostname does not resolve."; + } + else { + // generate proxy per returned address + for (const auto& address : addresses) { + S5BProxyRequest::StreamHost streamHost = proxy->getStreamHost().get(); + S5BProxyRequest::ref proxyForAddress = std::make_shared<S5BProxyRequest>(*proxy); + streamHost.host = address.toString(); + proxyForAddress->setStreamHost(streamHost); + addS5BProxy(proxyForAddress); + } + } + onDiscoveredProxiesChanged(); + } +} - // close other sessions - foreach(const ProxyJIDClientSessionMap::value_type& myPair, proxySessions[sessionID]) { - myPair.second->stop(); - } +void SOCKS5BytestreamProxiesManager::queryForProxies() { + proxyFinder_ = std::make_shared<SOCKS5BytestreamProxyFinder>(serviceRoot_, iqRouter_); - proxySessions.erase(sessionID); + proxyFinder_->onProxiesFound.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxiesFound, this, _1)); + proxyFinder_->start(); +} - return activeSession; +void SOCKS5BytestreamProxiesManager::handleProxySessionReady(const std::string& sessionID, const JID& jid, std::shared_ptr<SOCKS5BytestreamClientSession> session, bool error) { + session->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this, boost::cref(sessionID), boost::cref(jid), session, _1)); + if (!error) { + // The SOCKS5 bytestream session to the proxy succeeded; stop and remove other sessions. + if (proxySessions_.find(sessionID) != proxySessions_.end()) { + for (ProxyJIDClientSessionVector::iterator i = proxySessions_[sessionID].begin(); i != proxySessions_[sessionID].end();) { + if ((i->first == jid) && (i->second != session)) { + i->second->stop(); + i = proxySessions_[sessionID].erase(i); + } + else { + i++; + } + } + } + } } -boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr) { - SOCKS5BytestreamClientSession::ref connection = boost::make_shared<SOCKS5BytestreamClientSession>(connectionFactory->createConnection(), addressPort, destAddr, timerFactory); - return connection; +void SOCKS5BytestreamProxiesManager::handleProxySessionFinished(const std::string& sessionID, const JID& jid, std::shared_ptr<SOCKS5BytestreamClientSession> session, boost::optional<FileTransferError> error) { + session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionID, jid, session, _1)); + if (error.is_initialized()) { + // The SOCKS5 bytestream session to the proxy failed; remove it. + if (proxySessions_.find(sessionID) != proxySessions_.end()) { + for (ProxyJIDClientSessionVector::iterator i = proxySessions_[sessionID].begin(); i != proxySessions_[sessionID].end();) { + if ((i->first == jid) && (i->second == session)) { + i->second->stop(); + i = proxySessions_[sessionID].erase(i); + break; + } + else { + i++; + } + } + } + } } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h index f3fed80..b5c5173 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h @@ -4,47 +4,81 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + + #pragma once +#include <map> #include <string> +#include <utility> #include <vector> #include <Swiften/Base/API.h> #include <Swiften/Elements/S5BProxyRequest.h> #include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h> #include <Swiften/JID/JID.h> -#include <Swiften/Network/ConnectionFactory.h> -#include <Swiften/Network/TimerFactory.h> namespace Swift { - class SOCKS5BytestreamProxiesDiscoverRequest; + class TimerFactory; + class ConnectionFactory; + class DomainNameResolver; + class DomainNameResolveError; + class IQRouter; + + /** + * - manages list of working S5B proxies + * - creates initial connections (for the candidates you provide) + */ + class SWIFTEN_API SOCKS5BytestreamProxiesManager { + public: + SOCKS5BytestreamProxiesManager(ConnectionFactory*, TimerFactory*, DomainNameResolver*, IQRouter*, const JID&); + ~SOCKS5BytestreamProxiesManager(); + + void addS5BProxy(S5BProxyRequest::ref); + + /* + * Returns a list of external S5B proxies. If the optinal return value is not initialized a discovery process has been started and + * onDiscoveredProxiesChanged signal will be emitted when it is finished. + */ + const boost::optional<std::vector<S5BProxyRequest::ref> >& getOrDiscoverS5BProxies(); + + void connectToProxies(const std::string& sessionID); + std::shared_ptr<SOCKS5BytestreamClientSession> getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID); + + std::shared_ptr<SOCKS5BytestreamClientSession> createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr); - /** - * - manages list of working S5B proxies - * - creates initial connections (for the candidates you provide) - */ - class SWIFTEN_API SOCKS5BytestreamProxiesManager { - public: - SOCKS5BytestreamProxiesManager(ConnectionFactory*, TimerFactory*); + public: + boost::signals2::signal<void ()> onDiscoveredProxiesChanged; - boost::shared_ptr<SOCKS5BytestreamProxiesDiscoverRequest> createDiscoverProxiesRequest(); + private: + void handleProxiesFound(std::vector<S5BProxyRequest::ref> proxyHosts); + void handleNameLookupResult(const std::vector<HostAddress>&, boost::optional<DomainNameResolveError>, S5BProxyRequest::ref proxy); - void addS5BProxy(S5BProxyRequest::ref); - const std::vector<S5BProxyRequest::ref>& getS5BProxies() const; + void queryForProxies(); - void connectToProxies(const std::string& sessionID); - boost::shared_ptr<SOCKS5BytestreamClientSession> getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID); + void handleProxySessionReady(const std::string& sessionID, const JID& jid, std::shared_ptr<SOCKS5BytestreamClientSession> session, bool error); + void handleProxySessionFinished(const std::string& sessionID, const JID& jid, std::shared_ptr<SOCKS5BytestreamClientSession> session, boost::optional<FileTransferError> error); - boost::shared_ptr<SOCKS5BytestreamClientSession> createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr); + private: + ConnectionFactory* connectionFactory_; + TimerFactory* timerFactory_; + DomainNameResolver* resolver_; + IQRouter* iqRouter_; + JID serviceRoot_; - private: - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; + typedef std::vector<std::pair<JID, std::shared_ptr<SOCKS5BytestreamClientSession> > > ProxyJIDClientSessionVector; + typedef std::map<std::string, ProxyJIDClientSessionVector> ProxySessionsMap; + ProxySessionsMap proxySessions_; - typedef std::map<JID, boost::shared_ptr<SOCKS5BytestreamClientSession> > ProxyJIDClientSessionMap; - std::map<std::string, ProxyJIDClientSessionMap> proxySessions; + std::shared_ptr<SOCKS5BytestreamProxyFinder> proxyFinder_; - std::vector<S5BProxyRequest::ref> localS5BProxies; - }; + boost::optional<std::vector<S5BProxyRequest::ref> > localS5BProxies_; + }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp index 9d7505b..1efc54a 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp @@ -4,9 +4,16 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/bind.hpp> #include <Swiften/Base/Log.h> @@ -23,40 +30,57 @@ SOCKS5BytestreamProxyFinder::~SOCKS5BytestreamProxyFinder() { } void SOCKS5BytestreamProxyFinder::start() { - serviceWalker = boost::make_shared<DiscoServiceWalker>(service, iqRouter); - serviceWalker->onServiceFound.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2)); - serviceWalker->beginWalk(); + serviceWalker = std::make_shared<DiscoServiceWalker>(service, iqRouter); + serviceWalker->onServiceFound.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2)); + serviceWalker->onWalkComplete.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleWalkEnded, this)); + serviceWalker->beginWalk(); } void SOCKS5BytestreamProxyFinder::stop() { - serviceWalker->endWalk(); - serviceWalker->onServiceFound.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2)); - serviceWalker.reset(); + for (auto&& requester : pendingRequests) { + requester->onResponse.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, requester, _1, _2)); + } + + serviceWalker->endWalk(); + serviceWalker->onServiceFound.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2)); + serviceWalker->onWalkComplete.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleWalkEnded, this)); + serviceWalker.reset(); } void SOCKS5BytestreamProxyFinder::sendBytestreamQuery(const JID& jid) { - S5BProxyRequest::ref proxyRequest = boost::make_shared<S5BProxyRequest>(); - boost::shared_ptr<GenericRequest<S5BProxyRequest> > request = boost::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Get, jid, proxyRequest, iqRouter); - request->onResponse.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, _1, _2)); - request->send(); -} - -void SOCKS5BytestreamProxyFinder::handleServiceFound(const JID& jid, boost::shared_ptr<DiscoInfo> discoInfo) { - if (discoInfo->hasFeature(DiscoInfo::Bytestream)) { - sendBytestreamQuery(jid); - } -} - -void SOCKS5BytestreamProxyFinder::handleProxyResponse(boost::shared_ptr<S5BProxyRequest> request, ErrorPayload::ref error) { - if (error) { - SWIFT_LOG(debug) << "ERROR" << std::endl; - } else { - if (request) { - onProxyFound(request); - } else { - //assert(false); - } - } + S5BProxyRequest::ref proxyRequest = std::make_shared<S5BProxyRequest>(); + std::shared_ptr<GenericRequest<S5BProxyRequest> > request = std::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Get, jid, proxyRequest, iqRouter); + request->onResponse.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, request, _1, _2)); + pendingRequests.insert(request); + request->send(); +} + +void SOCKS5BytestreamProxyFinder::handleServiceFound(const JID& jid, std::shared_ptr<DiscoInfo> discoInfo) { + if (discoInfo->hasFeature(DiscoInfo::Bytestream)) { + sendBytestreamQuery(jid); + } +} + +void SOCKS5BytestreamProxyFinder::handleWalkEnded() { + if (pendingRequests.empty()) { + onProxiesFound(proxyHosts); + } +} + +void SOCKS5BytestreamProxyFinder::handleProxyResponse(std::shared_ptr<GenericRequest<S5BProxyRequest> > requester, std::shared_ptr<S5BProxyRequest> request, ErrorPayload::ref error) { + requester->onResponse.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, requester, _1, _2)); + pendingRequests.erase(requester); + if (error) { + SWIFT_LOG(debug) << "ERROR"; + } else { + if (request) { + SWIFT_LOG(debug) << "add request"; + proxyHosts.push_back(request); + } + } + if (pendingRequests.empty() && !serviceWalker->isActive()) { + onProxiesFound(proxyHosts); + } } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h index 8265157..893f475 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h @@ -4,12 +4,19 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + + #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Disco/DiscoServiceWalker.h> -#include <Swiften/Network/HostAddressPort.h> #include <Swiften/Elements/S5BProxyRequest.h> namespace Swift { @@ -17,26 +24,33 @@ namespace Swift { class JID; class IQRouter; -class SOCKS5BytestreamProxyFinder { - public: - SOCKS5BytestreamProxyFinder(const JID& service, IQRouter *iqRouter); - ~SOCKS5BytestreamProxyFinder(); - - void start(); - void stop(); - - boost::signal<void(boost::shared_ptr<S5BProxyRequest>)> onProxyFound; - - private: - void sendBytestreamQuery(const JID&); - - void handleServiceFound(const JID&, boost::shared_ptr<DiscoInfo>); - void handleProxyResponse(boost::shared_ptr<S5BProxyRequest>, ErrorPayload::ref); - private: - JID service; - IQRouter* iqRouter; - boost::shared_ptr<DiscoServiceWalker> serviceWalker; - std::vector<boost::shared_ptr<GenericRequest<S5BProxyRequest> > > requests; - }; +/* + * This class is designed to find possible SOCKS5 bytestream proxies which are used for peer-to-peer data transfers in + * restrictive environments. + */ +class SWIFTEN_API SOCKS5BytestreamProxyFinder { + public: + SOCKS5BytestreamProxyFinder(const JID& service, IQRouter *iqRouter); + ~SOCKS5BytestreamProxyFinder(); + + void start(); + void stop(); + + boost::signals2::signal<void(std::vector<std::shared_ptr<S5BProxyRequest> >)> onProxiesFound; + + private: + void sendBytestreamQuery(const JID&); + + void handleServiceFound(const JID&, std::shared_ptr<DiscoInfo>); + void handleProxyResponse(std::shared_ptr<GenericRequest<S5BProxyRequest> > requester, std::shared_ptr<S5BProxyRequest>, ErrorPayload::ref); + void handleWalkEnded(); + + private: + JID service; + IQRouter* iqRouter; + std::shared_ptr<DiscoServiceWalker> serviceWalker; + std::vector<S5BProxyRequest::ref> proxyHosts; + std::set<std::shared_ptr<GenericRequest<S5BProxyRequest> > > pendingRequests; +}; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp index cf4794c..9e214fc 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp @@ -1,16 +1,15 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> namespace Swift { @@ -18,20 +17,20 @@ SOCKS5BytestreamRegistry::SOCKS5BytestreamRegistry() { } void SOCKS5BytestreamRegistry::setHasBytestream(const std::string& destination, bool b) { - if (b) { - availableBytestreams.insert(destination); - } - else { - availableBytestreams.erase(destination); - } + if (b) { + availableBytestreams.insert(destination); + } + else { + availableBytestreams.erase(destination); + } } bool SOCKS5BytestreamRegistry::hasBytestream(const std::string& destination) const { - return availableBytestreams.find(destination) != availableBytestreams.end(); + return availableBytestreams.find(destination) != availableBytestreams.end(); } std::string SOCKS5BytestreamRegistry::generateSessionID() { - return idGenerator.generateID(); + return idGenerator.generateID(); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h index 4c05e47..33bc57c 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h @@ -1,35 +1,33 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <map> -#include <string> #include <set> +#include <string> #include <Swiften/Base/API.h> #include <Swiften/Base/IDGenerator.h> namespace Swift { - class SOCKS5BytestreamServerSession; - - class SWIFTEN_API SOCKS5BytestreamRegistry { - public: - SOCKS5BytestreamRegistry(); - - void setHasBytestream(const std::string& destination, bool); - bool hasBytestream(const std::string& destination) const; - - /** - * Generate a new session ID to use for new S5B streams. - */ - std::string generateSessionID(); - - private: - std::set<std::string> availableBytestreams; - IDGenerator idGenerator; - }; + class SWIFTEN_API SOCKS5BytestreamRegistry { + public: + SOCKS5BytestreamRegistry(); + + void setHasBytestream(const std::string& destination, bool); + bool hasBytestream(const std::string& destination) const; + + /** + * Generate a new session ID to use for new S5B streams. + */ + std::string generateSessionID(); + + private: + std::set<std::string> availableBytestreams; + IDGenerator idGenerator; + }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp index f491918..483ea18 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> @@ -9,60 +9,59 @@ #include <boost/bind.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> +#include <Swiften/StringCodecs/Hexify.h> namespace Swift { SOCKS5BytestreamServer::SOCKS5BytestreamServer( - boost::shared_ptr<ConnectionServer> connectionServer, - SOCKS5BytestreamRegistry* registry) : - connectionServer(connectionServer), - registry(registry) { + std::shared_ptr<ConnectionServer> connectionServer, + SOCKS5BytestreamRegistry* registry) : + connectionServer(connectionServer), + registry(registry) { } void SOCKS5BytestreamServer::start() { - connectionServer->onNewConnection.connect(boost::bind(&SOCKS5BytestreamServer::handleNewConnection, this, _1)); + connectionServer->onNewConnection.connect(boost::bind(&SOCKS5BytestreamServer::handleNewConnection, this, _1)); } void SOCKS5BytestreamServer::stop() { - connectionServer->onNewConnection.disconnect(boost::bind(&SOCKS5BytestreamServer::handleNewConnection, this, _1)); - foreach (boost::shared_ptr<SOCKS5BytestreamServerSession> session, sessions) { - session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); - session->stop(); - } - sessions.clear(); + connectionServer->onNewConnection.disconnect(boost::bind(&SOCKS5BytestreamServer::handleNewConnection, this, _1)); + for (auto&& session : sessions) { + session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); + session->stop(); + } + sessions.clear(); } -void SOCKS5BytestreamServer::handleNewConnection(boost::shared_ptr<Connection> connection) { - boost::shared_ptr<SOCKS5BytestreamServerSession> session = - boost::make_shared<SOCKS5BytestreamServerSession>(connection, registry); - session->onFinished.connect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); - sessions.push_back(session); - session->start(); +void SOCKS5BytestreamServer::handleNewConnection(std::shared_ptr<Connection> connection) { + std::shared_ptr<SOCKS5BytestreamServerSession> session = + std::make_shared<SOCKS5BytestreamServerSession>(connection, registry); + session->onFinished.connect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); + sessions.push_back(session); + session->start(); } HostAddressPort SOCKS5BytestreamServer::getAddressPort() const { - return connectionServer->getAddressPort(); + return connectionServer->getAddressPort(); } -std::vector< boost::shared_ptr<SOCKS5BytestreamServerSession> > SOCKS5BytestreamServer::getSessions( - const std::string& streamID) const { - std::vector< boost::shared_ptr<SOCKS5BytestreamServerSession> > result; - foreach (boost::shared_ptr<SOCKS5BytestreamServerSession> session, sessions) { - if (session->getStreamID() == streamID) { - result.push_back(session); - } - } - return result; +std::vector< std::shared_ptr<SOCKS5BytestreamServerSession> > SOCKS5BytestreamServer::getSessions( + const std::string& streamID) const { + std::vector< std::shared_ptr<SOCKS5BytestreamServerSession> > result; + for (auto&& session : sessions) { + if (session->getStreamID() == streamID) { + result.push_back(session); + } + } + return result; } -void SOCKS5BytestreamServer::handleSessionFinished(boost::shared_ptr<SOCKS5BytestreamServerSession> session) { - sessions.erase(std::remove(sessions.begin(), sessions.end(), session), sessions.end()); - session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); +void SOCKS5BytestreamServer::handleSessionFinished(std::shared_ptr<SOCKS5BytestreamServerSession> session) { + sessions.erase(std::remove(sessions.begin(), sessions.end(), session), sessions.end()); + session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServer.h b/Swiften/FileTransfer/SOCKS5BytestreamServer.h index 71605c4..16d3d29 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServer.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServer.h @@ -1,47 +1,47 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> #include <map> - -#include <Swiften/Network/ConnectionServer.h> +#include <memory> #include <string> -#include <Swiften/JID/JID.h> + +#include <Swiften/Base/API.h> #include <Swiften/FileTransfer/ReadBytestream.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Network/ConnectionServer.h> namespace Swift { - class SOCKS5BytestreamServerSession; - class CryptoProvider; + class SOCKS5BytestreamServerSession; - class SOCKS5BytestreamServer { - public: - SOCKS5BytestreamServer( - boost::shared_ptr<ConnectionServer> connectionServer, - SOCKS5BytestreamRegistry* registry); + class SWIFTEN_API SOCKS5BytestreamServer { + public: + SOCKS5BytestreamServer( + std::shared_ptr<ConnectionServer> connectionServer, + SOCKS5BytestreamRegistry* registry); - HostAddressPort getAddressPort() const; + HostAddressPort getAddressPort() const; - void start(); - void stop(); + void start(); + void stop(); - std::vector< boost::shared_ptr<SOCKS5BytestreamServerSession> > getSessions(const std::string& id) const; + std::vector< std::shared_ptr<SOCKS5BytestreamServerSession> > getSessions(const std::string& id) const; - private: - void handleNewConnection(boost::shared_ptr<Connection> connection); - void handleSessionFinished(boost::shared_ptr<SOCKS5BytestreamServerSession>); + private: + void handleNewConnection(std::shared_ptr<Connection> connection); + void handleSessionFinished(std::shared_ptr<SOCKS5BytestreamServerSession>); - private: - friend class SOCKS5BytestreamServerSession; + private: + friend class SOCKS5BytestreamServerSession; - boost::shared_ptr<ConnectionServer> connectionServer; - SOCKS5BytestreamRegistry* registry; - std::vector<boost::shared_ptr<SOCKS5BytestreamServerSession> > sessions; - }; + std::shared_ptr<ConnectionServer> connectionServer; + SOCKS5BytestreamRegistry* registry; + std::vector<std::shared_ptr<SOCKS5BytestreamServerSession> > sessions; + }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.cpp deleted file mode 100644 index 38735de..0000000 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.h> - -#include <boost/bind.hpp> - -#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> - -using namespace Swift; - -SOCKS5BytestreamServerInitializeRequest::SOCKS5BytestreamServerInitializeRequest(SOCKS5BytestreamServerManager* manager) : manager(manager) { -} - -SOCKS5BytestreamServerInitializeRequest::~SOCKS5BytestreamServerInitializeRequest() { -} - -void SOCKS5BytestreamServerInitializeRequest::start() { - if (manager->isInitialized()) { - handleInitialized(true); - } - else { - manager->onInitialized.connect( - boost::bind(&SOCKS5BytestreamServerInitializeRequest::handleInitialized, this, _1)); - manager->initialize(); - } -} - -void SOCKS5BytestreamServerInitializeRequest::stop() { - manager->onInitialized.disconnect( - boost::bind(&SOCKS5BytestreamServerInitializeRequest::handleInitialized, this, _1)); -} - -void SOCKS5BytestreamServerInitializeRequest::handleInitialized(bool success) { - onFinished(success); -} diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.h b/Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.h deleted file mode 100644 index aa073fc..0000000 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> - -namespace Swift { - class SOCKS5BytestreamServerManager; - - class SWIFTEN_API SOCKS5BytestreamServerInitializeRequest { - public: - SOCKS5BytestreamServerInitializeRequest(SOCKS5BytestreamServerManager* manager); - ~SOCKS5BytestreamServerInitializeRequest(); - - void start(); - void stop(); - - public: - boost::signal<void (bool /* success */)> onFinished; - - private: - void handleInitialized(bool success); - - private: - SOCKS5BytestreamServerManager* manager; - }; -} - diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp index 1d65d27..7fc1388 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ /* @@ -12,19 +12,21 @@ #include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/bind.hpp> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Base/Log.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h> #include <Swiften/Network/ConnectionServer.h> #include <Swiften/Network/ConnectionServerFactory.h> -#include <Swiften/Network/NetworkEnvironment.h> -#include <Swiften/Network/NATTraverser.h> -#include <Swiften/Network/NATTraversalGetPublicIPRequest.h> #include <Swiften/Network/NATTraversalForwardPortRequest.h> +#include <Swiften/Network/NATTraversalGetPublicIPRequest.h> +#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h> +#include <Swiften/Network/NATTraverser.h> +#include <Swiften/Network/NetworkEnvironment.h> using namespace Swift; @@ -32,164 +34,223 @@ static const int LISTEN_PORTS_BEGIN = 10000; static const int LISTEN_PORTS_END = 11000; SOCKS5BytestreamServerManager::SOCKS5BytestreamServerManager( - SOCKS5BytestreamRegistry* bytestreamRegistry, - ConnectionServerFactory* connectionServerFactory, - NetworkEnvironment* networkEnvironment, - NATTraverser* natTraverser) : - bytestreamRegistry(bytestreamRegistry), - connectionServerFactory(connectionServerFactory), - networkEnvironment(networkEnvironment), - natTraverser(natTraverser), - state(Start), - server(NULL) { + SOCKS5BytestreamRegistry* bytestreamRegistry, + ConnectionServerFactory* connectionServerFactory, + NetworkEnvironment* networkEnvironment, + NATTraverser* natTraverser) : + bytestreamRegistry(bytestreamRegistry), + connectionServerFactory(connectionServerFactory), + networkEnvironment(networkEnvironment), + natTraverser(natTraverser), + state(Start), + server(nullptr), + attemptedPortMapping_(false) { } SOCKS5BytestreamServerManager::~SOCKS5BytestreamServerManager() { - SWIFT_LOG_ASSERT(!connectionServer, warning) << std::endl; - SWIFT_LOG_ASSERT(!getPublicIPRequest, warning) << std::endl; - SWIFT_LOG_ASSERT(!forwardPortRequest, warning) << std::endl; - SWIFT_LOG_ASSERT(state == Start, warning) << std::endl; + SWIFT_LOG_ASSERT(!connectionServer, warning); + SWIFT_LOG_ASSERT(!getPublicIPRequest, warning); + SWIFT_LOG_ASSERT(!forwardPortRequest, warning); + SWIFT_LOG_ASSERT(state == Start, warning); + if (portMapping && !unforwardPortRequest) { + SWIFT_LOG(warning) << "Port forwarding still alive. Trying to remove it now."; + unforwardPortRequest = natTraverser->createRemovePortForwardingRequest(portMapping.get().getLocalPort(), portMapping.get().getPublicPort()); + unforwardPortRequest->start(); + } } - -boost::shared_ptr<SOCKS5BytestreamServerInitializeRequest> SOCKS5BytestreamServerManager::createInitializeRequest() { - return boost::make_shared<SOCKS5BytestreamServerInitializeRequest>(this); +std::shared_ptr<SOCKS5BytestreamServerResourceUser> SOCKS5BytestreamServerManager::aquireResourceUser() { + std::shared_ptr<SOCKS5BytestreamServerResourceUser> resourceUser; + if (s5bServerResourceUser_.expired()) { + resourceUser = std::make_shared<SOCKS5BytestreamServerResourceUser>(this); + s5bServerResourceUser_ = resourceUser; + } + else { + resourceUser = s5bServerResourceUser_.lock(); + } + return resourceUser; } -void SOCKS5BytestreamServerManager::stop() { - if (getPublicIPRequest) { - getPublicIPRequest->stop(); - getPublicIPRequest.reset(); - } - if (forwardPortRequest) { - forwardPortRequest->stop(); - forwardPortRequest.reset(); - } - if (connectionServer) { - connectionServer->stop(); - connectionServer.reset(); - } - // TODO: Remove port forwards - - state = Start; +std::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> SOCKS5BytestreamServerManager::aquirePortForwardingUser() { + std::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> portForwardingUser; + if (s5bServerPortForwardingUser_.expired()) { + portForwardingUser = std::make_shared<SOCKS5BytestreamServerPortForwardingUser>(this); + s5bServerPortForwardingUser_ = portForwardingUser; + } + else { + portForwardingUser = s5bServerPortForwardingUser_.lock(); + } + return portForwardingUser; } std::vector<HostAddressPort> SOCKS5BytestreamServerManager::getHostAddressPorts() const { - std::vector<HostAddressPort> result; - if (connectionServer) { - std::vector<NetworkInterface> networkInterfaces = networkEnvironment->getNetworkInterfaces(); - foreach (const NetworkInterface& networkInterface, networkInterfaces) { - foreach (const HostAddress& address, networkInterface.getAddresses()) { - result.push_back(HostAddressPort(address, connectionServerPort)); - } - } - } - return result; + std::vector<HostAddressPort> result; + if (connectionServer) { + std::vector<NetworkInterface> networkInterfaces = networkEnvironment->getNetworkInterfaces(); + for (const auto& networkInterface : networkInterfaces) { + for (const auto& address : networkInterface.getAddresses()) { + result.push_back(HostAddressPort(address, connectionServerPort)); + } + } + } + return result; } std::vector<HostAddressPort> SOCKS5BytestreamServerManager::getAssistedHostAddressPorts() const { - std::vector<HostAddressPort> result; - if (publicAddress && portMapping) { - result.push_back(HostAddressPort(*publicAddress, portMapping->getPublicPort())); - } - return result; + std::vector<HostAddressPort> result; + if (publicAddress && portMapping) { + result.push_back(HostAddressPort(*publicAddress, portMapping->getPublicPort())); + } + return result; } bool SOCKS5BytestreamServerManager::isInitialized() const { - return state == Initialized; + return state == Initialized; } void SOCKS5BytestreamServerManager::initialize() { - if (state == Start) { - state = Initializing; - - // Find a port to listen on - assert(!connectionServer); - int port; - for (port = LISTEN_PORTS_BEGIN; port < LISTEN_PORTS_END; ++port) { - SWIFT_LOG(debug) << "Trying to start server on port " << port << std::endl; - connectionServer = connectionServerFactory->createConnectionServer(HostAddress("0.0.0.0"), port); - boost::optional<ConnectionServer::Error> error = connectionServer->tryStart(); - if (!error) { - break; - } - else if (*error != ConnectionServer::Conflict) { - SWIFT_LOG(debug) << "Error starting server" << std::endl; - onInitialized(false); - return; - } - connectionServer.reset(); - } - if (!connectionServer) { - SWIFT_LOG(debug) << "Unable to find an open port" << std::endl; - onInitialized(false); - return; - } - SWIFT_LOG(debug) << "Server started succesfully" << std::endl; - connectionServerPort = port; - - // Start bytestream server. Should actually happen before the connectionserver is started - // but that doesn't really matter here. - assert(!server); - server = new SOCKS5BytestreamServer(connectionServer, bytestreamRegistry); - server->start(); - - // Retrieve public addresses - assert(!getPublicIPRequest); - publicAddress = boost::optional<HostAddress>(); - if ((getPublicIPRequest = natTraverser->createGetPublicIPRequest())) { - getPublicIPRequest->onResult.connect( - boost::bind(&SOCKS5BytestreamServerManager::handleGetPublicIPResult, this, _1)); - getPublicIPRequest->start(); - } - - // Forward ports - assert(!forwardPortRequest); - portMapping = boost::optional<NATPortMapping>(); - if ((forwardPortRequest = natTraverser->createForwardPortRequest(port, port))) { - forwardPortRequest->onResult.connect( - boost::bind(&SOCKS5BytestreamServerManager::handleForwardPortResult, this, _1)); - forwardPortRequest->start(); - } - } + if (state == Start) { + state = Initializing; + + // Find a port to listen on + assert(!connectionServer); + unsigned short port; + for (port = LISTEN_PORTS_BEGIN; port < LISTEN_PORTS_END; ++port) { + SWIFT_LOG(debug) << "Trying to start server on port " << port; + connectionServer = connectionServerFactory->createConnectionServer(HostAddress::fromString("::").get(), port); + boost::optional<ConnectionServer::Error> error = connectionServer->tryStart(); + if (!error) { + break; + } + else if (*error != ConnectionServer::Conflict) { + SWIFT_LOG(debug) << "Error starting server"; + onInitialized(false); + return; + } + connectionServer.reset(); + } + if (!connectionServer) { + SWIFT_LOG(debug) << "Unable to find an open port"; + onInitialized(false); + return; + } + SWIFT_LOG(debug) << "Server started succesfully"; + connectionServerPort = port; + + // Start bytestream server. Should actually happen before the connectionserver is started + // but that doesn't really matter here. + assert(!server); + server = new SOCKS5BytestreamServer(connectionServer, bytestreamRegistry); + server->start(); + checkInitializeFinished(); + } } -void SOCKS5BytestreamServerManager::handleGetPublicIPResult(boost::optional<HostAddress> address) { - if (address) { - SWIFT_LOG(debug) << "Public IP discovered as " << address.get().toString() << "." << std::endl; - } - else { - SWIFT_LOG(debug) << "No public IP discoverable." << std::endl; - } +bool SOCKS5BytestreamServerManager::isPortForwardingReady() const { + return attemptedPortMapping_ && !getPublicIPRequest && !forwardPortRequest; +} - publicAddress = address; +void SOCKS5BytestreamServerManager::setupPortForwarding() { + assert(server); + attemptedPortMapping_ = true; - getPublicIPRequest->stop(); - getPublicIPRequest.reset(); + // Retrieve public addresses + assert(!getPublicIPRequest); + publicAddress = boost::optional<HostAddress>(); + if ((getPublicIPRequest = natTraverser->createGetPublicIPRequest())) { + getPublicIPRequest->onResult.connect( + boost::bind(&SOCKS5BytestreamServerManager::handleGetPublicIPResult, this, _1)); + getPublicIPRequest->start(); + } - checkInitializeFinished(); + // Forward ports + auto port = server->getAddressPort().getPort(); + assert(!forwardPortRequest); + portMapping = boost::optional<NATPortMapping>(); + if ((forwardPortRequest = natTraverser->createForwardPortRequest(port, port))) { + forwardPortRequest->onResult.connect( + boost::bind(&SOCKS5BytestreamServerManager::handleForwardPortResult, this, _1)); + forwardPortRequest->start(); + } +} + +void SOCKS5BytestreamServerManager::removePortForwarding() { + // remove port forwards + if (portMapping) { + unforwardPortRequest = natTraverser->createRemovePortForwardingRequest(portMapping.get().getLocalPort(), portMapping.get().getPublicPort()); + unforwardPortRequest->onResult.connect(boost::bind(&SOCKS5BytestreamServerManager::handleUnforwardPortResult, this, _1)); + unforwardPortRequest->start(); + } +} + +void SOCKS5BytestreamServerManager::stop() { + if (getPublicIPRequest) { + getPublicIPRequest->stop(); + getPublicIPRequest.reset(); + } + if (forwardPortRequest) { + forwardPortRequest->stop(); + forwardPortRequest.reset(); + } + if (unforwardPortRequest) { + unforwardPortRequest->stop(); + unforwardPortRequest.reset(); + } + if (server) { + server->stop(); + delete server; + server = nullptr; + } + if (connectionServer) { + connectionServer->stop(); + connectionServer.reset(); + } + + state = Start; +} + +void SOCKS5BytestreamServerManager::handleGetPublicIPResult(boost::optional<HostAddress> address) { + if (address) { + SWIFT_LOG(debug) << "Public IP discovered as " << address.get().toString() << "."; + } + else { + SWIFT_LOG(debug) << "No public IP discoverable."; + } + + publicAddress = address; + + getPublicIPRequest->stop(); + getPublicIPRequest.reset(); } void SOCKS5BytestreamServerManager::handleForwardPortResult(boost::optional<NATPortMapping> mapping) { - if (mapping) { - SWIFT_LOG(debug) << "Mapping port was successful." << std::endl; - } - else { - SWIFT_LOG(debug) << "Mapping port has failed." << std::endl; - } + if (mapping) { + SWIFT_LOG(debug) << "Mapping port was successful."; + } + else { + SWIFT_LOG(debug) << "Mapping port has failed."; + } - portMapping = mapping; + portMapping = mapping; + onPortForwardingSetup(mapping.is_initialized()); - forwardPortRequest->stop(); - forwardPortRequest.reset(); + forwardPortRequest->stop(); + forwardPortRequest.reset(); +} - checkInitializeFinished(); +void SOCKS5BytestreamServerManager::handleUnforwardPortResult(boost::optional<bool> result) { + if (result.is_initialized() && result.get()) { + portMapping.reset(); + } + else { + SWIFT_LOG(warning) << "Failed to remove port forwarding."; + } + attemptedPortMapping_ = false; + unforwardPortRequest.reset(); } void SOCKS5BytestreamServerManager::checkInitializeFinished() { - assert(state == Initializing); - if (!getPublicIPRequest && !forwardPortRequest) { - state = Initialized; - onInitialized(true); - } + assert(state == Initializing); + state = Initialized; + onInitialized(true); } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h index 248a9b9..74578cc 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h @@ -1,73 +1,94 @@ /* - * Copyright (c) 2012-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <vector> -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/NATPortMapping.h> namespace Swift { - class NetworkEnvironment; - class NATTraverser; - class NATTraversalGetPublicIPRequest; - class NATTraversalForwardPortRequest; - class SOCKS5BytestreamRegistry; - class ConnectionServerFactory; - class ConnectionServer; - class SOCKS5BytestreamServerInitializeRequest; - class SOCKS5BytestreamServer; - - class SOCKS5BytestreamServerManager { - public: - SOCKS5BytestreamServerManager( - SOCKS5BytestreamRegistry* bytestreamRegistry, - ConnectionServerFactory* connectionServerFactory, - NetworkEnvironment* networkEnvironment, - NATTraverser* natTraverser); - ~SOCKS5BytestreamServerManager(); - - boost::shared_ptr<SOCKS5BytestreamServerInitializeRequest> createInitializeRequest(); - void stop(); - - std::vector<HostAddressPort> getHostAddressPorts() const; - std::vector<HostAddressPort> getAssistedHostAddressPorts() const; - - SOCKS5BytestreamServer* getServer() const { - return server; - } - - private: - bool isInitialized() const; - void initialize(); - void checkInitializeFinished(); - - void handleGetPublicIPResult(boost::optional<HostAddress> address); - void handleForwardPortResult(boost::optional<NATPortMapping> mapping); - - boost::signal<void (bool /* success */)> onInitialized; - - - private: - friend class SOCKS5BytestreamServerInitializeRequest; - SOCKS5BytestreamRegistry* bytestreamRegistry; - ConnectionServerFactory* connectionServerFactory; - NetworkEnvironment* networkEnvironment; - NATTraverser* natTraverser; - enum { Start, Initializing, Initialized } state; - SOCKS5BytestreamServer* server; - boost::shared_ptr<ConnectionServer> connectionServer; - int connectionServerPort; - boost::shared_ptr<NATTraversalGetPublicIPRequest> getPublicIPRequest; - boost::shared_ptr<NATTraversalForwardPortRequest> forwardPortRequest; - boost::optional<HostAddress> publicAddress; - boost::optional<NATPortMapping> portMapping; - }; + class NetworkEnvironment; + class NATTraverser; + class NATTraversalGetPublicIPRequest; + class NATTraversalForwardPortRequest; + class NATTraversalRemovePortForwardingRequest; + class SOCKS5BytestreamRegistry; + class ConnectionServerFactory; + class ConnectionServer; + class SOCKS5BytestreamServer; + class SOCKS5BytestreamServerResourceUser; + class SOCKS5BytestreamServerPortForwardingUser; + + class SWIFTEN_API SOCKS5BytestreamServerManager { + friend class SOCKS5BytestreamServerResourceUser; + friend class SOCKS5BytestreamServerPortForwardingUser; + + public: + SOCKS5BytestreamServerManager( + SOCKS5BytestreamRegistry* bytestreamRegistry, + ConnectionServerFactory* connectionServerFactory, + NetworkEnvironment* networkEnvironment, + NATTraverser* natTraverser); + ~SOCKS5BytestreamServerManager(); + + std::shared_ptr<SOCKS5BytestreamServerResourceUser> aquireResourceUser(); + std::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> aquirePortForwardingUser(); + + void stop(); + + std::vector<HostAddressPort> getHostAddressPorts() const; + std::vector<HostAddressPort> getAssistedHostAddressPorts() const; + + SOCKS5BytestreamServer* getServer() const { + return server; + } + + private: + bool isInitialized() const; + void initialize(); + + bool isPortForwardingReady() const; + void setupPortForwarding(); + void removePortForwarding(); + + void checkInitializeFinished(); + + void handleGetPublicIPResult(boost::optional<HostAddress> address); + void handleForwardPortResult(boost::optional<NATPortMapping> mapping); + void handleUnforwardPortResult(boost::optional<bool> result); + + boost::signals2::signal<void (bool /* success */)> onInitialized; + boost::signals2::signal<void (bool /* success */)> onPortForwardingSetup; + + private: + friend class SOCKS5BytestreamServerInitializeRequest; + SOCKS5BytestreamRegistry* bytestreamRegistry; + ConnectionServerFactory* connectionServerFactory; + NetworkEnvironment* networkEnvironment; + NATTraverser* natTraverser; + enum { Start, Initializing, Initialized } state; + SOCKS5BytestreamServer* server; + std::shared_ptr<ConnectionServer> connectionServer; + unsigned short connectionServerPort = 0; + + std::shared_ptr<NATTraversalGetPublicIPRequest> getPublicIPRequest; + std::shared_ptr<NATTraversalForwardPortRequest> forwardPortRequest; + std::shared_ptr<NATTraversalRemovePortForwardingRequest> unforwardPortRequest; + boost::optional<HostAddress> publicAddress; + boost::optional<NATPortMapping> portMapping; + bool attemptedPortMapping_; + + std::weak_ptr<SOCKS5BytestreamServerResourceUser> s5bServerResourceUser_; + std::weak_ptr<SOCKS5BytestreamServerPortForwardingUser> s5bServerPortForwardingUser_; + }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.cpp new file mode 100644 index 0000000..fc7fe58 --- /dev/null +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h> + +#include <boost/bind.hpp> + +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> + +namespace Swift { + +SOCKS5BytestreamServerPortForwardingUser::SOCKS5BytestreamServerPortForwardingUser(SOCKS5BytestreamServerManager* s5bServerManager) : s5bServerManager_(s5bServerManager) { + // the server should be initialized, so we know what port to setup a forward for + assert(s5bServerManager->isInitialized()); + if (s5bServerManager_->isPortForwardingReady()) { + onSetup(!s5bServerManager_->getAssistedHostAddressPorts().empty()); + } + else { + onPortForwardingSetupConnection_ = s5bServerManager_->onPortForwardingSetup.connect(boost::bind(&SOCKS5BytestreamServerPortForwardingUser::handleServerManagerPortForwardingSetup, this, _1)); + s5bServerManager_->setupPortForwarding(); + } +} + +SOCKS5BytestreamServerPortForwardingUser::~SOCKS5BytestreamServerPortForwardingUser() { + if (s5bServerManager_->isPortForwardingReady()) { + s5bServerManager_->removePortForwarding(); + } +} + +bool SOCKS5BytestreamServerPortForwardingUser::isForwardingSetup() const { + return s5bServerManager_->isPortForwardingReady(); +} + +void SOCKS5BytestreamServerPortForwardingUser::handleServerManagerPortForwardingSetup(bool successful) { + onSetup(successful); +} + +} diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h b/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h new file mode 100644 index 0000000..19f3897 --- /dev/null +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> + +namespace Swift { + +class SOCKS5BytestreamServerManager; + +class SWIFTEN_API SOCKS5BytestreamServerPortForwardingUser { + public: + SOCKS5BytestreamServerPortForwardingUser(SOCKS5BytestreamServerManager* s5bServerManager); + ~SOCKS5BytestreamServerPortForwardingUser(); + + bool isForwardingSetup() const; + + boost::signals2::signal<void (bool /* success */)> onSetup; + + private: + void handleServerManagerPortForwardingSetup(bool successful); + + private: + SOCKS5BytestreamServerManager* s5bServerManager_; + boost::signals2::scoped_connection onPortForwardingSetupConnection_; +}; + +} diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.cpp new file mode 100644 index 0000000..2fc2e76 --- /dev/null +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h> + +#include <boost/bind.hpp> + +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> + +namespace Swift { + +SOCKS5BytestreamServerResourceUser::SOCKS5BytestreamServerResourceUser(SOCKS5BytestreamServerManager* s5bServerManager) : s5bServerManager_(s5bServerManager) { + assert(!s5bServerManager_->isInitialized()); + onInitializedConnection_ = s5bServerManager_->onInitialized.connect(boost::bind(&SOCKS5BytestreamServerResourceUser::handleServerManagerInitialized, this, _1)); + s5bServerManager_->initialize(); +} + +SOCKS5BytestreamServerResourceUser::~SOCKS5BytestreamServerResourceUser() { + if (s5bServerManager_->isInitialized()) { + s5bServerManager_->stop(); + } +} + +bool SOCKS5BytestreamServerResourceUser::isInitialized() const { + return s5bServerManager_->isInitialized(); +} + +void SOCKS5BytestreamServerResourceUser::handleServerManagerInitialized(bool successfulInitialize) { + onSuccessfulInitialized(successfulInitialize); +} + +} diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h b/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h new file mode 100644 index 0000000..8e42637 --- /dev/null +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> + +namespace Swift { + +class SOCKS5BytestreamServerManager; + +class SWIFTEN_API SOCKS5BytestreamServerResourceUser { + public: + SOCKS5BytestreamServerResourceUser(SOCKS5BytestreamServerManager* s5bServerManager); + ~SOCKS5BytestreamServerResourceUser(); + + bool isInitialized() const; + + boost::signals2::signal<void (bool /* success */)> onSuccessfulInitialized; + + private: + void handleServerManagerInitialized(bool successfulInitialize); + + private: + SOCKS5BytestreamServerManager* s5bServerManager_; + boost::signals2::scoped_connection onInitializedConnection_; +}; + +} diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp index 12a0f12..a4ab751 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp @@ -1,199 +1,202 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <boost/bind.hpp> #include <boost/numeric/conversion/cast.hpp> -#include <iostream> -#include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/SafeByteArray.h> #include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Concat.h> #include <Swiften/Base/Log.h> -#include <Swiften/Network/HostAddressPort.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/FileTransfer/BytestreamException.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/Network/HostAddressPort.h> namespace Swift { SOCKS5BytestreamServerSession::SOCKS5BytestreamServerSession( - boost::shared_ptr<Connection> connection, - SOCKS5BytestreamRegistry* bytestreams) : - connection(connection), - bytestreams(bytestreams), - state(Initial), - chunkSize(131072), - waitingForData(false) { - disconnectedConnection = connection->onDisconnected.connect(boost::bind(&SOCKS5BytestreamServerSession::handleDisconnected, this, _1)); + std::shared_ptr<Connection> connection, + SOCKS5BytestreamRegistry* bytestreams) : + connection(connection), + bytestreams(bytestreams), + state(Initial), + chunkSize(131072), + waitingForData(false) { + disconnectedConnection = connection->onDisconnected.connect(boost::bind(&SOCKS5BytestreamServerSession::handleDisconnected, this, _1)); } SOCKS5BytestreamServerSession::~SOCKS5BytestreamServerSession() { - if (state != Finished && state != Initial) { - std::cerr << "Warning: SOCKS5BytestreamServerSession unfinished" << std::endl; - finish(false); - } + if (state != Finished && state != Initial) { + SWIFT_LOG(warning) << "SOCKS5BytestreamServerSession unfinished"; + finish(); + } } void SOCKS5BytestreamServerSession::start() { - SWIFT_LOG(debug) << std::endl; - dataReadConnection = connection->onDataRead.connect( - boost::bind(&SOCKS5BytestreamServerSession::handleDataRead, this, _1)); - state = WaitingForAuthentication; + SWIFT_LOG(debug); + dataReadConnection = connection->onDataRead.connect( + boost::bind(&SOCKS5BytestreamServerSession::handleDataRead, this, _1)); + state = WaitingForAuthentication; } void SOCKS5BytestreamServerSession::stop() { - finish(false); + finish(); } -void SOCKS5BytestreamServerSession::startSending(boost::shared_ptr<ReadBytestream> stream) { - if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!" << std::endl; return; } +void SOCKS5BytestreamServerSession::startSending(std::shared_ptr<ReadBytestream> stream) { + if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!"; return; } - readBytestream = stream; - state = WritingData; - dataAvailableConnection = readBytestream->onDataAvailable.connect( - boost::bind(&SOCKS5BytestreamServerSession::handleDataAvailable, this)); - dataWrittenConnection = connection->onDataWritten.connect( - boost::bind(&SOCKS5BytestreamServerSession::sendData, this)); - sendData(); + readBytestream = stream; + state = WritingData; + dataAvailableConnection = readBytestream->onDataAvailable.connect( + boost::bind(&SOCKS5BytestreamServerSession::handleDataAvailable, this)); + dataWrittenConnection = connection->onDataWritten.connect( + boost::bind(&SOCKS5BytestreamServerSession::sendData, this)); + sendData(); } -void SOCKS5BytestreamServerSession::startReceiving(boost::shared_ptr<WriteBytestream> stream) { - if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!" << std::endl; return; } +void SOCKS5BytestreamServerSession::startReceiving(std::shared_ptr<WriteBytestream> stream) { + if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!"; return; } - writeBytestream = stream; - state = ReadingData; - writeBytestream->write(unprocessedData); - onBytesReceived(unprocessedData.size()); - unprocessedData.clear(); + writeBytestream = stream; + state = ReadingData; + writeBytestream->write(unprocessedData); + // onBytesReceived(unprocessedData.size()); + unprocessedData.clear(); } HostAddressPort SOCKS5BytestreamServerSession::getAddressPort() const { - return connection->getLocalAddress(); + return connection->getLocalAddress(); } -void SOCKS5BytestreamServerSession::handleDataRead(boost::shared_ptr<SafeByteArray> data) { - if (state != ReadingData) { - append(unprocessedData, *data); - process(); - } else { - writeBytestream->write(createByteArray(vecptr(*data), data->size())); - onBytesReceived(data->size()); - } +void SOCKS5BytestreamServerSession::handleDataRead(std::shared_ptr<SafeByteArray> data) { + if (state != ReadingData) { + append(unprocessedData, *data); + process(); + } else { + if (!writeBytestream->write(createByteArray(vecptr(*data), data->size()))) { + finish(boost::optional<FileTransferError>(FileTransferError::WriteError)); + } + } } void SOCKS5BytestreamServerSession::handleDataAvailable() { - if (waitingForData) { - sendData(); - } + if (waitingForData) { + sendData(); + } } void SOCKS5BytestreamServerSession::handleDisconnected(const boost::optional<Connection::Error>& error) { - SWIFT_LOG(debug) << (error ? (error == Connection::ReadError ? "Read Error" : "Write Error") : "No Error") << std::endl; - finish(error); + SWIFT_LOG(debug) << (error ? (error == Connection::ReadError ? "Read Error" : "Write Error") : "No Error"); + finish(error ? boost::optional<FileTransferError>(FileTransferError::PeerError) : boost::optional<FileTransferError>()); } void SOCKS5BytestreamServerSession::process() { - if (state == WaitingForAuthentication) { - if (unprocessedData.size() >= 2) { - size_t authCount = unprocessedData[1]; - size_t i = 2; - while (i < 2 + authCount && i < unprocessedData.size()) { - // Skip authentication mechanism - ++i; - } - if (i == 2 + authCount) { - // Authentication message is complete - if (i != unprocessedData.size()) { - SWIFT_LOG(debug) << "Junk after authentication mechanism" << std::endl; - } - unprocessedData.clear(); - connection->write(createSafeByteArray("\x05\x00", 2)); - state = WaitingForRequest; - } - } - } - else if (state == WaitingForRequest) { - if (unprocessedData.size() >= 5) { - ByteArray requestID; - size_t i = 5; - size_t hostnameSize = unprocessedData[4]; - while (i < 5 + hostnameSize && i < unprocessedData.size()) { - requestID.push_back(unprocessedData[i]); - ++i; - } - // Skip the port: 2 byte large, one already skipped. Add one for comparison with size - i += 2; - if (i <= unprocessedData.size()) { - if (i != unprocessedData.size()) { - SWIFT_LOG(debug) << "Junk after authentication mechanism" << std::endl; - } - unprocessedData.clear(); - streamID = byteArrayToString(requestID); - bool hasBytestream = bytestreams->hasBytestream(streamID); - SafeByteArray result = createSafeByteArray("\x05", 1); - result.push_back(hasBytestream ? 0x0 : 0x4); - append(result, createByteArray("\x00\x03", 2)); - result.push_back(boost::numeric_cast<unsigned char>(requestID.size())); - append(result, concat(requestID, createByteArray("\x00\x00", 2))); - if (!hasBytestream) { - SWIFT_LOG(debug) << "Readstream or Wrtiestream with ID " << streamID << " not found!" << std::endl; - connection->write(result); - finish(true); - } - else { - SWIFT_LOG(debug) << "Found stream. Sent OK." << std::endl; - connection->write(result); - state = ReadyForTransfer; - } - } - } - } + if (state == WaitingForAuthentication) { + if (unprocessedData.size() >= 2) { + size_t authCount = unprocessedData[1]; + size_t i = 2; + while (i < 2 + authCount && i < unprocessedData.size()) { + // Skip authentication mechanism + ++i; + } + if (i == 2 + authCount) { + // Authentication message is complete + if (i != unprocessedData.size()) { + SWIFT_LOG(debug) << "Junk after authentication mechanism"; + } + unprocessedData.clear(); + connection->write(createSafeByteArray("\x05\x00", 2)); + state = WaitingForRequest; + } + } + } + else if (state == WaitingForRequest) { + if (unprocessedData.size() >= 5) { + ByteArray requestID; + size_t i = 5; + size_t hostnameSize = unprocessedData[4]; + while (i < 5 + hostnameSize && i < unprocessedData.size()) { + requestID.push_back(unprocessedData[i]); + ++i; + } + // Skip the port: 2 byte large, one already skipped. Add one for comparison with size + i += 2; + if (i <= unprocessedData.size()) { + if (i != unprocessedData.size()) { + SWIFT_LOG(debug) << "Junk after authentication mechanism"; + } + unprocessedData.clear(); + streamID = byteArrayToString(requestID); + bool hasBytestream = bytestreams->hasBytestream(streamID); + SafeByteArray result = createSafeByteArray("\x05", 1); + result.push_back(hasBytestream ? 0x0 : 0x4); + append(result, createByteArray("\x00\x03", 2)); + try { + result.push_back(boost::numeric_cast<unsigned char>(requestID.size())); + } + catch (const boost::numeric::bad_numeric_cast& e) { + SWIFT_LOG(warning) << "SOCKS5 request ID is too long (" << requestID.size() << "): " << e.what(); + finish(); + return; + } + append(result, concat(requestID, createByteArray("\x00\x00", 2))); + if (!hasBytestream) { + SWIFT_LOG(debug) << "Readstream or Wrtiestream with ID " << streamID << " not found!"; + connection->write(result); + finish(boost::optional<FileTransferError>(FileTransferError::PeerError)); + } + else { + SWIFT_LOG(debug) << "Found stream. Sent OK."; + connection->write(result); + state = ReadyForTransfer; + } + } + } + } } void SOCKS5BytestreamServerSession::sendData() { - if (!readBytestream->isFinished()) { - try { - SafeByteArray dataToSend = createSafeByteArray(*readBytestream->read(boost::numeric_cast<size_t>(chunkSize))); - if (!dataToSend.empty()) { - connection->write(dataToSend); - onBytesSent(dataToSend.size()); - waitingForData = false; - } - else { - waitingForData = true; - } - } - catch (const BytestreamException&) { - finish(true); - } - } - else { - finish(false); - } + if (!readBytestream->isFinished()) { + try { + SafeByteArray dataToSend = createSafeByteArray(*readBytestream->read(boost::numeric_cast<size_t>(chunkSize))); + if (!dataToSend.empty()) { + connection->write(dataToSend); + onBytesSent(dataToSend.size()); + waitingForData = false; + } + else { + waitingForData = true; + } + } + catch (const BytestreamException&) { + finish(boost::optional<FileTransferError>(FileTransferError::PeerError)); + } + } + else { + finish(); + } } -void SOCKS5BytestreamServerSession::finish(bool error) { - SWIFT_LOG(debug) << error << " " << state << std::endl; - if (state == Finished) { - return; - } - - disconnectedConnection.disconnect(); - dataReadConnection.disconnect(); - dataWrittenConnection.disconnect(); - dataAvailableConnection.disconnect(); - readBytestream.reset(); - state = Finished; - if (error) { - onFinished(boost::optional<FileTransferError>(FileTransferError::PeerError)); - } else { - onFinished(boost::optional<FileTransferError>()); - } +void SOCKS5BytestreamServerSession::finish(const boost::optional<FileTransferError>& error) { + SWIFT_LOG(debug) << "state: " << state; + if (state == Finished) { + return; + } + + disconnectedConnection.disconnect(); + dataReadConnection.disconnect(); + dataWrittenConnection.disconnect(); + dataAvailableConnection.disconnect(); + readBytestream.reset(); + state = Finished; + onFinished(error); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h index 762db8b..c7e252c 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h @@ -1,84 +1,84 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Network/Connection.h> +#include <Swiften/FileTransfer/FileTransferError.h> #include <Swiften/FileTransfer/ReadBytestream.h> #include <Swiften/FileTransfer/WriteBytestream.h> -#include <Swiften/FileTransfer/FileTransferError.h> +#include <Swiften/Network/Connection.h> namespace Swift { - class SOCKS5BytestreamRegistry; - - class SWIFTEN_API SOCKS5BytestreamServerSession { - public: - typedef boost::shared_ptr<SOCKS5BytestreamServerSession> ref; - - public: - enum State { - Initial, - WaitingForAuthentication, - WaitingForRequest, - ReadyForTransfer, - ReadingData, - WritingData, - Finished - }; - - SOCKS5BytestreamServerSession(boost::shared_ptr<Connection> connection, SOCKS5BytestreamRegistry* registry); - ~SOCKS5BytestreamServerSession(); - - void setChunkSize(int chunkSize) { - this->chunkSize = chunkSize; - } - - void start(); - void stop(); - - void startSending(boost::shared_ptr<ReadBytestream>); - void startReceiving(boost::shared_ptr<WriteBytestream>); - - HostAddressPort getAddressPort() const; - - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - boost::signal<void (unsigned long long)> onBytesSent; - boost::signal<void (unsigned long long)> onBytesReceived; - - const std::string& getStreamID() const { - return streamID; - } - - private: - void finish(bool error); - void process(); - void handleDataRead(boost::shared_ptr<SafeByteArray>); - void handleDisconnected(const boost::optional<Connection::Error>&); - void handleDataAvailable(); - void sendData(); - - private: - boost::shared_ptr<Connection> connection; - SOCKS5BytestreamRegistry* bytestreams; - ByteArray unprocessedData; - State state; - int chunkSize; - std::string streamID; - boost::shared_ptr<ReadBytestream> readBytestream; - boost::shared_ptr<WriteBytestream> writeBytestream; - bool waitingForData; - - boost::bsignals::connection disconnectedConnection; - boost::bsignals::connection dataReadConnection; - boost::bsignals::connection dataWrittenConnection; - boost::bsignals::connection dataAvailableConnection; - - }; + class SOCKS5BytestreamRegistry; + + class SWIFTEN_API SOCKS5BytestreamServerSession { + public: + typedef std::shared_ptr<SOCKS5BytestreamServerSession> ref; + + public: + enum State { + Initial, + WaitingForAuthentication, + WaitingForRequest, + ReadyForTransfer, + ReadingData, + WritingData, + Finished + }; + + SOCKS5BytestreamServerSession(std::shared_ptr<Connection> connection, SOCKS5BytestreamRegistry* registry); + ~SOCKS5BytestreamServerSession(); + + void setChunkSize(int chunkSize) { + this->chunkSize = chunkSize; + } + + void start(); + void stop(); + + void startSending(std::shared_ptr<ReadBytestream>); + void startReceiving(std::shared_ptr<WriteBytestream>); + + HostAddressPort getAddressPort() const; + + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + boost::signals2::signal<void (unsigned long long)> onBytesSent; + + const std::string& getStreamID() const { + return streamID; + } + + private: + void finish(const boost::optional<FileTransferError>& error = boost::optional<FileTransferError>()); + void process(); + void handleDataRead(std::shared_ptr<SafeByteArray>); + void handleDisconnected(const boost::optional<Connection::Error>&); + void handleDataAvailable(); + void sendData(); + + private: + std::shared_ptr<Connection> connection; + SOCKS5BytestreamRegistry* bytestreams; + ByteArray unprocessedData; + State state; + int chunkSize; + std::string streamID; + std::shared_ptr<ReadBytestream> readBytestream; + std::shared_ptr<WriteBytestream> writeBytestream; + bool waitingForData; + + boost::signals2::connection disconnectedConnection; + boost::signals2::connection dataReadConnection; + boost::signals2::connection dataWrittenConnection; + boost::signals2::connection dataAvailableConnection; + + }; } diff --git a/Swiften/FileTransfer/StreamInitiationRequest.h b/Swiften/FileTransfer/StreamInitiationRequest.h index 658a8a9..44e826c 100644 --- a/Swiften/FileTransfer/StreamInitiationRequest.h +++ b/Swiften/FileTransfer/StreamInitiationRequest.h @@ -1,33 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamInitiation.h> - +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class StreamInitiationRequest : public GenericRequest<StreamInitiation> { - public: - typedef boost::shared_ptr<StreamInitiationRequest> ref; + class SWIFTEN_API StreamInitiationRequest : public GenericRequest<StreamInitiation> { + public: + typedef std::shared_ptr<StreamInitiationRequest> ref; - static ref create(const JID& jid, boost::shared_ptr<StreamInitiation> payload, IQRouter* router) { - return ref(new StreamInitiationRequest(jid, payload, router)); - } + static ref create(const JID& jid, std::shared_ptr<StreamInitiation> payload, IQRouter* router) { + return ref(new StreamInitiationRequest(jid, payload, router)); + } - static ref create(const JID& from, const JID& to, boost::shared_ptr<StreamInitiation> payload, IQRouter* router) { - return ref(new StreamInitiationRequest(from, to, payload, router)); - } + static ref create(const JID& from, const JID& to, std::shared_ptr<StreamInitiation> payload, IQRouter* router) { + return ref(new StreamInitiationRequest(from, to, payload, router)); + } - private: - StreamInitiationRequest(const JID& jid, boost::shared_ptr<StreamInitiation> payload, IQRouter* router) : GenericRequest<StreamInitiation>(IQ::Set, jid, payload, router) { - } + private: + StreamInitiationRequest(const JID& jid, std::shared_ptr<StreamInitiation> payload, IQRouter* router) : GenericRequest<StreamInitiation>(IQ::Set, jid, payload, router) { + } - StreamInitiationRequest(const JID& from, const JID& to, boost::shared_ptr<StreamInitiation> payload, IQRouter* router) : GenericRequest<StreamInitiation>(IQ::Set, from, to, payload, router) { - } - }; + StreamInitiationRequest(const JID& from, const JID& to, std::shared_ptr<StreamInitiation> payload, IQRouter* router) : GenericRequest<StreamInitiation>(IQ::Set, from, to, payload, router) { + } + }; } diff --git a/Swiften/FileTransfer/TransportSession.cpp b/Swiften/FileTransfer/TransportSession.cpp index 154cb89..19f128a 100644 --- a/Swiften/FileTransfer/TransportSession.cpp +++ b/Swiften/FileTransfer/TransportSession.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/FileTransfer/TransportSession.h b/Swiften/FileTransfer/TransportSession.h index e5a90db..2d56517 100644 --- a/Swiften/FileTransfer/TransportSession.h +++ b/Swiften/FileTransfer/TransportSession.h @@ -1,25 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> #include <Swiften/FileTransfer/FileTransferError.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class SWIFTEN_API TransportSession { - public: - virtual ~TransportSession(); + class SWIFTEN_API TransportSession { + public: + virtual ~TransportSession(); - virtual void start() = 0; - virtual void stop() = 0; + virtual void start() = 0; + virtual void stop() = 0; - boost::signal<void (size_t)> onBytesSent; - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - }; + boost::signals2::signal<void (size_t)> onBytesSent; + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + }; } diff --git a/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h b/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h index 26adb05..6119658 100644 --- a/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h +++ b/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h @@ -4,46 +4,52 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <string> -#include <boost/filesystem/path.hpp> + #include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/filesystem/path.hpp> -#include <Swiften/Base/Override.h> #include <Swiften/FileTransfer/FileTransferManager.h> namespace Swift { - class S5BProxyRequest; - class FileTransferOptions; - - class DummyFileTransferManager : public FileTransferManager { - public: - DummyFileTransferManager() : FileTransferManager() { - } - - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID&, - const boost::filesystem::path&, - const std::string&, - boost::shared_ptr<ReadBytestream>, - const FileTransferOptions&) SWIFTEN_OVERRIDE { - return OutgoingFileTransfer::ref(); - } - - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID&, - const std::string&, - const std::string&, - const boost::uintmax_t, - const boost::posix_time::ptime&, - boost::shared_ptr<ReadBytestream>, - const FileTransferOptions&) SWIFTEN_OVERRIDE { - return OutgoingFileTransfer::ref(); - } - - virtual void addS5BProxy(boost::shared_ptr<S5BProxyRequest>) { - } - - }; + class S5BProxyRequest; + class FileTransferOptions; + + class DummyFileTransferManager : public FileTransferManager { + public: + DummyFileTransferManager() : FileTransferManager() { + } + + virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID&, + const boost::filesystem::path&, + const std::string&, + std::shared_ptr<ReadBytestream>, + const FileTransferOptions&) override { + return OutgoingFileTransfer::ref(); + } + + virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID&, + const std::string&, + const std::string&, + const boost::uintmax_t, + const boost::posix_time::ptime&, + std::shared_ptr<ReadBytestream>, + const FileTransferOptions&) override { + return OutgoingFileTransfer::ref(); + } + + virtual void addS5BProxy(std::shared_ptr<S5BProxyRequest>) { + } + + }; } diff --git a/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h b/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h new file mode 100644 index 0000000..5db3368 --- /dev/null +++ b/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> +#include <Swiften/FileTransfer/FileTransferTransporter.h> +#include <Swiften/FileTransfer/FileTransferTransporterFactory.h> +#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/FileTransfer/IBBReceiveTransportSession.h> +#include <Swiften/FileTransfer/IBBSendSession.h> +#include <Swiften/FileTransfer/IBBSendTransportSession.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <Swiften/FileTransfer/TransportSession.h> +#include <Swiften/JID/JID.h> +#include <Swiften/StringCodecs/Hexify.h> + +namespace Swift { + +class DummyFileTransferTransporter : public FileTransferTransporter { +public: + enum Role { + Initiator, + Responder + }; + +public: + DummyFileTransferTransporter( + const JID& initiator, + const JID& responder, + Role role, + SOCKS5BytestreamRegistry* s5bRegistry, + SOCKS5BytestreamServerManager* /* s5bServerManager */, + SOCKS5BytestreamProxiesManager* /* s5bProxy */, + IDGenerator* /* idGenerator */, + ConnectionFactory*, + TimerFactory*, + CryptoProvider* cryptoProvider, + IQRouter* iqRouter, + const FileTransferOptions& ftOptions) : initiator_(initiator), responder_(responder), role_(role), s5bRegistry_(s5bRegistry), crypto_(cryptoProvider), iqRouter_(iqRouter), ftOptions_(ftOptions) { + + } + + void initialize() { + s5bSessionID_ = s5bRegistry_->generateSessionID(); + } + + virtual void startGeneratingLocalCandidates() { + std::vector<JingleS5BTransportPayload::Candidate> candidates; + if (ftOptions_.isDirectAllowed()) { + JingleS5BTransportPayload::Candidate candidate; + candidate.cid = "123"; + candidate.priority = 1235; + candidates.push_back(candidate); + } + onLocalCandidatesGenerated(s5bSessionID_, candidates, getSOCKS5DstAddr()); + } + + virtual void stopGeneratingLocalCandidates() { + } + + virtual void addRemoteCandidates(const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string&) { + } + + virtual void startTryingRemoteCandidates() { + onRemoteCandidateSelectFinished(s5bSessionID_, boost::optional<JingleS5BTransportPayload::Candidate>()); + } + + virtual void stopTryingRemoteCandidates() { + } + + virtual void startActivatingProxy(const JID& /* proxy */) { + } + + virtual void stopActivatingProxy() { + } + + virtual std::shared_ptr<TransportSession> createIBBSendSession(const std::string& sessionID, unsigned int blockSize, std::shared_ptr<ReadBytestream> stream) { + std::shared_ptr<IBBSendSession> ibbSession = std::make_shared<IBBSendSession>( + sessionID, initiator_, responder_, stream, iqRouter_); + ibbSession->setBlockSize(blockSize); + return std::make_shared<IBBSendTransportSession>(ibbSession); + } + + virtual std::shared_ptr<TransportSession> createIBBReceiveSession(const std::string& sessionID, unsigned long long size, std::shared_ptr<WriteBytestream> stream) { + std::shared_ptr<IBBReceiveSession> ibbSession = std::make_shared<IBBReceiveSession>( + sessionID, initiator_, responder_, size, stream, iqRouter_); + return std::make_shared<IBBReceiveTransportSession>(ibbSession); + } + + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + +private: + std::string getSOCKS5DstAddr() const { + std::string result; + if (role_ == Initiator) { + result = getInitiatorCandidateSOCKS5DstAddr(); + } + else { + result = getResponderCandidateSOCKS5DstAddr(); + } + return result; + } + + std::string getInitiatorCandidateSOCKS5DstAddr() const { + return Hexify::hexify(crypto_->getSHA1Hash(createSafeByteArray(s5bSessionID_ + initiator_.toString() + responder_.toString()))); + } + + std::string getResponderCandidateSOCKS5DstAddr() const { + return Hexify::hexify(crypto_->getSHA1Hash(createSafeByteArray(s5bSessionID_ + responder_.toString() + initiator_.toString()))); + } + + +private: + JID initiator_; + JID responder_; + Role role_; + SOCKS5BytestreamRegistry* s5bRegistry_; + CryptoProvider* crypto_; + std::string s5bSessionID_; + IQRouter* iqRouter_; + FileTransferOptions ftOptions_; +}; + +class DummyFileTransferTransporterFactory : public FileTransferTransporterFactory { +public: + DummyFileTransferTransporterFactory( + SOCKS5BytestreamRegistry* s5bRegistry, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + IDGenerator* idGenerator, + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + CryptoProvider* cryptoProvider, + IQRouter* iqRouter) : s5bRegistry_(s5bRegistry), s5bServerManager_(s5bServerManager), s5bProxy_(s5bProxy), idGenerator_(idGenerator), connectionFactory_(connectionFactory), timerFactory_(timerFactory), cryptoProvider_(cryptoProvider), iqRouter_(iqRouter) { + + } + + virtual ~DummyFileTransferTransporterFactory() { + } + + virtual FileTransferTransporter* createInitiatorTransporter(const JID& initiator, const JID& responder, const FileTransferOptions& options) { + DummyFileTransferTransporter* transporter = new DummyFileTransferTransporter( + initiator, + responder, + DummyFileTransferTransporter::Initiator, + s5bRegistry_, + s5bServerManager_, + s5bProxy_, + idGenerator_, + connectionFactory_, + timerFactory_, + cryptoProvider_, + iqRouter_, + options); + transporter->initialize(); + return transporter; + } + + virtual FileTransferTransporter* createResponderTransporter(const JID& /* initiator */, const JID& /* responder */, const std::string& /* s5bSessionID */, const FileTransferOptions& /* options */) { + return nullptr; + } + +private: + SOCKS5BytestreamRegistry* s5bRegistry_; + SOCKS5BytestreamServerManager* s5bServerManager_; + SOCKS5BytestreamProxiesManager* s5bProxy_; + IDGenerator* idGenerator_; + ConnectionFactory* connectionFactory_; + TimerFactory* timerFactory_; + CryptoProvider* cryptoProvider_; + IQRouter* iqRouter_; +}; + +} diff --git a/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp b/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp index 339e245..31f46de 100644 --- a/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp @@ -1,185 +1,187 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <memory> #include <vector> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Base/ByteArray.h> -#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/FileTransfer/ByteArrayWriteBytestream.h> +#include <Swiften/FileTransfer/IBBReceiveSession.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Client/DummyStanzaChannel.h> using namespace Swift; class IBBReceiveSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IBBReceiveSessionTest); - CPPUNIT_TEST(testOpen); - CPPUNIT_TEST(testReceiveData); - CPPUNIT_TEST(testReceiveMultipleData); - CPPUNIT_TEST(testReceiveDataForOtherSession); - CPPUNIT_TEST(testReceiveDataOutOfOrder); - CPPUNIT_TEST(testReceiveLastData); - CPPUNIT_TEST(testReceiveClose); - CPPUNIT_TEST(testStopWhileActive); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - finished = false; - bytestream = boost::make_shared<ByteArrayWriteBytestream>(); - } + CPPUNIT_TEST_SUITE(IBBReceiveSessionTest); + CPPUNIT_TEST(testOpen); + CPPUNIT_TEST(testReceiveData); + CPPUNIT_TEST(testReceiveMultipleData); + CPPUNIT_TEST(testReceiveDataForOtherSession); + CPPUNIT_TEST(testReceiveDataOutOfOrder); + CPPUNIT_TEST(testReceiveLastData); + CPPUNIT_TEST(testReceiveClose); + CPPUNIT_TEST(testStopWhileActive); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + finished = false; + bytestream = std::make_shared<ByteArrayWriteBytestream>(); + } - void tearDown() { - delete iqRouter; - delete stanzaChannel; - } - - void testOpen() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + void tearDown() { + delete iqRouter; + delete stanzaChannel; + } + + void testOpen() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(0, "id-open")); - CPPUNIT_ASSERT(!finished); - - testling->stop(); - } + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(0, "id-open")); + CPPUNIT_ASSERT(!finished); + + testling->stop(); + } - void testReceiveData() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(1, "id-a")); - CPPUNIT_ASSERT(createByteArray("abc") == bytestream->getData()); - CPPUNIT_ASSERT(!finished); - - testling->stop(); - } - - void testReceiveMultipleData() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); - - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); - CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); - CPPUNIT_ASSERT(!finished); - - testling->stop(); - } - - void testReceiveDataForOtherSession() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("othersession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - - CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(1, "id-a")); - - testling->stop(); - } - - void testReceiveDataOutOfOrder() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("def")), "foo@bar.com/baz", "id-b")); - - CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(2, "id-b")); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(error); - - testling->stop(); - } - - void testReceiveLastData() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession", 6)); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); - - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); - CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - - testling->stop(); - } - - void testReceiveClose() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBClose("mysession"), "foo@bar.com/baz", "id-close")); + void testReceiveData() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(1, "id-a")); + CPPUNIT_ASSERT(createByteArray("abc") == bytestream->getData()); + CPPUNIT_ASSERT(!finished); + + testling->stop(); + } + + void testReceiveMultipleData() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); + + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); + CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); + CPPUNIT_ASSERT(!finished); + + testling->stop(); + } + + void testReceiveDataForOtherSession() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("othersession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + + CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(1, "id-a")); + + testling->stop(); + } + + void testReceiveDataOutOfOrder() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("def")), "foo@bar.com/baz", "id-b")); + + CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(2, "id-b")); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(error); + + testling->stop(); + } + + void testReceiveLastData() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession", 6)); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); + + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); + CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + + testling->stop(); + } + + void testReceiveClose() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBClose("mysession"), "foo@bar.com/baz", "id-close")); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(error); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(error); - testling->stop(); - } + testling->stop(); + } - void testStopWhileActive() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + void testStopWhileActive() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - testling->stop(); + testling->stop(); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); - CPPUNIT_ASSERT_EQUAL(std::string("mysession"), ibb->getStreamID()); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - } + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); + CPPUNIT_ASSERT_EQUAL(std::string("mysession"), ibb->getStreamID()); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + } - private: - IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { - IQ::ref request = IQ::createRequest(IQ::Set, JID("baz@fum.com/dum"), id, ibb); - request->setFrom(from); - return request; - } + private: + IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { + IQ::ref request = IQ::createRequest(IQ::Set, JID("baz@fum.com/dum"), id, ibb); + request->setFrom(from); + return request; + } - IBBReceiveSession* createSession(const std::string& from, const std::string& id, size_t size = 0x1000) { - IBBReceiveSession* session = new IBBReceiveSession(id, JID(from), JID(), size, bytestream, iqRouter); - session->onFinished.connect(boost::bind(&IBBReceiveSessionTest::handleFinished, this, _1)); - return session; - } + IBBReceiveSession* createSession(const std::string& from, const std::string& id, size_t size = 0x1000) { + IBBReceiveSession* session = new IBBReceiveSession(id, JID(from), JID(), size, bytestream, iqRouter); + session->onFinished.connect(boost::bind(&IBBReceiveSessionTest::handleFinished, this, _1)); + return session; + } - void handleFinished(boost::optional<FileTransferError> error) { - finished = true; - this->error = error; - } + void handleFinished(boost::optional<FileTransferError> error) { + finished = true; + this->error = error; + } - private: - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - bool finished; - boost::optional<FileTransferError> error; - boost::shared_ptr<ByteArrayWriteBytestream> bytestream; + private: + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + bool finished; + boost::optional<FileTransferError> error; + std::shared_ptr<ByteArrayWriteBytestream> bytestream; }; CPPUNIT_TEST_SUITE_REGISTRATION(IBBReceiveSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp b/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp index 13b73bb..2399cbe 100644 --- a/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp @@ -1,230 +1,232 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> #include <vector> + #include <boost/bind.hpp> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + #include <Swiften/Base/ByteArray.h> -#include <Swiften/FileTransfer/IBBSendSession.h> +#include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> +#include <Swiften/FileTransfer/IBBSendSession.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Client/DummyStanzaChannel.h> using namespace Swift; class IBBSendSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IBBSendSessionTest); - CPPUNIT_TEST(testStart); - CPPUNIT_TEST(testStart_ResponseStartsSending); - CPPUNIT_TEST(testResponseContinuesSending); - CPPUNIT_TEST(testRespondToAllFinishes); - CPPUNIT_TEST(testErrorResponseFinishesWithError); - CPPUNIT_TEST(testStopDuringSessionCloses); - CPPUNIT_TEST(testStopAfterFinishedDoesNotClose); - CPPUNIT_TEST(testDataStreamPauseStopsSendingData); - CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); - CPPUNIT_TEST(testDataStreamResumeBeforePauseDoesNotSendData); - CPPUNIT_TEST(testDataStreamResumeAfterResumeDoesNotSendData); - - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - bytestream = boost::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); - finished = false; - } - - void tearDown() { - delete iqRouter; - delete stanzaChannel; - } - - void testStart() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(1234); - - testling->start(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(0, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[0]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Open, ibb->getAction()); - CPPUNIT_ASSERT_EQUAL(1234, ibb->getBlockSize()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - } - - void testStart_ResponseStartsSending() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); - CPPUNIT_ASSERT(createByteArray("abc") == ibb->getData()); - CPPUNIT_ASSERT_EQUAL(0, ibb->getSequenceNumber()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - } - - void testResponseContinuesSending() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(2, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[2]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); - CPPUNIT_ASSERT(createByteArray("def") == ibb->getData()); - CPPUNIT_ASSERT_EQUAL(1, ibb->getSequenceNumber()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - } - - void testRespondToAllFinishes() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - } - - void testErrorResponseFinishesWithError() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(error); - } - - void testStopDuringSessionCloses() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - testling->stop(); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - } - - void testStopAfterFinishedDoesNotClose() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(16); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - CPPUNIT_ASSERT(finished); - - testling->stop(); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamPauseStopsSendingData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT(!finished); - CPPUNIT_ASSERT(!error); - - CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamResumeAfterPauseSendsData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - bytestream->addData(createByteArray("xyz")); - - CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamResumeBeforePauseDoesNotSendData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - - bytestream->addData(createByteArray("xyz")); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamResumeAfterResumeDoesNotSendData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - bytestream->addData(createByteArray("xyz")); - bytestream->addData(createByteArray("xuv")); - - CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - private: - IQ::ref createIBBResult() { - return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getTo(), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getID(), boost::shared_ptr<IBB>()); - } - - private: - boost::shared_ptr<IBBSendSession> createSession(const std::string& to) { - boost::shared_ptr<IBBSendSession> session(new IBBSendSession("myid", JID(), JID(to), bytestream, iqRouter)); - session->onFinished.connect(boost::bind(&IBBSendSessionTest::handleFinished, this, _1)); - return session; - } - - void handleFinished(boost::optional<FileTransferError> error) { - finished = true; - this->error = error; - } - - private: - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - bool finished; - boost::optional<FileTransferError> error; - boost::shared_ptr<ByteArrayReadBytestream> bytestream; + CPPUNIT_TEST_SUITE(IBBSendSessionTest); + CPPUNIT_TEST(testStart); + CPPUNIT_TEST(testStart_ResponseStartsSending); + CPPUNIT_TEST(testResponseContinuesSending); + CPPUNIT_TEST(testRespondToAllFinishes); + CPPUNIT_TEST(testErrorResponseFinishesWithError); + CPPUNIT_TEST(testStopDuringSessionCloses); + CPPUNIT_TEST(testStopAfterFinishedDoesNotClose); + CPPUNIT_TEST(testDataStreamPauseStopsSendingData); + CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); + CPPUNIT_TEST(testDataStreamResumeBeforePauseDoesNotSendData); + CPPUNIT_TEST(testDataStreamResumeAfterResumeDoesNotSendData); + + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + bytestream = std::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); + finished = false; + } + + void tearDown() { + delete iqRouter; + delete stanzaChannel; + } + + void testStart() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(1234); + + testling->start(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(0, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[0]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Open, ibb->getAction()); + CPPUNIT_ASSERT_EQUAL(1234u, ibb->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + } + + void testStart_ResponseStartsSending() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); + CPPUNIT_ASSERT(createByteArray("abc") == ibb->getData()); + CPPUNIT_ASSERT_EQUAL(0, ibb->getSequenceNumber()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + } + + void testResponseContinuesSending() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(2, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[2]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); + CPPUNIT_ASSERT(createByteArray("def") == ibb->getData()); + CPPUNIT_ASSERT_EQUAL(1, ibb->getSequenceNumber()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + } + + void testRespondToAllFinishes() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + } + + void testErrorResponseFinishesWithError() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(error); + } + + void testStopDuringSessionCloses() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + testling->stop(); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + } + + void testStopAfterFinishedDoesNotClose() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(16); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + CPPUNIT_ASSERT(finished); + + testling->stop(); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamPauseStopsSendingData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT(!finished); + CPPUNIT_ASSERT(!error); + + CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamResumeAfterPauseSendsData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + bytestream->addData(createByteArray("xyz")); + + CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamResumeBeforePauseDoesNotSendData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + + bytestream->addData(createByteArray("xyz")); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamResumeAfterResumeDoesNotSendData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + bytestream->addData(createByteArray("xyz")); + bytestream->addData(createByteArray("xuv")); + + CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + private: + IQ::ref createIBBResult() { + return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getTo(), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getID(), std::shared_ptr<IBB>()); + } + + private: + std::shared_ptr<IBBSendSession> createSession(const std::string& to) { + std::shared_ptr<IBBSendSession> session(new IBBSendSession("myid", JID(), JID(to), bytestream, iqRouter)); + session->onFinished.connect(boost::bind(&IBBSendSessionTest::handleFinished, this, _1)); + return session; + } + + void handleFinished(boost::optional<FileTransferError> error) { + finished = true; + this->error = error; + } + + private: + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + bool finished; + boost::optional<FileTransferError> error; + std::shared_ptr<ByteArrayReadBytestream> bytestream; }; CPPUNIT_TEST_SUITE_REGISTRATION(IBBSendSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp index 669ed80..9793b87 100644 --- a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp @@ -5,214 +5,238 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ +#include <iostream> +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/Override.h> #include <Swiften/Base/Log.h> #include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/Elements/IBB.h> +#include <Swiften/Elements/JingleFileTransferDescription.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/FileTransfer/ByteArrayWriteBytestream.h> +#include <Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h> #include <Swiften/FileTransfer/IncomingJingleFileTransfer.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> #include <Swiften/Jingle/FakeJingleSession.h> -#include <Swiften/Network/DummyTimerFactory.h> -#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Network/DummyConnectionFactory.h> +#include <Swiften/Network/DummyConnectionServerFactory.h> +#include <Swiften/Network/DummyTimerFactory.h> +#include <Swiften/Network/NATTraverser.h> #include <Swiften/Network/PlatformNATTraversalWorker.h> +#include <Swiften/Network/PlatformNetworkEnvironment.h> +#include <Swiften/Network/StaticDomainNameResolver.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Crypto/PlatformCryptoProvider.h> - -#include <iostream> using namespace Swift; -using namespace boost; class IncomingJingleFileTransferTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IncomingJingleFileTransferTest); - //CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept); - //CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks); - //CPPUNIT_TEST(test_AcceptFailingS5BFallsBackToIBB); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(IncomingJingleFileTransferTest); + CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept); + CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks); + //CPPUNIT_TEST(test_AcceptFailingS5BFallsBackToIBB); + CPPUNIT_TEST_SUITE_END(); public: - // shared_ptr<IncomingJingleFileTransfer> createTestling() { - // JID ourJID("our@jid.org/full"); - // return boost::shared_ptr<IncomingJingleFileTransfer>(new IncomingJingleFileTransfer(ourJID, shared_ptr<JingleSession>(session), jingleContentPayload, fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, bytestreamRegistry, bytestreamProxy, timerFactory, crypto.get())); - // } - - // IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { - // IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); - // request->setFrom(from); - // return request; - // } - - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - eventLoop = new DummyEventLoop(); - session = boost::make_shared<FakeJingleSession>("foo@bar.com/baz", "mysession"); - // jingleContentPayload = make_shared<JingleContentPayload>(); - // fakeRJTCSF = make_shared<FakeRemoteJingleTransportCandidateSelectorFactory>(); - // fakeLJTCF = make_shared<FakeLocalJingleTransportCandidateGeneratorFactory>(); - // stanzaChannel = new DummyStanzaChannel(); - // iqRouter = new IQRouter(stanzaChannel); - // bytestreamRegistry = new SOCKS5BytestreamRegistry(); - // timerFactory = new DummyTimerFactory(); - // connectionFactory = new DummyConnectionFactory(eventLoop); - // bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory); - } - - void tearDown() { - // delete bytestreamProxy; - // delete connectionFactory; - // delete timerFactory; - // delete bytestreamRegistry; - // delete iqRouter; - // delete stanzaChannel; - delete eventLoop; - } - - // Tests whether IncomingJingleFileTransfer would accept a IBB only file transfer. + std::shared_ptr<IncomingJingleFileTransfer> createTestling() { + JID ourJID("our@jid.org/full"); + return std::make_shared<IncomingJingleFileTransfer>(ourJID, std::shared_ptr<JingleSession>(session), jingleContentPayload, ftTransporterFactory, timerFactory, crypto.get()); + } + + IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { + IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); + request->setFrom(from); + return request; + } + + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + eventLoop = new DummyEventLoop(); + resolver = new StaticDomainNameResolver(eventLoop); + session = std::make_shared<FakeJingleSession>("foo@bar.com/baz", "mysession"); + jingleContentPayload = std::make_shared<JingleContentPayload>(); + // fakeRJTCSF = std::make_shared<FakeRemoteJingleTransportCandidateSelectorFactory>(); + // fakeLJTCF = std::make_shared<FakeLocalJingleTransportCandidateGeneratorFactory>(); + stanzaChannel = new DummyStanzaChannel(); + connectionFactory = new DummyConnectionFactory(eventLoop); + serverConnectionFactory = new DummyConnectionServerFactory(eventLoop); + iqRouter = new IQRouter(stanzaChannel); + bytestreamRegistry = new SOCKS5BytestreamRegistry(); + networkEnvironment = new PlatformNetworkEnvironment(); + natTraverser = new PlatformNATTraversalWorker(eventLoop); + bytestreamServerManager = new SOCKS5BytestreamServerManager(bytestreamRegistry, serverConnectionFactory, networkEnvironment, natTraverser); + idGenerator = new SimpleIDGenerator(); + timerFactory = new DummyTimerFactory(); + bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, resolver, iqRouter, "bar.com"); + ftTransporterFactory = new DefaultFileTransferTransporterFactory(bytestreamRegistry, bytestreamServerManager, bytestreamProxy, idGenerator, connectionFactory, timerFactory, crypto.get(), iqRouter); + } + + void tearDown() { + delete ftTransporterFactory; + delete bytestreamProxy; + delete timerFactory; + delete idGenerator; + delete bytestreamServerManager; + delete natTraverser; + delete networkEnvironment; + delete bytestreamRegistry; + delete iqRouter; + delete serverConnectionFactory; + delete connectionFactory; + delete stanzaChannel; + delete resolver; + delete eventLoop; + Log::setLogLevel(Log::error); + } + + // Tests whether IncomingJingleFileTransfer would accept a IBB only file transfer. + void test_AcceptOnyIBBSendsSessionAccept() { + //1. create your test incoming file transfer + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo("foo.txt", "", 10)); + jingleContentPayload->addDescription(desc); + JingleIBBTransportPayload::ref tpRef = std::make_shared<JingleIBBTransportPayload>(); + tpRef->setSessionID("mysession"); + jingleContentPayload->addTransport(tpRef); + + std::shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); + + //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) + std::shared_ptr<ByteArrayWriteBytestream> byteStream = std::make_shared<ByteArrayWriteBytestream>(); + fileTransfer->accept(byteStream); + + // check whether accept has been called + getCall<FakeJingleSession::AcceptCall>(0); + } + + void test_OnlyIBBTransferReceiveWorks() { + //1. create your test incoming file transfer + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10)); + jingleContentPayload->addDescription(desc); + JingleIBBTransportPayload::ref tpRef = std::make_shared<JingleIBBTransportPayload>(); + tpRef->setSessionID("mysession"); + jingleContentPayload->addTransport(tpRef); + + std::shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); + + //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) + std::shared_ptr<ByteArrayWriteBytestream> byteStream = std::make_shared<ByteArrayWriteBytestream>(); + fileTransfer->accept(byteStream); + + // check whether accept has been called + getCall<FakeJingleSession::AcceptCall>(0); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); + } + + void test_AcceptFailingS5BFallsBackToIBB() { + //1. create your test incoming file transfer + addFileTransferDescription(); + + // add SOCKS5BytestreamTransportPayload + JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); + + std::shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); + + //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) + std::shared_ptr<ByteArrayWriteBytestream> byteStream = std::make_shared<ByteArrayWriteBytestream>(); + fileTransfer->accept(byteStream); + + // candidates are gathered + + // check whether accept has been called + FakeJingleSession::AcceptCall acceptCall = getCall<FakeJingleSession::AcceptCall>(0); + CPPUNIT_ASSERT_EQUAL(payLoad->getSessionID(), acceptCall.payload->getSessionID()); + + // check for candidate error + FakeJingleSession::InfoTransportCall infoTransportCall = getCall<FakeJingleSession::InfoTransportCall>(1); + JingleS5BTransportPayload::ref s5bPayload = std::dynamic_pointer_cast<JingleS5BTransportPayload>(infoTransportCall.payload); + CPPUNIT_ASSERT(s5bPayload->hasCandidateError()); + + // indicate transport replace (Romeo) + session->handleTransportReplaceReceived(getContentID(), addJingleIBBPayload()); + + FakeJingleSession::AcceptTransportCall acceptTransportCall = getCall<FakeJingleSession::AcceptTransportCall>(2); + + // send a bit of data + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); + } #if 0 - void test_AcceptOnyIBBSendsSessionAccept() { - //1. create your test incoming file transfer - shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); - desc->addOffer(StreamInitiationFileInfo("foo.txt", "", 10)); - jingleContentPayload->addDescription(desc); - JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>(); - tpRef->setSessionID("mysession"); - jingleContentPayload->addTransport(tpRef); - - shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); - - //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) - shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>(); - fileTransfer->accept(byteStream); - - // check whether accept has been called - getCall<FakeJingleSession::AcceptCall>(0); - } - - void test_OnlyIBBTransferReceiveWorks() { - //1. create your test incoming file transfer - shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); - desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10)); - jingleContentPayload->addDescription(desc); - JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>(); - tpRef->setSessionID("mysession"); - jingleContentPayload->addTransport(tpRef); - - shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); - - //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) - shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>(); - fileTransfer->accept(byteStream); - - // check whether accept has been called - getCall<FakeJingleSession::AcceptCall>(0); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); - } - - void test_AcceptFailingS5BFallsBackToIBB() { - //1. create your test incoming file transfer - addFileTransferDescription(); - - // add SOCKS5BytestreamTransportPayload - JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); - - shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); - - //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) - shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>(); - fileTransfer->accept(byteStream); - - // check whether accept has been called - FakeJingleSession::AcceptCall acceptCall = getCall<FakeJingleSession::AcceptCall>(0); - CPPUNIT_ASSERT_EQUAL(payLoad->getSessionID(), acceptCall.payload->getSessionID()); - - // check for candidate error - FakeJingleSession::InfoTransportCall infoTransportCall = getCall<FakeJingleSession::InfoTransportCall>(1); - JingleS5BTransportPayload::ref s5bPayload = dynamic_pointer_cast<JingleS5BTransportPayload>(infoTransportCall.payload); - CPPUNIT_ASSERT(s5bPayload->hasCandidateError()); - - // indicate transport replace (Romeo) - session->onTransportReplaceReceived(getContentID(), addJingleIBBPayload()); - - FakeJingleSession::AcceptTransportCall acceptTransportCall = getCall<FakeJingleSession::AcceptTransportCall>(2); - - // send a bit of data - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); - } - - void test_S5BTransferReceiveTest() { - addFileTransferDescription(); - JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); - } - -private: - void addFileTransferDescription() { - shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); - desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10)); - jingleContentPayload->addDescription(desc); - } - - shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { - JingleS5BTransportPayload::ref payLoad = make_shared<JingleS5BTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { - JingleIBBTransportPayload::ref payLoad = make_shared<JingleIBBTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - JingleContentID getContentID() const { - return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); - } - - template <typename T> T getCall(int i) const { - size_t index = static_cast<size_t>(i); - CPPUNIT_ASSERT(index < session->calledCommands.size()); - T* cmd = boost::get<T>(&session->calledCommands[index]); - CPPUNIT_ASSERT(cmd); - return *cmd; - } + void test_S5BTransferReceiveTest() { + addFileTransferDescription(); + JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); + } #endif +private: + void addFileTransferDescription() { + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10)); + jingleContentPayload->addDescription(desc); + } + + std::shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { + JingleS5BTransportPayload::ref payLoad = std::make_shared<JingleS5BTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + std::shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { + JingleIBBTransportPayload::ref payLoad = std::make_shared<JingleIBBTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + JingleContentID getContentID() const { + return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); + } + + template <typename T> T getCall(int i) const { + size_t index = static_cast<size_t>(i); + CPPUNIT_ASSERT(index < session->calledCommands.size()); + T* cmd = boost::get<T>(&session->calledCommands[index]); + CPPUNIT_ASSERT(cmd); + return *cmd; + } private: - EventLoop* eventLoop; - boost::shared_ptr<CryptoProvider> crypto; - boost::shared_ptr<FakeJingleSession> session; -#if 0 - shared_ptr<JingleContentPayload> jingleContentPayload; - shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; - shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - SOCKS5BytestreamRegistry* bytestreamRegistry; - DummyConnectionFactory* connectionFactory; - SOCKS5BytestreamProxiesManager* bytestreamProxy; - DummyTimerFactory* timerFactory; -#endif + EventLoop* eventLoop; + std::shared_ptr<CryptoProvider> crypto; + std::shared_ptr<FakeJingleSession> session; + std::shared_ptr<JingleContentPayload> jingleContentPayload; +// shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; +// shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; + FileTransferTransporterFactory* ftTransporterFactory; + SOCKS5BytestreamServerManager* bytestreamServerManager; + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + SOCKS5BytestreamRegistry* bytestreamRegistry; + DummyConnectionFactory* connectionFactory; + DummyConnectionServerFactory* serverConnectionFactory; + SOCKS5BytestreamProxiesManager* bytestreamProxy; + DummyTimerFactory* timerFactory; + NetworkEnvironment* networkEnvironment; + NATTraverser* natTraverser; + IDGenerator* idGenerator; + DomainNameResolver* resolver; }; CPPUNIT_TEST_SUITE_REGISTRATION(IncomingJingleFileTransferTest); diff --git a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp index 16b1225..a0fe057 100644 --- a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp +++ b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp @@ -5,290 +5,278 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <iostream> +#include <memory> #include <boost/bind.hpp> #include <boost/optional.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> -#include <Swiften/Jingle/FakeJingleSession.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Client/DummyStanzaChannel.h> -#include <Swiften/FileTransfer/ByteArrayReadBytestream.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Elements/JingleIBBTransportPayload.h> -#include <Swiften/Elements/JingleS5BTransportPayload.h> -#include <Swiften/Elements/JingleFileTransferDescription.h> -#include <Swiften/Elements/IBB.h> #include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/Override.h> #include <Swiften/Base/IDGenerator.h> +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Elements/IBB.h> +#include <Swiften/Elements/JingleFileTransferDescription.h> +#include <Swiften/Elements/JingleIBBTransportPayload.h> +#include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/Network/PlatformNATTraversalWorker.h> -#include <Swiften/Network/DummyTimerFactory.h> -#include <Swiften/Network/DummyConnection.h> +#include <Swiften/FileTransfer/ByteArrayReadBytestream.h> +#include <Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h> +#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> +#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h> +#include <Swiften/Jingle/FakeJingleSession.h> #include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/DummyConnection.h> #include <Swiften/Network/DummyConnectionFactory.h> -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Crypto/PlatformCryptoProvider.h> - -#include <Swiften/Base/Log.h> - -#include <iostream> +#include <Swiften/Network/DummyConnectionServer.h> +#include <Swiften/Network/DummyConnectionServerFactory.h> +#include <Swiften/Network/DummyTimerFactory.h> +#include <Swiften/Network/PlatformNATTraversalWorker.h> +#include <Swiften/Network/PlatformNetworkEnvironment.h> +#include <Swiften/Queries/IQRouter.h> -#if 0 using namespace Swift; -class OFakeRemoteJingleTransportCandidateSelector : public RemoteJingleTransportCandidateSelector { - void addRemoteTransportCandidates(JingleTransportPayload::ref cand) { - candidate = cand; - } - - void selectCandidate() { - JingleS5BTransportPayload::ref payload = boost::make_shared<JingleS5BTransportPayload>(); - payload->setCandidateError(true); - payload->setSessionID(candidate->getSessionID()); - onRemoteTransportCandidateSelectFinished(payload); - } - - void setMinimumPriority(int) { - - } - - bool isActualCandidate(JingleTransportPayload::ref) { - return false; - } - - int getPriority(JingleTransportPayload::ref) { - return 0; - } - - JingleTransport::ref selectTransport(JingleTransportPayload::ref) { - return JingleTransport::ref(); - } - -private: - JingleTransportPayload::ref candidate; -}; - -class OFakeRemoteJingleTransportCandidateSelectorFactory : public RemoteJingleTransportCandidateSelectorFactory { -public: - virtual ~OFakeRemoteJingleTransportCandidateSelectorFactory() { - - } - - virtual RemoteJingleTransportCandidateSelector* createCandidateSelector() { - return new OFakeRemoteJingleTransportCandidateSelector(); - } -}; - -class OFakeLocalJingleTransportCandidateGenerator : public LocalJingleTransportCandidateGenerator { -public: - void emitonLocalTransportCandidatesGenerated(const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - onLocalTransportCandidatesGenerated(candidates); - } - - virtual bool isActualCandidate(JingleTransportPayload::ref) { - return false; - } - - virtual int getPriority(JingleTransportPayload::ref) { - return 0; - } - - virtual JingleTransport::ref selectTransport(JingleTransportPayload::ref) { - return JingleTransport::ref(); - } - - virtual void start() SWIFTEN_OVERRIDE { - //JingleTransportPayload::ref payL = make_shared<JingleTransportPayload>(); - //payL->setSessionID(payload->getSessionID()); - // JingleS5BTransportPayload::ref payL = boost::make_shared<JingleS5BTransportPayload>(); - - onLocalTransportCandidatesGenerated(std::vector<JingleS5BTransportPayload::Candidate>()); - } - - virtual void stop() SWIFTEN_OVERRIDE {} -}; - -class OFakeLocalJingleTransportCandidateGeneratorFactory : public LocalJingleTransportCandidateGeneratorFactory { -public: - virtual LocalJingleTransportCandidateGenerator* createCandidateGenerator() { - return new OFakeLocalJingleTransportCandidateGenerator(); - } -}; - class OutgoingJingleFileTransferTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(OutgoingJingleFileTransferTest); - CPPUNIT_TEST(test_SendSessionInitiateOnStart); - CPPUNIT_TEST(test_IBBStartsAfterSendingSessionAccept); - CPPUNIT_TEST(test_ReceiveSessionTerminateAfterSessionInitiate); - CPPUNIT_TEST_SUITE_END(); - - class FTStatusHelper { - public: - bool finishedCalled; - FileTransferError::Type error; - void handleFileTransferFinished(boost::optional<FileTransferError> error) { - finishedCalled = true; - if (error.is_initialized()) this->error = error.get().getType(); - } - }; + CPPUNIT_TEST_SUITE(OutgoingJingleFileTransferTest); + CPPUNIT_TEST(test_SendSessionInitiateOnStart); + CPPUNIT_TEST(test_FallbackToIBBAfterFailingS5B); + CPPUNIT_TEST(test_ReceiveSessionTerminateAfterSessionInitiate); + CPPUNIT_TEST(test_DeclineEmitsFinishedStateCanceled); + CPPUNIT_TEST_SUITE_END(); + + class FTStatusHelper { + public: + FTStatusHelper() : finishedCalled(false), error(FileTransferError::UnknownError) { + } + + void handleFileTransferFinished(boost::optional<FileTransferError> error) { + finishedCalled = true; + if (error.is_initialized()) this->error = error.get().getType(); + } + + void handleFileTransferStatusChanged(FileTransfer::State fileTransferSTate) { + state = fileTransferSTate; + } + + public: + bool finishedCalled; + FileTransferError::Type error; + boost::optional<FileTransfer::State> state; + }; + public: - boost::shared_ptr<OutgoingJingleFileTransfer> createTestling() { - JID to("test@foo.com/bla"); - StreamInitiationFileInfo fileInfo; - fileInfo.setDescription("some file"); - fileInfo.setName("test.bin"); - fileInfo.setHash("asdjasdas"); - fileInfo.setSize(1024 * 1024); - return boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(boost::shared_ptr<JingleSession>(fakeJingleSession), fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, idGen, JID(), to, stream, fileInfo, s5bRegistry, s5bProxy, crypto.get())); - } - - IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { - IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); - request->setFrom(from); - return request; - } - - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - fakeJingleSession = new FakeJingleSession("foo@bar.com/baz", "mysession"); - jingleContentPayload = boost::make_shared<JingleContentPayload>(); - fakeRJTCSF = boost::make_shared<OFakeRemoteJingleTransportCandidateSelectorFactory>(); - fakeLJTCF = boost::make_shared<OFakeLocalJingleTransportCandidateGeneratorFactory>(); - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - eventLoop = new DummyEventLoop(); - timerFactory = new DummyTimerFactory(); - connectionFactory = new DummyConnectionFactory(eventLoop); - s5bRegistry = new SOCKS5BytestreamRegistry(); - s5bProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory); - - data.clear(); - for (int n=0; n < 1024 * 1024; ++n) { - data.push_back(34); - } - - stream = boost::make_shared<ByteArrayReadBytestream>(data); - - idGen = new IDGenerator(); - } - - void tearDown() { - delete idGen; - delete s5bRegistry; - delete connectionFactory; - delete timerFactory; - delete eventLoop; - delete iqRouter; - delete stanzaChannel; - } - - - void test_SendSessionInitiateOnStart() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); - transfer->start(); - FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); - JingleFileTransferDescription::ref description = boost::dynamic_pointer_cast<JingleFileTransferDescription>(call.description); - CPPUNIT_ASSERT(description); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), description->getOffers().size()); - CPPUNIT_ASSERT(static_cast<size_t>(1048576) == description->getOffers()[0].getSize()); - - JingleS5BTransportPayload::ref transport = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(call.payload); - CPPUNIT_ASSERT(transport); - } - - void test_IBBStartsAfterSendingSessionAccept() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); - transfer->start(); - - FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); - // FIXME: we initiate with SOCSK5 now and not IBB, needs to be fixed. - /* - fakeJingleSession->onSessionAcceptReceived(call.id, call.description, call.payload); - IQ::ref iqOpenStanza = stanzaChannel->getStanzaAtIndex<IQ>(0); - CPPUNIT_ASSERT(iqOpenStanza); - */ - } - - void test_ReceiveSessionTerminateAfterSessionInitiate() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); - transfer->start(); - - getCall<FakeJingleSession::InitiateCall>(0); - - FTStatusHelper helper; - helper.finishedCalled = false; - transfer->onFinished.connect(bind(&FTStatusHelper::handleFileTransferFinished, &helper, _1)); - fakeJingleSession->onSessionTerminateReceived(JinglePayload::Reason(JinglePayload::Reason::Busy)); - CPPUNIT_ASSERT_EQUAL(true, helper.finishedCalled); - CPPUNIT_ASSERT(FileTransferError::PeerError == helper.error); - } - + std::shared_ptr<OutgoingJingleFileTransfer> createTestling(const FileTransferOptions& options = FileTransferOptions().withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false)) { + JID to("test@foo.com/bla"); + JingleFileTransferFileInfo fileInfo; + fileInfo.setDescription("some file"); + fileInfo.setName("test.bin"); + fileInfo.addHash(HashElement("sha-1", ByteArray())); + fileInfo.setSize(1024 * 1024); + return std::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer( + to, + std::shared_ptr<JingleSession>(fakeJingleSession), + stream, + ftTransportFactory, + timerFactory, + idGen, + fileInfo, + options, + crypto.get())); + } + + IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { + IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); + request->setFrom(from); + return request; + } + + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + fakeJingleSession = new FakeJingleSession("foo@bar.com/baz", "mysession"); + jingleContentPayload = std::make_shared<JingleContentPayload>(); + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + eventLoop = new DummyEventLoop(); + timerFactory = new DummyTimerFactory(); + connectionFactory = new DummyConnectionFactory(eventLoop); + serverConnectionFactory = new DummyConnectionServerFactory(eventLoop); + s5bRegistry = new SOCKS5BytestreamRegistry(); + networkEnvironment = new PlatformNetworkEnvironment(); + natTraverser = new PlatformNATTraversalWorker(eventLoop); + bytestreamServerManager = new SOCKS5BytestreamServerManager(s5bRegistry, serverConnectionFactory, networkEnvironment, natTraverser); + + data.clear(); + for (int n=0; n < 1024 * 1024; ++n) { + data.push_back(34); + } + + stream = std::make_shared<ByteArrayReadBytestream>(data); + + idGen = new IDGenerator(); + s5bProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, resolver, iqRouter, "bar.com"); + ftTransportFactory = new DummyFileTransferTransporterFactory(s5bRegistry, bytestreamServerManager, s5bProxy, idGen, connectionFactory, timerFactory, crypto.get(), iqRouter); + } + + void tearDown() { + delete ftTransportFactory; + delete s5bProxy; + delete idGen; + delete bytestreamServerManager; + delete natTraverser; + delete networkEnvironment; + delete s5bRegistry; + delete serverConnectionFactory; + delete connectionFactory; + delete timerFactory; + delete eventLoop; + delete iqRouter; + delete stanzaChannel; + } + + + void test_SendSessionInitiateOnStart() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); + transfer->start(); + + FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); + JingleFileTransferDescription::ref description = std::dynamic_pointer_cast<JingleFileTransferDescription>(call.description); + CPPUNIT_ASSERT(description); + CPPUNIT_ASSERT(static_cast<size_t>(1048576) == description->getFileInfo().getSize()); + + JingleIBBTransportPayload::ref transport = std::dynamic_pointer_cast<JingleIBBTransportPayload>(call.payload); + CPPUNIT_ASSERT(transport); + } + + void test_FallbackToIBBAfterFailingS5B() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(FileTransferOptions().withAssistedAllowed(true).withDirectAllowed(true).withProxiedAllowed(true)); + transfer->start(); + + FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); + + CPPUNIT_ASSERT(std::dynamic_pointer_cast<JingleS5BTransportPayload>(call.payload)); + fakeJingleSession->handleSessionAcceptReceived(call.id, call.description, call.payload); + + // send candidate failure + JingleS5BTransportPayload::ref candidateFailurePayload = std::make_shared<JingleS5BTransportPayload>(); + candidateFailurePayload->setCandidateError(true); + candidateFailurePayload->setSessionID(call.payload->getSessionID()); + fakeJingleSession->handleTransportInfoReceived(call.id, candidateFailurePayload); + + // no S5B candidates -> fallback to IBB + // call at position 1 is the candidate our candidate error + FakeJingleSession::ReplaceTransportCall replaceCall = getCall<FakeJingleSession::ReplaceTransportCall>(2); + + // accept transport replace + fakeJingleSession->handleTransportAcceptReceived(replaceCall.id, replaceCall.payload); + + IQ::ref iqOpenStanza = stanzaChannel->getStanzaAtIndex<IQ>(0); + CPPUNIT_ASSERT(iqOpenStanza); + IBB::ref ibbOpen = iqOpenStanza->getPayload<IBB>(); + CPPUNIT_ASSERT(ibbOpen); + CPPUNIT_ASSERT_EQUAL(IBB::Open, ibbOpen->getAction()); + } + + void test_ReceiveSessionTerminateAfterSessionInitiate() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); + transfer->start(); + + getCall<FakeJingleSession::InitiateCall>(0); + + FTStatusHelper helper; + helper.finishedCalled = false; + transfer->onFinished.connect(bind(&FTStatusHelper::handleFileTransferFinished, &helper, _1)); + fakeJingleSession->handleSessionTerminateReceived(JinglePayload::Reason(JinglePayload::Reason::Busy)); + CPPUNIT_ASSERT_EQUAL(true, helper.finishedCalled); + CPPUNIT_ASSERT(FileTransferError::PeerError == helper.error); + } + + void test_DeclineEmitsFinishedStateCanceled() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); + transfer->start(); + + getCall<FakeJingleSession::InitiateCall>(0); + + FTStatusHelper helper; + helper.finishedCalled = false; + transfer->onFinished.connect(bind(&FTStatusHelper::handleFileTransferFinished, &helper, _1)); + transfer->onStateChanged.connect(bind(&FTStatusHelper::handleFileTransferStatusChanged, &helper, _1)); + fakeJingleSession->handleSessionTerminateReceived(JinglePayload::Reason(JinglePayload::Reason::Decline)); + CPPUNIT_ASSERT_EQUAL(true, helper.finishedCalled); + CPPUNIT_ASSERT(FileTransferError::UnknownError == helper.error); + CPPUNIT_ASSERT_EQUAL(true, helper.state.is_initialized()); + CPPUNIT_ASSERT(FileTransfer::State::Canceled == helper.state.get().type); + } //TODO: some more testcases private: - void addFileTransferDescription() { - boost::shared_ptr<JingleFileTransferDescription> desc = boost::make_shared<JingleFileTransferDescription>(); - desc->addOffer(StreamInitiationFileInfo()); - jingleContentPayload->addDescription(desc); - } - - boost::shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { - JingleS5BTransportPayload::ref payLoad = boost::make_shared<JingleS5BTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - boost::shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { - JingleIBBTransportPayload::ref payLoad = boost::make_shared<JingleIBBTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - JingleContentID getContentID() const { - return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); - } - - template <typename T> T getCall(int i) const { - size_t index = static_cast<size_t>(i); - CPPUNIT_ASSERT(index < fakeJingleSession->calledCommands.size()); - T* cmd = boost::get<T>(&fakeJingleSession->calledCommands[index]); - CPPUNIT_ASSERT(cmd); - return *cmd; - } + void addFileTransferDescription() { + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo()); + jingleContentPayload->addDescription(desc); + } + + std::shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { + JingleS5BTransportPayload::ref payLoad = std::make_shared<JingleS5BTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + std::shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { + JingleIBBTransportPayload::ref payLoad = std::make_shared<JingleIBBTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + JingleContentID getContentID() const { + return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); + } + + template <typename T> T getCall(int i) const { + size_t index = static_cast<size_t>(i); + CPPUNIT_ASSERT(index < fakeJingleSession->calledCommands.size()); + T* cmd = boost::get<T>(&fakeJingleSession->calledCommands[index]); + CPPUNIT_ASSERT(cmd); + return *cmd; + } private: - std::vector<unsigned char> data; - boost::shared_ptr<ByteArrayReadBytestream> stream; - FakeJingleSession* fakeJingleSession; - boost::shared_ptr<JingleContentPayload> jingleContentPayload; - boost::shared_ptr<OFakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; - boost::shared_ptr<OFakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - IDGenerator* idGen; - EventLoop *eventLoop; - SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamProxiesManager* s5bProxy; - DummyTimerFactory* timerFactory; - DummyConnectionFactory* connectionFactory; - boost::shared_ptr<CryptoProvider> crypto; + std::vector<unsigned char> data; + std::shared_ptr<ByteArrayReadBytestream> stream; + FakeJingleSession* fakeJingleSession; + std::shared_ptr<JingleContentPayload> jingleContentPayload; + FileTransferTransporterFactory* ftTransportFactory; + SOCKS5BytestreamServerManager* bytestreamServerManager; + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + IDGenerator* idGen; + EventLoop *eventLoop; + SOCKS5BytestreamRegistry* s5bRegistry; + SOCKS5BytestreamProxiesManager* s5bProxy; + DummyTimerFactory* timerFactory; + DummyConnectionFactory* connectionFactory; + DummyConnectionServerFactory* serverConnectionFactory; + std::shared_ptr<CryptoProvider> crypto; + NetworkEnvironment* networkEnvironment; + NATTraverser* natTraverser; + DomainNameResolver* resolver; }; CPPUNIT_TEST_SUITE_REGISTRATION(OutgoingJingleFileTransferTest); -#endif diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp index 78ea8ed..fad02da 100644 --- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp @@ -4,23 +4,31 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include <Swiften/Base/ByteArray.h> -#include <QA/Checker/IO.h> +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <memory> #include <boost/bind.hpp> #include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_int.hpp> #include <boost/random/variate_generator.hpp> -#include <boost/smart_ptr/make_shared.hpp> + +#include <QA/Checker/IO.h> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Concat.h> #include <Swiften/Base/Log.h> #include <Swiften/Base/StartStopper.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> #include <Swiften/FileTransfer/ByteArrayWriteBytestream.h> @@ -30,280 +38,277 @@ #include <Swiften/Network/DummyConnection.h> #include <Swiften/Network/DummyTimerFactory.h> #include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/Crypto/PlatformCryptoProvider.h> using namespace Swift; static boost::mt19937 randomGen; class SOCKS5BytestreamClientSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SOCKS5BytestreamClientSessionTest); - CPPUNIT_TEST(testForSessionReady); - CPPUNIT_TEST(testErrorHandlingHello); - CPPUNIT_TEST(testErrorHandlingRequest); - CPPUNIT_TEST(testWriteBytestream); - CPPUNIT_TEST(testReadBytestream); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(SOCKS5BytestreamClientSessionTest); + CPPUNIT_TEST(testForSessionReady); + CPPUNIT_TEST(testErrorHandlingHello); + CPPUNIT_TEST(testErrorHandlingRequest); + CPPUNIT_TEST(testWriteBytestream); + CPPUNIT_TEST(testReadBytestream); + CPPUNIT_TEST_SUITE_END(); public: - SOCKS5BytestreamClientSessionTest() : destinationAddressPort(HostAddressPort(HostAddress("127.0.0.1"), 8888)) {} - - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - destination = "092a44d859d19c9eed676b551ee80025903351c2"; - randomGen.seed(static_cast<unsigned int>(time(NULL))); - eventLoop = new DummyEventLoop(); - timerFactory = new DummyTimerFactory(); - connection = boost::make_shared<MockeryConnection>(failingPorts, true, eventLoop); - //connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); - //stream1 = boost::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg"))); -// connection->onDataRead.connect(boost::bind(&SOCKS5BytestreamClientSessionTest::handleDataRead, this, _1)); - } - - void tearDown() { - //connection.reset(); - delete timerFactory; - delete eventLoop; - } - - void testForSessionReady() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - CPPUNIT_ASSERT(createByteArray("\x05\x01\x00", 3) == helper.unprocessedInput); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); - CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); - CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); - - helper.unprocessedInput.clear(); - serverRespondRequestOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); - } - - void testErrorHandlingHello() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); - - helper.unprocessedInput.clear(); - serverRespondHelloAuthFail(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); - CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); - } - - void testErrorHandlingRequest() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); - CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); - CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); - - helper.unprocessedInput.clear(); - serverRespondRequestFail(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); - CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); - } - - void testWriteBytestream() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondRequestOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); - - boost::shared_ptr<ByteArrayWriteBytestream> output = boost::make_shared<ByteArrayWriteBytestream>(); - clientSession->startReceiving(output); - - ByteArray transferData = generateRandomByteArray(1024); - connection->onDataRead(createSafeByteArrayRef(vecptr(transferData), transferData.size())); - CPPUNIT_ASSERT_EQUAL(transferData, output->getData()); - } - - void testReadBytestream() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondRequestOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); - - helper.unprocessedInput.clear(); - ByteArray transferData = generateRandomByteArray(1024); - boost::shared_ptr<ByteArrayReadBytestream> input = boost::make_shared<ByteArrayReadBytestream>(transferData); - clientSession->startSending(input); - eventLoop->processEvents(); + SOCKS5BytestreamClientSessionTest() : destinationAddressPort(HostAddressPort(HostAddress::fromString("127.0.0.1").get(), 8888)) {} + + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + destination = "092a44d859d19c9eed676b551ee80025903351c2"; + randomGen.seed(static_cast<unsigned int>(time(nullptr))); + eventLoop = std::make_unique<DummyEventLoop>(); + timerFactory = std::make_unique<DummyTimerFactory>(); + connection = std::make_shared<MockeryConnection>(failingPorts, true, eventLoop.get()); + //connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); + //stream1 = std::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg"))); +// connection->onDataRead.connect(boost::bind(&SOCKS5BytestreamClientSessionTest::handleDataRead, this, _1)); + } + + void tearDown() { + //connection.reset(); + } + + void testForSessionReady() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + CPPUNIT_ASSERT(createByteArray("\x05\x01\x00", 3) == helper.unprocessedInput); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); + CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); + CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); + + helper.unprocessedInput.clear(); + serverRespondRequestOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); + } + + void testErrorHandlingHello() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); + + helper.unprocessedInput.clear(); + serverRespondHelloAuthFail(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); + CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); + } + + void testErrorHandlingRequest() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); + CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); + CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); + + helper.unprocessedInput.clear(); + serverRespondRequestFail(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); + CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); + } + + void testWriteBytestream() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondRequestOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); + + std::shared_ptr<ByteArrayWriteBytestream> output = std::make_shared<ByteArrayWriteBytestream>(); + clientSession->startReceiving(output); + + ByteArray transferData = generateRandomByteArray(1024); + connection->onDataRead(createSafeByteArrayRef(vecptr(transferData), transferData.size())); + CPPUNIT_ASSERT_EQUAL(transferData, output->getData()); + } + + void testReadBytestream() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondRequestOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); + + helper.unprocessedInput.clear(); + ByteArray transferData = generateRandomByteArray(1024); + std::shared_ptr<ByteArrayReadBytestream> input = std::make_shared<ByteArrayReadBytestream>(transferData); + clientSession->startSending(input); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(createByteArray(vecptr(transferData), transferData.size()), helper.unprocessedInput); + } - CPPUNIT_ASSERT_EQUAL(createByteArray(vecptr(transferData), transferData.size()), helper.unprocessedInput); - } +private: + static ByteArray generateRandomByteArray(size_t len) { + boost::uniform_int<> dist(0, 255); + boost::variate_generator<boost::mt19937&, boost::uniform_int<> > randomByte(randomGen, dist); + ByteArray result(len); + for (size_t i=0; i < len; ++i ) { + result[i] = static_cast<unsigned char>(randomByte()); + } + return result; + } + + // Server responses + void serverRespondHelloOK() { + connection->onDataRead(createSafeByteArrayRef("\x05\00", 2)); + } + + void serverRespondHelloAuthFail() { + connection->onDataRead(createSafeByteArrayRef("\x05\xFF", 2)); + } + + void serverRespondRequestOK() { + std::shared_ptr<SafeByteArray> dataToSend = createSafeByteArrayRef("\x05\x00\x00\x03", 4); + append(*dataToSend, createSafeByteArray(static_cast<char>(destination.size()))); + append(*dataToSend, createSafeByteArray(destination)); + append(*dataToSend, createSafeByteArray("\x00", 1)); + connection->onDataRead(dataToSend); + } + + void serverRespondRequestFail() { + std::shared_ptr<SafeByteArray> correctData = createSafeByteArrayRef("\x05\x00\x00\x03", 4); + append(*correctData, createSafeByteArray(static_cast<char>(destination.size()))); + append(*correctData, createSafeByteArray(destination)); + append(*correctData, createSafeByteArray("\x00", 1)); + + std::shared_ptr<SafeByteArray> dataToSend; + //ByteArray failingData = Hexify::unhexify("8417947d1d305c72c11520ea7d2c6e787396705e72c312c6ccc3f66613d7cae1b91b7ab48e8b59a17d559c15fb51"); + //append(dataToSend, failingData); + //SWIFT_LOG(debug) << "hexed: " << Hexify::hexify(failingData); + do { + ByteArray rndArray = generateRandomByteArray(correctData->size()); + dataToSend = createSafeByteArrayRef(vecptr(rndArray), rndArray.size()); + } while (*dataToSend == *correctData); + connection->onDataRead(dataToSend); + } +private: + struct TestHelper { + TestHelper() : sessionReadyCalled(false), sessionReadyError(false) {} + ByteArray unprocessedInput; + bool sessionReadyCalled; + bool sessionReadyError; + void handleConnectionDataWritten(const SafeByteArray& data) { + append(unprocessedInput, data); + //SWIFT_LOG(debug) << "unprocessedInput (" << unprocessedInput.size() << "): " << Hexify::hexify(unprocessedInput); + } + + void handleSessionReady(bool error) { + sessionReadyCalled = true; + sessionReadyError = error; + } + }; -private: - static ByteArray generateRandomByteArray(size_t len) { - boost::uniform_int<> dist(0, 255); - boost::variate_generator<boost::mt19937&, boost::uniform_int<> > randomByte(randomGen, dist); - ByteArray result(len); - for (size_t i=0; i < len; ++i ) { - result[i] = static_cast<unsigned char>(randomByte()); - } - return result; - } - - // Server responses - void serverRespondHelloOK() { - connection->onDataRead(createSafeByteArrayRef("\x05\00", 2)); - } - - void serverRespondHelloAuthFail() { - connection->onDataRead(createSafeByteArrayRef("\x05\xFF", 2)); - } - - void serverRespondRequestOK() { - boost::shared_ptr<SafeByteArray> dataToSend = createSafeByteArrayRef("\x05\x00\x00\x03", 4); - append(*dataToSend, createSafeByteArray(static_cast<char>(destination.size()))); - append(*dataToSend, createSafeByteArray(destination)); - append(*dataToSend, createSafeByteArray("\x00", 1)); - connection->onDataRead(dataToSend); - } - - void serverRespondRequestFail() { - boost::shared_ptr<SafeByteArray> correctData = createSafeByteArrayRef("\x05\x00\x00\x03", 4); - append(*correctData, createSafeByteArray(static_cast<char>(destination.size()))); - append(*correctData, createSafeByteArray(destination)); - append(*correctData, createSafeByteArray("\x00", 1)); - - boost::shared_ptr<SafeByteArray> dataToSend; - //ByteArray failingData = Hexify::unhexify("8417947d1d305c72c11520ea7d2c6e787396705e72c312c6ccc3f66613d7cae1b91b7ab48e8b59a17d559c15fb51"); - //append(dataToSend, failingData); - //SWIFT_LOG(debug) << "hexed: " << Hexify::hexify(failingData) << std::endl; - do { - ByteArray rndArray = generateRandomByteArray(correctData->size()); - dataToSend = createSafeByteArrayRef(vecptr(rndArray), rndArray.size()); - } while (*dataToSend == *correctData); - connection->onDataRead(dataToSend); - } private: - struct TestHelper { - TestHelper() : sessionReadyCalled(false), sessionReadyError(false) {} - ByteArray unprocessedInput; - bool sessionReadyCalled; - bool sessionReadyError; + struct MockeryConnection : public Connection, public EventOwner, public std::enable_shared_from_this<MockeryConnection> { + public: + MockeryConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive), disconnectCalled(false) {} - void handleConnectionDataWritten(const SafeByteArray& data) { - append(unprocessedInput, data); - //SWIFT_LOG(debug) << "unprocessedInput (" << unprocessedInput.size() << "): " << Hexify::hexify(unprocessedInput) << std::endl; - } + void listen() { assert(false); } + void connect(const HostAddressPort& address) { + hostAddressPort = address; + if (isResponsive) { + bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); + } + } - void handleSessionReady(bool error) { - sessionReadyCalled = true; - sessionReadyError = error; - } - }; + HostAddressPort getLocalAddress() const { return HostAddressPort(); } + HostAddressPort getRemoteAddress() const { return HostAddressPort(); } -private: - struct MockeryConnection : public Connection, public EventOwner, public boost::enable_shared_from_this<MockeryConnection> { - public: - MockeryConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive), disconnectCalled(false) {} - - void listen() { assert(false); } - void connect(const HostAddressPort& address) { - hostAddressPort = address; - if (isResponsive) { - bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); - } - } - - HostAddressPort getLocalAddress() const { return HostAddressPort(); } - void disconnect() { - disconnectCalled = true; - } - - void write(const SafeByteArray& data) { - eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); - onDataSent(data); - } - - boost::signal<void (const SafeByteArray&)> onDataSent; - - EventLoop* eventLoop; - boost::optional<HostAddressPort> hostAddressPort; - std::vector<HostAddressPort> failingPorts; - bool isResponsive; - bool disconnectCalled; - }; + void disconnect() { + disconnectCalled = true; + } + + void write(const SafeByteArray& data) { + eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); + onDataSent(data); + } + + boost::signals2::signal<void (const SafeByteArray&)> onDataSent; + + EventLoop* eventLoop; + boost::optional<HostAddressPort> hostAddressPort; + std::vector<HostAddressPort> failingPorts; + bool isResponsive; + bool disconnectCalled; + }; private: - HostAddressPort destinationAddressPort; - std::string destination; - DummyEventLoop* eventLoop; - DummyTimerFactory* timerFactory; - boost::shared_ptr<MockeryConnection> connection; - const std::vector<HostAddressPort> failingPorts; - boost::shared_ptr<CryptoProvider> crypto; + HostAddressPort destinationAddressPort; + std::string destination; + std::unique_ptr<DummyEventLoop> eventLoop; + std::unique_ptr<DummyTimerFactory> timerFactory; + std::shared_ptr<MockeryConnection> connection; + const std::vector<HostAddressPort> failingPorts; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(SOCKS5BytestreamClientSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp index 7af546f..d419b8a 100644 --- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp @@ -1,213 +1,213 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> +#include <boost/bind.hpp> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Concat.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> +#include <Swiften/Base/StartStopper.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <Swiften/Network/DummyConnection.h> -#include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/Base/StartStopper.h> using namespace Swift; class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SOCKS5BytestreamServerSessionTest); - CPPUNIT_TEST(testAuthenticate); - CPPUNIT_TEST(testAuthenticate_Chunked); - CPPUNIT_TEST(testRequest); - CPPUNIT_TEST(testRequest_UnknownBytestream); - CPPUNIT_TEST(testReceiveData); - CPPUNIT_TEST(testReceiveData_Chunked); - CPPUNIT_TEST(testDataStreamPauseStopsSendingData); - CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - receivedDataChunks = 0; - eventLoop = new DummyEventLoop(); - bytestreams = new SOCKS5BytestreamRegistry(); - connection = boost::make_shared<DummyConnection>(eventLoop); - connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); - stream1 = boost::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); - finished = false; - } - - void tearDown() { - connection.reset(); - delete bytestreams; - delete eventLoop; - } - - void testAuthenticate() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - - receive(createSafeByteArray("\x05\x02\x01\x02")); - - CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); - } - - void testAuthenticate_Chunked() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - - receive(createSafeByteArray("\x05\x02\x01")); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedData.size())); - receive(createSafeByteArray("\x01")); - CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); - } - - void testRequest() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - - ByteArray hostname(createByteArray("abcdef")); - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); - CPPUNIT_ASSERT(createByteArray("\x05\x00\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == createByteArray(&receivedData[0], 13)); - } - - void testRequest_UnknownBytestream() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - authenticate(); - - ByteArray hostname(createByteArray("abcdef")); - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); - CPPUNIT_ASSERT(createByteArray("\x05\x04\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == receivedData); - } - - void testReceiveData() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - skipHeader("abcdef"); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); - CPPUNIT_ASSERT_EQUAL(2, receivedDataChunks); - } - - void testReceiveData_Chunked() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - testling->setChunkSize(3); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - eventLoop->processEvents(); - skipHeader("abcdef"); - CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); - CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); - } - - void testDataStreamPauseStopsSendingData() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - testling->setChunkSize(3); - stream1->setDataComplete(false); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - eventLoop->processEvents(); - skipHeader("abcdef"); - CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); - CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); - - CPPUNIT_ASSERT(!finished); - CPPUNIT_ASSERT(!error); - } - - void testDataStreamResumeAfterPauseSendsData() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - testling->setChunkSize(3); - stream1->setDataComplete(false); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - eventLoop->processEvents(); - skipHeader("abcdef"); - - stream1->addData(createByteArray("xyz")); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(createByteArray("abcdefgxyz") == receivedData); - CPPUNIT_ASSERT(!finished); - CPPUNIT_ASSERT(!error); - } - - private: - void receive(const SafeByteArray& data) { - connection->receive(data); - eventLoop->processEvents(); - } - - void authenticate() { - receive(createSafeByteArray("\x05\x02\x01\x02")); - receivedData.clear(); - receivedDataChunks = 0; - } - - void request(const std::string& hostname) { - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); - } - - void skipHeader(const std::string& hostname) { - size_t headerSize = 7 + hostname.size(); - receivedData = createByteArray(&receivedData[headerSize], receivedData.size() - headerSize); - } - - - void handleDataWritten(const SafeByteArray& data) { - receivedData.insert(receivedData.end(), data.begin(), data.end()); - receivedDataChunks++; - } - - private: - SOCKS5BytestreamServerSession* createSession() { - SOCKS5BytestreamServerSession* session = new SOCKS5BytestreamServerSession(connection, bytestreams); - session->onFinished.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleFinished, this, _1)); - return session; - } - - void handleFinished(boost::optional<FileTransferError> error) { - finished = true; - this->error = error; - } - - private: - DummyEventLoop* eventLoop; - SOCKS5BytestreamRegistry* bytestreams; - boost::shared_ptr<DummyConnection> connection; - std::vector<unsigned char> receivedData; - int receivedDataChunks; - boost::shared_ptr<ByteArrayReadBytestream> stream1; - bool finished; - boost::optional<FileTransferError> error; + CPPUNIT_TEST_SUITE(SOCKS5BytestreamServerSessionTest); + CPPUNIT_TEST(testAuthenticate); + CPPUNIT_TEST(testAuthenticate_Chunked); + CPPUNIT_TEST(testRequest); + CPPUNIT_TEST(testRequest_UnknownBytestream); + CPPUNIT_TEST(testReceiveData); + CPPUNIT_TEST(testReceiveData_Chunked); + CPPUNIT_TEST(testDataStreamPauseStopsSendingData); + CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + receivedDataChunks = 0; + eventLoop = new DummyEventLoop(); + bytestreams = new SOCKS5BytestreamRegistry(); + connection = std::make_shared<DummyConnection>(eventLoop); + connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); + stream1 = std::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); + finished = false; + } + + void tearDown() { + connection.reset(); + delete bytestreams; + delete eventLoop; + } + + void testAuthenticate() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + + receive(createSafeByteArray("\x05\x02\x01\x02")); + + CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); + } + + void testAuthenticate_Chunked() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + + receive(createSafeByteArray("\x05\x02\x01")); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedData.size())); + receive(createSafeByteArray("\x01")); + CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); + } + + void testRequest() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + + ByteArray hostname(createByteArray("abcdef")); + receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + CPPUNIT_ASSERT(createByteArray("\x05\x00\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == createByteArray(&receivedData[0], 13)); + } + + void testRequest_UnknownBytestream() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + authenticate(); + + ByteArray hostname(createByteArray("abcdef")); + receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + CPPUNIT_ASSERT(createByteArray("\x05\x04\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == receivedData); + } + + void testReceiveData() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + skipHeader("abcdef"); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); + CPPUNIT_ASSERT_EQUAL(2, receivedDataChunks); + } + + void testReceiveData_Chunked() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + testling->setChunkSize(3); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + eventLoop->processEvents(); + skipHeader("abcdef"); + CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); + CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); + } + + void testDataStreamPauseStopsSendingData() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + testling->setChunkSize(3); + stream1->setDataComplete(false); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + eventLoop->processEvents(); + skipHeader("abcdef"); + CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); + CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); + + CPPUNIT_ASSERT(!finished); + CPPUNIT_ASSERT(!error); + } + + void testDataStreamResumeAfterPauseSendsData() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + testling->setChunkSize(3); + stream1->setDataComplete(false); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + eventLoop->processEvents(); + skipHeader("abcdef"); + + stream1->addData(createByteArray("xyz")); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(createByteArray("abcdefgxyz") == receivedData); + CPPUNIT_ASSERT(!finished); + CPPUNIT_ASSERT(!error); + } + + private: + void receive(const SafeByteArray& data) { + connection->receive(data); + eventLoop->processEvents(); + } + + void authenticate() { + receive(createSafeByteArray("\x05\x02\x01\x02")); + receivedData.clear(); + receivedDataChunks = 0; + } + + void request(const std::string& hostname) { + receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + } + + void skipHeader(const std::string& hostname) { + size_t headerSize = 7 + hostname.size(); + receivedData = createByteArray(&receivedData[headerSize], receivedData.size() - headerSize); + } + + + void handleDataWritten(const SafeByteArray& data) { + receivedData.insert(receivedData.end(), data.begin(), data.end()); + receivedDataChunks++; + } + + private: + SOCKS5BytestreamServerSession* createSession() { + SOCKS5BytestreamServerSession* session = new SOCKS5BytestreamServerSession(connection, bytestreams); + session->onFinished.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleFinished, this, _1)); + return session; + } + + void handleFinished(boost::optional<FileTransferError> error) { + finished = true; + this->error = error; + } + + private: + DummyEventLoop* eventLoop; + SOCKS5BytestreamRegistry* bytestreams; + std::shared_ptr<DummyConnection> connection; + std::vector<unsigned char> receivedData; + int receivedDataChunks; + std::shared_ptr<ByteArrayReadBytestream> stream1; + bool finished; + boost::optional<FileTransferError> error; }; CPPUNIT_TEST_SUITE_REGISTRATION(SOCKS5BytestreamServerSessionTest); diff --git a/Swiften/FileTransfer/WriteBytestream.cpp b/Swiften/FileTransfer/WriteBytestream.cpp index 8d10193..751dd60 100644 --- a/Swiften/FileTransfer/WriteBytestream.cpp +++ b/Swiften/FileTransfer/WriteBytestream.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/WriteBytestream.h> diff --git a/Swiften/FileTransfer/WriteBytestream.h b/Swiften/FileTransfer/WriteBytestream.h index 6085e78..5452317 100644 --- a/Swiften/FileTransfer/WriteBytestream.h +++ b/Swiften/FileTransfer/WriteBytestream.h @@ -1,26 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <vector> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class SWIFTEN_API WriteBytestream { - public: - typedef boost::shared_ptr<WriteBytestream> ref; + class SWIFTEN_API WriteBytestream { + public: + typedef std::shared_ptr<WriteBytestream> ref; - virtual ~WriteBytestream(); + virtual ~WriteBytestream(); - virtual void write(const std::vector<unsigned char>&) = 0; + /** + * Write data from vector argument to bytestream. + * + * On success true is returned and \ref onWrite is called. On failure false is returned. + */ + virtual bool write(const std::vector<unsigned char>&) = 0; + virtual void close() {} - boost::signal<void (const std::vector<unsigned char>&)> onWrite; - }; + boost::signals2::signal<void (const std::vector<unsigned char>&)> onWrite; + }; } diff --git a/Swiften/History/HistoryMessage.h b/Swiften/History/HistoryMessage.h index b3d977f..e910899 100644 --- a/Swiften/History/HistoryMessage.h +++ b/Swiften/History/HistoryMessage.h @@ -1,72 +1,74 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/JID/JID.h> #include <boost/date_time/posix_time/posix_time_types.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/JID/JID.h> + namespace Swift { - class HistoryMessage { - public: - enum Type { - Chat = 0, - Groupchat = 1, - PrivateMessage = 2 - }; + class SWIFTEN_API HistoryMessage { + public: + enum Type { + Chat = 0, + Groupchat = 1, + PrivateMessage = 2 + }; - HistoryMessage( - const std::string& message, - const JID& fromJID, - const JID& toJID, - Type type, - const boost::posix_time::ptime& time, - int utcOffset = 0) : - message_(message), - fromJID_(fromJID), - toJID_(toJID), - type_(type), - time_(time), - utcOffset_(utcOffset) { - } + HistoryMessage( + const std::string& message, + const JID& fromJID, + const JID& toJID, + Type type, + const boost::posix_time::ptime& time, + int utcOffset = 0) : + message_(message), + fromJID_(fromJID), + toJID_(toJID), + type_(type), + time_(time), + utcOffset_(utcOffset) { + } - const std::string& getMessage() const { - return message_; - } + const std::string& getMessage() const { + return message_; + } - const JID& getFromJID() const { - return fromJID_; - } + const JID& getFromJID() const { + return fromJID_; + } - const JID& getToJID() const { - return toJID_; - } + const JID& getToJID() const { + return toJID_; + } - Type getType() const { - return type_; - } + Type getType() const { + return type_; + } - boost::posix_time::ptime getTime() const { - return time_; - } + boost::posix_time::ptime getTime() const { + return time_; + } - int getOffset() const { - return utcOffset_; - } + int getOffset() const { + return utcOffset_; + } - bool operator==(const HistoryMessage& o) const { - return message_ == o.message_ && fromJID_ == o.fromJID_ && toJID_ == o.toJID_ && type_ == o.type_ && time_ == o.time_; - } + bool operator==(const HistoryMessage& o) const { + return message_ == o.message_ && fromJID_ == o.fromJID_ && toJID_ == o.toJID_ && type_ == o.type_ && time_ == o.time_; + } - private: - std::string message_; - JID fromJID_; - JID toJID_; - Type type_; - boost::posix_time::ptime time_; - int utcOffset_; - }; + private: + std::string message_; + JID fromJID_; + JID toJID_; + Type type_; + boost::posix_time::ptime time_; + int utcOffset_; + }; } diff --git a/Swiften/History/HistoryStorage.h b/Swiften/History/HistoryStorage.h index 6d24d15..10b6bb0 100644 --- a/Swiften/History/HistoryStorage.h +++ b/Swiften/History/HistoryStorage.h @@ -1,33 +1,36 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <set> #include <map> +#include <set> #include <vector> -#include <Swiften/JID/JID.h> -#include <Swiften/History/HistoryMessage.h> + #include <boost/date_time/gregorian/gregorian_types.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/History/HistoryMessage.h> +#include <Swiften/JID/JID.h> + namespace Swift { - typedef std::map<JID, std::set<boost::gregorian::date> > ContactsMap; + typedef std::map<JID, std::set<boost::gregorian::date> > ContactsMap; - class HistoryStorage { - /** - * Messages are stored using localtime timestamps. - */ - public: - virtual ~HistoryStorage() {} + class SWIFTEN_API HistoryStorage { + /** + * Messages are stored using localtime timestamps. + */ + public: + virtual ~HistoryStorage() {} - virtual void addMessage(const HistoryMessage& message) = 0; - virtual std::vector<HistoryMessage> getMessagesFromDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const = 0; - virtual std::vector<HistoryMessage> getMessagesFromNextDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const = 0; - virtual std::vector<HistoryMessage> getMessagesFromPreviousDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const = 0; - virtual ContactsMap getContacts(const JID& selfJID, HistoryMessage::Type type, const std::string& keyword) const = 0; - virtual boost::posix_time::ptime getLastTimeStampFromMUC(const JID& selfJID, const JID& mucJID) const = 0; - }; + virtual void addMessage(const HistoryMessage& message) = 0; + virtual std::vector<HistoryMessage> getMessagesFromDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const = 0; + virtual std::vector<HistoryMessage> getMessagesFromNextDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const = 0; + virtual std::vector<HistoryMessage> getMessagesFromPreviousDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const = 0; + virtual ContactsMap getContacts(const JID& selfJID, HistoryMessage::Type type, const std::string& keyword) const = 0; + virtual boost::posix_time::ptime getLastTimeStampFromMUC(const JID& selfJID, const JID& mucJID) const = 0; + }; } diff --git a/Swiften/History/SConscript b/Swiften/History/SConscript index ac3cf3b..65be489 100644 --- a/Swiften/History/SConscript +++ b/Swiften/History/SConscript @@ -2,10 +2,10 @@ Import("swiften_env") myenv = swiften_env.Clone() if myenv["target"] == "native": - myenv.MergeFlags(swiften_env.get("SQLITE_FLAGS", {})) + myenv.MergeFlags(swiften_env.get("SQLITE_FLAGS", {})) if myenv["experimental"]: - objects = myenv.SwiftenObject([ - "SQLiteHistoryStorage.cpp", - ]) - swiften_env.Append(SWIFTEN_OBJECTS = [objects]) + objects = myenv.SwiftenObject([ + "SQLiteHistoryStorage.cpp", + ]) + swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/History/SQLiteHistoryStorage.cpp b/Swiften/History/SQLiteHistoryStorage.cpp index dda8766..1b12367 100644 --- a/Swiften/History/SQLiteHistoryStorage.cpp +++ b/Swiften/History/SQLiteHistoryStorage.cpp @@ -1,379 +1,383 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <Swiften/History/SQLiteHistoryStorage.h> + #include <iostream> + +#include <boost/bind.hpp> +#include <boost/date_time/gregorian/gregorian.hpp> #include <boost/lexical_cast.hpp> #include <boost/numeric/conversion/cast.hpp> #include <sqlite3.h> -#include <Swiften/History/SQLiteHistoryStorage.h> -#include <boost/date_time/gregorian/gregorian.hpp> + #include <Swiften/Base/Path.h> inline std::string getEscapedString(const std::string& s) { - std::string result(s); - - size_t pos = result.find('\''); - while (pos != std::string::npos) { - result.insert(pos, "'"); - pos = result.find('\'', pos + 2); - } - return result; + std::string result(s); + + size_t pos = result.find('\''); + while (pos != std::string::npos) { + result.insert(pos, "'"); + pos = result.find('\'', pos + 2); + } + return result; } namespace Swift { -SQLiteHistoryStorage::SQLiteHistoryStorage(const boost::filesystem::path& file) : db_(0) { - thread_ = new boost::thread(boost::bind(&SQLiteHistoryStorage::run, this)); - - sqlite3_open(pathToString(file).c_str(), &db_); - if (!db_) { - std::cerr << "Error opening database " << pathToString(file) << std::endl; - } - - char* errorMessage; - int result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS messages('message' STRING, 'fromBare' INTEGER, 'fromResource' STRING, 'toBare' INTEGER, 'toResource' STRING, 'type' INTEGER, 'time' INTEGER, 'offset' INTEGER)", 0, 0, &errorMessage); - if (result != SQLITE_OK) { - std::cerr << "SQL Error: " << errorMessage << std::endl; - sqlite3_free(errorMessage); - } - - result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS jids('id' INTEGER PRIMARY KEY ASC AUTOINCREMENT, 'jid' STRING UNIQUE NOT NULL)", 0, 0, &errorMessage); - if (result != SQLITE_OK) { - std::cerr << "SQL Error: " << errorMessage << std::endl; - sqlite3_free(errorMessage); - } +SQLiteHistoryStorage::SQLiteHistoryStorage(const boost::filesystem::path& file) : db_(nullptr) { + thread_ = new std::thread(boost::bind(&SQLiteHistoryStorage::run, this)); + + sqlite3_open(pathToString(file).c_str(), &db_); + if (!db_) { + std::cerr << "Error opening database " << pathToString(file) << std::endl; + } + + char* errorMessage; + int result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS messages('message' STRING, 'fromBare' INTEGER, 'fromResource' STRING, 'toBare' INTEGER, 'toResource' STRING, 'type' INTEGER, 'time' INTEGER, 'offset' INTEGER)", nullptr, nullptr, &errorMessage); + if (result != SQLITE_OK) { + std::cerr << "SQL Error: " << errorMessage << std::endl; + sqlite3_free(errorMessage); + } + + result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS jids('id' INTEGER PRIMARY KEY ASC AUTOINCREMENT, 'jid' STRING UNIQUE NOT NULL)", nullptr, nullptr, &errorMessage); + if (result != SQLITE_OK) { + std::cerr << "SQL Error: " << errorMessage << std::endl; + sqlite3_free(errorMessage); + } } SQLiteHistoryStorage::~SQLiteHistoryStorage() { - sqlite3_close(db_); - delete thread_; + sqlite3_close(db_); + delete thread_; } void SQLiteHistoryStorage::addMessage(const HistoryMessage& message) { - int secondsSinceEpoch = (message.getTime() - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds(); - - std::string statement = std::string("INSERT INTO messages('message', 'fromBare', 'fromResource', 'toBare', 'toResource', 'type', 'time', 'offset') VALUES(") + - "'" + getEscapedString(message.getMessage()) + "', " + - boost::lexical_cast<std::string>(getIDForJID(message.getFromJID().toBare())) + ", '" + - getEscapedString(message.getFromJID().getResource()) + "', " + - boost::lexical_cast<std::string>(getIDForJID(message.getToJID().toBare())) + ", '" + - getEscapedString(message.getToJID().getResource()) + "', " + - boost::lexical_cast<std::string>(message.getType()) + ", " + - boost::lexical_cast<std::string>(secondsSinceEpoch) + ", " + - boost::lexical_cast<std::string>(message.getOffset()) + ")"; - char* errorMessage; - int result = sqlite3_exec(db_, statement.c_str(), 0, 0, &errorMessage); - if (result != SQLITE_OK) { - std::cerr << "SQL Error: " << errorMessage << std::endl; - sqlite3_free(errorMessage); - } + int secondsSinceEpoch = (message.getTime() - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds(); + + std::string statement = std::string("INSERT INTO messages('message', 'fromBare', 'fromResource', 'toBare', 'toResource', 'type', 'time', 'offset') VALUES(") + + "'" + getEscapedString(message.getMessage()) + "', " + + boost::lexical_cast<std::string>(getIDForJID(message.getFromJID().toBare())) + ", '" + + getEscapedString(message.getFromJID().getResource()) + "', " + + boost::lexical_cast<std::string>(getIDForJID(message.getToJID().toBare())) + ", '" + + getEscapedString(message.getToJID().getResource()) + "', " + + boost::lexical_cast<std::string>(message.getType()) + ", " + + boost::lexical_cast<std::string>(secondsSinceEpoch) + ", " + + boost::lexical_cast<std::string>(message.getOffset()) + ")"; + char* errorMessage; + int result = sqlite3_exec(db_, statement.c_str(), nullptr, nullptr, &errorMessage); + if (result != SQLITE_OK) { + std::cerr << "SQL Error: " << errorMessage << std::endl; + sqlite3_free(errorMessage); + } } std::vector<HistoryMessage> SQLiteHistoryStorage::getMessagesFromDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const { - sqlite3_stmt* selectStatement; - - boost::optional<long long> selfID = getIDFromJID(selfJID.toBare()); - boost::optional<long long> contactID = getIDFromJID(contactJID.toBare()); - - if (!selfID || !contactID) { - // JIDs missing from the database - return std::vector<HistoryMessage>(); - } - - std::string selectQuery = "SELECT * FROM messages WHERE (type=" + boost::lexical_cast<std::string>(type); - if (contactJID.isBare()) { - // match only bare jid - selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND toBare=" + - boost::lexical_cast<std::string>(*contactID) + ") OR (fromBare=" + - boost::lexical_cast<std::string>(*contactID) + " AND toBare=" + boost::lexical_cast<std::string>(*selfID) + ")))"; - } - else { - // match resource too - selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND (toBare=" + - boost::lexical_cast<std::string>(*contactID) +" AND toResource='" + - getEscapedString(contactJID.getResource()) + "')) OR ((fromBare=" + - boost::lexical_cast<std::string>(*contactID) + " AND fromResource='" + - getEscapedString(contactJID.getResource()) + "') AND toBare=" + - boost::lexical_cast<std::string>(*selfID) + ")))"; - } - - if (!date.is_not_a_date()) { - int lowerBound = (boost::posix_time::ptime(date) - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds(); - int upperBound = lowerBound + 86400; - - selectQuery += " AND (time>=" + boost::lexical_cast<std::string>(lowerBound) + - " AND time<" + boost::lexical_cast<std::string>(upperBound) + ")"; - } - - int r = sqlite3_prepare(db_, selectQuery.c_str(), boost::numeric_cast<int>(selectQuery.size()), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - r = sqlite3_step(selectStatement); - - // Retrieve result - std::vector<HistoryMessage> result; - while (r == SQLITE_ROW) { - std::string message(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 0))); - - // fromJID - boost::optional<JID> fromJID(getJIDFromID(sqlite3_column_int(selectStatement, 1))); - std::string fromResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 2))); - if (fromJID) { - fromJID = boost::optional<JID>(JID(fromJID->getNode(), fromJID->getDomain(), fromResource)); - } - - // toJID - boost::optional<JID> toJID(getJIDFromID(sqlite3_column_int(selectStatement, 3))); - std::string toResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 4))); - if (toJID) { - toJID = boost::optional<JID>(JID(toJID->getNode(), toJID->getDomain(), toResource)); - } - - // message type - HistoryMessage::Type type = static_cast<HistoryMessage::Type>(sqlite3_column_int(selectStatement, 5)); - - // timestamp - int secondsSinceEpoch(sqlite3_column_int(selectStatement, 6)); - boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); - - // offset from utc - int offset = sqlite3_column_int(selectStatement, 7); - - result.push_back(HistoryMessage(message, (fromJID ? *fromJID : JID()), (toJID ? *toJID : JID()), type, time, offset)); - r = sqlite3_step(selectStatement); - } - if (r != SQLITE_DONE) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - sqlite3_finalize(selectStatement); - - return result; + sqlite3_stmt* selectStatement; + + boost::optional<long long> selfID = getIDFromJID(selfJID.toBare()); + boost::optional<long long> contactID = getIDFromJID(contactJID.toBare()); + + if (!selfID || !contactID) { + // JIDs missing from the database + return std::vector<HistoryMessage>(); + } + + std::string selectQuery = "SELECT * FROM messages WHERE (type=" + boost::lexical_cast<std::string>(type); + if (contactJID.isBare()) { + // match only bare jid + selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND toBare=" + + boost::lexical_cast<std::string>(*contactID) + ") OR (fromBare=" + + boost::lexical_cast<std::string>(*contactID) + " AND toBare=" + boost::lexical_cast<std::string>(*selfID) + ")))"; + } + else { + // match resource too + selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND (toBare=" + + boost::lexical_cast<std::string>(*contactID) +" AND toResource='" + + getEscapedString(contactJID.getResource()) + "')) OR ((fromBare=" + + boost::lexical_cast<std::string>(*contactID) + " AND fromResource='" + + getEscapedString(contactJID.getResource()) + "') AND toBare=" + + boost::lexical_cast<std::string>(*selfID) + ")))"; + } + + if (!date.is_not_a_date()) { + int lowerBound = (boost::posix_time::ptime(date) - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds(); + int upperBound = lowerBound + 86400; + + selectQuery += " AND (time>=" + boost::lexical_cast<std::string>(lowerBound) + + " AND time<" + boost::lexical_cast<std::string>(upperBound) + ")"; + } + + int r = sqlite3_prepare(db_, selectQuery.c_str(), boost::numeric_cast<int>(selectQuery.size()), &selectStatement, nullptr); + if (r != SQLITE_OK) { + std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; + } + r = sqlite3_step(selectStatement); + + // Retrieve result + std::vector<HistoryMessage> result; + while (r == SQLITE_ROW) { + std::string message(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 0))); + + // fromJID + boost::optional<JID> fromJID(getJIDFromID(sqlite3_column_int(selectStatement, 1))); + std::string fromResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 2))); + if (fromJID) { + fromJID = boost::optional<JID>(JID(fromJID->getNode(), fromJID->getDomain(), fromResource)); + } + + // toJID + boost::optional<JID> toJID(getJIDFromID(sqlite3_column_int(selectStatement, 3))); + std::string toResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 4))); + if (toJID) { + toJID = boost::optional<JID>(JID(toJID->getNode(), toJID->getDomain(), toResource)); + } + + // message type + HistoryMessage::Type type = static_cast<HistoryMessage::Type>(sqlite3_column_int(selectStatement, 5)); + + // timestamp + int secondsSinceEpoch(sqlite3_column_int(selectStatement, 6)); + boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); + + // offset from utc + int offset = sqlite3_column_int(selectStatement, 7); + + result.push_back(HistoryMessage(message, (fromJID ? *fromJID : JID()), (toJID ? *toJID : JID()), type, time, offset)); + r = sqlite3_step(selectStatement); + } + if (r != SQLITE_DONE) { + std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; + } + sqlite3_finalize(selectStatement); + + return result; } long long SQLiteHistoryStorage::getIDForJID(const JID& jid) { - boost::optional<long long> id = getIDFromJID(jid); - if (id) { - return *id; - } - else { - return addJID(jid); - } + boost::optional<long long> id = getIDFromJID(jid); + if (id) { + return *id; + } + else { + return addJID(jid); + } } long long SQLiteHistoryStorage::addJID(const JID& jid) { - std::string statement = std::string("INSERT INTO jids('jid') VALUES('") + getEscapedString(jid.toString()) + "')"; - char* errorMessage; - int result = sqlite3_exec(db_, statement.c_str(), 0, 0, &errorMessage); - if (result != SQLITE_OK) { - std::cerr << "SQL Error: " << errorMessage << std::endl; - sqlite3_free(errorMessage); - } - return sqlite3_last_insert_rowid(db_); + std::string statement = std::string("INSERT INTO jids('jid') VALUES('") + getEscapedString(jid.toString()) + "')"; + char* errorMessage; + int result = sqlite3_exec(db_, statement.c_str(), nullptr, nullptr, &errorMessage); + if (result != SQLITE_OK) { + std::cerr << "SQL Error: " << errorMessage << std::endl; + sqlite3_free(errorMessage); + } + return sqlite3_last_insert_rowid(db_); } boost::optional<JID> SQLiteHistoryStorage::getJIDFromID(long long id) const { - boost::optional<JID> result; - sqlite3_stmt* selectStatement; - std::string selectQuery("SELECT jid FROM jids WHERE id=" + boost::lexical_cast<std::string>(id)); - int r = sqlite3_prepare(db_, selectQuery.c_str(), boost::numeric_cast<int>(selectQuery.size()), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - r = sqlite3_step(selectStatement); - if (r == SQLITE_ROW) { - result = boost::optional<JID>(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 0))); - } - sqlite3_finalize(selectStatement); - return result; + boost::optional<JID> result; + sqlite3_stmt* selectStatement; + std::string selectQuery("SELECT jid FROM jids WHERE id=" + boost::lexical_cast<std::string>(id)); + int r = sqlite3_prepare(db_, selectQuery.c_str(), boost::numeric_cast<int>(selectQuery.size()), &selectStatement, nullptr); + if (r != SQLITE_OK) { + std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; + } + r = sqlite3_step(selectStatement); + if (r == SQLITE_ROW) { + result = boost::optional<JID>(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 0))); + } + sqlite3_finalize(selectStatement); + return result; } boost::optional<long long> SQLiteHistoryStorage::getIDFromJID(const JID& jid) const { - boost::optional<long long> result; - sqlite3_stmt* selectStatement; - std::string selectQuery("SELECT id FROM jids WHERE jid='" + jid.toString() + "'"); - long long r = sqlite3_prepare(db_, selectQuery.c_str(), boost::numeric_cast<int>(selectQuery.size()), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - r = sqlite3_step(selectStatement); - if (r == SQLITE_ROW) { - result = boost::optional<long long>(sqlite3_column_int(selectStatement, 0)); - } - sqlite3_finalize(selectStatement); - return result; + boost::optional<long long> result; + sqlite3_stmt* selectStatement; + std::string selectQuery("SELECT id FROM jids WHERE jid='" + jid.toString() + "'"); + long long r = sqlite3_prepare(db_, selectQuery.c_str(), boost::numeric_cast<int>(selectQuery.size()), &selectStatement, nullptr); + if (r != SQLITE_OK) { + std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; + } + r = sqlite3_step(selectStatement); + if (r == SQLITE_ROW) { + result = boost::optional<long long>(sqlite3_column_int(selectStatement, 0)); + } + sqlite3_finalize(selectStatement); + return result; } ContactsMap SQLiteHistoryStorage::getContacts(const JID& selfJID, HistoryMessage::Type type, const std::string& keyword) const { - ContactsMap result; - sqlite3_stmt* selectStatement; - - // get id - boost::optional<long long> id = getIDFromJID(selfJID); - if (!id) { - return result; - } - - // get contacts - std::string query = "SELECT DISTINCT messages.'fromBare', messages.'fromResource', messages.'toBare', messages.'toResource', messages.'time' " - "FROM messages WHERE (type=" - + boost::lexical_cast<std::string>(type) + " AND (toBare=" - + boost::lexical_cast<std::string>(*id) + " OR fromBare=" + boost::lexical_cast<std::string>(*id) + "))"; - - // match keyword - if (getEscapedString(keyword).length()) { - query += " AND message LIKE '%" + getEscapedString(keyword) + "%'"; - } - - int r = sqlite3_prepare(db_, query.c_str(), boost::numeric_cast<int>(query.size()), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - - r = sqlite3_step(selectStatement); - while (r == SQLITE_ROW) { - int fromBareID = sqlite3_column_int(selectStatement, 0); - std::string fromResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 1))); - int toBareID = sqlite3_column_int(selectStatement, 2); - std::string toResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 3))); - std::string resource; - - int secondsSinceEpoch(sqlite3_column_int(selectStatement, 4)); - boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); - - boost::optional<JID> contactJID; - - if (fromBareID == *id) { - contactJID = getJIDFromID(toBareID); - resource = toResource; - } - else { - contactJID = getJIDFromID(fromBareID); - resource = fromResource; - } - - // check if it is a MUC contact (from a private conversation) - if (type == HistoryMessage::PrivateMessage) { - contactJID = boost::optional<JID>(JID(contactJID->getNode(), contactJID->getDomain(), resource)); - } - - if (contactJID) { - result[*contactJID].insert(time.date()); - } - - r = sqlite3_step(selectStatement); - } - - if (r != SQLITE_DONE) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - sqlite3_finalize(selectStatement); - - return result; + ContactsMap result; + sqlite3_stmt* selectStatement; + + // get id + boost::optional<long long> id = getIDFromJID(selfJID); + if (!id) { + return result; + } + + // get contacts + std::string query = "SELECT DISTINCT messages.'fromBare', messages.'fromResource', messages.'toBare', messages.'toResource', messages.'time' " + "FROM messages WHERE (type=" + + boost::lexical_cast<std::string>(type) + " AND (toBare=" + + boost::lexical_cast<std::string>(*id) + " OR fromBare=" + boost::lexical_cast<std::string>(*id) + "))"; + + // match keyword + if (getEscapedString(keyword).length()) { + query += " AND message LIKE '%" + getEscapedString(keyword) + "%'"; + } + + int r = sqlite3_prepare(db_, query.c_str(), boost::numeric_cast<int>(query.size()), &selectStatement, nullptr); + if (r != SQLITE_OK) { + std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; + } + + r = sqlite3_step(selectStatement); + while (r == SQLITE_ROW) { + int fromBareID = sqlite3_column_int(selectStatement, 0); + std::string fromResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 1))); + int toBareID = sqlite3_column_int(selectStatement, 2); + std::string toResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 3))); + std::string resource; + + int secondsSinceEpoch(sqlite3_column_int(selectStatement, 4)); + boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); + + boost::optional<JID> contactJID; + + if (fromBareID == *id) { + contactJID = getJIDFromID(toBareID); + resource = toResource; + } + else { + contactJID = getJIDFromID(fromBareID); + resource = fromResource; + } + + // check if it is a MUC contact (from a private conversation) + if (type == HistoryMessage::PrivateMessage) { + contactJID = boost::optional<JID>(JID(contactJID->getNode(), contactJID->getDomain(), resource)); + } + + if (contactJID) { + result[*contactJID].insert(time.date()); + } + + r = sqlite3_step(selectStatement); + } + + if (r != SQLITE_DONE) { + std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; + } + sqlite3_finalize(selectStatement); + + return result; } boost::gregorian::date SQLiteHistoryStorage::getNextDateWithLogs(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date, bool reverseOrder) const { - sqlite3_stmt* selectStatement; - boost::optional<long long> selfID = getIDFromJID(selfJID.toBare()); - boost::optional<long long> contactID = getIDFromJID(contactJID.toBare()); - - if (!selfID || !contactID) { - // JIDs missing from the database - return boost::gregorian::date(boost::gregorian::not_a_date_time); - } - - std::string selectQuery = "SELECT time FROM messages WHERE (type=" + boost::lexical_cast<std::string>(type); - if (contactJID.isBare()) { - // match only bare jid - selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND toBare=" + - boost::lexical_cast<std::string>(*contactID) + ") OR (fromBare=" + - boost::lexical_cast<std::string>(*contactID) + " AND toBare=" + boost::lexical_cast<std::string>(*selfID) + ")))"; - } - else { - // match resource too - selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND (toBare=" + - boost::lexical_cast<std::string>(*contactID) +" AND toResource='" + - getEscapedString(contactJID.getResource()) + "')) OR ((fromBare=" + - boost::lexical_cast<std::string>(*contactID) + " AND fromResource='" + - getEscapedString(contactJID.getResource()) + "') AND toBare=" + - boost::lexical_cast<std::string>(*selfID) + ")))"; - } - - int timeStamp = (boost::posix_time::ptime(date) - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds() + (reverseOrder ? 0 : 86400); - - selectQuery += " AND time" + (reverseOrder ? std::string("<") : std::string(">")) + boost::lexical_cast<std::string>(timeStamp); - selectQuery += " ORDER BY time " + (reverseOrder ? std::string("DESC") : std::string("ASC")) + " LIMIT 1"; - - int r = sqlite3_prepare(db_, selectQuery.c_str(), boost::numeric_cast<int>(selectQuery.size()), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - - r = sqlite3_step(selectStatement); - if (r == SQLITE_ROW) { - int secondsSinceEpoch(sqlite3_column_int(selectStatement, 0)); - boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); - std::cout << "next day is: " << time.date() << "\n"; - return time.date(); - } - - return boost::gregorian::date(boost::gregorian::not_a_date_time); + sqlite3_stmt* selectStatement; + boost::optional<long long> selfID = getIDFromJID(selfJID.toBare()); + boost::optional<long long> contactID = getIDFromJID(contactJID.toBare()); + + if (!selfID || !contactID) { + // JIDs missing from the database + return boost::gregorian::date(boost::gregorian::not_a_date_time); + } + + std::string selectQuery = "SELECT time FROM messages WHERE (type=" + boost::lexical_cast<std::string>(type); + if (contactJID.isBare()) { + // match only bare jid + selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND toBare=" + + boost::lexical_cast<std::string>(*contactID) + ") OR (fromBare=" + + boost::lexical_cast<std::string>(*contactID) + " AND toBare=" + boost::lexical_cast<std::string>(*selfID) + ")))"; + } + else { + // match resource too + selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND (toBare=" + + boost::lexical_cast<std::string>(*contactID) +" AND toResource='" + + getEscapedString(contactJID.getResource()) + "')) OR ((fromBare=" + + boost::lexical_cast<std::string>(*contactID) + " AND fromResource='" + + getEscapedString(contactJID.getResource()) + "') AND toBare=" + + boost::lexical_cast<std::string>(*selfID) + ")))"; + } + + int timeStamp = (boost::posix_time::ptime(date) - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds() + (reverseOrder ? 0 : 86400); + + selectQuery += " AND time" + (reverseOrder ? std::string("<") : std::string(">")) + boost::lexical_cast<std::string>(timeStamp); + selectQuery += " ORDER BY time " + (reverseOrder ? std::string("DESC") : std::string("ASC")) + " LIMIT 1"; + + int r = sqlite3_prepare(db_, selectQuery.c_str(), boost::numeric_cast<int>(selectQuery.size()), &selectStatement, nullptr); + if (r != SQLITE_OK) { + std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; + } + + r = sqlite3_step(selectStatement); + if (r == SQLITE_ROW) { + int secondsSinceEpoch(sqlite3_column_int(selectStatement, 0)); + boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); + std::cout << "next day is: " << time.date() << "\n"; + return time.date(); + } + + return boost::gregorian::date(boost::gregorian::not_a_date_time); } std::vector<HistoryMessage> SQLiteHistoryStorage::getMessagesFromNextDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const { - boost::gregorian::date nextDate = getNextDateWithLogs(selfJID, contactJID, type, date, false); + boost::gregorian::date nextDate = getNextDateWithLogs(selfJID, contactJID, type, date, false); - if (nextDate.is_not_a_date()) { - return std::vector<HistoryMessage>(); - } + if (nextDate.is_not_a_date()) { + return std::vector<HistoryMessage>(); + } - return getMessagesFromDate(selfJID, contactJID, type, nextDate); + return getMessagesFromDate(selfJID, contactJID, type, nextDate); } std::vector<HistoryMessage> SQLiteHistoryStorage::getMessagesFromPreviousDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const { - boost::gregorian::date previousDate = getNextDateWithLogs(selfJID, contactJID, type, date, true); + boost::gregorian::date previousDate = getNextDateWithLogs(selfJID, contactJID, type, date, true); - if (previousDate.is_not_a_date()) { - return std::vector<HistoryMessage>(); - } + if (previousDate.is_not_a_date()) { + return std::vector<HistoryMessage>(); + } - return getMessagesFromDate(selfJID, contactJID, type, previousDate); + return getMessagesFromDate(selfJID, contactJID, type, previousDate); } boost::posix_time::ptime SQLiteHistoryStorage::getLastTimeStampFromMUC(const JID& selfJID, const JID& mucJID) const { - boost::optional<long long> selfID = getIDFromJID(selfJID.toBare()); - boost::optional<long long> mucID = getIDFromJID(mucJID.toBare()); + boost::optional<long long> selfID = getIDFromJID(selfJID.toBare()); + boost::optional<long long> mucID = getIDFromJID(mucJID.toBare()); - if (!selfID || !mucID) { - // JIDs missing from the database - return boost::posix_time::ptime(boost::posix_time::not_a_date_time); - } + if (!selfID || !mucID) { + // JIDs missing from the database + return boost::posix_time::ptime(boost::posix_time::not_a_date_time); + } - sqlite3_stmt* selectStatement; - std::string selectQuery = "SELECT messages.'time', messages.'offset' from messages WHERE type=1 AND (toBare=" + - boost::lexical_cast<std::string>(*selfID) + " AND fromBare=" + - boost::lexical_cast<std::string>(*mucID) + ") ORDER BY time DESC LIMIT 1"; + sqlite3_stmt* selectStatement; + std::string selectQuery = "SELECT messages.'time', messages.'offset' from messages WHERE type=1 AND (toBare=" + + boost::lexical_cast<std::string>(*selfID) + " AND fromBare=" + + boost::lexical_cast<std::string>(*mucID) + ") ORDER BY time DESC LIMIT 1"; - int r = sqlite3_prepare(db_, selectQuery.c_str(), boost::numeric_cast<int>(selectQuery.size()), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } + int r = sqlite3_prepare(db_, selectQuery.c_str(), boost::numeric_cast<int>(selectQuery.size()), &selectStatement, nullptr); + if (r != SQLITE_OK) { + std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; + } - r = sqlite3_step(selectStatement); - if (r == SQLITE_ROW) { - int secondsSinceEpoch(sqlite3_column_int(selectStatement, 0)); - boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); - int offset = sqlite3_column_int(selectStatement, 1); + r = sqlite3_step(selectStatement); + if (r == SQLITE_ROW) { + int secondsSinceEpoch(sqlite3_column_int(selectStatement, 0)); + boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); + int offset = sqlite3_column_int(selectStatement, 1); - return time - boost::posix_time::hours(offset); - } + return time - boost::posix_time::hours(offset); + } - return boost::posix_time::ptime(boost::posix_time::not_a_date_time); + return boost::posix_time::ptime(boost::posix_time::not_a_date_time); } void SQLiteHistoryStorage::run() { diff --git a/Swiften/History/SQLiteHistoryStorage.h b/Swiften/History/SQLiteHistoryStorage.h index 2c1ba7a..57f0d35 100644 --- a/Swiften/History/SQLiteHistoryStorage.h +++ b/Swiften/History/SQLiteHistoryStorage.h @@ -1,43 +1,44 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <thread> + +#include <boost/filesystem/path.hpp> #include <boost/optional.hpp> #include <Swiften/Base/API.h> #include <Swiften/History/HistoryStorage.h> -#include <boost/thread.hpp> -#include <boost/filesystem/path.hpp> struct sqlite3; namespace Swift { - class SWIFTEN_API SQLiteHistoryStorage : public HistoryStorage { - public: - SQLiteHistoryStorage(const boost::filesystem::path& file); - ~SQLiteHistoryStorage(); - - void addMessage(const HistoryMessage& message); - ContactsMap getContacts(const JID& selfJID, HistoryMessage::Type type, const std::string& keyword) const; - std::vector<HistoryMessage> getMessagesFromDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const; - std::vector<HistoryMessage> getMessagesFromNextDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const; - std::vector<HistoryMessage> getMessagesFromPreviousDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const; - boost::posix_time::ptime getLastTimeStampFromMUC(const JID& selfJID, const JID& mucJID) const; - - private: - void run(); - boost::gregorian::date getNextDateWithLogs(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date, bool reverseOrder) const; - long long getIDForJID(const JID&); - long long addJID(const JID&); - - boost::optional<JID> getJIDFromID(long long id) const; - boost::optional<long long> getIDFromJID(const JID& jid) const; - - sqlite3* db_; - boost::thread* thread_; - }; + class SWIFTEN_API SQLiteHistoryStorage : public HistoryStorage { + public: + SQLiteHistoryStorage(const boost::filesystem::path& file); + ~SQLiteHistoryStorage(); + + void addMessage(const HistoryMessage& message); + ContactsMap getContacts(const JID& selfJID, HistoryMessage::Type type, const std::string& keyword) const; + std::vector<HistoryMessage> getMessagesFromDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const; + std::vector<HistoryMessage> getMessagesFromNextDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const; + std::vector<HistoryMessage> getMessagesFromPreviousDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const; + boost::posix_time::ptime getLastTimeStampFromMUC(const JID& selfJID, const JID& mucJID) const; + + private: + void run(); + boost::gregorian::date getNextDateWithLogs(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date, bool reverseOrder) const; + long long getIDForJID(const JID&); + long long addJID(const JID&); + + boost::optional<JID> getJIDFromID(long long id) const; + boost::optional<long long> getIDFromJID(const JID& jid) const; + + sqlite3* db_; + std::thread* thread_; + }; } diff --git a/Swiften/History/UnitTest/SQLiteHistoryManagerTest.cpp b/Swiften/History/UnitTest/SQLiteHistoryManagerTest.cpp index 4123008..4d8a111 100644 --- a/Swiften/History/UnitTest/SQLiteHistoryManagerTest.cpp +++ b/Swiften/History/UnitTest/SQLiteHistoryManagerTest.cpp @@ -1,115 +1,116 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <boost/date_time/posix_time/posix_time.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/date_time/posix_time/posix_time.hpp> #include <Swiften/History/SQLiteHistoryManager.h> using namespace Swift; class SQLiteHistoryManagerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SQLiteHistoryManagerTest); - //CPPUNIT_TEST(testAddMessage); - //CPPUNIT_TEST(testAddMessage_TwoMessages); - //CPPUNIT_TEST(testGetIDForJID_SameJID); - //CPPUNIT_TEST(testGetIDForJID_DifferentJIDs); - //CPPUNIT_TEST(getJIDFromID); - //CPPUNIT_TEST(getJIDFromID_UnexistingID); - //CPPUNIT_TEST(getIDFromJID); - //CPPUNIT_TEST(getIDFromJID_UnexistingJID); - //CPPUNIT_TEST_SUITE_END(); - - public: - SQLiteHistoryManagerTest() {} - - void setUp() { - } - - void tearDown() { - } - - void testAddMessage() { - boost::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); - HistoryMessage testMessage("Test", JID("foo@bar.com"), JID("fum@baz.org"), boost::posix_time::time_from_string("1980-01-21 22:03")); - testling->addMessage(testMessage); - - std::vector<HistoryMessage> messages = testling->getMessages(); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(messages.size())); - CPPUNIT_ASSERT(testMessage == messages[0]); - } - - void testAddMessage_TwoMessages() { - boost::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); - HistoryMessage testMessage1("Test1", JID("foo@bar.com"), JID("fum@baz.org"), boost::posix_time::time_from_string("1980-01-21 22:03")); - testling->addMessage(testMessage1); - HistoryMessage testMessage2("Test2", JID("fum@baz.org"), JID("foo@bar.com"), boost::posix_time::time_from_string("1975-03-09 22:04")); - testling->addMessage(testMessage2); - - std::vector<HistoryMessage> messages = testling->getMessages(); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(messages.size())); - CPPUNIT_ASSERT(testMessage1 == messages[0]); - CPPUNIT_ASSERT(testMessage2 == messages[1]); - } - - void testGetIDForJID_SameJID() { - boost::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); - int id1 = testling->getIDForJID(JID("foo@bar.com")); - int id2 = testling->getIDForJID(JID("foo@bar.com")); - - CPPUNIT_ASSERT_EQUAL(id1, id2); - } - - void testGetIDForJID_DifferentJIDs() { - boost::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); - int id1 = testling->getIDForJID(JID("foo@bar.com")); - int id2 = testling->getIDForJID(JID("foo@baz.com")); - - CPPUNIT_ASSERT(id1 != id2); - } - - void getJIDFromID() { - boost::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); - int id = testling->addJID(JID("foo@bar.com")); - - boost::optional<JID> result(testling->getJIDFromID(id)); - CPPUNIT_ASSERT(result); - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), *result); - } - - void getJIDFromID_UnexistingID() { - boost::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); - - boost::optional<JID> result(testling->getJIDFromID(1)); - - CPPUNIT_ASSERT(!result); - } - - void getIDFromJID() { - boost::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); - int id = testling->addJID(JID("foo@bar.com")); - - boost::optional<int> result(testling->getIDFromJID(JID("foo@bar.com"))); - CPPUNIT_ASSERT(result); - CPPUNIT_ASSERT_EQUAL(id, *result); - } - - void getIDFromJID_UnexistingJID() { - boost::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); - - boost::optional<int> result(testling->getIDFromJID(JID("foo@bar.com"))); - - CPPUNIT_ASSERT(!result); - } - - private: - SQLiteHistoryManager* createHistoryManager() { - return new SQLiteHistoryManager(":memory:"); - } + CPPUNIT_TEST_SUITE(SQLiteHistoryManagerTest); + //CPPUNIT_TEST(testAddMessage); + //CPPUNIT_TEST(testAddMessage_TwoMessages); + //CPPUNIT_TEST(testGetIDForJID_SameJID); + //CPPUNIT_TEST(testGetIDForJID_DifferentJIDs); + //CPPUNIT_TEST(getJIDFromID); + //CPPUNIT_TEST(getJIDFromID_UnexistingID); + //CPPUNIT_TEST(getIDFromJID); + //CPPUNIT_TEST(getIDFromJID_UnexistingJID); + //CPPUNIT_TEST_SUITE_END(); + + public: + SQLiteHistoryManagerTest() {} + + void setUp() { + } + + void tearDown() { + } + + void testAddMessage() { + std::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); + HistoryMessage testMessage("Test", JID("foo@bar.com"), JID("fum@baz.org"), boost::posix_time::time_from_string("1980-01-21 22:03")); + testling->addMessage(testMessage); + + std::vector<HistoryMessage> messages = testling->getMessages(); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(messages.size())); + CPPUNIT_ASSERT(testMessage == messages[0]); + } + + void testAddMessage_TwoMessages() { + std::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); + HistoryMessage testMessage1("Test1", JID("foo@bar.com"), JID("fum@baz.org"), boost::posix_time::time_from_string("1980-01-21 22:03")); + testling->addMessage(testMessage1); + HistoryMessage testMessage2("Test2", JID("fum@baz.org"), JID("foo@bar.com"), boost::posix_time::time_from_string("1975-03-09 22:04")); + testling->addMessage(testMessage2); + + std::vector<HistoryMessage> messages = testling->getMessages(); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(messages.size())); + CPPUNIT_ASSERT(testMessage1 == messages[0]); + CPPUNIT_ASSERT(testMessage2 == messages[1]); + } + + void testGetIDForJID_SameJID() { + std::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); + int id1 = testling->getIDForJID(JID("foo@bar.com")); + int id2 = testling->getIDForJID(JID("foo@bar.com")); + + CPPUNIT_ASSERT_EQUAL(id1, id2); + } + + void testGetIDForJID_DifferentJIDs() { + std::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); + int id1 = testling->getIDForJID(JID("foo@bar.com")); + int id2 = testling->getIDForJID(JID("foo@baz.com")); + + CPPUNIT_ASSERT(id1 != id2); + } + + void getJIDFromID() { + std::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); + int id = testling->addJID(JID("foo@bar.com")); + + boost::optional<JID> result(testling->getJIDFromID(id)); + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), *result); + } + + void getJIDFromID_UnexistingID() { + std::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); + + boost::optional<JID> result(testling->getJIDFromID(1)); + + CPPUNIT_ASSERT(!result); + } + + void getIDFromJID() { + std::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); + int id = testling->addJID(JID("foo@bar.com")); + + boost::optional<int> result(testling->getIDFromJID(JID("foo@bar.com"))); + CPPUNIT_ASSERT(result); + CPPUNIT_ASSERT_EQUAL(id, *result); + } + + void getIDFromJID_UnexistingJID() { + std::shared_ptr<SQLiteHistoryManager> testling(createHistoryManager()); + + boost::optional<int> result(testling->getIDFromJID(JID("foo@bar.com"))); + + CPPUNIT_ASSERT(!result); + } + + private: + SQLiteHistoryManager* createHistoryManager() { + return new SQLiteHistoryManager(":memory:"); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(SQLiteHistoryManagerTest); diff --git a/Swiften/IDN/ICUConverter.cpp b/Swiften/IDN/ICUConverter.cpp index 18ff231..37ce708 100644 --- a/Swiften/IDN/ICUConverter.cpp +++ b/Swiften/IDN/ICUConverter.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/IDN/ICUConverter.h> @@ -19,139 +19,134 @@ using namespace Swift; using boost::numeric_cast; namespace { - typedef std::vector<UChar, SafeAllocator<UChar> > ICUString; - - const char* toConstCharArray(const std::string& input) { - return input.c_str(); - } - - const char* toConstCharArray(const std::vector<unsigned char, SafeAllocator<unsigned char> >& input) { - return reinterpret_cast<const char*>(vecptr(input)); - } - - template<typename T> - ICUString convertToICUString(const T& s) { - ICUString result; - result.resize(s.size()); - UErrorCode status = U_ZERO_ERROR; - int32_t icuResultLength = numeric_cast<int32_t>(result.size()); - u_strFromUTF8Lenient(vecptr(result), numeric_cast<int32_t>(result.size()), &icuResultLength, toConstCharArray(s), numeric_cast<int32_t>(s.size()), &status); - if (status == U_BUFFER_OVERFLOW_ERROR) { - status = U_ZERO_ERROR; - result.resize(numeric_cast<size_t>(icuResultLength)); - u_strFromUTF8Lenient(vecptr(result), numeric_cast<int32_t>(result.size()), &icuResultLength, toConstCharArray(s), numeric_cast<int32_t>(s.size()), &status); - } - if (U_FAILURE(status)) { - return ICUString(); - } - result.resize(numeric_cast<size_t>(icuResultLength)); - return result; - } - - std::vector<char, SafeAllocator<char> > convertToArray(const ICUString& input) { - std::vector<char, SafeAllocator<char> > result; - result.resize(input.size()); - UErrorCode status = U_ZERO_ERROR; - int32_t inputLength = numeric_cast<int32_t>(result.size()); - u_strToUTF8(vecptr(result), numeric_cast<int32_t>(result.size()), &inputLength, vecptr(input), numeric_cast<int32_t>(input.size()), &status); - if (status == U_BUFFER_OVERFLOW_ERROR) { - status = U_ZERO_ERROR; - result.resize(numeric_cast<size_t>(inputLength)); - u_strToUTF8(vecptr(result), numeric_cast<int32_t>(result.size()), &inputLength, vecptr(input), numeric_cast<int32_t>(input.size()), &status); - } - if (U_FAILURE(status)) { - return std::vector<char, SafeAllocator<char> >(); - } - - result.resize(numeric_cast<size_t>(inputLength) + 1); - result[result.size() - 1] = '\0'; - return result; - } - - std::string convertToString(const ICUString& input) { - return std::string(vecptr(convertToArray(input))); - } - - UStringPrepProfileType getICUProfileType(IDNConverter::StringPrepProfile profile) { - switch(profile) { - case IDNConverter::NamePrep: return USPREP_RFC3491_NAMEPREP; - case IDNConverter::XMPPNodePrep: return USPREP_RFC3920_NODEPREP; - case IDNConverter::XMPPResourcePrep: return USPREP_RFC3920_RESOURCEPREP; - case IDNConverter::SASLPrep: return USPREP_RFC4013_SASLPREP; - } - assert(false); - return USPREP_RFC3491_NAMEPREP; - } - - template<typename StringType> - std::vector<char, SafeAllocator<char> > getStringPreparedDetail(const StringType& s, IDNConverter::StringPrepProfile profile) { - UErrorCode status = U_ZERO_ERROR; - - boost::shared_ptr<UStringPrepProfile> icuProfile(usprep_openByType(getICUProfileType(profile), &status), usprep_close); - assert(U_SUCCESS(status)); - - ICUString icuInput = convertToICUString(s); - ICUString icuResult; - UParseError parseError; - icuResult.resize(icuInput.size()); - int32_t icuResultLength = usprep_prepare(icuProfile.get(), vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), USPREP_ALLOW_UNASSIGNED, &parseError, &status); - icuResult.resize(numeric_cast<size_t>(icuResultLength)); - if (status == U_BUFFER_OVERFLOW_ERROR) { - status = U_ZERO_ERROR; - icuResult.resize(numeric_cast<size_t>(icuResultLength)); - icuResultLength = usprep_prepare(icuProfile.get(), vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), USPREP_ALLOW_UNASSIGNED, &parseError, &status); - icuResult.resize(numeric_cast<size_t>(icuResultLength)); - } - if (U_FAILURE(status)) { - return std::vector<char, SafeAllocator<char> >(); - } - icuResult.resize(numeric_cast<size_t>(icuResultLength)); - - return convertToArray(icuResult); - } + static constexpr auto maxStringPrepLength = 1023; + + typedef std::vector<UChar, SafeAllocator<UChar> > ICUString; + + const char* toConstCharArray(const std::string& input) { + return input.c_str(); + } + + const char* toConstCharArray(const std::vector<unsigned char, SafeAllocator<unsigned char> >& input) { + return reinterpret_cast<const char*>(vecptr(input)); + } + + template<typename T> + ICUString convertToICUString(const T& s) { + ICUString result; + result.resize(s.size()); + UErrorCode status = U_ZERO_ERROR; + int32_t icuResultLength = numeric_cast<int32_t>(result.size()); + u_strFromUTF8Lenient(vecptr(result), numeric_cast<int32_t>(result.size()), &icuResultLength, toConstCharArray(s), numeric_cast<int32_t>(s.size()), &status); + if (status == U_BUFFER_OVERFLOW_ERROR) { + status = U_ZERO_ERROR; + result.resize(numeric_cast<size_t>(icuResultLength)); + u_strFromUTF8Lenient(vecptr(result), numeric_cast<int32_t>(result.size()), &icuResultLength, toConstCharArray(s), numeric_cast<int32_t>(s.size()), &status); + } + if (U_FAILURE(status)) { + return ICUString(); + } + result.resize(numeric_cast<size_t>(icuResultLength)); + return result; + } + + std::vector<char, SafeAllocator<char> > convertToArray(const ICUString& input) { + std::vector<char, SafeAllocator<char> > result; + result.resize(input.size()); + UErrorCode status = U_ZERO_ERROR; + int32_t inputLength = numeric_cast<int32_t>(result.size()); + u_strToUTF8(vecptr(result), numeric_cast<int32_t>(result.size()), &inputLength, vecptr(input), numeric_cast<int32_t>(input.size()), &status); + if (status == U_BUFFER_OVERFLOW_ERROR) { + status = U_ZERO_ERROR; + result.resize(numeric_cast<size_t>(inputLength)); + u_strToUTF8(vecptr(result), numeric_cast<int32_t>(result.size()), &inputLength, vecptr(input), numeric_cast<int32_t>(input.size()), &status); + } + if (U_FAILURE(status)) { + return std::vector<char, SafeAllocator<char> >(); + } + + result.resize(numeric_cast<size_t>(inputLength) + 1); + result[result.size() - 1] = '\0'; + return result; + } + + std::string convertToString(const ICUString& input) { + return std::string(vecptr(convertToArray(input))); + } + + UStringPrepProfileType getICUProfileType(IDNConverter::StringPrepProfile profile) { + switch(profile) { + case IDNConverter::NamePrep: return USPREP_RFC3491_NAMEPREP; + case IDNConverter::XMPPNodePrep: return USPREP_RFC3920_NODEPREP; + case IDNConverter::XMPPResourcePrep: return USPREP_RFC3920_RESOURCEPREP; + case IDNConverter::SASLPrep: return USPREP_RFC4013_SASLPREP; + } + assert(false); + return USPREP_RFC3491_NAMEPREP; + } + + template<typename StringType> + std::vector<char, SafeAllocator<char> > getStringPreparedDetail(const StringType& s, IDNConverter::StringPrepProfile profile) { + UErrorCode status = U_ZERO_ERROR; + + std::shared_ptr<UStringPrepProfile> icuProfile(usprep_openByType(getICUProfileType(profile), &status), usprep_close); + assert(U_SUCCESS(status)); + + ICUString icuInput = convertToICUString(s); + ICUString icuResult; + UParseError parseError; + icuResult.resize(maxStringPrepLength); + int32_t icuResultLength = usprep_prepare(icuProfile.get(), vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), USPREP_ALLOW_UNASSIGNED, &parseError, &status); + if (U_FAILURE(status)) { + return std::vector<char, SafeAllocator<char> >(); + } + icuResult.resize(numeric_cast<size_t>(icuResultLength)); + + return convertToArray(icuResult); + } } namespace Swift { std::string ICUConverter::getStringPrepared(const std::string& s, StringPrepProfile profile) { - if (s.empty()) { - return ""; - } - std::vector<char, SafeAllocator<char> > preparedData = getStringPreparedDetail(s, profile); - if (preparedData.empty()) { - throw std::exception(); - } - return std::string(vecptr(preparedData)); + if (s.empty()) { + return ""; + } + std::vector<char, SafeAllocator<char> > preparedData = getStringPreparedDetail(s, profile); + if (preparedData.empty()) { + throw std::exception(); + } + return std::string(vecptr(preparedData)); } SafeByteArray ICUConverter::getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) { - if (s.empty()) { - return SafeByteArray(); - } - std::vector<char, SafeAllocator<char> > preparedData = getStringPreparedDetail(s, profile); - if (preparedData.empty()) { - throw std::exception(); - } - return createSafeByteArray(reinterpret_cast<const char*>(vecptr(preparedData))); + if (s.empty()) { + return SafeByteArray(); + } + std::vector<char, SafeAllocator<char> > preparedData = getStringPreparedDetail(s, profile); + if (preparedData.empty()) { + throw std::exception(); + } + return createSafeByteArray(reinterpret_cast<const char*>(vecptr(preparedData))); } -std::string ICUConverter::getIDNAEncoded(const std::string& domain) { - UErrorCode status = U_ZERO_ERROR; - ICUString icuInput = convertToICUString(domain); - ICUString icuResult; - icuResult.resize(icuInput.size()); - UParseError parseError; - int32_t icuResultLength = uidna_IDNToASCII(vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), UIDNA_DEFAULT, &parseError, &status); - if (status == U_BUFFER_OVERFLOW_ERROR) { - status = U_ZERO_ERROR; - icuResult.resize(numeric_cast<size_t>(icuResultLength)); - icuResultLength = uidna_IDNToASCII(vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), UIDNA_DEFAULT, &parseError, &status); - } - if (U_FAILURE(status)) { - return domain; - } - icuResult.resize(numeric_cast<size_t>(icuResultLength)); - return convertToString(icuResult); +boost::optional<std::string> ICUConverter::getIDNAEncoded(const std::string& domain) { + UErrorCode status = U_ZERO_ERROR; + ICUString icuInput = convertToICUString(domain); + ICUString icuResult; + icuResult.resize(icuInput.size()); + UParseError parseError; + int32_t icuResultLength = uidna_IDNToASCII(vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), UIDNA_USE_STD3_RULES, &parseError, &status); + if (status == U_BUFFER_OVERFLOW_ERROR) { + status = U_ZERO_ERROR; + icuResult.resize(numeric_cast<size_t>(icuResultLength)); + icuResultLength = uidna_IDNToASCII(vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), UIDNA_USE_STD3_RULES, &parseError, &status); + } + if (U_FAILURE(status)) { + return boost::optional<std::string>(); + } + icuResult.resize(numeric_cast<size_t>(icuResultLength)); + return convertToString(icuResult); } } diff --git a/Swiften/IDN/ICUConverter.h b/Swiften/IDN/ICUConverter.h index 8ba9bb5..b0f5d85 100644 --- a/Swiften/IDN/ICUConverter.h +++ b/Swiften/IDN/ICUConverter.h @@ -1,22 +1,22 @@ /* - * Copyright (c) 2012-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + #include <Swiften/Base/API.h> -#include <Swiften/Base/Override.h> #include <Swiften/IDN/IDNConverter.h> namespace Swift { - class SWIFTEN_API ICUConverter : public IDNConverter { - public: - virtual std::string getStringPrepared(const std::string& s, StringPrepProfile profile) SWIFTEN_OVERRIDE; - virtual SafeByteArray getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) SWIFTEN_OVERRIDE; + class SWIFTEN_API ICUConverter : public IDNConverter { + public: + virtual std::string getStringPrepared(const std::string& s, StringPrepProfile profile) override; + virtual SafeByteArray getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) override; - virtual std::string getIDNAEncoded(const std::string& s) SWIFTEN_OVERRIDE; - }; + virtual boost::optional<std::string> getIDNAEncoded(const std::string& s) override; + }; } diff --git a/Swiften/IDN/IDNConverter.cpp b/Swiften/IDN/IDNConverter.cpp index 7705812..b2f575f 100644 --- a/Swiften/IDN/IDNConverter.cpp +++ b/Swiften/IDN/IDNConverter.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/IDN/IDNConverter.h> diff --git a/Swiften/IDN/IDNConverter.h b/Swiften/IDN/IDNConverter.h index c55d969..27ddd78 100644 --- a/Swiften/IDN/IDNConverter.h +++ b/Swiften/IDN/IDNConverter.h @@ -1,31 +1,34 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + +#include <boost/optional.hpp> + #include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class SWIFTEN_API IDNConverter { - public: - virtual ~IDNConverter(); - - enum StringPrepProfile { - NamePrep, - XMPPNodePrep, - XMPPResourcePrep, - SASLPrep - }; - - virtual std::string getStringPrepared(const std::string& s, StringPrepProfile profile) = 0; - virtual SafeByteArray getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) = 0; - - // Thread-safe - virtual std::string getIDNAEncoded(const std::string& s) = 0; - }; + class SWIFTEN_API IDNConverter { + public: + virtual ~IDNConverter(); + + enum StringPrepProfile { + NamePrep, + XMPPNodePrep, + XMPPResourcePrep, + SASLPrep + }; + + virtual std::string getStringPrepared(const std::string& s, StringPrepProfile profile) = 0; + virtual SafeByteArray getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) = 0; + + // Thread-safe + virtual boost::optional<std::string> getIDNAEncoded(const std::string& s) = 0; + }; } diff --git a/Swiften/IDN/LibIDNConverter.cpp b/Swiften/IDN/LibIDNConverter.cpp index c4a1c18..e2a87be 100644 --- a/Swiften/IDN/LibIDNConverter.cpp +++ b/Swiften/IDN/LibIDNConverter.cpp @@ -1,80 +1,91 @@ /* - * Copyright (c) 2012-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/IDN/LibIDNConverter.h> extern "C" { - #include <stringprep.h> - #include <idna.h> + #include <stringprep.h> + #include <idna.h> } -#include <vector> #include <cassert> #include <cstdlib> +#include <vector> + +#include <memory> + #include <Swiften/Base/ByteArray.h> #include <Swiften/Base/SafeAllocator.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/IDN/UTF8Validator.h> using namespace Swift; namespace { - static const int MAX_STRINGPREP_SIZE = 1024; + static const size_t MAX_STRINGPREP_SIZE = 1024; + + const Stringprep_profile* getLibIDNProfile(IDNConverter::StringPrepProfile profile) { + switch(profile) { + case IDNConverter::NamePrep: return stringprep_nameprep; + case IDNConverter::XMPPNodePrep: return stringprep_xmpp_nodeprep; + case IDNConverter::XMPPResourcePrep: return stringprep_xmpp_resourceprep; + case IDNConverter::SASLPrep: return stringprep_saslprep; + } + assert(false); + return nullptr; + } - const Stringprep_profile* getLibIDNProfile(IDNConverter::StringPrepProfile profile) { - switch(profile) { - case IDNConverter::NamePrep: return stringprep_nameprep; - case IDNConverter::XMPPNodePrep: return stringprep_xmpp_nodeprep; - case IDNConverter::XMPPResourcePrep: return stringprep_xmpp_resourceprep; - case IDNConverter::SASLPrep: return stringprep_saslprep; - } - assert(false); - return 0; - } + template<typename StringType, typename ContainerType> + ContainerType getStringPreparedInternal(const StringType& s, IDNConverter::StringPrepProfile profile) { + ContainerType input(s.begin(), s.end()); + if (!UTF8IsValid(s.data(), s.size())) { + return ContainerType(); + } - template<typename StringType, typename ContainerType> - ContainerType getStringPreparedInternal(const StringType& s, IDNConverter::StringPrepProfile profile) { - ContainerType input(s.begin(), s.end()); - input.resize(MAX_STRINGPREP_SIZE); - if (stringprep(&input[0], MAX_STRINGPREP_SIZE, static_cast<Stringprep_profile_flags>(0), getLibIDNProfile(profile)) == 0) { - return input; - } - else { - return ContainerType(); - } - } + // Ensure we have enough space for stringprepping, and that input is always NUL terminated + input.resize(std::max(MAX_STRINGPREP_SIZE, input.size() + 1)); + if (stringprep(&input[0], MAX_STRINGPREP_SIZE, static_cast<Stringprep_profile_flags>(0), getLibIDNProfile(profile)) == 0) { + return input; + } + else { + return ContainerType(); + } + } } namespace Swift { std::string LibIDNConverter::getStringPrepared(const std::string& s, StringPrepProfile profile) { - std::vector<char> preparedData = getStringPreparedInternal< std::string, std::vector<char> >(s, profile); - if (preparedData.empty()) { - throw std::exception(); - } - return std::string(vecptr(preparedData)); + std::vector<char> preparedData = getStringPreparedInternal< std::string, std::vector<char> >(s, profile); + if (preparedData.empty()) { + throw std::exception(); + } + return std::string(vecptr(preparedData)); } SafeByteArray LibIDNConverter::getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) { - std::vector<char, SafeAllocator<char> > preparedData = getStringPreparedInternal<SafeByteArray, std::vector<char, SafeAllocator<char> > >(s, profile); - if (preparedData.empty()) { - throw std::exception(); - } - return createSafeByteArray(reinterpret_cast<const char*>(vecptr(preparedData))); + std::vector<char, SafeAllocator<char> > preparedData = getStringPreparedInternal<SafeByteArray, std::vector<char, SafeAllocator<char> > >(s, profile); + if (preparedData.empty()) { + throw std::exception(); + } + return createSafeByteArray(reinterpret_cast<const char*>(vecptr(preparedData))); } -std::string LibIDNConverter::getIDNAEncoded(const std::string& domain) { - char* output; - if (idna_to_ascii_8z(domain.c_str(), &output, 0) == IDNA_SUCCESS) { - std::string result(output); - free(output); - return result; - } - else { - return domain; - } +boost::optional<std::string> LibIDNConverter::getIDNAEncoded(const std::string& domain) { + char* output; + if (idna_to_ascii_8z(domain.c_str(), &output, IDNA_USE_STD3_ASCII_RULES) == IDNA_SUCCESS) { + std::string result(output); + free(output); + if (result.size() > 255) { + return boost::optional<std::string>(); + } + return result; + } + else { + return boost::optional<std::string>(); + } } } diff --git a/Swiften/IDN/LibIDNConverter.h b/Swiften/IDN/LibIDNConverter.h index 23f6bbd..5553ab3 100644 --- a/Swiften/IDN/LibIDNConverter.h +++ b/Swiften/IDN/LibIDNConverter.h @@ -1,23 +1,23 @@ /* - * Copyright (c) 2012-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + #include <Swiften/Base/API.h> -#include <Swiften/Base/Override.h> #include <Swiften/IDN/IDNConverter.h> namespace Swift { - class SWIFTEN_API LibIDNConverter : public IDNConverter { - public: - virtual std::string getStringPrepared(const std::string& s, StringPrepProfile profile) SWIFTEN_OVERRIDE; - virtual SafeByteArray getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) SWIFTEN_OVERRIDE; + class SWIFTEN_API LibIDNConverter : public IDNConverter { + public: + virtual std::string getStringPrepared(const std::string& s, StringPrepProfile profile) override; + virtual SafeByteArray getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) override; - virtual std::string getIDNAEncoded(const std::string& s) SWIFTEN_OVERRIDE; - }; + virtual boost::optional<std::string> getIDNAEncoded(const std::string& s) override; + }; } diff --git a/Swiften/IDN/PlatformIDNConverter.cpp b/Swiften/IDN/PlatformIDNConverter.cpp index 6d9cff7..3564bb9 100644 --- a/Swiften/IDN/PlatformIDNConverter.cpp +++ b/Swiften/IDN/PlatformIDNConverter.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/IDN/PlatformIDNConverter.h> @@ -13,14 +13,17 @@ namespace Swift { -IDNConverter* PlatformIDNConverter::create() { +std::unique_ptr<IDNConverter> PlatformIDNConverter::create() { #if defined(HAVE_LIBIDN) - return new LibIDNConverter(); + return std::make_unique<LibIDNConverter>(); #elif defined(HAVE_ICU) - return new ICUConverter(); + return std::make_unique<ICUConverter>(); #else +#if defined(NEED_IDN) #error "No IDN implementation" - return 0; +#else + return {}; +#endif #endif } diff --git a/Swiften/IDN/PlatformIDNConverter.h b/Swiften/IDN/PlatformIDNConverter.h index 4b1025b..3b9a275 100644 --- a/Swiften/IDN/PlatformIDNConverter.h +++ b/Swiften/IDN/PlatformIDNConverter.h @@ -1,17 +1,19 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> +#include <memory> + namespace Swift { - class IDNConverter; + class IDNConverter; - namespace PlatformIDNConverter { - SWIFTEN_API IDNConverter* create(); - } + namespace PlatformIDNConverter { + SWIFTEN_API std::unique_ptr<IDNConverter> create(); + } } diff --git a/Swiften/IDN/SConscript b/Swiften/IDN/SConscript index 9d3b8f9..0afad0e 100644 --- a/Swiften/IDN/SConscript +++ b/Swiften/IDN/SConscript @@ -4,23 +4,29 @@ Import("swiften_env", "env") objects = swiften_env.SwiftenObject(["IDNConverter.cpp"]) myenv = swiften_env.Clone() +if myenv.get("NEED_IDN"): + myenv.Append(CPPDEFINES = ["NEED_IDN"]) if myenv.get("HAVE_ICU") : - myenv.MergeFlags(swiften_env["ICU_FLAGS"]) - myenv.Append(CPPDEFINES = ["HAVE_ICU"]) - objects += myenv.SwiftenObject(["ICUConverter.cpp"]) + myenv.MergeFlags(swiften_env["ICU_FLAGS"]) + myenv.Append(CPPDEFINES = ["HAVE_ICU"]) + objects += myenv.SwiftenObject(["ICUConverter.cpp"]) if myenv.get("HAVE_LIBIDN") : - myenv.MergeFlags(swiften_env["LIBIDN_FLAGS"]) - myenv.Append(CPPDEFINES = ["HAVE_LIBIDN"]) - objects += myenv.SwiftenObject(["LibIDNConverter.cpp"]) -objects += myenv.SwiftenObject(["PlatformIDNConverter.cpp"]) + myenv.MergeFlags(swiften_env["LIBIDN_FLAGS"]) + myenv.Append(CPPDEFINES = ["HAVE_LIBIDN"]) + objects += myenv.SwiftenObject(["LibIDNConverter.cpp"]) +objects += myenv.SwiftenObject([ + "PlatformIDNConverter.cpp" + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) if env["TEST"] : - test_env = myenv.Clone() - test_env.UseFlags(swiften_env["CPPUNIT_FLAGS"]) - env.Append(UNITTEST_OBJECTS = test_env.SwiftenObject([ - File("UnitTest/IDNConverterTest.cpp"), - ])) + test_env = myenv.Clone() + test_env.UseFlags(swiften_env["CPPUNIT_FLAGS"]) + test_env.UseFlags(myenv.get("GOOGLETEST_FLAGS", "")) + env.Append(UNITTEST_OBJECTS = test_env.SwiftenObject([ + File("UnitTest/IDNConverterTest.cpp"), + File("UnitTest/UTF8ValidatorTest.cpp") + ])) diff --git a/Swiften/IDN/UTF8Validator.h b/Swiften/IDN/UTF8Validator.h new file mode 100644 index 0000000..d912ef9 --- /dev/null +++ b/Swiften/IDN/UTF8Validator.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <cstddef> + +namespace Swift { + +// UTF-8 validation based on the description in https://tools.ietf.org/html/rfc3629#section-3 . +template <typename CharType> +bool UTF8IsValid(const CharType* data, size_t length) { + bool isValid = true; + const CharType* current = data; + const CharType* end = data + length; + while (isValid && (current < end)) { + // one byte sequences + if ((*current & 0x80) == 0x0) { + current++; + continue; + } + // longer byte sequences + else { + // two byte sequences + if ((*current & 0xE0) == 0xC0) { + current++; + if ( (current < end) && ((*current & 0xC0) == 0x80) ) { + current++; + continue; + } + } + // three byte sequences + else if ((*current & 0xF0) == 0xE0) { + current++; + if ( ((current + 1) < end) && ((*current & 0xC0) == 0x80) ) { + current++; + if ((*current & 0xC0) == 0x80) { + current++; + continue; + } + } + } + // four byte sequences + else if ((*current & 0xF8) == 0xF0) { + current++; + if ( ((current + 2) < end) && ((*current & 0xC0) == 0x80) ) { + current++; + if ((*current & 0xC0) == 0x80) { + current++; + if ((*current & 0xC0) == 0x80) { + current++; + continue; + } + } + } + } + // invalid sequences + isValid = false; + } + } + return isValid; +} + +} diff --git a/Swiften/IDN/UnitTest/IDNConverterTest.cpp b/Swiften/IDN/UnitTest/IDNConverterTest.cpp index 285cf4b..77a1ece 100644 --- a/Swiften/IDN/UnitTest/IDNConverterTest.cpp +++ b/Swiften/IDN/UnitTest/IDNConverterTest.cpp @@ -1,56 +1,98 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <memory> + +#include <gtest/gtest.h> -#include <boost/shared_ptr.hpp> #include <Swiften/IDN/IDNConverter.h> #include <Swiften/IDN/PlatformIDNConverter.h> using namespace Swift; -class IDNConverterTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IDNConverterTest); - CPPUNIT_TEST(testStringPrep); - CPPUNIT_TEST(testStringPrep_Empty); - CPPUNIT_TEST(testGetEncoded); - CPPUNIT_TEST(testGetEncoded_International); - CPPUNIT_TEST_SUITE_END(); +class IDNConverterTest : public ::testing::Test { + +protected: + virtual void SetUp() { + testling_ = std::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); + } - public: - void setUp() { - testling = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); - } + std::shared_ptr<IDNConverter> testling_; +}; - void testStringPrep() { - std::string result = testling->getStringPrepared("tron\xc3\x87on", IDNConverter::NamePrep); +TEST_F(IDNConverterTest, testStringPrep) { + std::string result = testling_->getStringPrepared("tron\xc3\x87on", IDNConverter::NamePrep); - CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), result); - } + ASSERT_EQ(std::string("tron\xc3\xa7on"), result); +} - void testStringPrep_Empty() { - CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::NamePrep)); - CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::XMPPNodePrep)); - CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::XMPPResourcePrep)); - } +TEST_F(IDNConverterTest, testStringPrep_Empty) { + ASSERT_EQ(std::string(""), testling_->getStringPrepared("", IDNConverter::NamePrep)); + ASSERT_EQ(std::string(""), testling_->getStringPrepared("", IDNConverter::XMPPNodePrep)); + ASSERT_EQ(std::string(""), testling_->getStringPrepared("", IDNConverter::XMPPResourcePrep)); +} - void testGetEncoded() { - std::string result = testling->getIDNAEncoded("www.swift.im"); - CPPUNIT_ASSERT_EQUAL(std::string("www.swift.im"), result); - } +TEST_F(IDNConverterTest, testStringPrep_MaximumOutputSize) { + const std::string input(1023, 'x'); + ASSERT_EQ(input, testling_->getStringPrepared(input, IDNConverter::NamePrep)); + ASSERT_EQ(input, testling_->getStringPrepared(input, IDNConverter::XMPPNodePrep)); + ASSERT_EQ(input, testling_->getStringPrepared(input, IDNConverter::XMPPResourcePrep)); +} - void testGetEncoded_International() { - std::string result = testling->getIDNAEncoded("www.tron\xc3\x87on.com"); - CPPUNIT_ASSERT_EQUAL(std::string("www.xn--tronon-zua.com"), result); - } +TEST_F(IDNConverterTest, testStringPrep_TooLong) { + const std::string input(1024, 'x'); + ASSERT_THROW(testling_->getStringPrepared(input, IDNConverter::NamePrep), std::exception); + ASSERT_THROW(testling_->getStringPrepared(input, IDNConverter::XMPPNodePrep), std::exception); + ASSERT_THROW(testling_->getStringPrepared(input, IDNConverter::XMPPResourcePrep), std::exception); +} +TEST_F(IDNConverterTest, testStringPrep_ShrinkingBelow1023) { + std::string input; + std::string expected; + // The four byte \u03b1\u0313 UTF-8 string will shrink to the three byte \u1f00 + for (auto i = 0; i < 300; ++i) { + input +="\xce\xb1\xcc\x93"; // UTF-8 repesentation of U+03B1 U+0313 + expected += "\xe1\xbc\x80"; // UTF-8 representation of U+1F00 + } + ASSERT_EQ(expected, testling_->getStringPrepared(input, IDNConverter::NamePrep)); + ASSERT_EQ(expected, testling_->getStringPrepared(input, IDNConverter::XMPPNodePrep)); + ASSERT_EQ(expected, testling_->getStringPrepared(input, IDNConverter::XMPPResourcePrep)); +} - private: - boost::shared_ptr<IDNConverter> testling; -}; +TEST_F(IDNConverterTest, testGetEncoded) { + boost::optional<std::string> result = testling_->getIDNAEncoded("www.swift.im"); + ASSERT_TRUE(!!result); + ASSERT_EQ(std::string("www.swift.im"), *result); +} + +TEST_F(IDNConverterTest, testGetEncoded_International) { + boost::optional<std::string> result = testling_->getIDNAEncoded("www.tron\xc3\x87on.com"); + ASSERT_TRUE(result); + ASSERT_EQ(std::string("www.xn--tronon-zua.com"), *result); +} + +TEST_F(IDNConverterTest, testGetEncoded_Invalid) { + boost::optional<std::string> result = testling_->getIDNAEncoded("www.foo,bar.com"); + ASSERT_FALSE(result); +} + +TEST_F(IDNConverterTest, testRFC1035LengthRestrictions) { + // label size check, 63 octets or less + ASSERT_TRUE(testling_->getIDNAEncoded(std::string(63, 'a') + ".example")); + ASSERT_TRUE(testling_->getIDNAEncoded(std::string(63, 'a') + "." + std::string(63, 'a') + ".example")); + ASSERT_FALSE(testling_->getIDNAEncoded(std::string(64, 'a') + "." + std::string(63, 'a') + ".example")); + ASSERT_FALSE(testling_->getIDNAEncoded(std::string(63, 'a') + "." + std::string(64, 'a') + ".example")); + ASSERT_FALSE(testling_->getIDNAEncoded(std::string(0, 'a') + "." + std::string(63, 'a') + ".example")); + ASSERT_FALSE(testling_->getIDNAEncoded(std::string(63, 'a') + "." + std::string(0, 'a') + ".example")); -CPPUNIT_TEST_SUITE_REGISTRATION(IDNConverterTest); + // domain name 255 octets or less + ASSERT_TRUE(testling_->getIDNAEncoded(std::string(63, 'a') + ".example")); + ASSERT_TRUE(testling_->getIDNAEncoded(std::string(63, 'a') + "." + std::string(63, 'a') + ".example")); + ASSERT_TRUE(testling_->getIDNAEncoded(std::string(63, 'a') + "." + std::string(63, 'a') + "." + std::string(63, 'a') + ".example")); + ASSERT_TRUE(testling_->getIDNAEncoded(std::string(63, 'a') + "." + std::string(63, 'a') + "." + std::string(63, 'a') + "." + std::string(55, 'a') + ".example")); + ASSERT_FALSE(testling_->getIDNAEncoded(std::string(63, 'a') + "." + std::string(63, 'a') + "." + std::string(63, 'a') + "." + std::string(56, 'a') + ".example")); + ASSERT_FALSE(testling_->getIDNAEncoded(std::string(63, 'a') + "." + std::string(56, 'a') + "." + std::string(63, 'a') + "." + std::string(63, 'a') + ".example")); +} diff --git a/Swiften/IDN/UnitTest/UTF8ValidatorTest.cpp b/Swiften/IDN/UnitTest/UTF8ValidatorTest.cpp new file mode 100644 index 0000000..6db7770 --- /dev/null +++ b/Swiften/IDN/UnitTest/UTF8ValidatorTest.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/IDN/UTF8Validator.h> + +using namespace Swift; + +class UTF8ValidatorTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(UTF8ValidatorTest); + + CPPUNIT_TEST(testValidUTF8Sequences); + CPPUNIT_TEST(testInvalidUTF8Sequences); + + CPPUNIT_TEST_SUITE_END(); + +public: + void testValidUTF8Sequences() { + { + unsigned char test[] = {0x74, 0x65, 0x73, 0x74}; + CPPUNIT_ASSERT(UTF8IsValid(test, sizeof(test))); + } + + { + unsigned char test[] = {0xf4, 0x8f, 0x80, 0xbf}; + CPPUNIT_ASSERT(UTF8IsValid(test, sizeof(test))); + } + } + + void testInvalidUTF8Sequences() { + { + unsigned char test[] = {0x41, 0xC2, 0x3E, 0x42}; + CPPUNIT_ASSERT(!UTF8IsValid(test, sizeof(test))); + } + + { + unsigned char test[] = {0xf4}; + CPPUNIT_ASSERT(!UTF8IsValid(test, sizeof(test))); + } + + { + unsigned char test[] = {0xf4, 0x8f, 0x65, 0x73, 0x80, 0xbf}; + CPPUNIT_ASSERT(!UTF8IsValid(test, sizeof(test))); + } + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(UTF8ValidatorTest); diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp index 0f2d8d1..eb72014 100644 --- a/Swiften/JID/JID.cpp +++ b/Swiften/JID/JID.cpp @@ -1,326 +1,281 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#define SWIFTEN_CACHE_JID_PREP - +#include <sstream> +#include <string> #include <vector> -#include <list> -#include <iostream> -#include <string> -#ifdef SWIFTEN_CACHE_JID_PREP -#include <boost/thread/mutex.hpp> -#include <boost/unordered_map.hpp> -#endif -#include <boost/assign/list_of.hpp> -#include <boost/algorithm/string/find_format.hpp> -#include <boost/algorithm/string/finder.hpp> #include <boost/optional.hpp> -#include <iostream> -#include <sstream> #include <Swiften/Base/String.h> -#include <Swiften/JID/JID.h> #include <Swiften/IDN/IDNConverter.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Network/HostAddress.h> + #ifndef SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/IDN/PlatformIDNConverter.h> #endif using namespace Swift; -#ifdef SWIFTEN_CACHE_JID_PREP -typedef boost::unordered_map<std::string, std::string> PrepCache; - -static boost::mutex namePrepCacheMutex; -static PrepCache nodePrepCache; -static PrepCache domainPrepCache; -static PrepCache resourcePrepCache; -#endif - -static const std::list<char> escapedChars = boost::assign::list_of(' ')('"')('&')('\'')('/')('<')('>')('@')(':'); +static const std::vector<char> escapedChars = {' ', '"', '&', '\'', '/', '<', '>', '@', ':'}; -static IDNConverter* idnConverter = NULL; +static IDNConverter* idnConverter = nullptr; #ifndef SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER namespace { - struct IDNInitializer { - IDNInitializer() : defaultIDNConverter(PlatformIDNConverter::create()) { - idnConverter = defaultIDNConverter.get(); - } - boost::shared_ptr<IDNConverter> defaultIDNConverter; - } initializer; + struct IDNInitializer { + IDNInitializer() : defaultIDNConverter(PlatformIDNConverter::create()) { + idnConverter = defaultIDNConverter.get(); + } + std::shared_ptr<IDNConverter> defaultIDNConverter; + } initializer; } #endif static std::string getEscaped(char c) { - return makeString() << '\\' << std::hex << static_cast<int>(c); + return makeString() << '\\' << std::hex << static_cast<int>(c); } static bool getEscapeSequenceValue(const std::string& sequence, unsigned char& value) { - std::stringstream s; - unsigned int v; - s << std::hex << sequence; - s >> v; - value = static_cast<unsigned char>(v); - return (!s.fail() && !s.bad() && (value == 0x5C || std::find(escapedChars.begin(), escapedChars.end(), value) != escapedChars.end())); + std::stringstream s; + unsigned int v; + s << std::hex << sequence; + s >> v; + value = static_cast<unsigned char>(v); + return (!s.fail() && !s.bad() && (value == 0x5C || std::find(escapedChars.begin(), escapedChars.end(), value) != escapedChars.end())); } -// Disabling this code for now, since GCC4.5+boost1.42 (on ubuntu) seems to -// result in a bug. Replacing it with naive code. -#if 0 -struct UnescapedCharacterFinder { - template<typename Iterator> boost::iterator_range<Iterator> operator()(Iterator begin, Iterator end) { - for (; begin != end; ++begin) { - if (std::find(escapedChars.begin(), escapedChars.end(), *begin) != escapedChars.end()) { - return boost::iterator_range<Iterator>(begin, begin + 1); - } - else if (*begin == '\\') { - // Check if we have an escaped dissalowed character sequence - Iterator innerBegin = begin + 1; - if (innerBegin != end && innerBegin + 1 != end) { - Iterator innerEnd = innerBegin + 2; - unsigned char value; - if (getEscapeSequenceValue(std::string(innerBegin, innerEnd), value)) { - return boost::iterator_range<Iterator>(begin, begin + 1); - } - } - } - } - return boost::iterator_range<Iterator>(end, end); - } -}; - -struct UnescapedCharacterFormatter { - template<typename FindResult> std::string operator()(const FindResult& match) const { - std::ostringstream s; - s << '\\' << std::hex << static_cast<int>(*match.begin()); - return s.str(); - } -}; - -struct EscapedCharacterFinder { - template<typename Iterator> boost::iterator_range<Iterator> operator()(Iterator begin, Iterator end) { - for (; begin != end; ++begin) { - if (*begin == '\\') { - Iterator innerEnd = begin + 1; - for (size_t i = 0; i < 2 && innerEnd != end; ++i, ++innerEnd) { - } - unsigned char value; - if (getEscapeSequenceValue(std::string(begin + 1, innerEnd), value)) { - return boost::iterator_range<Iterator>(begin, innerEnd); - } - } - } - return boost::iterator_range<Iterator>(end, end); - } -}; - -struct EscapedCharacterFormatter { - template<typename FindResult> std::string operator()(const FindResult& match) const { - unsigned char value; - if (getEscapeSequenceValue(std::string(match.begin() + 1, match.end()), value)) { - return std::string(reinterpret_cast<const char*>(&value), 1); - } - return boost::copy_range<std::string>(match); - } -}; -#endif - namespace Swift { JID::JID(const char* jid) : valid_(true) { - assert(jid); - initializeFromString(std::string(jid)); + assert(jid); + initializeFromString(std::string(jid)); } JID::JID(const std::string& jid) : valid_(true) { - initializeFromString(jid); + initializeFromString(jid); } JID::JID(const std::string& node, const std::string& domain) : valid_(true), hasResource_(false) { - nameprepAndSetComponents(node, domain, ""); + nameprepAndSetComponents(node, domain, ""); } JID::JID(const std::string& node, const std::string& domain, const std::string& resource) : valid_(true), hasResource_(true) { - nameprepAndSetComponents(node, domain, resource); + if (resource.empty()) { + valid_ = false; + } + nameprepAndSetComponents(node, domain, resource); +} + +JID::JID(const JID& other) { + this->operator=(other); +} + +JID::JID(JID&& other) { + this->operator=(std::move(other)); +} + +JID& JID::operator=(const JID& other) { + valid_ = other.valid_; + node_ = other.node_; + domain_ = other.domain_; + hasResource_ = other.hasResource_; + resource_ = other.resource_; + return *this; +} + +JID& JID::operator=(JID&& other) { + valid_ = other.valid_; + other.valid_ = false; + node_ = std::move(other.node_); + domain_ = std::move(other.domain_); + hasResource_ = other.hasResource_; + resource_ = std::move(other.resource_); + return *this; } void JID::initializeFromString(const std::string& jid) { - if (String::beginsWith(jid, '@')) { - valid_ = false; - return; - } - - std::string bare, resource; - size_t slashIndex = jid.find('/'); - if (slashIndex != jid.npos) { - hasResource_ = true; - bare = jid.substr(0, slashIndex); - resource = jid.substr(slashIndex + 1, jid.npos); - } - else { - hasResource_ = false; - bare = jid; - } - std::pair<std::string,std::string> nodeAndDomain = String::getSplittedAtFirst(bare, '@'); - if (nodeAndDomain.second.empty()) { - nameprepAndSetComponents("", nodeAndDomain.first, resource); - } - else { - nameprepAndSetComponents(nodeAndDomain.first, nodeAndDomain.second, resource); - } + if (String::beginsWith(jid, '@')) { + valid_ = false; + return; + } + + std::string bare, resource; + size_t slashIndex = jid.find('/'); + if (slashIndex != jid.npos) { + hasResource_ = true; + bare = jid.substr(0, slashIndex); + resource = jid.substr(slashIndex + 1, jid.npos); + } + else { + hasResource_ = false; + bare = jid; + } + auto firstMatch = bare.find('@'); + if (firstMatch != bare.npos) { + nameprepAndSetComponents(bare.substr(0, firstMatch), bare.substr(firstMatch + 1), resource); + } + else { + nameprepAndSetComponents("", bare, resource); + } } +void JID::setComponents(const std::string& node, const std::string& domain, const std::string& resource) { + domain_ = domain; + try { + node_ = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); + resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); + } + catch (...) { + valid_ = false; + return; + } +} void JID::nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource) { - if (domain.empty()) { - valid_ = false; - return; - } -#ifndef SWIFTEN_CACHE_JID_PREP - node_ = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); - domain_ = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep); - resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); -#else - boost::mutex::scoped_lock lock(namePrepCacheMutex); - - std::pair<PrepCache::iterator, bool> r; - - r = nodePrepCache.insert(std::make_pair(node, std::string())); - if (r.second) { - try { - r.first->second = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); - } - catch (...) { - nodePrepCache.erase(r.first); - valid_ = false; - return; - } - } - node_ = r.first->second; - - r = domainPrepCache.insert(std::make_pair(domain, std::string())); - if (r.second) { - try { - r.first->second = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep); - } - catch (...) { - domainPrepCache.erase(r.first); - valid_ = false; - return; - } - } - domain_ = r.first->second; - - r = resourcePrepCache.insert(std::make_pair(resource, std::string())); - if (r.second) { - try { - r.first->second = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); - } - catch (...) { - resourcePrepCache.erase(r.first); - valid_ = false; - return; - } - } - resource_ = r.first->second; -#endif - - if (domain_.empty()) { - valid_ = false; - return; - } + if (domain.empty() || (hasResource_ && resource.empty())) { + valid_ = false; + return; + } + + // Handling IPv6 addresses according to RFC 3986 rules + // saying that they are enclosed in square brackets + // which we have to remove when passing to HostAddress + if (domain.size() > 2 && domain.front() == '[' && domain.back() == ']') { + auto inner = std::string(domain.begin() + 1, domain.end() - 1); + auto hostAddress = HostAddress::fromString(inner); + if (hostAddress && hostAddress->isValid()) { + setComponents(node, domain, resource); + return; + } + } + + const auto isAnyOfNonNumericAndNotDot = std::any_of(std::begin(domain), std::end(domain), [](char c) {return !::isdigit(c) && c != '.'; }); + const auto isDomainAllNumeric = std::all_of(std::begin(domain), std::end(domain), [](char c) {return ::isdigit(c) ; }); + + //Prevent Windows validating non-dotted integers as OK if it can unpack them + if (!isAnyOfNonNumericAndNotDot && !isDomainAllNumeric) { + auto hostAddress = HostAddress::fromString(domain); + if (hostAddress && hostAddress->isValid()) { + setComponents(node, domain, resource); + return; + } + } + + if (!isAnyOfNonNumericAndNotDot || !idnConverter->getIDNAEncoded(domain)) { + valid_ = false; + return; + } + + try { + node_ = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); + if (domain.back() == '.') { + domain_ = idnConverter->getStringPrepared(domain.substr(0, domain.size() - 1), IDNConverter::NamePrep); + } + else { + domain_ = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep); + } + resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); + } + catch (...) { + valid_ = false; + return; + } + + if (domain_.empty()) { + valid_ = false; + return; + } } std::string JID::toString() const { - std::string string; - if (!node_.empty()) { - string += node_ + "@"; - } - string += domain_; - if (!isBare()) { - string += "/" + resource_; - } - return string; + std::string string; + if (!node_.empty()) { + string += node_ + "@"; + } + string += domain_; + if (!isBare()) { + string += "/" + resource_; + } + return string; } int JID::compare(const Swift::JID& o, CompareType compareType) const { - if (node_ < o.node_) { return -1; } - if (node_ > o.node_) { return 1; } - if (domain_ < o.domain_) { return -1; } - if (domain_ > o.domain_) { return 1; } - if (compareType == WithResource) { - if (hasResource_ != o.hasResource_) { - return hasResource_ ? 1 : -1; - } - if (resource_ < o.resource_) { return -1; } - if (resource_ > o.resource_) { return 1; } - } - return 0; + if (node_ < o.node_) { return -1; } + if (node_ > o.node_) { return 1; } + if (domain_ < o.domain_) { return -1; } + if (domain_ > o.domain_) { return 1; } + if (compareType == WithResource) { + if (hasResource_ != o.hasResource_) { + return hasResource_ ? 1 : -1; + } + if (resource_ < o.resource_) { return -1; } + if (resource_ > o.resource_) { return 1; } + } + return 0; } std::string JID::getEscapedNode(const std::string& node) { - std::string result; - for (std::string::const_iterator i = node.begin(); i != node.end(); ++i) { - if (std::find(escapedChars.begin(), escapedChars.end(), *i) != escapedChars.end()) { - result += getEscaped(*i); - continue; - } - else if (*i == '\\') { - // Check if we have an escaped dissalowed character sequence - std::string::const_iterator innerBegin = i + 1; - if (innerBegin != node.end() && innerBegin + 1 != node.end()) { - std::string::const_iterator innerEnd = innerBegin + 2; - unsigned char value; - if (getEscapeSequenceValue(std::string(innerBegin, innerEnd), value)) { - result += getEscaped(*i); - continue; - } - } - } - result += *i; - } - return result; - //return boost::find_format_all_copy(node, UnescapedCharacterFinder(), UnescapedCharacterFormatter()); + std::string result; + for (std::string::const_iterator i = node.begin(); i != node.end(); ++i) { + if (std::find(escapedChars.begin(), escapedChars.end(), *i) != escapedChars.end()) { + result += getEscaped(*i); + continue; + } + else if (*i == '\\') { + // Check if we have an escaped dissalowed character sequence + std::string::const_iterator innerBegin = i + 1; + if (innerBegin != node.end() && innerBegin + 1 != node.end()) { + std::string::const_iterator innerEnd = innerBegin + 2; + unsigned char value; + if (getEscapeSequenceValue(std::string(innerBegin, innerEnd), value)) { + result += getEscaped(*i); + continue; + } + } + } + result += *i; + } + return result; } - + std::string JID::getUnescapedNode() const { - std::string result; - for (std::string::const_iterator j = node_.begin(); j != node_.end();) { - if (*j == '\\') { - std::string::const_iterator innerEnd = j + 1; - for (size_t i = 0; i < 2 && innerEnd != node_.end(); ++i, ++innerEnd) { - } - unsigned char value; - if (getEscapeSequenceValue(std::string(j + 1, innerEnd), value)) { - result += std::string(reinterpret_cast<const char*>(&value), 1); - j = innerEnd; - continue; - } - } - result += *j; - ++j; - } - return result; - //return boost::find_format_all_copy(node_, EscapedCharacterFinder(), EscapedCharacterFormatter()); + std::string result; + for (std::string::const_iterator j = node_.begin(); j != node_.end();) { + if (*j == '\\') { + std::string::const_iterator innerEnd = j + 1; + for (size_t i = 0; i < 2 && innerEnd != node_.end(); ++i, ++innerEnd) { + } + unsigned char value; + if (getEscapeSequenceValue(std::string(j + 1, innerEnd), value)) { + result += std::string(reinterpret_cast<const char*>(&value), 1); + j = innerEnd; + continue; + } + } + result += *j; + ++j; + } + return result; } void JID::setIDNConverter(IDNConverter* converter) { - idnConverter = converter; + idnConverter = converter; } std::ostream& operator<<(std::ostream& os, const JID& j) { - os << j.toString(); - return os; + os << j.toString(); + return os; } boost::optional<JID> JID::parse(const std::string& s) { - JID jid(s); - return jid.isValid() ? jid : boost::optional<JID>(); + JID jid(s); + return jid.isValid() ? jid : boost::optional<JID>(); } } diff --git a/Swiften/JID/JID.h b/Swiften/JID/JID.h index 126a7b1..aecc7cb 100644 --- a/Swiften/JID/JID.h +++ b/Swiften/JID/JID.h @@ -1,190 +1,204 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <string> #include <iosfwd> +#include <string> + +#include <boost/optional/optional.hpp> #include <Swiften/Base/API.h> -#include <boost/optional/optional_fwd.hpp> namespace Swift { - class IDNConverter; - - /** - * This represents the JID used in XMPP - * (RFC6120 - http://tools.ietf.org/html/rfc6120 ). - * For a description of format, see the RFC or page 14 of - * XMPP: The Definitive Guide (Saint-Andre et al.) - * - * Particularly - a Bare JID is a JID without a resource part. - * - * A JID can be invalid (when isValid() returns false). No member methods are - * guaranteed to work correctly if they do. - */ - class SWIFTEN_API JID { - public: - enum CompareType { - WithResource, WithoutResource - }; - - /** - * Create a JID from its String representation. - * - * e.g. - * wonderland.lit - * wonderland.lit/rabbithole - * alice@wonderland.lit - * alice@wonderland.lit/TeaParty - * - * @param jid String representation. Invalid JID if empty or invalid. - */ - JID(const std::string& jid = std::string()); - - /** - * See std::string constructor. - * - * Must not be NULL. - */ - JID(const char*); - - /** - * Create a bare JID from the node and domain parts. - * - * JID("node@domain") == JID("node", "domain") - * unless you pass in empty values. - * - * @param node JID node part. - * @param domain JID domain part. - */ - JID(const std::string& node, const std::string& domain); - /** - * Create a bare JID from the node, domain and resource parts. - * - * JID("node@domain/resource") == JID("node", "domain", "resource") - * unless you pass in empty values. - * - * @param node JID node part. - * @param domain JID domain part. - * @param resource JID resource part. - */ - JID(const std::string& node, const std::string& domain, const std::string& resource); - - /** - * @return Is a correctly-formatted JID. - */ - bool isValid() const { - return valid_; - } - - /** - * e.g. JID("node@domain").getNode() == "node" - * @return could be empty. - */ - const std::string& getNode() const { - return node_; - } - - /** - * e.g. JID("node@domain").getDomain() == "domain" - */ - const std::string& getDomain() const { - return domain_; - } - - /** - * e.g. JID("node@domain/resource").getResource() == "resource" - * @return could be empty. - */ - const std::string& getResource() const { - return resource_; - } - - /** - * Is a bare JID, i.e. has no resource part. - */ - bool isBare() const { - return !hasResource_; - } - - /** - * Returns the given node, escaped according to XEP-0106. - * The resulting node is a valid node for a JID, whereas the input value can contain characters - * that are not allowed. - */ - static std::string getEscapedNode(const std::string& node); - - /** - * Returns the node of the current JID, unescaped according to XEP-0106. - */ - std::string getUnescapedNode() const; - - /** - * Get the JID without a resource. - * @return Invalid if the original is invalid. - */ - JID toBare() const { - JID result(*this); - result.hasResource_ = false; - result.resource_ = ""; - return result; - } - - std::string toString() const; - - bool equals(const JID& o, CompareType compareType) const { - return compare(o, compareType) == 0; - } - - int compare(const JID& o, CompareType compareType) const; - - operator std::string() const { - return toString(); - } - - bool operator<(const Swift::JID& b) const { - return compare(b, Swift::JID::WithResource) < 0; - } - - SWIFTEN_API friend std::ostream& operator<<(std::ostream& os, const Swift::JID& j); - - friend bool operator==(const Swift::JID& a, const Swift::JID& b) { - return a.compare(b, Swift::JID::WithResource) == 0; - } - - friend bool operator!=(const Swift::JID& a, const Swift::JID& b) { - return a.compare(b, Swift::JID::WithResource) != 0; - } - - /** - * Returns an empty optional if the JID is invalid, and an - * optional with a value if the JID is valid. - */ - static boost::optional<JID> parse(const std::string&); - - /** - * If Swiften was compiled with SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER (not default), use this method at - * the beginning of the program to set an IDN converter to use for JID IDN conversions. - * By default, this method shouldn't be used. - */ - static void setIDNConverter(IDNConverter*); - - private: - void nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource); - void initializeFromString(const std::string&); - - private: - bool valid_; - std::string node_; - std::string domain_; - bool hasResource_; - std::string resource_; - }; - - SWIFTEN_API std::ostream& operator<<(std::ostream& os, const Swift::JID& j); + class IDNConverter; + + /** + * This represents the JID used in XMPP + * (RFC6120 - http://tools.ietf.org/html/rfc6120 ). + * For a description of format, see the RFC or page 14 of + * XMPP: The Definitive Guide (Saint-Andre et al.) + * + * Particularly - a Bare JID is a JID without a resource part. + * + * A JID can be invalid (when isValid() returns false). No member methods are + * guaranteed to work correctly if they do. + */ + class SWIFTEN_API JID { + public: + enum CompareType { + WithResource, WithoutResource + }; + + /** + * Create a JID from its String representation. + * + * e.g. + * wonderland.lit + * wonderland.lit/rabbithole + * alice@wonderland.lit + * alice@wonderland.lit/TeaParty + * + * @param jid String representation. Invalid JID if empty or invalid. + */ + JID(const std::string& jid = std::string()); + + /** + * See std::string constructor. + * + * Must not be NULL. + */ + JID(const char*); + + /** + * Create a bare JID from the node and domain parts. + * + * JID("node@domain") == JID("node", "domain") + * unless you pass in empty values. + * + * @param node JID node part. + * @param domain JID domain part. + */ + JID(const std::string& node, const std::string& domain); + /** + * Create a bare JID from the node, domain and resource parts. + * + * JID("node@domain/resource") == JID("node", "domain", "resource") + * unless you pass in empty values. + * + * @param node JID node part. + * @param domain JID domain part. + * @param resource JID resource part. + */ + JID(const std::string& node, const std::string& domain, const std::string& resource); + + JID(const JID& other); + JID(JID&& other); + JID& operator=(const JID& other); + JID& operator=(JID&& other); + + /** + * @return Is a correctly-formatted JID. + */ + bool isValid() const { + return valid_; + } + + /** + * e.g. JID("node@domain").getNode() == "node" + * @return could be empty. + */ + const std::string& getNode() const { + return node_; + } + + /** + * e.g. JID("node@domain").getDomain() == "domain" + */ + const std::string& getDomain() const { + return domain_; + } + + /** + * e.g. JID("node@domain/resource").getResource() == "resource" + * @return could be empty. + */ + const std::string& getResource() const { + return resource_; + } + + /** + * Is a bare JID, i.e. has no resource part. + */ + bool isBare() const { + return !hasResource_; + } + + /** + * Returns the given node, escaped according to XEP-0106. + * The resulting node is a valid node for a JID, whereas the input value can contain characters + * that are not allowed. + */ + static std::string getEscapedNode(const std::string& node); + + /** + * Returns the node of the current JID, unescaped according to XEP-0106. + */ + std::string getUnescapedNode() const; + + /** + * Get the JID without a resource. + * @return Invalid if the original is invalid. + */ + JID toBare() const { + JID result(*this); + result.hasResource_ = false; + result.resource_ = ""; + return result; + } + + /** + * Get the full JID with the supplied resource. + */ + JID withResource(const std::string& resource) const { + JID result(this->getNode(), this->getDomain(), resource); + return result; + } + + std::string toString() const; + + bool equals(const JID& o, CompareType compareType) const { + return compare(o, compareType) == 0; + } + + int compare(const JID& o, CompareType compareType) const; + + operator std::string() const { + return toString(); + } + + bool operator<(const Swift::JID& b) const { + return compare(b, Swift::JID::WithResource) < 0; + } + + SWIFTEN_API friend std::ostream& operator<<(std::ostream& os, const Swift::JID& j); + + friend bool operator==(const Swift::JID& a, const Swift::JID& b) { + return a.compare(b, Swift::JID::WithResource) == 0; + } + + friend bool operator!=(const Swift::JID& a, const Swift::JID& b) { + return a.compare(b, Swift::JID::WithResource) != 0; + } + + /** + * Returns an empty optional if the JID is invalid, and an + * optional with a value if the JID is valid. + */ + static boost::optional<JID> parse(const std::string&); + + /** + * If Swiften was compiled with SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER (not default), use this method at + * the beginning of the program to set an IDN converter to use for JID IDN conversions. + * By default, this method shouldn't be used. + */ + static void setIDNConverter(IDNConverter*); + + private: + void nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource); + void setComponents(const std::string& node, const std::string& domain, const std::string& resource); + void initializeFromString(const std::string&); + + private: + bool valid_; + std::string node_; + std::string domain_; + bool hasResource_; + std::string resource_; + }; + + SWIFTEN_API std::ostream& operator<<(std::ostream& os, const Swift::JID& j); } - diff --git a/Swiften/JID/SConscript b/Swiften/JID/SConscript index 12565fc..122388e 100644 --- a/Swiften/JID/SConscript +++ b/Swiften/JID/SConscript @@ -2,6 +2,6 @@ Import("swiften_env") myenv = swiften_env.Clone() objects = myenv.SwiftenObject([ - "JID.cpp", - ]) + "JID.cpp", + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/JID/UnitTest/JIDTest.cpp b/Swiften/JID/UnitTest/JIDTest.cpp index 72ca884..fc7583f 100644 --- a/Swiften/JID/UnitTest/JIDTest.cpp +++ b/Swiften/JID/UnitTest/JIDTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,384 +13,536 @@ using namespace Swift; class JIDTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(JIDTest); - CPPUNIT_TEST(testConstructorWithString); - CPPUNIT_TEST(testConstructorWithString_NoResource); - CPPUNIT_TEST(testConstructorWithString_NoNode); - CPPUNIT_TEST(testConstructorWithString_EmptyResource); - CPPUNIT_TEST(testConstructorWithString_OnlyDomain); - CPPUNIT_TEST(testConstructorWithString_UpperCaseNode); - CPPUNIT_TEST(testConstructorWithString_UpperCaseDomain); - CPPUNIT_TEST(testConstructorWithString_UpperCaseResource); - CPPUNIT_TEST(testConstructorWithString_EmptyNode); - CPPUNIT_TEST(testConstructorWithString_IllegalResource); - CPPUNIT_TEST(testConstructorWithString_SpacesInNode); - CPPUNIT_TEST(testConstructorWithStrings); - CPPUNIT_TEST(testConstructorWithStrings_EmptyDomain); - CPPUNIT_TEST(testIsBare); - CPPUNIT_TEST(testIsBare_NotBare); - CPPUNIT_TEST(testToBare); - CPPUNIT_TEST(testToBare_EmptyNode); - CPPUNIT_TEST(testToBare_EmptyResource); - CPPUNIT_TEST(testToString); - CPPUNIT_TEST(testToString_EmptyNode); - CPPUNIT_TEST(testToString_EmptyResource); - CPPUNIT_TEST(testToString_NoResource); - CPPUNIT_TEST(testCompare_SmallerNode); - CPPUNIT_TEST(testCompare_LargerNode); - CPPUNIT_TEST(testCompare_SmallerDomain); - CPPUNIT_TEST(testCompare_LargerDomain); - CPPUNIT_TEST(testCompare_SmallerResource); - CPPUNIT_TEST(testCompare_LargerResource); - CPPUNIT_TEST(testCompare_Equal); - CPPUNIT_TEST(testCompare_EqualWithoutResource); - CPPUNIT_TEST(testCompare_NoResourceAndEmptyResource); - CPPUNIT_TEST(testCompare_EmptyResourceAndNoResource); - CPPUNIT_TEST(testEquals); - CPPUNIT_TEST(testEquals_NotEqual); - CPPUNIT_TEST(testEquals_WithoutResource); - CPPUNIT_TEST(testSmallerThan); - CPPUNIT_TEST(testSmallerThan_Equal); - CPPUNIT_TEST(testSmallerThan_Larger); - CPPUNIT_TEST(testHasResource); - CPPUNIT_TEST(testHasResource_NoResource); - CPPUNIT_TEST(testGetEscapedNode); - CPPUNIT_TEST(testGetEscapedNode_XEP106Examples); - CPPUNIT_TEST(testGetEscapedNode_BackslashAtEnd); - CPPUNIT_TEST(testGetUnescapedNode); - CPPUNIT_TEST(testGetUnescapedNode_XEP106Examples); - CPPUNIT_TEST_SUITE_END(); - - public: - JIDTest() {} - - void testConstructorWithString() { - JID testling("foo@bar/baz"); - - CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); - CPPUNIT_ASSERT_EQUAL(std::string("baz"), testling.getResource()); - CPPUNIT_ASSERT(!testling.isBare()); - } - - void testConstructorWithString_NoResource() { - JID testling("foo@bar"); - - CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); - CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getResource()); - CPPUNIT_ASSERT(testling.isBare()); - } - - void testConstructorWithString_EmptyResource() { - JID testling("bar/"); - - CPPUNIT_ASSERT(testling.isValid()); - CPPUNIT_ASSERT(!testling.isBare()); - } - - void testConstructorWithString_NoNode() { - JID testling("bar/baz"); - - CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); - CPPUNIT_ASSERT_EQUAL(std::string("baz"), testling.getResource()); - CPPUNIT_ASSERT(!testling.isBare()); - } - - void testConstructorWithString_OnlyDomain() { - JID testling("bar"); - - CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); - CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getResource()); - CPPUNIT_ASSERT(testling.isBare()); - } - - void testConstructorWithString_UpperCaseNode() { - JID testling("Fo\xCE\xA9@bar"); - - CPPUNIT_ASSERT_EQUAL(std::string("fo\xCF\x89"), testling.getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); - } - - void testConstructorWithString_UpperCaseDomain() { - JID testling("Fo\xCE\xA9"); - - CPPUNIT_ASSERT_EQUAL(std::string("fo\xCF\x89"), testling.getDomain()); - } - - void testConstructorWithString_UpperCaseResource() { - JID testling("bar/Fo\xCE\xA9"); - - CPPUNIT_ASSERT_EQUAL(testling.getResource(), std::string("Fo\xCE\xA9")); - } - - void testConstructorWithString_EmptyNode() { - JID testling("@bar"); - - CPPUNIT_ASSERT(!testling.isValid()); - } - - void testConstructorWithString_IllegalResource() { - JID testling("foo@bar.com/\xd8\xb1\xd9\x85\xd9\x82\xd9\x87\x20\xd8\xaa\xd8\xb1\xd9\x86\xd8\xb3\x20"); - - CPPUNIT_ASSERT(!testling.isValid()); - } - - void testConstructorWithString_SpacesInNode() { - CPPUNIT_ASSERT(!JID(" alice@wonderland.lit").isValid()); - CPPUNIT_ASSERT(!JID("alice @wonderland.lit").isValid()); - } - - void testConstructorWithStrings() { - JID testling("foo", "bar", "baz"); + CPPUNIT_TEST_SUITE(JIDTest); + CPPUNIT_TEST(testConstructorWithString); + CPPUNIT_TEST(testConstructorWithString_Empty); + CPPUNIT_TEST(testConstructorWithString_NoResource); + CPPUNIT_TEST(testConstructorWithString_NoNode); + CPPUNIT_TEST(testConstructorWithString_EmptyResource); + CPPUNIT_TEST(testConstructorWithString_OnlyDomain); + CPPUNIT_TEST(testConstructorWithString_OnlyDomainWithDot); + CPPUNIT_TEST(testConstructorWithString_OnlyDomainDotStrippedOff); + CPPUNIT_TEST(testConstructorWithString_InvalidOnlyDomainSingleDot); + CPPUNIT_TEST(testConstructorWithString_InvalidDomain); + CPPUNIT_TEST(testConstructorWithString_InvalidDomainOnlyDigits); + CPPUNIT_TEST(testConstructorWithString_InvalidDomainEmptyLabel); + CPPUNIT_TEST(testConstructorWithString_UpperCaseNode); + CPPUNIT_TEST(testConstructorWithString_UpperCaseDomain); + CPPUNIT_TEST(testConstructorWithString_UpperCaseResource); + CPPUNIT_TEST(testConstructorWithString_EmptyNode); + CPPUNIT_TEST(testConstructorWithString_EmptyDomain); + CPPUNIT_TEST(testConstructorWithString_EmptyDomainWithResource); + CPPUNIT_TEST(testConstructorWithString_DotDomain); + CPPUNIT_TEST(testConstructorWithString_DotDomainWithResource); + CPPUNIT_TEST(testConstructorWithString_IllegalResource); + CPPUNIT_TEST(testConstructorWithString_SpacesInNode); + CPPUNIT_TEST(testConstructorWithStrings); + CPPUNIT_TEST(testConstructorWithStrings_EmptyDomain); + CPPUNIT_TEST(testConstructorWithStrings_EmptyResource); + CPPUNIT_TEST(testIsBare); + CPPUNIT_TEST(testIsBare_NotBare); + CPPUNIT_TEST(testToBare); + CPPUNIT_TEST(testToBare_EmptyNode); + CPPUNIT_TEST(testToBare_EmptyResource); + CPPUNIT_TEST(testToString); + CPPUNIT_TEST(testToString_EmptyNode); + CPPUNIT_TEST(testToString_EmptyResource); + CPPUNIT_TEST(testToString_NoResource); + CPPUNIT_TEST(testCompare_SmallerNode); + CPPUNIT_TEST(testCompare_LargerNode); + CPPUNIT_TEST(testCompare_SmallerDomain); + CPPUNIT_TEST(testCompare_LargerDomain); + CPPUNIT_TEST(testCompare_SmallerResource); + CPPUNIT_TEST(testCompare_LargerResource); + CPPUNIT_TEST(testCompare_Equal); + CPPUNIT_TEST(testCompare_EqualWithoutResource); + CPPUNIT_TEST(testCompare_NoResourceAndEmptyResource); + CPPUNIT_TEST(testCompare_EmptyResourceAndNoResource); + CPPUNIT_TEST(testEquals); + CPPUNIT_TEST(testEquals_NotEqual); + CPPUNIT_TEST(testEquals_WithoutResource); + CPPUNIT_TEST(testSmallerThan); + CPPUNIT_TEST(testSmallerThan_Equal); + CPPUNIT_TEST(testSmallerThan_Larger); + CPPUNIT_TEST(testHasResource); + CPPUNIT_TEST(testHasResource_NoResource); + CPPUNIT_TEST(testGetEscapedNode); + CPPUNIT_TEST(testGetEscapedNode_XEP106Examples); + CPPUNIT_TEST(testGetEscapedNode_BackslashAtEnd); + CPPUNIT_TEST(testGetUnescapedNode); + CPPUNIT_TEST(testGetUnescapedNode_XEP106Examples); + CPPUNIT_TEST(testStringPrepFailures); + CPPUNIT_TEST(testConstructorWithString_DomainIPv4); + CPPUNIT_TEST(testConstructorWithString_DomainNOTIPv4); + CPPUNIT_TEST(testConstructorWithString_ValidDomainNOTIPv4); + CPPUNIT_TEST(testConstructorWithString_DomainIPv6); + CPPUNIT_TEST(testConstructorWithString_DomainInvalidIPv6); + CPPUNIT_TEST(testConstructorWithString_DomainIPv6NoBrackets); + CPPUNIT_TEST_SUITE_END(); + + public: + JIDTest() {} + + void testConstructorWithString() { + JID testling("foo@bar/baz"); + + CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("baz"), testling.getResource()); + CPPUNIT_ASSERT(!testling.isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_Empty() { + JID testling(""); + CPPUNIT_ASSERT_EQUAL(false, testling.isValid()); + } + + void testConstructorWithString_NoResource() { + JID testling("foo@bar"); + + CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getResource()); + CPPUNIT_ASSERT(testling.isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_EmptyResource() { + JID testling("bar/"); + + CPPUNIT_ASSERT(!testling.isValid()); + CPPUNIT_ASSERT(!testling.isBare()); + } + + void testConstructorWithString_NoNode() { + JID testling("bar/baz"); + + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("baz"), testling.getResource()); + CPPUNIT_ASSERT(!testling.isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_OnlyDomain() { + JID testling("bar"); + + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getResource()); + CPPUNIT_ASSERT(testling.isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_OnlyDomainWithDot() { + JID testling("bar."); + + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getResource()); + CPPUNIT_ASSERT(testling.isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_OnlyDomainDotStrippedOff() { + JID testling("foo.@bar./resource."); + + CPPUNIT_ASSERT_EQUAL(std::string("foo."), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("resource."), testling.getResource()); + CPPUNIT_ASSERT(!testling.isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_InvalidOnlyDomainSingleDot() { + CPPUNIT_ASSERT(!JID(".").isValid()); + } + + void testConstructorWithString_InvalidDomain() { + CPPUNIT_ASSERT(!JID("foo@bar,baz").isValid()); + } + + void testConstructorWithString_InvalidDomainOnlyDigits() { + CPPUNIT_ASSERT(!JID("1234").isValid()); + } + + void testConstructorWithString_InvalidDomainEmptyLabel() { + CPPUNIT_ASSERT(!JID("foo@bar..").isValid()); + } + + void testConstructorWithString_UpperCaseNode() { + JID testling("Fo\xCE\xA9@bar"); - CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); - CPPUNIT_ASSERT_EQUAL(std::string("baz"), testling.getResource()); - } + CPPUNIT_ASSERT_EQUAL(std::string("fo\xCF\x89"), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); + CPPUNIT_ASSERT(testling.isValid()); + } - void testConstructorWithStrings_EmptyDomain() { - JID testling("foo", "", "baz"); + void testConstructorWithString_UpperCaseDomain() { + JID testling("Fo\xCE\xA9"); - CPPUNIT_ASSERT(!testling.isValid()); - } + CPPUNIT_ASSERT_EQUAL(std::string("fo\xCF\x89"), testling.getDomain()); + CPPUNIT_ASSERT(testling.isValid()); + } - void testIsBare() { - CPPUNIT_ASSERT(JID("foo@bar").isBare()); - } + void testConstructorWithString_UpperCaseResource() { + JID testling("bar/Fo\xCE\xA9"); - void testIsBare_NotBare() { - CPPUNIT_ASSERT(!JID("foo@bar/baz").isBare()); - } + CPPUNIT_ASSERT_EQUAL(testling.getResource(), std::string("Fo\xCE\xA9")); + CPPUNIT_ASSERT(testling.isValid()); + } - void testToBare() { - JID testling("foo@bar/baz"); + void testConstructorWithString_EmptyNode() { + JID testling("@bar"); - CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.toBare().getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.toBare().getDomain()); - CPPUNIT_ASSERT(testling.toBare().isBare()); - } + CPPUNIT_ASSERT(!testling.isValid()); + } - void testToBare_EmptyNode() { - JID testling("bar/baz"); + void testConstructorWithString_EmptyDomain() { + JID testling("bar@"); - CPPUNIT_ASSERT_EQUAL(std::string(""), testling.toBare().getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.toBare().getDomain()); - CPPUNIT_ASSERT(testling.toBare().isBare()); - } + CPPUNIT_ASSERT(!testling.isValid()); + } - void testToBare_EmptyResource() { - JID testling("bar/"); + void testStringPrepFailures() { + CPPUNIT_ASSERT_EQUAL(false, JID("foo@bar", "example.com").isValid()); + CPPUNIT_ASSERT_EQUAL(false, JID("foo^", "example*com").isValid()); + CPPUNIT_ASSERT_EQUAL(false, JID("foobar", "example^com").isValid()); + } - CPPUNIT_ASSERT_EQUAL(std::string(""), testling.toBare().getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.toBare().getDomain()); - CPPUNIT_ASSERT(testling.toBare().isBare()); - } + void testConstructorWithString_EmptyDomainWithResource() { + JID testling("bar@/resource"); - void testToString() { - JID testling("foo@bar/baz"); + CPPUNIT_ASSERT(!testling.isValid()); + } - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar/baz"), testling.toString()); - } + void testConstructorWithString_DotDomain() { + JID testling("bar@."); - void testToString_EmptyNode() { - JID testling("bar/baz"); + CPPUNIT_ASSERT(!testling.isValid()); + } - CPPUNIT_ASSERT_EQUAL(std::string("bar/baz"), testling.toString()); - } + void testConstructorWithString_DotDomainWithResource() { + JID testling("bar@./resource"); - void testToString_NoResource() { - JID testling("foo@bar"); + CPPUNIT_ASSERT(!testling.isValid()); + } - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), testling.toString()); - } + void testConstructorWithString_IllegalResource() { + JID testling("foo@bar.com/\xd8\xb1\xd9\x85\xd9\x82\xd9\x87\x20\xd8\xaa\xd8\xb1\xd9\x86\xd8\xb3\x20"); - void testToString_EmptyResource() { - JID testling("foo@bar/"); + CPPUNIT_ASSERT(!testling.isValid()); + } - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar/"), testling.toString()); - } + void testConstructorWithString_SpacesInNode() { + CPPUNIT_ASSERT(!JID(" alice@wonderland.lit").isValid()); + CPPUNIT_ASSERT(!JID("alice @wonderland.lit").isValid()); + } - void testCompare_SmallerNode() { - JID testling1("a@c"); - JID testling2("b@b"); + void testConstructorWithStrings() { + JID testling("foo", "bar", "baz"); - CPPUNIT_ASSERT_EQUAL(-1, testling1.compare(testling2, JID::WithResource)); - } + CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("baz"), testling.getResource()); + CPPUNIT_ASSERT(testling.isValid()); + } - void testCompare_LargerNode() { - JID testling1("c@a"); - JID testling2("b@b"); + void testConstructorWithStrings_EmptyDomain() { + JID testling("foo", "", "baz"); - CPPUNIT_ASSERT_EQUAL(1, testling1.compare(testling2, JID::WithResource)); - } + CPPUNIT_ASSERT(!testling.isValid()); + } - void testCompare_SmallerDomain() { - JID testling1("x@a/c"); - JID testling2("x@b/b"); + void testConstructorWithStrings_EmptyResource() { + JID testling("foo", "bar", ""); - CPPUNIT_ASSERT_EQUAL(-1, testling1.compare(testling2, JID::WithResource)); - } + CPPUNIT_ASSERT(!testling.isValid()); + } - void testCompare_LargerDomain() { - JID testling1("x@b/b"); - JID testling2("x@a/c"); + void testIsBare() { + CPPUNIT_ASSERT(JID("foo@bar").isBare()); + } - CPPUNIT_ASSERT_EQUAL(1, testling1.compare(testling2, JID::WithResource)); - } + void testIsBare_NotBare() { + CPPUNIT_ASSERT(!JID("foo@bar/baz").isBare()); + } - void testCompare_SmallerResource() { - JID testling1("x@y/a"); - JID testling2("x@y/b"); + void testToBare() { + JID testling("foo@bar/baz"); - CPPUNIT_ASSERT_EQUAL(-1, testling1.compare(testling2, JID::WithResource)); - } + CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.toBare().getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.toBare().getDomain()); + CPPUNIT_ASSERT(testling.toBare().isBare()); + } - void testCompare_LargerResource() { - JID testling1("x@y/b"); - JID testling2("x@y/a"); + void testToBare_EmptyNode() { + JID testling("bar/baz"); - CPPUNIT_ASSERT_EQUAL(1, testling1.compare(testling2, JID::WithResource)); - } + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.toBare().getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.toBare().getDomain()); + CPPUNIT_ASSERT(testling.toBare().isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } - void testCompare_Equal() { - JID testling1("x@y/z"); - JID testling2("x@y/z"); + void testToBare_EmptyResource() { + JID testling("bar/"); - CPPUNIT_ASSERT_EQUAL(0, testling1.compare(testling2, JID::WithResource)); - } + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.toBare().getNode()); + CPPUNIT_ASSERT(!testling.isValid()); + } - void testCompare_EqualWithoutResource() { - JID testling1("x@y/a"); - JID testling2("x@y/b"); + void testToString() { + JID testling("foo@bar/baz"); - CPPUNIT_ASSERT_EQUAL(0, testling1.compare(testling2, JID::WithoutResource)); - } + CPPUNIT_ASSERT_EQUAL(std::string("foo@bar/baz"), testling.toString()); + } - void testCompare_NoResourceAndEmptyResource() { - JID testling1("x@y/"); - JID testling2("x@y"); + void testToString_EmptyNode() { + JID testling("bar/baz"); - CPPUNIT_ASSERT_EQUAL(1, testling1.compare(testling2, JID::WithResource)); - } + CPPUNIT_ASSERT_EQUAL(std::string("bar/baz"), testling.toString()); + } - void testCompare_EmptyResourceAndNoResource() { - JID testling1("x@y"); - JID testling2("x@y/"); + void testToString_NoResource() { + JID testling("foo@bar"); - CPPUNIT_ASSERT_EQUAL(-1, testling1.compare(testling2, JID::WithResource)); - } + CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), testling.toString()); + } - void testEquals() { - JID testling1("x@y/c"); - JID testling2("x@y/c"); + void testToString_EmptyResource() { + JID testling("foo@bar/"); - CPPUNIT_ASSERT(testling1.equals(testling2, JID::WithResource)); - } - - void testEquals_NotEqual() { - JID testling1("x@y/c"); - JID testling2("x@y/d"); - - CPPUNIT_ASSERT(!testling1.equals(testling2, JID::WithResource)); - } - - void testEquals_WithoutResource() { - JID testling1("x@y/c"); - JID testling2("x@y/d"); - - CPPUNIT_ASSERT(testling1.equals(testling2, JID::WithoutResource)); - } - - void testSmallerThan() { - JID testling1("x@y/c"); - JID testling2("x@y/d"); - - CPPUNIT_ASSERT(testling1 < testling2); - } - - void testSmallerThan_Equal() { - JID testling1("x@y/d"); - JID testling2("x@y/d"); - - CPPUNIT_ASSERT(!(testling1 < testling2)); - } - - void testSmallerThan_Larger() { - JID testling1("x@y/d"); - JID testling2("x@y/c"); - - CPPUNIT_ASSERT(!(testling1 < testling2)); - } - - void testHasResource() { - JID testling("x@y/d"); - - CPPUNIT_ASSERT(!testling.isBare()); - } - - void testHasResource_NoResource() { - JID testling("x@y"); - - CPPUNIT_ASSERT(testling.isBare()); - } - - void testGetEscapedNode() { - std::string escaped = JID::getEscapedNode("alice@wonderland.lit"); - CPPUNIT_ASSERT_EQUAL(std::string("alice\\40wonderland.lit"), escaped); - - escaped = JID::getEscapedNode("\\& \" ' / <\\\\> @ :\\3a\\40"); - CPPUNIT_ASSERT_EQUAL(std::string("\\\\26\\20\\22\\20\\27\\20\\2f\\20\\3c\\\\\\3e\\20\\40\\20\\3a\\5c3a\\5c40"), escaped); - } - - void testGetEscapedNode_XEP106Examples() { - CPPUNIT_ASSERT_EQUAL(std::string("\\2plus\\2is\\4"), JID::getEscapedNode("\\2plus\\2is\\4")); - CPPUNIT_ASSERT_EQUAL(std::string("foo\\bar"), JID::getEscapedNode("foo\\bar")); - CPPUNIT_ASSERT_EQUAL(std::string("foob\\41r"), JID::getEscapedNode("foob\\41r")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("space cadet"), std::string("space\\20cadet")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("call me \"ishmael\""), std::string("call\\20me\\20\\22ishmael\\22")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("at&t guy"), std::string("at\\26t\\20guy")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("d'artagnan"), std::string("d\\27artagnan")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("/.fanboy"), std::string("\\2f.fanboy")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("::foo::"), std::string("\\3a\\3afoo\\3a\\3a")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("<foo>"), std::string("\\3cfoo\\3e")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("user@host"), std::string("user\\40host")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\net"), std::string("c\\3a\\net")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\\\net"), std::string("c\\3a\\\\net")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\cool stuff"), std::string("c\\3a\\cool\\20stuff")); - CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\5commas"), std::string("c\\3a\\5c5commas")); - } - - void testGetEscapedNode_BackslashAtEnd() { - CPPUNIT_ASSERT_EQUAL(std::string("foo\\"), JID::getEscapedNode("foo\\")); - } - - void testGetUnescapedNode() { - std::string input = "\\& \" ' / <\\\\> @ : \\5c\\40"; - JID testling(JID::getEscapedNode(input) + "@y"); - CPPUNIT_ASSERT(testling.isValid()); - CPPUNIT_ASSERT_EQUAL(input, testling.getUnescapedNode()); - } - - void testGetUnescapedNode_XEP106Examples() { - CPPUNIT_ASSERT_EQUAL(std::string("\\2plus\\2is\\4"), JID("\\2plus\\2is\\4@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("foo\\bar"), JID("foo\\bar@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("foob\\41r"), JID("foob\\41r@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("space cadet"), JID("space\\20cadet@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("call me \"ishmael\""), JID("call\\20me\\20\\22ishmael\\22@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("at&t guy"), JID("at\\26t\\20guy@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("d'artagnan"), JID("d\\27artagnan@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("/.fanboy"), JID("\\2f.fanboy@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("::foo::"), JID("\\3a\\3afoo\\3a\\3a@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("<foo>"), JID("\\3cfoo\\3e@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("user@host"), JID("user\\40host@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("c:\\net"), JID("c\\3a\\net@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("c:\\\\net"), JID("c\\3a\\\\net@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("c:\\cool stuff"), JID("c\\3a\\cool\\20stuff@example.com").getUnescapedNode()); - CPPUNIT_ASSERT_EQUAL(std::string("c:\\5commas"), JID("c\\3a\\5c5commas@example.com").getUnescapedNode()); - } + CPPUNIT_ASSERT_EQUAL(false, testling.isValid()); + } + + void testCompare_SmallerNode() { + JID testling1("a@c"); + JID testling2("b@b"); + + CPPUNIT_ASSERT_EQUAL(-1, testling1.compare(testling2, JID::WithResource)); + } + + void testCompare_LargerNode() { + JID testling1("c@a"); + JID testling2("b@b"); + + CPPUNIT_ASSERT_EQUAL(1, testling1.compare(testling2, JID::WithResource)); + } + + void testCompare_SmallerDomain() { + JID testling1("x@a/c"); + JID testling2("x@b/b"); + + CPPUNIT_ASSERT_EQUAL(-1, testling1.compare(testling2, JID::WithResource)); + } + + void testCompare_LargerDomain() { + JID testling1("x@b/b"); + JID testling2("x@a/c"); + + CPPUNIT_ASSERT_EQUAL(1, testling1.compare(testling2, JID::WithResource)); + } + + void testCompare_SmallerResource() { + JID testling1("x@y/a"); + JID testling2("x@y/b"); + + CPPUNIT_ASSERT_EQUAL(-1, testling1.compare(testling2, JID::WithResource)); + } + + void testCompare_LargerResource() { + JID testling1("x@y/b"); + JID testling2("x@y/a"); + + CPPUNIT_ASSERT_EQUAL(1, testling1.compare(testling2, JID::WithResource)); + } + + void testCompare_Equal() { + JID testling1("x@y/z"); + JID testling2("x@y/z"); + + CPPUNIT_ASSERT_EQUAL(0, testling1.compare(testling2, JID::WithResource)); + } + + void testCompare_EqualWithoutResource() { + JID testling1("x@y/a"); + JID testling2("x@y/b"); + + CPPUNIT_ASSERT_EQUAL(0, testling1.compare(testling2, JID::WithoutResource)); + } + + void testCompare_NoResourceAndEmptyResource() { + JID testling1("x@y/"); + JID testling2("x@y"); + + CPPUNIT_ASSERT_EQUAL(-1, testling1.compare(testling2, JID::WithResource)); + } + + void testCompare_EmptyResourceAndNoResource() { + JID testling1("x@y"); + JID testling2("x@y/"); + + CPPUNIT_ASSERT_EQUAL(1, testling1.compare(testling2, JID::WithResource)); + } + + void testEquals() { + JID testling1("x@y/c"); + JID testling2("x@y/c"); + + CPPUNIT_ASSERT(testling1.equals(testling2, JID::WithResource)); + } + + void testEquals_NotEqual() { + JID testling1("x@y/c"); + JID testling2("x@y/d"); + + CPPUNIT_ASSERT(!testling1.equals(testling2, JID::WithResource)); + } + + void testEquals_WithoutResource() { + JID testling1("x@y/c"); + JID testling2("x@y/d"); + + CPPUNIT_ASSERT(testling1.equals(testling2, JID::WithoutResource)); + } + + void testSmallerThan() { + JID testling1("x@y/c"); + JID testling2("x@y/d"); + + CPPUNIT_ASSERT(testling1 < testling2); + } + + void testSmallerThan_Equal() { + JID testling1("x@y/d"); + JID testling2("x@y/d"); + + CPPUNIT_ASSERT(!(testling1 < testling2)); + } + + void testSmallerThan_Larger() { + JID testling1("x@y/d"); + JID testling2("x@y/c"); + + CPPUNIT_ASSERT(!(testling1 < testling2)); + } + + void testHasResource() { + JID testling("x@y/d"); + + CPPUNIT_ASSERT(!testling.isBare()); + } + + void testHasResource_NoResource() { + { + JID testling("x@y"); + + CPPUNIT_ASSERT(testling.isBare()); + CPPUNIT_ASSERT_EQUAL(true, testling.isValid()); + } + + { + JID testling("node@domain/"); + CPPUNIT_ASSERT_EQUAL(false, testling.isValid()); + } + } + + void testGetEscapedNode() { + std::string escaped = JID::getEscapedNode("alice@wonderland.lit"); + CPPUNIT_ASSERT_EQUAL(std::string("alice\\40wonderland.lit"), escaped); + + escaped = JID::getEscapedNode("\\& \" ' / <\\\\> @ :\\3a\\40"); + CPPUNIT_ASSERT_EQUAL(std::string("\\\\26\\20\\22\\20\\27\\20\\2f\\20\\3c\\\\\\3e\\20\\40\\20\\3a\\5c3a\\5c40"), escaped); + } + + void testGetEscapedNode_XEP106Examples() { + CPPUNIT_ASSERT_EQUAL(std::string("\\2plus\\2is\\4"), JID::getEscapedNode("\\2plus\\2is\\4")); + CPPUNIT_ASSERT_EQUAL(std::string("foo\\bar"), JID::getEscapedNode("foo\\bar")); + CPPUNIT_ASSERT_EQUAL(std::string("foob\\41r"), JID::getEscapedNode("foob\\41r")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("space cadet"), std::string("space\\20cadet")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("call me \"ishmael\""), std::string("call\\20me\\20\\22ishmael\\22")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("at&t guy"), std::string("at\\26t\\20guy")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("d'artagnan"), std::string("d\\27artagnan")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("/.fanboy"), std::string("\\2f.fanboy")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("::foo::"), std::string("\\3a\\3afoo\\3a\\3a")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("<foo>"), std::string("\\3cfoo\\3e")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("user@host"), std::string("user\\40host")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\net"), std::string("c\\3a\\net")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\\\net"), std::string("c\\3a\\\\net")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\cool stuff"), std::string("c\\3a\\cool\\20stuff")); + CPPUNIT_ASSERT_EQUAL(JID::getEscapedNode("c:\\5commas"), std::string("c\\3a\\5c5commas")); + } + + void testGetEscapedNode_BackslashAtEnd() { + CPPUNIT_ASSERT_EQUAL(std::string("foo\\"), JID::getEscapedNode("foo\\")); + } + + void testGetUnescapedNode() { + std::string input = "\\& \" ' / <\\\\> @ : \\5c\\40"; + JID testling(JID::getEscapedNode(input) + "@y"); + CPPUNIT_ASSERT(testling.isValid()); + CPPUNIT_ASSERT_EQUAL(input, testling.getUnescapedNode()); + } + + void testGetUnescapedNode_XEP106Examples() { + CPPUNIT_ASSERT_EQUAL(std::string("\\2plus\\2is\\4"), JID("\\2plus\\2is\\4@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("foo\\bar"), JID("foo\\bar@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("foob\\41r"), JID("foob\\41r@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("space cadet"), JID("space\\20cadet@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("call me \"ishmael\""), JID("call\\20me\\20\\22ishmael\\22@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("at&t guy"), JID("at\\26t\\20guy@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("d'artagnan"), JID("d\\27artagnan@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("/.fanboy"), JID("\\2f.fanboy@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("::foo::"), JID("\\3a\\3afoo\\3a\\3a@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("<foo>"), JID("\\3cfoo\\3e@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("user@host"), JID("user\\40host@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("c:\\net"), JID("c\\3a\\net@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("c:\\\\net"), JID("c\\3a\\\\net@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("c:\\cool stuff"), JID("c\\3a\\cool\\20stuff@example.com").getUnescapedNode()); + CPPUNIT_ASSERT_EQUAL(std::string("c:\\5commas"), JID("c\\3a\\5c5commas@example.com").getUnescapedNode()); + } + + void testConstructorWithString_DomainIPv4() { + JID testling("foo@192.34.12.1/resource"); + + CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("192.34.12.1"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("resource"), testling.getResource()); + CPPUNIT_ASSERT(!testling.isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_DomainNOTIPv4() { + JID testling("foo@500.34.12.1/resource"); + CPPUNIT_ASSERT(!testling.isValid()); + } + + void testConstructorWithString_ValidDomainNOTIPv4() { + JID testling("foo@500.34.12.1a/resource"); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_DomainIPv6() { + JID testling("foo@[fe80::a857:33ff:febd:3580]/resource"); + + CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("[fe80::a857:33ff:febd:3580]"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("resource"), testling.getResource()); + CPPUNIT_ASSERT(!testling.isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_DomainInvalidIPv6() { + JID testling("foo@[1111::a1111:1111:111!:!!!!]/resource"); + CPPUNIT_ASSERT(!testling.isValid()); + } + + void testConstructorWithString_DomainIPv6NoBrackets() { + JID testling("foo@fe80::a857:33ff:febd:3580/resource"); + CPPUNIT_ASSERT(!testling.isValid()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(JIDTest); diff --git a/Swiften/Jingle/AbstractJingleSessionListener.cpp b/Swiften/Jingle/AbstractJingleSessionListener.cpp index eaa1a47..56d2e92 100644 --- a/Swiften/Jingle/AbstractJingleSessionListener.cpp +++ b/Swiften/Jingle/AbstractJingleSessionListener.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2019 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -10,32 +10,32 @@ using namespace Swift; -void AbstractJingleSessionListener::handleSessionAcceptReceived(const JingleContentID&, boost::shared_ptr<JingleDescription>, boost::shared_ptr<JingleTransportPayload>) { - SWIFT_LOG(warning) << "Unimplemented" << std::endl; +void AbstractJingleSessionListener::handleSessionAcceptReceived(const JingleContentID&, std::shared_ptr<JingleDescription>, std::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(warning) << "Unimplemented"; } -void AbstractJingleSessionListener::handleSessionInfoReceived(boost::shared_ptr<JinglePayload>) { - SWIFT_LOG(warning) << "Unimplemented" << std::endl; +void AbstractJingleSessionListener::handleSessionInfoReceived(std::shared_ptr<JinglePayload>) { + SWIFT_LOG(warning) << "Unimplemented"; } void AbstractJingleSessionListener::handleSessionTerminateReceived(boost::optional<JinglePayload::Reason>) { - SWIFT_LOG(warning) << "Unimplemented" << std::endl; + SWIFT_LOG(warning) << "Unimplemented"; } -void AbstractJingleSessionListener::handleTransportAcceptReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) { - SWIFT_LOG(warning) << "Unimplemented" << std::endl; +void AbstractJingleSessionListener::handleTransportAcceptReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(warning) << "Unimplemented"; } -void AbstractJingleSessionListener::handleTransportInfoReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) { - SWIFT_LOG(warning) << "Unimplemented" << std::endl; +void AbstractJingleSessionListener::handleTransportInfoReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(warning) << "Unimplemented"; } -void AbstractJingleSessionListener::handleTransportRejectReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) { - SWIFT_LOG(warning) << "Unimplemented" << std::endl; +void AbstractJingleSessionListener::handleTransportRejectReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(warning) << "Unimplemented"; } -void AbstractJingleSessionListener::handleTransportReplaceReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) { - SWIFT_LOG(warning) << "Unimplemented" << std::endl; +void AbstractJingleSessionListener::handleTransportReplaceReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(warning) << "Unimplemented"; } void AbstractJingleSessionListener::handleTransportInfoAcknowledged(const std::string&) { diff --git a/Swiften/Jingle/AbstractJingleSessionListener.h b/Swiften/Jingle/AbstractJingleSessionListener.h index 4f76675..dd8bd1e 100644 --- a/Swiften/Jingle/AbstractJingleSessionListener.h +++ b/Swiften/Jingle/AbstractJingleSessionListener.h @@ -1,26 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Base/Override.h> #include <Swiften/Jingle/JingleSessionListener.h> namespace Swift { - class SWIFTEN_API AbstractJingleSessionListener : public JingleSessionListener { - public: - virtual void handleSessionAcceptReceived(const JingleContentID&, boost::shared_ptr<JingleDescription>, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; - virtual void handleSessionInfoReceived(boost::shared_ptr<JinglePayload>) SWIFTEN_OVERRIDE; - virtual void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason>) SWIFTEN_OVERRIDE; - virtual void handleTransportAcceptReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; - virtual void handleTransportInfoReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; - virtual void handleTransportRejectReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; - virtual void handleTransportReplaceReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; - virtual void handleTransportInfoAcknowledged(const std::string& id) SWIFTEN_OVERRIDE; - }; + class SWIFTEN_API AbstractJingleSessionListener : public JingleSessionListener { + public: + virtual void handleSessionAcceptReceived(const JingleContentID&, std::shared_ptr<JingleDescription>, std::shared_ptr<JingleTransportPayload>) override; + virtual void handleSessionInfoReceived(std::shared_ptr<JinglePayload>) override; + virtual void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason>) override; + virtual void handleTransportAcceptReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>) override; + virtual void handleTransportInfoReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>) override; + virtual void handleTransportRejectReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>) override; + virtual void handleTransportReplaceReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>) override; + virtual void handleTransportInfoAcknowledged(const std::string& id) override; + }; } diff --git a/Swiften/Jingle/FakeJingleSession.cpp b/Swiften/Jingle/FakeJingleSession.cpp index 1df106a..6b88477 100644 --- a/Swiften/Jingle/FakeJingleSession.cpp +++ b/Swiften/Jingle/FakeJingleSession.cpp @@ -4,9 +4,17 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Jingle/FakeJingleSession.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + +#include <Swiften/Jingle/JingleSessionListener.h> namespace Swift { @@ -18,36 +26,56 @@ FakeJingleSession::~FakeJingleSession() { } void FakeJingleSession::sendInitiate(const JingleContentID& id, JingleDescription::ref desc, JingleTransportPayload::ref payload) { - calledCommands.push_back(InitiateCall(id, desc, payload)); + calledCommands.push_back(InitiateCall(id, desc, payload)); } void FakeJingleSession::sendTerminate(JinglePayload::Reason::Type reason) { - calledCommands.push_back(TerminateCall(reason)); + calledCommands.push_back(TerminateCall(reason)); } -void FakeJingleSession::sendInfo(boost::shared_ptr<Payload> payload) { - calledCommands.push_back(InfoCall(payload)); +void FakeJingleSession::sendInfo(std::shared_ptr<Payload> payload) { + calledCommands.push_back(InfoCall(payload)); } void FakeJingleSession::sendAccept(const JingleContentID& id, JingleDescription::ref desc, JingleTransportPayload::ref payload) { - calledCommands.push_back(AcceptCall(id, desc, payload)); + calledCommands.push_back(AcceptCall(id, desc, payload)); } std::string FakeJingleSession::sendTransportInfo(const JingleContentID& id, JingleTransportPayload::ref payload) { - calledCommands.push_back(InfoTransportCall(id, payload)); - return idGenerator.generateID(); + calledCommands.push_back(InfoTransportCall(id, payload)); + return idGenerator.generateID(); } void FakeJingleSession::sendTransportAccept(const JingleContentID& id, JingleTransportPayload::ref payload) { - calledCommands.push_back(AcceptTransportCall(id, payload)); + calledCommands.push_back(AcceptTransportCall(id, payload)); } void FakeJingleSession::sendTransportReject(const JingleContentID& id, JingleTransportPayload::ref payload) { - calledCommands.push_back(RejectTransportCall(id, payload)); + calledCommands.push_back(RejectTransportCall(id, payload)); } void FakeJingleSession::sendTransportReplace(const JingleContentID& id, JingleTransportPayload::ref payload) { - calledCommands.push_back(ReplaceTransportCall(id, payload)); + calledCommands.push_back(ReplaceTransportCall(id, payload)); +} + +void FakeJingleSession::handleTransportReplaceReceived(const JingleContentID& contentID, JingleTransportPayload::ref transport) { + notifyListeners(&JingleSessionListener::handleTransportReplaceReceived, contentID, transport); +} + +void FakeJingleSession::handleTransportAcceptReceived(const JingleContentID& contentID, JingleTransportPayload::ref transport) { + notifyListeners(&JingleSessionListener::handleTransportAcceptReceived, contentID, transport); +} + +void FakeJingleSession::handleTransportInfoReceived(const JingleContentID& contentID, JingleTransportPayload::ref transport) { + notifyListeners(&JingleSessionListener::handleTransportInfoReceived, contentID, transport); +} + +void FakeJingleSession::handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason) { + notifyListeners(&JingleSessionListener::handleSessionTerminateReceived, reason); +} + +void FakeJingleSession::handleSessionAcceptReceived(const JingleContentID& contentID, std::shared_ptr<JingleDescription> desc, std::shared_ptr<JingleTransportPayload> payload) { + notifyListeners(&JingleSessionListener::handleSessionAcceptReceived, contentID, desc, payload); } } diff --git a/Swiften/Jingle/FakeJingleSession.h b/Swiften/Jingle/FakeJingleSession.h index 651ac5f..0ed97d5 100644 --- a/Swiften/Jingle/FakeJingleSession.h +++ b/Swiften/Jingle/FakeJingleSession.h @@ -5,99 +5,109 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> #include <vector> + +#include <boost/signals2.hpp> #include <boost/variant.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/SimpleIDGenerator.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Base/Override.h> -#include <Swiften/JID/JID.h> #include <Swiften/Elements/JinglePayload.h> -#include <Swiften/Jingle/JingleSession.h> +#include <Swiften/JID/JID.h> #include <Swiften/Jingle/JingleContentID.h> +#include <Swiften/Jingle/JingleSession.h> namespace Swift { - class JingleContentID; - - class SWIFTEN_API FakeJingleSession : public JingleSession { - public: - struct InitiateCall { - InitiateCall(JingleContentID contentId, JingleDescription::ref desc, JingleTransportPayload::ref payL) : id(contentId), description(desc), payload(payL) {} - JingleContentID id; - JingleDescription::ref description; - JingleTransportPayload::ref payload; - }; - - struct TerminateCall { - TerminateCall(JinglePayload::Reason::Type r) : reason(r) {} - JinglePayload::Reason::Type reason; - }; - - struct InfoCall { - InfoCall(boost::shared_ptr<Payload> info) : payload(info) {} - boost::shared_ptr<Payload> payload; - }; - - struct AcceptCall { - AcceptCall(JingleContentID contentId, JingleDescription::ref desc, JingleTransportPayload::ref payL) : id(contentId), description(desc), payload(payL) {} - JingleContentID id; - JingleDescription::ref description; - JingleTransportPayload::ref payload; - }; - - struct InfoTransportCall { - InfoTransportCall(JingleContentID contentId, JingleTransportPayload::ref payL) : id(contentId), payload(payL) {} - JingleContentID id; - JingleTransportPayload::ref payload; - }; - - struct AcceptTransportCall { - AcceptTransportCall(JingleContentID contentId, JingleTransportPayload::ref payL) : id(contentId), payload(payL) {} - JingleContentID id; - JingleTransportPayload::ref payload; - }; - - struct RejectTransportCall { - RejectTransportCall(JingleContentID contentId, JingleTransportPayload::ref payL) : id(contentId), payload(payL) {} - JingleContentID id; - JingleTransportPayload::ref payload; - }; - - struct ReplaceTransportCall { - ReplaceTransportCall(JingleContentID contentId, JingleTransportPayload::ref payL) : id(contentId), payload(payL) {} - JingleContentID id; - JingleTransportPayload::ref payload; - }; - - typedef boost::variant<InitiateCall, TerminateCall, AcceptCall, InfoCall, InfoTransportCall, AcceptTransportCall, RejectTransportCall, ReplaceTransportCall> Command; - - public: - typedef boost::shared_ptr<FakeJingleSession> ref; - - FakeJingleSession(const JID& initiator, const std::string& id); - virtual ~FakeJingleSession(); - - virtual void sendInitiate(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref) SWIFTEN_OVERRIDE; - virtual void sendTerminate(JinglePayload::Reason::Type reason) SWIFTEN_OVERRIDE; - virtual void sendInfo(boost::shared_ptr<Payload>) SWIFTEN_OVERRIDE; - virtual void sendAccept(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref = JingleTransportPayload::ref()) SWIFTEN_OVERRIDE; - virtual std::string sendTransportInfo(const JingleContentID&, JingleTransportPayload::ref) SWIFTEN_OVERRIDE; - virtual void sendTransportAccept(const JingleContentID&, JingleTransportPayload::ref) SWIFTEN_OVERRIDE; - virtual void sendTransportReject(const JingleContentID&, JingleTransportPayload::ref) SWIFTEN_OVERRIDE; - virtual void sendTransportReplace(const JingleContentID&, JingleTransportPayload::ref) SWIFTEN_OVERRIDE; - - public: - std::vector<Command> calledCommands; - SimpleIDGenerator idGenerator; - }; + class JingleContentID; + + class SWIFTEN_API FakeJingleSession : public JingleSession { + public: + struct InitiateCall { + InitiateCall(JingleContentID contentId, JingleDescription::ref desc, JingleTransportPayload::ref payL) : id(contentId), description(desc), payload(payL) {} + JingleContentID id; + JingleDescription::ref description; + JingleTransportPayload::ref payload; + }; + + struct TerminateCall { + TerminateCall(JinglePayload::Reason::Type r) : reason(r) {} + JinglePayload::Reason::Type reason; + }; + + struct InfoCall { + InfoCall(std::shared_ptr<Payload> info) : payload(info) {} + std::shared_ptr<Payload> payload; + }; + + struct AcceptCall { + AcceptCall(JingleContentID contentId, JingleDescription::ref desc, JingleTransportPayload::ref payL) : id(contentId), description(desc), payload(payL) {} + JingleContentID id; + JingleDescription::ref description; + JingleTransportPayload::ref payload; + }; + + struct InfoTransportCall { + InfoTransportCall(JingleContentID contentId, JingleTransportPayload::ref payL) : id(contentId), payload(payL) {} + JingleContentID id; + JingleTransportPayload::ref payload; + }; + + struct AcceptTransportCall { + AcceptTransportCall(JingleContentID contentId, JingleTransportPayload::ref payL) : id(contentId), payload(payL) {} + JingleContentID id; + JingleTransportPayload::ref payload; + }; + + struct RejectTransportCall { + RejectTransportCall(JingleContentID contentId, JingleTransportPayload::ref payL) : id(contentId), payload(payL) {} + JingleContentID id; + JingleTransportPayload::ref payload; + }; + + struct ReplaceTransportCall { + ReplaceTransportCall(JingleContentID contentId, JingleTransportPayload::ref payL) : id(contentId), payload(payL) {} + JingleContentID id; + JingleTransportPayload::ref payload; + }; + + typedef boost::variant<InitiateCall, TerminateCall, AcceptCall, InfoCall, InfoTransportCall, AcceptTransportCall, RejectTransportCall, ReplaceTransportCall> Command; + + public: + typedef std::shared_ptr<FakeJingleSession> ref; + + FakeJingleSession(const JID& initiator, const std::string& id); + virtual ~FakeJingleSession() override; + + virtual void sendInitiate(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref) override; + virtual void sendTerminate(JinglePayload::Reason::Type reason) override; + virtual void sendInfo(std::shared_ptr<Payload>) override; + virtual void sendAccept(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref = JingleTransportPayload::ref()) override; + virtual std::string sendTransportInfo(const JingleContentID&, JingleTransportPayload::ref) override; + virtual void sendTransportAccept(const JingleContentID&, JingleTransportPayload::ref) override; + virtual void sendTransportReject(const JingleContentID&, JingleTransportPayload::ref) override; + virtual void sendTransportReplace(const JingleContentID&, JingleTransportPayload::ref) override; + + void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason>); + void handleSessionAcceptReceived(const JingleContentID&, std::shared_ptr<JingleDescription>, std::shared_ptr<JingleTransportPayload>); + void handleSessionInfoReceived(std::shared_ptr<JinglePayload>); + + void handleTransportReplaceReceived(const JingleContentID&, JingleTransportPayload::ref); + void handleTransportAcceptReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>); + void handleTransportInfoReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>); + void handleTransportRejectReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>); + void handleTransportInfoAcknowledged(const std::string& id); + + public: + std::vector<Command> calledCommands; + SimpleIDGenerator idGenerator; + }; } diff --git a/Swiften/Jingle/IncomingJingleSessionHandler.cpp b/Swiften/Jingle/IncomingJingleSessionHandler.cpp index d38118c..8a4c3e4 100644 --- a/Swiften/Jingle/IncomingJingleSessionHandler.cpp +++ b/Swiften/Jingle/IncomingJingleSessionHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Jingle/IncomingJingleSessionHandler.h> diff --git a/Swiften/Jingle/IncomingJingleSessionHandler.h b/Swiften/Jingle/IncomingJingleSessionHandler.h index d23570d..4c30f7c 100644 --- a/Swiften/Jingle/IncomingJingleSessionHandler.h +++ b/Swiften/Jingle/IncomingJingleSessionHandler.h @@ -1,18 +1,19 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Jingle/JingleSession.h> namespace Swift { - class IncomingJingleSessionHandler { - public: - virtual ~IncomingJingleSessionHandler(); + class SWIFTEN_API IncomingJingleSessionHandler { + public: + virtual ~IncomingJingleSessionHandler(); - virtual bool handleIncomingJingleSession(JingleSession::ref, const std::vector<JingleContentPayload::ref>& contents, const JID& recipient) = 0; - }; + virtual bool handleIncomingJingleSession(JingleSession::ref, const std::vector<JingleContentPayload::ref>& contents, const JID& recipient) = 0; + }; } diff --git a/Swiften/Jingle/Jingle.h b/Swiften/Jingle/Jingle.h index ba4dfe3..0cd1a23 100644 --- a/Swiften/Jingle/Jingle.h +++ b/Swiften/Jingle/Jingle.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,15 +11,15 @@ #include <Swiften/Elements/JingleContentPayload.h> namespace Swift { - namespace Jingle { - template<typename T> - JingleContentPayload::ref getContentWithDescription(const std::vector<JingleContentPayload::ref>& contents) { - for (size_t i = 0; i < contents.size(); ++i) { - if (contents[i]->getDescription<T>()) { - return contents[i]; - } - } - return JingleContentPayload::ref(); - } - } + namespace Jingle { + template<typename T> + JingleContentPayload::ref getContentWithDescription(const std::vector<JingleContentPayload::ref>& contents) { + for (const auto& content : contents) { + if (content->getDescription<T>()) { + return content; + } + } + return JingleContentPayload::ref(); + } + } } diff --git a/Swiften/Jingle/JingleContentID.h b/Swiften/Jingle/JingleContentID.h index fc0cc8f..60f412b 100644 --- a/Swiften/Jingle/JingleContentID.h +++ b/Swiften/Jingle/JingleContentID.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleContentPayload.h> namespace Swift { - class JingleContentID { - public: - JingleContentID(const std::string& name, JingleContentPayload::Creator creator) : name(name), creator(creator) { - } - - const std::string getName() const { - return this->name; - } - - JingleContentPayload::Creator getCreator() const { - return this->creator; - } + class SWIFTEN_API JingleContentID { + public: + JingleContentID(const std::string& name, JingleContentPayload::Creator creator) : name(name), creator(creator) { + } - private: - std::string name; - JingleContentPayload::Creator creator; - }; + const std::string getName() const { + return this->name; + } + + JingleContentPayload::Creator getCreator() const { + return this->creator; + } + + private: + std::string name; + JingleContentPayload::Creator creator; + }; } diff --git a/Swiften/Jingle/JingleResponder.cpp b/Swiften/Jingle/JingleResponder.cpp index 4c82f51..af9808e 100644 --- a/Swiften/Jingle/JingleResponder.cpp +++ b/Swiften/Jingle/JingleResponder.cpp @@ -1,17 +1,16 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Jingle/JingleResponder.h> -#include <boost/smart_ptr/make_shared.hpp> - -#include <Swiften/Jingle/JingleSessionManager.h> -#include <Swiften/Jingle/JingleSessionImpl.h> +#include <memory> #include <Swiften/Base/Log.h> +#include <Swiften/Jingle/JingleSessionImpl.h> +#include <Swiften/Jingle/JingleSessionManager.h> namespace Swift { @@ -21,42 +20,42 @@ JingleResponder::JingleResponder(JingleSessionManager* sessionManager, IQRouter* JingleResponder::~JingleResponder() { } -bool JingleResponder::handleSetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<JinglePayload> payload) { - if (payload->getAction() == JinglePayload::SessionInitiate) { - if (sessionManager->getSession(from, payload->getSessionID())) { - // TODO: Add tie-break error - sendError(from, id, ErrorPayload::Conflict, ErrorPayload::Cancel); - } - else { - sendResponse(from, id, boost::shared_ptr<JinglePayload>()); - if (!payload->getInitiator().isBare()) { - JingleSessionImpl::ref session = boost::make_shared<JingleSessionImpl>(payload->getInitiator(), from, payload->getSessionID(), router); - sessionManager->handleIncomingSession(from, to, session, payload->getContents()); - } else { - SWIFT_LOG(debug) << "Unable to create Jingle session due to initiator not being a full JID." << std::endl; - } - } - } - else { - JingleSessionImpl::ref session; - if (payload->getInitiator().isValid()) { - SWIFT_LOG(debug) << "Lookup session by initiator." << std::endl; - session = sessionManager->getSession(payload->getInitiator(), payload->getSessionID()); - } else { - SWIFT_LOG(debug) << "Lookup session by from attribute." << std::endl; - session = sessionManager->getSession(from, payload->getSessionID()); - } - if (session) { - session->handleIncomingAction(payload); - sendResponse(from, id, boost::shared_ptr<JinglePayload>()); - } - else { - std::cerr << "WARN: Didn't find jingle session!" << std::endl; - // TODO: Add jingle-specific error - sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); - } - } - return true; +bool JingleResponder::handleSetRequest(const JID& from, const JID& to, const std::string& id, std::shared_ptr<JinglePayload> payload) { + if (payload->getAction() == JinglePayload::SessionInitiate) { + if (sessionManager->getSession(from, payload->getSessionID())) { + // TODO: Add tie-break error + sendError(from, id, ErrorPayload::Conflict, ErrorPayload::Cancel); + } + else { + sendResponse(from, id, std::shared_ptr<JinglePayload>()); + if (!payload->getInitiator().isBare()) { + JingleSessionImpl::ref session = std::make_shared<JingleSessionImpl>(payload->getInitiator(), from, payload->getSessionID(), router); + sessionManager->handleIncomingSession(from, to, session, payload->getContents()); + } else { + SWIFT_LOG(debug) << "Unable to create Jingle session due to initiator not being a full JID."; + } + } + } + else { + JingleSessionImpl::ref session; + if (payload->getInitiator().isValid()) { + SWIFT_LOG(debug) << "Lookup session by initiator."; + session = sessionManager->getSession(payload->getInitiator(), payload->getSessionID()); + } else { + SWIFT_LOG(debug) << "Lookup session by from attribute."; + session = sessionManager->getSession(from, payload->getSessionID()); + } + if (session) { + session->handleIncomingAction(payload); + sendResponse(from, id, std::shared_ptr<JinglePayload>()); + } + else { + SWIFT_LOG(warning) << "Didn't find jingle session!"; + // TODO: Add jingle-specific error + sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); + } + } + return true; } } diff --git a/Swiften/Jingle/JingleResponder.h b/Swiften/Jingle/JingleResponder.h index 6f4d688..cb9220c 100644 --- a/Swiften/Jingle/JingleResponder.h +++ b/Swiften/Jingle/JingleResponder.h @@ -1,27 +1,28 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Queries/SetResponder.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/JinglePayload.h> +#include <Swiften/Queries/SetResponder.h> namespace Swift { - class IQRouter; - class JingleSessionManager; + class IQRouter; + class JingleSessionManager; - class JingleResponder : public SetResponder<JinglePayload> { - public: - JingleResponder(JingleSessionManager* sessionManager, IQRouter* router); - virtual ~JingleResponder(); - private: - virtual bool handleSetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<JinglePayload> payload); + class SWIFTEN_API JingleResponder : public SetResponder<JinglePayload> { + public: + JingleResponder(JingleSessionManager* sessionManager, IQRouter* router); + virtual ~JingleResponder(); + private: + virtual bool handleSetRequest(const JID& from, const JID& to, const std::string& id, std::shared_ptr<JinglePayload> payload); - private: - JingleSessionManager* sessionManager; - IQRouter* router; - }; + private: + JingleSessionManager* sessionManager; + IQRouter* router; + }; } diff --git a/Swiften/Jingle/JingleSession.cpp b/Swiften/Jingle/JingleSession.cpp index 7e09014..b5cfbef 100644 --- a/Swiften/Jingle/JingleSession.cpp +++ b/Swiften/Jingle/JingleSession.cpp @@ -1,23 +1,23 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Jingle/JingleSession.h> -#include <boost/smart_ptr/make_shared.hpp> #include <algorithm> -#include <boost/function.hpp> +#include <cassert> +#include <memory> -#include <Swiften/Base/foreach.h> +#include <boost/function.hpp> using namespace Swift; JingleSession::JingleSession(const JID& initiator, const std::string& id) : initiator(initiator), id(id) { - // initiator must always be a full JID; session lookup based on it wouldn't work otherwise - // this is checked on an upper level so that the assert never fails - assert(!initiator.isBare()); + // initiator must always be a full JID; session lookup based on it wouldn't work otherwise + // this is checked on an upper level so that the assert never fails + assert(!initiator.isBare()); } JingleSession::~JingleSession() { diff --git a/Swiften/Jingle/JingleSession.h b/Swiften/Jingle/JingleSession.h index 8307311..22e6901 100644 --- a/Swiften/Jingle/JingleSession.h +++ b/Swiften/Jingle/JingleSession.h @@ -1,52 +1,54 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <string> #include <vector> -#include <boost/shared_ptr.hpp> + #include <boost/optional.hpp> +#include <boost/signals2.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Base/Listenable.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/JID/JID.h> #include <Swiften/Elements/JinglePayload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class JingleSessionListener; - class JingleContentID; - - class JingleSession : public Listenable<JingleSessionListener> { - public: - typedef boost::shared_ptr<JingleSession> ref; - - JingleSession(const JID& initiator, const std::string& id); - virtual ~JingleSession(); - - const JID& getInitiator() const { - return initiator; - } - - const std::string& getID() const { - return id; - } - - virtual void sendInitiate(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref) = 0; - virtual void sendTerminate(JinglePayload::Reason::Type reason) = 0; - virtual void sendInfo(boost::shared_ptr<Payload>) = 0; - virtual void sendAccept(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref = JingleTransportPayload::ref()) = 0; - virtual std::string sendTransportInfo(const JingleContentID&, JingleTransportPayload::ref) = 0; - virtual void sendTransportAccept(const JingleContentID&, JingleTransportPayload::ref) = 0; - virtual void sendTransportReject(const JingleContentID&, JingleTransportPayload::ref) = 0; - virtual void sendTransportReplace(const JingleContentID&, JingleTransportPayload::ref) = 0; - - private: - JID initiator; - std::string id; - std::vector<JingleSessionListener*> listeners; - }; + class JingleSessionListener; + class JingleContentID; + + class SWIFTEN_API JingleSession : public Listenable<JingleSessionListener> { + public: + typedef std::shared_ptr<JingleSession> ref; + + JingleSession(const JID& initiator, const std::string& id); + virtual ~JingleSession(); + + const JID& getInitiator() const { + return initiator; + } + + const std::string& getID() const { + return id; + } + + virtual void sendInitiate(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref) = 0; + virtual void sendTerminate(JinglePayload::Reason::Type reason) = 0; + virtual void sendInfo(std::shared_ptr<Payload>) = 0; + virtual void sendAccept(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref = JingleTransportPayload::ref()) = 0; + virtual std::string sendTransportInfo(const JingleContentID&, JingleTransportPayload::ref) = 0; + virtual void sendTransportAccept(const JingleContentID&, JingleTransportPayload::ref) = 0; + virtual void sendTransportReject(const JingleContentID&, JingleTransportPayload::ref) = 0; + virtual void sendTransportReplace(const JingleContentID&, JingleTransportPayload::ref) = 0; + + private: + JID initiator; + std::string id; + std::vector<JingleSessionListener*> listeners; + }; } diff --git a/Swiften/Jingle/JingleSessionImpl.cpp b/Swiften/Jingle/JingleSessionImpl.cpp index ff22d11..b4c5d03 100644 --- a/Swiften/Jingle/JingleSessionImpl.cpp +++ b/Swiften/Jingle/JingleSessionImpl.cpp @@ -1,199 +1,207 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Jingle/JingleSessionImpl.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/bind.hpp> #include <algorithm> +#include <memory> -#include <Swiften/Parser/PayloadParsers/JingleParser.h> +#include <boost/bind.hpp> + +#include <Swiften/Base/Log.h> +#include <Swiften/Elements/JingleContentPayload.h> #include <Swiften/Jingle/JingleContentID.h> #include <Swiften/Jingle/JingleSessionListener.h> -#include <Swiften/Elements/JingleContentPayload.h> -#include <Swiften/Queries/Request.h> +#include <Swiften/Parser/PayloadParsers/JingleParser.h> #include <Swiften/Queries/GenericRequest.h> - -#include <Swiften/Base/Log.h> - +#include <Swiften/Queries/Request.h> #include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h> namespace Swift { JingleSessionImpl::JingleSessionImpl(const JID& initiator, const JID& peerJID, const std::string& id, IQRouter* router) : JingleSession(initiator, id), iqRouter(router), peerJID(peerJID) { - SWIFT_LOG(debug) << "initiator: " << initiator << ", peerJID: " << peerJID << std::endl; + SWIFT_LOG(debug) << "initiator: " << initiator << ", peerJID: " << peerJID; } void JingleSessionImpl::handleIncomingAction(JinglePayload::ref action) { - if (action->getAction() == JinglePayload::SessionTerminate) { - notifyListeners(&JingleSessionListener::handleSessionTerminateReceived, action->getReason()); - return; - } - if (action->getAction() == JinglePayload::SessionInfo) { - notifyListeners(&JingleSessionListener::handleSessionInfoReceived, action); - return; - } - - JingleContentPayload::ref content = action->getPayload<JingleContentPayload>(); - if (!content) { - SWIFT_LOG(debug) << "no content payload!" << std::endl; - return; - } - JingleContentID contentID(content->getName(), content->getCreator()); - JingleDescription::ref description = content->getDescriptions().empty() ? JingleDescription::ref() : content->getDescriptions()[0]; - JingleTransportPayload::ref transport = content->getTransports().empty() ? JingleTransportPayload::ref() : content->getTransports()[0]; - switch(action->getAction()) { - case JinglePayload::SessionAccept: - notifyListeners(&JingleSessionListener::handleSessionAcceptReceived, contentID, description, transport); - return; - case JinglePayload::TransportAccept: - notifyListeners(&JingleSessionListener::handleTransportAcceptReceived, contentID, transport); - return; - case JinglePayload::TransportInfo: - notifyListeners(&JingleSessionListener::handleTransportInfoReceived, contentID, transport); - return; - case JinglePayload::TransportReject: - notifyListeners(&JingleSessionListener::handleTransportRejectReceived, contentID, transport); - return; - case JinglePayload::TransportReplace: - notifyListeners(&JingleSessionListener::handleTransportReplaceReceived, contentID, transport); - return; - // following unused Jingle actions - case JinglePayload::ContentAccept: - case JinglePayload::ContentAdd: - case JinglePayload::ContentModify: - case JinglePayload::ContentReject: - case JinglePayload::ContentRemove: - case JinglePayload::DescriptionInfo: - case JinglePayload::SecurityInfo: - - // handled elsewhere - case JinglePayload::SessionInitiate: - case JinglePayload::SessionInfo: - case JinglePayload::SessionTerminate: - - case JinglePayload::UnknownAction: - return; - } - assert(false); + if (action->getAction() == JinglePayload::SessionTerminate) { + notifyListeners(&JingleSessionListener::handleSessionTerminateReceived, action->getReason()); + return; + } + if (action->getAction() == JinglePayload::SessionInfo) { + notifyListeners(&JingleSessionListener::handleSessionInfoReceived, action); + return; + } + + JingleContentPayload::ref content = action->getPayload<JingleContentPayload>(); + if (!content) { + SWIFT_LOG(debug) << "no content payload!"; + return; + } + JingleContentID contentID(content->getName(), content->getCreator()); + JingleDescription::ref description = content->getDescriptions().empty() ? JingleDescription::ref() : content->getDescriptions()[0]; + JingleTransportPayload::ref transport = content->getTransports().empty() ? JingleTransportPayload::ref() : content->getTransports()[0]; + switch(action->getAction()) { + case JinglePayload::SessionAccept: + notifyListeners(&JingleSessionListener::handleSessionAcceptReceived, contentID, description, transport); + return; + case JinglePayload::TransportAccept: + notifyListeners(&JingleSessionListener::handleTransportAcceptReceived, contentID, transport); + return; + case JinglePayload::TransportInfo: + notifyListeners(&JingleSessionListener::handleTransportInfoReceived, contentID, transport); + return; + case JinglePayload::TransportReject: + notifyListeners(&JingleSessionListener::handleTransportRejectReceived, contentID, transport); + return; + case JinglePayload::TransportReplace: + notifyListeners(&JingleSessionListener::handleTransportReplaceReceived, contentID, transport); + return; + // following unused Jingle actions + case JinglePayload::ContentAccept: + case JinglePayload::ContentAdd: + case JinglePayload::ContentModify: + case JinglePayload::ContentReject: + case JinglePayload::ContentRemove: + case JinglePayload::DescriptionInfo: + case JinglePayload::SecurityInfo: + + // handled elsewhere + case JinglePayload::SessionInitiate: + case JinglePayload::SessionInfo: + case JinglePayload::SessionTerminate: + + case JinglePayload::UnknownAction: + return; + } + assert(false); } void JingleSessionImpl::sendInitiate(const JingleContentID& id, JingleDescription::ref description, JingleTransportPayload::ref transport) { - JinglePayload::ref payload = boost::make_shared<JinglePayload>(JinglePayload::SessionInitiate, getID()); - payload->setInitiator(getInitiator()); - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(id.getCreator()); - content->setName(id.getName()); - content->addDescription(description); - content->addTransport(transport); - payload->addPayload(content); - - sendSetRequest(payload); + JinglePayload::ref payload = std::make_shared<JinglePayload>(JinglePayload::SessionInitiate, getID()); + payload->setInitiator(getInitiator()); + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(id.getCreator()); + content->setName(id.getName()); + content->addDescription(description); + content->addTransport(transport); + payload->addPayload(content); + + sendSetRequest(payload); } void JingleSessionImpl::sendTerminate(JinglePayload::Reason::Type reason) { - JinglePayload::ref payload = boost::make_shared<JinglePayload>(JinglePayload::SessionTerminate, getID()); - payload->setReason(JinglePayload::Reason(reason)); - payload->setInitiator(getInitiator()); - sendSetRequest(payload); + JinglePayload::ref payload = std::make_shared<JinglePayload>(JinglePayload::SessionTerminate, getID()); + payload->setReason(JinglePayload::Reason(reason)); + payload->setInitiator(getInitiator()); + sendSetRequest(payload); } -void JingleSessionImpl::sendInfo(boost::shared_ptr<Payload> info) { - JinglePayload::ref payload = boost::make_shared<JinglePayload>(JinglePayload::SessionInfo, getID()); - payload->addPayload(info); +void JingleSessionImpl::sendInfo(std::shared_ptr<Payload> info) { + JinglePayload::ref payload = std::make_shared<JinglePayload>(JinglePayload::SessionInfo, getID()); + payload->addPayload(info); - sendSetRequest(payload); + sendSetRequest(payload); } void JingleSessionImpl::sendAccept(const JingleContentID& id, JingleDescription::ref description, JingleTransportPayload::ref transPayload) { - JinglePayload::ref payload = createPayload(); - - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(id.getCreator()); - content->setName(id.getName()); - content->addTransport(transPayload); - content->addDescription(description); - payload->setAction(JinglePayload::SessionAccept); - payload->addPayload(content); - - // put into IQ:set and send it away - sendSetRequest(payload); + JinglePayload::ref payload = createPayload(); + + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(id.getCreator()); + content->setName(id.getName()); + content->addTransport(transPayload); + content->addDescription(description); + payload->setAction(JinglePayload::SessionAccept); + payload->addPayload(content); + + // put into IQ:set and send it away + sendSetRequest(payload); } void JingleSessionImpl::sendTransportAccept(const JingleContentID& id, JingleTransportPayload::ref transPayload) { - JinglePayload::ref payload = createPayload(); + JinglePayload::ref payload = createPayload(); - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(id.getCreator()); - content->setName(id.getName()); - content->addTransport(transPayload); - payload->setAction(JinglePayload::TransportAccept); - payload->addPayload(content); + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(id.getCreator()); + content->setName(id.getName()); + content->addTransport(transPayload); + payload->setAction(JinglePayload::TransportAccept); + payload->addPayload(content); - // put into IQ:set and send it away - sendSetRequest(payload); + // put into IQ:set and send it away + sendSetRequest(payload); } std::string JingleSessionImpl::sendTransportInfo(const JingleContentID& id, JingleTransportPayload::ref transPayload) { - JinglePayload::ref payload = createPayload(); + JinglePayload::ref payload = createPayload(); - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(id.getCreator()); - content->setName(id.getName()); - content->addTransport(transPayload); - payload->setAction(JinglePayload::TransportInfo); - payload->addPayload(content); + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(id.getCreator()); + content->setName(id.getName()); + content->addTransport(transPayload); + payload->setAction(JinglePayload::TransportInfo); + payload->addPayload(content); - return sendSetRequest(payload); + return sendSetRequest(payload); } -void JingleSessionImpl::sendTransportReject(const JingleContentID& /* id */, JingleTransportPayload::ref /* transPayload */) { - SWIFT_LOG(debug) << "NOT IMPLEMENTED YET!!!!" << std::endl; +void JingleSessionImpl::sendTransportReject(const JingleContentID& id, JingleTransportPayload::ref transPayload) { + JinglePayload::ref payload = createPayload(); + + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(id.getCreator()); + content->setName(id.getName()); + content->addTransport(transPayload); + payload->setAction(JinglePayload::TransportReject); + payload->addPayload(content); + + sendSetRequest(payload); } void JingleSessionImpl::sendTransportReplace(const JingleContentID& id, JingleTransportPayload::ref transPayload) { - JinglePayload::ref payload = createPayload(); + JinglePayload::ref payload = createPayload(); - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(id.getCreator()); - content->setName(id.getName()); - content->addTransport(transPayload); - payload->setAction(JinglePayload::TransportReplace); - payload->addContent(content); + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(id.getCreator()); + content->setName(id.getName()); + content->addTransport(transPayload); + payload->setAction(JinglePayload::TransportReplace); + payload->addContent(content); - sendSetRequest(payload); + sendSetRequest(payload); } std::string JingleSessionImpl::sendSetRequest(JinglePayload::ref payload) { - boost::shared_ptr<GenericRequest<JinglePayload> > request = boost::make_shared<GenericRequest<JinglePayload> >( - IQ::Set, peerJID, payload, iqRouter); - pendingRequests.insert(std::make_pair( - request, - request->onResponse.connect(boost::bind(&JingleSessionImpl::handleRequestResponse, this, request)))); - return request->send(); + std::shared_ptr<GenericRequest<JinglePayload> > request = std::make_shared<GenericRequest<JinglePayload> >( + IQ::Set, peerJID, payload, iqRouter); + pendingRequests.insert(std::make_pair( + request, + request->onResponse.connect(boost::bind(&JingleSessionImpl::handleRequestResponse, this, request)))); + return request->send(); } JinglePayload::ref JingleSessionImpl::createPayload() const { - JinglePayload::ref payload = boost::make_shared<JinglePayload>(); - payload->setSessionID(getID()); - payload->setInitiator(getInitiator()); - return payload; + JinglePayload::ref payload = std::make_shared<JinglePayload>(); + payload->setSessionID(getID()); + payload->setInitiator(getInitiator()); + return payload; } void JingleSessionImpl::handleRequestResponse(RequestRef request) { - RequestsMap::iterator i = pendingRequests.find(request); - assert(i != pendingRequests.end()); - if (i->first->getPayloadGeneric()->getAction() == JinglePayload::TransportInfo) { - notifyListeners(&JingleSessionListener::handleTransportInfoAcknowledged, i->first->getID()); - } - i->second.disconnect(); - pendingRequests.erase(i); + RequestsMap::iterator i = pendingRequests.find(request); + assert(i != pendingRequests.end()); + if (i->first->getPayloadGeneric()->getAction() == JinglePayload::TransportInfo) { + notifyListeners(&JingleSessionListener::handleTransportInfoAcknowledged, i->first->getID()); + } + i->second.disconnect(); + pendingRequests.erase(i); } diff --git a/Swiften/Jingle/JingleSessionImpl.h b/Swiften/Jingle/JingleSessionImpl.h index b7f4a55..ae2458c 100644 --- a/Swiften/Jingle/JingleSessionImpl.h +++ b/Swiften/Jingle/JingleSessionImpl.h @@ -1,50 +1,49 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> #include <map> +#include <memory> #include <Swiften/Jingle/JingleSession.h> #include <Swiften/Queries/GenericRequest.h> namespace Swift { - class IQRouter; - class Request; - - class JingleSessionImpl : public JingleSession { - friend class JingleResponder; - public: - typedef boost::shared_ptr<JingleSessionImpl> ref; - - JingleSessionImpl(const JID& initiator, const JID&, const std::string& id, IQRouter* router); - - virtual void sendInitiate(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref); - virtual void sendTerminate(JinglePayload::Reason::Type reason); - virtual void sendInfo(boost::shared_ptr<Payload>); - virtual void sendAccept(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref); - virtual std::string sendTransportInfo(const JingleContentID&, JingleTransportPayload::ref); - virtual void sendTransportAccept(const JingleContentID&, JingleTransportPayload::ref); - virtual void sendTransportReject(const JingleContentID&, JingleTransportPayload::ref); - virtual void sendTransportReplace(const JingleContentID&, JingleTransportPayload::ref); - - private: - typedef boost::shared_ptr<GenericRequest<JinglePayload> > RequestRef; - - void handleIncomingAction(JinglePayload::ref); - - std::string sendSetRequest(JinglePayload::ref payload); - JinglePayload::ref createPayload() const; - void handleRequestResponse(RequestRef); - - private: - IQRouter *iqRouter; - JID peerJID; - typedef std::map<RequestRef, boost::bsignals::connection > RequestsMap; - RequestsMap pendingRequests; - }; + class IQRouter; + + class JingleSessionImpl : public JingleSession { + friend class JingleResponder; + public: + typedef std::shared_ptr<JingleSessionImpl> ref; + + JingleSessionImpl(const JID& initiator, const JID&, const std::string& id, IQRouter* router); + + virtual void sendInitiate(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref); + virtual void sendTerminate(JinglePayload::Reason::Type reason); + virtual void sendInfo(std::shared_ptr<Payload>); + virtual void sendAccept(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref); + virtual std::string sendTransportInfo(const JingleContentID&, JingleTransportPayload::ref); + virtual void sendTransportAccept(const JingleContentID&, JingleTransportPayload::ref); + virtual void sendTransportReject(const JingleContentID&, JingleTransportPayload::ref); + virtual void sendTransportReplace(const JingleContentID&, JingleTransportPayload::ref); + + private: + typedef std::shared_ptr<GenericRequest<JinglePayload> > RequestRef; + + void handleIncomingAction(JinglePayload::ref); + + std::string sendSetRequest(JinglePayload::ref payload); + JinglePayload::ref createPayload() const; + void handleRequestResponse(RequestRef); + + private: + IQRouter *iqRouter; + JID peerJID; + typedef std::map<RequestRef, boost::signals2::connection > RequestsMap; + RequestsMap pendingRequests; + }; } diff --git a/Swiften/Jingle/JingleSessionListener.cpp b/Swiften/Jingle/JingleSessionListener.cpp index 75d3be9..540480c 100644 --- a/Swiften/Jingle/JingleSessionListener.cpp +++ b/Swiften/Jingle/JingleSessionListener.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Jingle/JingleSessionListener.h b/Swiften/Jingle/JingleSessionListener.h index e1270c4..7c015f0 100644 --- a/Swiften/Jingle/JingleSessionListener.h +++ b/Swiften/Jingle/JingleSessionListener.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -10,31 +10,31 @@ #include <Swiften/Elements/JinglePayload.h> namespace Swift { - class JingleContentID; - class JingleTransportPayload; - class JingleDescription; + class JingleContentID; + class JingleTransportPayload; + class JingleDescription; - class SWIFTEN_API JingleSessionListener { - public: - virtual ~JingleSessionListener(); + class SWIFTEN_API JingleSessionListener { + public: + virtual ~JingleSessionListener(); - virtual void handleSessionAcceptReceived( - const JingleContentID&, - boost::shared_ptr<JingleDescription>, - boost::shared_ptr<JingleTransportPayload>) = 0; - virtual void handleSessionInfoReceived(boost::shared_ptr<JinglePayload>) = 0; - virtual void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason>) = 0; - virtual void handleTransportAcceptReceived( - const JingleContentID&, - boost::shared_ptr<JingleTransportPayload>) = 0; - virtual void handleTransportInfoReceived( - const JingleContentID&, - boost::shared_ptr<JingleTransportPayload>) = 0; - virtual void handleTransportRejectReceived( - const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) = 0; - virtual void handleTransportReplaceReceived( - const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) = 0; + virtual void handleSessionAcceptReceived( + const JingleContentID&, + std::shared_ptr<JingleDescription>, + std::shared_ptr<JingleTransportPayload>) = 0; + virtual void handleSessionInfoReceived(std::shared_ptr<JinglePayload>) = 0; + virtual void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason>) = 0; + virtual void handleTransportAcceptReceived( + const JingleContentID&, + std::shared_ptr<JingleTransportPayload>) = 0; + virtual void handleTransportInfoReceived( + const JingleContentID&, + std::shared_ptr<JingleTransportPayload>) = 0; + virtual void handleTransportRejectReceived( + const JingleContentID&, std::shared_ptr<JingleTransportPayload>) = 0; + virtual void handleTransportReplaceReceived( + const JingleContentID&, std::shared_ptr<JingleTransportPayload>) = 0; - virtual void handleTransportInfoAcknowledged(const std::string& id) = 0; - }; + virtual void handleTransportInfoAcknowledged(const std::string& id) = 0; + }; } diff --git a/Swiften/Jingle/JingleSessionManager.cpp b/Swiften/Jingle/JingleSessionManager.cpp index f31ddb8..083554a 100644 --- a/Swiften/Jingle/JingleSessionManager.cpp +++ b/Swiften/Jingle/JingleSessionManager.cpp @@ -1,54 +1,54 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Jingle/JingleSessionManager.h> -#include <Swiften/Jingle/JingleResponder.h> -#include <Swiften/Jingle/IncomingJingleSessionHandler.h> -#include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> + #include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/Log.h> +#include <Swiften/Jingle/IncomingJingleSessionHandler.h> +#include <Swiften/Jingle/JingleResponder.h> namespace Swift { JingleSessionManager::JingleSessionManager(IQRouter* router) : router(router) { - responder = new JingleResponder(this, router); - responder->start(); + responder = new JingleResponder(this, router); + responder->start(); } JingleSessionManager::~JingleSessionManager() { - responder->stop(); - delete responder; + responder->stop(); + delete responder; } JingleSessionImpl::ref JingleSessionManager::getSession(const JID& jid, const std::string& id) const { - SessionMap::const_iterator i = sessions.find(JIDSession(jid, id)); - return i != sessions.end() ? i->second : JingleSessionImpl::ref(); + SessionMap::const_iterator i = sessions.find(JIDSession(jid, id)); + return i != sessions.end() ? i->second : JingleSessionImpl::ref(); } void JingleSessionManager::addIncomingSessionHandler(IncomingJingleSessionHandler* handler) { - incomingSessionHandlers.push_back(handler); + incomingSessionHandlers.push_back(handler); } void JingleSessionManager::removeIncomingSessionHandler(IncomingJingleSessionHandler* handler) { - erase(incomingSessionHandlers, handler); + erase(incomingSessionHandlers, handler); } void JingleSessionManager::registerOutgoingSession(const JID& initiator, JingleSessionImpl::ref session) { - sessions.insert(std::make_pair(JIDSession(initiator, session->getID()), session)); - SWIFT_LOG(debug) << "Added session " << session->getID() << " for initiator " << initiator.toString() << std::endl; + sessions.insert(std::make_pair(JIDSession(initiator, session->getID()), session)); + SWIFT_LOG(debug) << "Added session " << session->getID() << " for initiator " << initiator.toString(); } void JingleSessionManager::handleIncomingSession(const JID& initiator, const JID& recipient, JingleSessionImpl::ref session, const std::vector<JingleContentPayload::ref>& contents) { - sessions.insert(std::make_pair(JIDSession(initiator, session->getID()), session)); - foreach (IncomingJingleSessionHandler* handler, incomingSessionHandlers) { - if (handler->handleIncomingJingleSession(session, contents, recipient)) { - return; - } - } - // TODO: Finish session + sessions.insert(std::make_pair(JIDSession(initiator, session->getID()), session)); + for (auto handler : incomingSessionHandlers) { + if (handler->handleIncomingJingleSession(session, contents, recipient)) { + return; + } + } + // TODO: Finish session } diff --git a/Swiften/Jingle/JingleSessionManager.h b/Swiften/Jingle/JingleSessionManager.h index 3412709..f67a0fe 100644 --- a/Swiften/Jingle/JingleSessionManager.h +++ b/Swiften/Jingle/JingleSessionManager.h @@ -1,51 +1,52 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> #include <map> +#include <memory> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Jingle/JingleSessionImpl.h> namespace Swift { - class IQRouter; - class JingleResponder; - class IncomingJingleSessionHandler; - - class SWIFTEN_API JingleSessionManager { - friend class JingleResponder; - public: - JingleSessionManager(IQRouter* router); - ~JingleSessionManager(); - - JingleSessionImpl::ref getSession(const JID& jid, const std::string& id) const; - - void addIncomingSessionHandler(IncomingJingleSessionHandler* handler); - void removeIncomingSessionHandler(IncomingJingleSessionHandler* handler); - - void registerOutgoingSession(const JID& initiator, JingleSessionImpl::ref); - protected: - void handleIncomingSession(const JID& initiator, const JID& recipient, JingleSessionImpl::ref, const std::vector<JingleContentPayload::ref>& contents); - - private: - IQRouter* router; - JingleResponder* responder; - std::vector<IncomingJingleSessionHandler*> incomingSessionHandlers; - struct JIDSession { - JIDSession(const JID& initiator, const std::string& session) : initiator(initiator), session(session) {} - bool operator<(const JIDSession& o) const { - return initiator == o.initiator ? session < o.session : initiator < o.initiator; - } - JID initiator; - std::string session; - }; - typedef std::map<JIDSession, JingleSessionImpl::ref> SessionMap; - SessionMap sessions; - }; + class IQRouter; + class JingleResponder; + class IncomingJingleSessionHandler; + + class SWIFTEN_API JingleSessionManager { + friend class JingleResponder; + public: + JingleSessionManager(IQRouter* router); + ~JingleSessionManager(); + + JingleSessionImpl::ref getSession(const JID& jid, const std::string& id) const; + + void addIncomingSessionHandler(IncomingJingleSessionHandler* handler); + void removeIncomingSessionHandler(IncomingJingleSessionHandler* handler); + + void registerOutgoingSession(const JID& initiator, JingleSessionImpl::ref); + protected: + void handleIncomingSession(const JID& initiator, const JID& recipient, JingleSessionImpl::ref, const std::vector<JingleContentPayload::ref>& contents); + + private: + IQRouter* router; + JingleResponder* responder; + std::vector<IncomingJingleSessionHandler*> incomingSessionHandlers; + struct JIDSession { + JIDSession(const JID& initiator, const std::string& session) : initiator(initiator), session(session) {} + bool operator<(const JIDSession& o) const { + return initiator == o.initiator ? session < o.session : initiator < o.initiator; + } + JID initiator; + std::string session; + }; + typedef std::map<JIDSession, JingleSessionImpl::ref> SessionMap; + SessionMap sessions; + }; } diff --git a/Swiften/Jingle/SConscript b/Swiften/Jingle/SConscript index 546c1b2..4d25a78 100644 --- a/Swiften/Jingle/SConscript +++ b/Swiften/Jingle/SConscript @@ -1,14 +1,14 @@ Import("swiften_env") sources = [ - "JingleSession.cpp", - "JingleSessionListener.cpp", - "AbstractJingleSessionListener.cpp", - "JingleSessionImpl.cpp", - "IncomingJingleSessionHandler.cpp", - "JingleSessionManager.cpp", - "JingleResponder.cpp", - "FakeJingleSession.cpp", - ] + "JingleSession.cpp", + "JingleSessionListener.cpp", + "AbstractJingleSessionListener.cpp", + "JingleSessionImpl.cpp", + "IncomingJingleSessionHandler.cpp", + "JingleSessionManager.cpp", + "JingleResponder.cpp", + "FakeJingleSession.cpp", + ] swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources)) diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.cpp index e31bf87..a1bdb3e 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.cpp @@ -1,60 +1,61 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h> -#include <boost/bind.hpp> #include <iostream> +#include <boost/bind.hpp> + #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h> namespace Swift { void AvahiBrowseQuery::startBrowsing() { - std::cout << "Start browsing" << std::endl; - assert(!browser); - avahi_threaded_poll_lock(querier->getThreadedPoll()); - browser = avahi_service_browser_new(querier->getClient(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_presence._tcp", NULL, static_cast<AvahiLookupFlags>(0), &handleServiceDiscoveredStatic, this); - if (!browser) { - std::cout << "Error" << std::endl; - eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this()); - } - avahi_threaded_poll_unlock(querier->getThreadedPoll()); + std::cout << "Start browsing" << std::endl; + assert(!browser); + avahi_threaded_poll_lock(querier->getThreadedPoll()); + browser = avahi_service_browser_new(querier->getClient(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_presence._tcp", NULL, static_cast<AvahiLookupFlags>(0), &handleServiceDiscoveredStatic, this); + if (!browser) { + std::cout << "Error" << std::endl; + eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this()); + } + avahi_threaded_poll_unlock(querier->getThreadedPoll()); } void AvahiBrowseQuery::stopBrowsing() { - std::cout << "Stop browsing" << std::endl; - avahi_threaded_poll_lock(querier->getThreadedPoll()); - avahi_service_browser_free(browser); - browser = NULL; - avahi_threaded_poll_unlock(querier->getThreadedPoll()); + std::cout << "Stop browsing" << std::endl; + avahi_threaded_poll_lock(querier->getThreadedPoll()); + avahi_service_browser_free(browser); + browser = NULL; + avahi_threaded_poll_unlock(querier->getThreadedPoll()); } void AvahiBrowseQuery::handleServiceDiscovered(AvahiServiceBrowser *, AvahiIfIndex interfaceIndex, AvahiProtocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags) { - switch (event) { - case AVAHI_BROWSER_FAILURE: - std::cout << "Service browse error" << std::endl; - eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this()); - break; - case AVAHI_BROWSER_NEW: { - DNSSDServiceID service(name, domain, type, interfaceIndex); - std::cout << "Service discovered " << name << " " << domain << " " << type << " " << interfaceIndex << std::endl; - eventLoop->postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this()); - break; - } - case AVAHI_BROWSER_REMOVE: { - std::cout << "Service went away " << name << " " << domain << " " << type << " " << interfaceIndex << std::endl; - DNSSDServiceID service(name, domain, type, interfaceIndex); - eventLoop->postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this()); - break; - } - case AVAHI_BROWSER_ALL_FOR_NOW: - case AVAHI_BROWSER_CACHE_EXHAUSTED: - break; - } + switch (event) { + case AVAHI_BROWSER_FAILURE: + std::cout << "Service browse error" << std::endl; + eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this()); + break; + case AVAHI_BROWSER_NEW: { + DNSSDServiceID service(name, domain, type, interfaceIndex); + std::cout << "Service discovered " << name << " " << domain << " " << type << " " << interfaceIndex << std::endl; + eventLoop->postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this()); + break; + } + case AVAHI_BROWSER_REMOVE: { + std::cout << "Service went away " << name << " " << domain << " " << type << " " << interfaceIndex << std::endl; + DNSSDServiceID service(name, domain, type, interfaceIndex); + eventLoop->postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this()); + break; + } + case AVAHI_BROWSER_ALL_FOR_NOW: + case AVAHI_BROWSER_CACHE_EXHAUSTED: + break; + } } } diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h index 38e796d..a227613 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h @@ -1,37 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <avahi-client/lookup.h> +#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h> #include <Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h> -#include <Swiften/EventLoop/EventLoop.h> namespace Swift { - class AvahiQuerier; + class AvahiQuerier; + + class AvahiBrowseQuery : public DNSSDBrowseQuery, public AvahiQuery { + public: + AvahiBrowseQuery(std::shared_ptr<AvahiQuerier> q, EventLoop* eventLoop) : AvahiQuery(q, eventLoop), browser(NULL) { + } - class AvahiBrowseQuery : public DNSSDBrowseQuery, public AvahiQuery { - public: - AvahiBrowseQuery(boost::shared_ptr<AvahiQuerier> q, EventLoop* eventLoop) : AvahiQuery(q, eventLoop), browser(NULL) { - } + void startBrowsing(); + void stopBrowsing(); - void startBrowsing(); - void stopBrowsing(); + private: + static void handleServiceDiscoveredStatic(AvahiServiceBrowser *b, AvahiIfIndex interfaceIndex, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void* context) { + static_cast<AvahiBrowseQuery*>(context)->handleServiceDiscovered(b, interfaceIndex, protocol, event, name, type, domain, flags); + } - private: - static void handleServiceDiscoveredStatic(AvahiServiceBrowser *b, AvahiIfIndex interfaceIndex, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void* context) { - static_cast<AvahiBrowseQuery*>(context)->handleServiceDiscovered(b, interfaceIndex, protocol, event, name, type, domain, flags); - } + void handleServiceDiscovered(AvahiServiceBrowser *, AvahiIfIndex interfaceIndex, AvahiProtocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags); - void handleServiceDiscovered(AvahiServiceBrowser *, AvahiIfIndex interfaceIndex, AvahiProtocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags); + private: + AvahiServiceBrowser* browser; - private: - AvahiServiceBrowser* browser; - - }; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.cpp index e9f5564..66b4ae8 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.cpp +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h> @@ -9,9 +9,9 @@ #include <iostream> #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h> -#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h> -#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h> #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h> +#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h> +#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h> namespace Swift { @@ -21,46 +21,46 @@ AvahiQuerier::AvahiQuerier(EventLoop* eventLoop) : eventLoop(eventLoop), client( AvahiQuerier::~AvahiQuerier() { } -boost::shared_ptr<DNSSDBrowseQuery> AvahiQuerier::createBrowseQuery() { - return boost::shared_ptr<DNSSDBrowseQuery>(new AvahiBrowseQuery(shared_from_this(), eventLoop)); +std::shared_ptr<DNSSDBrowseQuery> AvahiQuerier::createBrowseQuery() { + return std::make_shared<AvahiBrowseQuery>(shared_from_this(), eventLoop); } -boost::shared_ptr<DNSSDRegisterQuery> AvahiQuerier::createRegisterQuery(const std::string& name, int port, const ByteArray& info) { - return boost::shared_ptr<DNSSDRegisterQuery>(new AvahiRegisterQuery(name, port, info, shared_from_this(), eventLoop)); +std::shared_ptr<DNSSDRegisterQuery> AvahiQuerier::createRegisterQuery(const std::string& name, unsigned short port, const ByteArray& info) { + return std::make_shared<AvahiRegisterQuery>(name, port, info, shared_from_this(), eventLoop); } -boost::shared_ptr<DNSSDResolveServiceQuery> AvahiQuerier::createResolveServiceQuery(const DNSSDServiceID& service) { - return boost::shared_ptr<DNSSDResolveServiceQuery>(new AvahiResolveServiceQuery(service, shared_from_this(), eventLoop)); +std::shared_ptr<DNSSDResolveServiceQuery> AvahiQuerier::createResolveServiceQuery(const DNSSDServiceID& service) { + return std::make_shared<AvahiResolveServiceQuery>(service, shared_from_this(), eventLoop); } -boost::shared_ptr<DNSSDResolveHostnameQuery> AvahiQuerier::createResolveHostnameQuery(const std::string& hostname, int interfaceIndex) { - return boost::shared_ptr<DNSSDResolveHostnameQuery>(new AvahiResolveHostnameQuery(hostname, interfaceIndex, shared_from_this(), eventLoop)); +std::shared_ptr<DNSSDResolveHostnameQuery> AvahiQuerier::createResolveHostnameQuery(const std::string& hostname, int interfaceIndex) { + return std::make_shared<AvahiResolveHostnameQuery>(hostname, interfaceIndex, shared_from_this(), eventLoop); } void AvahiQuerier::start() { - std::cout << "Starrting querier" << std::endl; - assert(!threadedPoll); - threadedPoll = avahi_threaded_poll_new(); - int error; - assert(!client); - client = avahi_client_new( - avahi_threaded_poll_get(threadedPoll), - static_cast<AvahiClientFlags>(0), NULL, this, &error); // TODO - if (!client) { - // TODO - std::cerr << "Avahi Error: " << avahi_strerror(error) << std::endl; - return; - } - std::cout << "Starrting event loop" << std::endl; - avahi_threaded_poll_start(threadedPoll); + std::cout << "Starrting querier" << std::endl; + assert(!threadedPoll); + threadedPoll = avahi_threaded_poll_new(); + int error; + assert(!client); + client = avahi_client_new( + avahi_threaded_poll_get(threadedPoll), + static_cast<AvahiClientFlags>(0), NULL, this, &error); // TODO + if (!client) { + // TODO + std::cerr << "Avahi Error: " << avahi_strerror(error) << std::endl; + return; + } + std::cout << "Starrting event loop" << std::endl; + avahi_threaded_poll_start(threadedPoll); } void AvahiQuerier::stop() { - assert(threadedPoll); - avahi_threaded_poll_stop(threadedPoll); - assert(client); - avahi_client_free(client); - avahi_threaded_poll_free(threadedPoll); + assert(threadedPoll); + avahi_threaded_poll_stop(threadedPoll); + assert(client); + avahi_client_free(client); + avahi_threaded_poll_free(threadedPoll); } } diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h index 6ddd23d..73dd11d 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h @@ -1,55 +1,55 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <memory> + #include <avahi-client/client.h> #include <avahi-client/lookup.h> +#include <avahi-common/error.h> +#include <avahi-common/malloc.h> #include <avahi-common/thread-watch.h> #include <avahi-common/watch.h> -#include <avahi-common/malloc.h> -#include <avahi-common/error.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDQuerier.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDQuerier.h> namespace Swift { - class EventLoop; - - class AvahiQuerier : - public DNSSDQuerier, - public boost::enable_shared_from_this<AvahiQuerier> { - public: - AvahiQuerier(EventLoop* eventLoop); - ~AvahiQuerier(); - - boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery(); - boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery( - const std::string& name, int port, const ByteArray& info); - boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery( - const DNSSDServiceID&); - boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery( - const std::string& hostname, int interfaceIndex); - - void start(); - void stop(); - - AvahiThreadedPoll* getThreadedPoll() const { - return threadedPoll; - } - - AvahiClient* getClient() const { - return client; - } - - private: - EventLoop* eventLoop; - AvahiClient* client; - AvahiThreadedPoll* threadedPoll; - }; + class EventLoop; + + class AvahiQuerier : + public DNSSDQuerier, + public std::enable_shared_from_this<AvahiQuerier> { + public: + AvahiQuerier(EventLoop* eventLoop); + ~AvahiQuerier(); + + std::shared_ptr<DNSSDBrowseQuery> createBrowseQuery(); + std::shared_ptr<DNSSDRegisterQuery> createRegisterQuery( + const std::string& name, unsigned short port, const ByteArray& info); + std::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery( + const DNSSDServiceID&); + std::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery( + const std::string& hostname, int interfaceIndex); + + void start(); + void stop(); + + AvahiThreadedPoll* getThreadedPoll() const { + return threadedPoll; + } + + AvahiClient* getClient() const { + return client; + } + + private: + EventLoop* eventLoop; + AvahiClient* client; + AvahiThreadedPoll* threadedPoll; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.cpp index 3b0e8da..08997f6 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.cpp @@ -1,15 +1,16 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h> + #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h> namespace Swift { -AvahiQuery::AvahiQuery(boost::shared_ptr<AvahiQuerier> q, EventLoop* eventLoop) : querier(q), eventLoop(eventLoop) { +AvahiQuery::AvahiQuery(std::shared_ptr<AvahiQuerier> q, EventLoop* eventLoop) : querier(q), eventLoop(eventLoop) { } AvahiQuery::~AvahiQuery() { diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h index 047e1cd..1b98bbf 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h @@ -1,30 +1,29 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <memory> #include <Swiften/EventLoop/EventOwner.h> namespace Swift { - class AvahiQuerier; - class EventLoop; + class AvahiQuerier; + class EventLoop; - class AvahiQuery : - public EventOwner, - public boost::enable_shared_from_this<AvahiQuery> { - public: - AvahiQuery(boost::shared_ptr<AvahiQuerier>, EventLoop* eventLoop); - virtual ~AvahiQuery(); - - protected: - boost::shared_ptr<AvahiQuerier> querier; - EventLoop* eventLoop; - }; + class AvahiQuery : + public EventOwner, + public std::enable_shared_from_this<AvahiQuery> { + public: + AvahiQuery(std::shared_ptr<AvahiQuerier>, EventLoop* eventLoop); + virtual ~AvahiQuery(); + + protected: + std::shared_ptr<AvahiQuerier> querier; + EventLoop* eventLoop; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.cpp index 8a7ed3b..04790d5 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h> #include <iostream> + #include <boost/bind.hpp> #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h> @@ -14,87 +15,87 @@ namespace Swift { void AvahiRegisterQuery::registerService() { - std::cout << "Registering service " << name << ":" << port << std::endl; - avahi_threaded_poll_lock(querier->getThreadedPoll()); - if (!group) { - std::cout << "Creating entry group" << std::endl; - group = avahi_entry_group_new(querier->getClient(), handleEntryGroupChange, this); - if (!group) { - std::cout << "Error ceating entry group" << std::endl; - eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); - } - } - - doRegisterService(); - avahi_threaded_poll_unlock(querier->getThreadedPoll()); + std::cout << "Registering service " << name << ":" << port << std::endl; + avahi_threaded_poll_lock(querier->getThreadedPoll()); + if (!group) { + std::cout << "Creating entry group" << std::endl; + group = avahi_entry_group_new(querier->getClient(), handleEntryGroupChange, this); + if (!group) { + std::cout << "Error ceating entry group" << std::endl; + eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); + } + } + + doRegisterService(); + avahi_threaded_poll_unlock(querier->getThreadedPoll()); } void AvahiRegisterQuery::unregisterService() { - if (group) { - avahi_entry_group_free(group); - group = NULL; - } + if (group) { + avahi_entry_group_free(group); + group = NULL; + } } void AvahiRegisterQuery::updateServiceInfo(const ByteArray& txtRecord) { - this->txtRecord = txtRecord; - avahi_threaded_poll_lock(querier->getThreadedPoll()); - assert(group); - avahi_entry_group_reset(group); - doRegisterService(); - avahi_threaded_poll_unlock(querier->getThreadedPoll()); + this->txtRecord = txtRecord; + avahi_threaded_poll_lock(querier->getThreadedPoll()); + assert(group); + avahi_entry_group_reset(group); + doRegisterService(); + avahi_threaded_poll_unlock(querier->getThreadedPoll()); } void AvahiRegisterQuery::doRegisterService() { - AvahiStringList* txtList; - avahi_string_list_parse(vecptr(txtRecord), txtRecord.size(), &txtList); - - int result = avahi_entry_group_add_service_strlst(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, static_cast<AvahiPublishFlags>(0), name.c_str(), "_presence._tcp", NULL, NULL, port, txtList); - if (result < 0) { - std::cout << "Error registering service: " << avahi_strerror(result) << std::endl; - eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); - } - result = avahi_entry_group_commit(group); - if (result < 0) { - std::cout << "Error registering service: " << avahi_strerror(result) << std::endl; - } + AvahiStringList* txtList; + avahi_string_list_parse(vecptr(txtRecord), txtRecord.size(), &txtList); + + int result = avahi_entry_group_add_service_strlst(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, static_cast<AvahiPublishFlags>(0), name.c_str(), "_presence._tcp", NULL, NULL, port, txtList); + if (result < 0) { + std::cout << "Error registering service: " << avahi_strerror(result) << std::endl; + eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); + } + result = avahi_entry_group_commit(group); + if (result < 0) { + std::cout << "Error registering service: " << avahi_strerror(result) << std::endl; + } } void AvahiRegisterQuery::handleEntryGroupChange(AvahiEntryGroup* g, AvahiEntryGroupState state) { - std::cout << "ENtry group callback: " << state << std::endl; - switch (state) { - case AVAHI_ENTRY_GROUP_ESTABLISHED : - // Domain is a hack! - eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>(DNSSDServiceID(name, "local", "_presence._tcp", 0))), shared_from_this()); - std::cout << "Entry group established" << std::endl; - break; - case AVAHI_ENTRY_GROUP_COLLISION : { - std::cout << "Entry group collision" << std::endl; - /*char *n; - n = avahi_alternative_service_name(name); - avahi_free(name); - name = n;*/ - break; - } - - case AVAHI_ENTRY_GROUP_FAILURE : - std::cout << "Entry group failure " << avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))) << std::endl; - break; - - case AVAHI_ENTRY_GROUP_UNCOMMITED: - case AVAHI_ENTRY_GROUP_REGISTERING: - ; - - /* - DNSServiceErrorType result = DNSServiceRegister( - &sdRef, 0, 0, name.c_str(), "_presence._tcp", NULL, NULL, port, - txtRecord.getSize(), txtRecord.getData(), - &AvahiRegisterQuery::handleServiceRegisteredStatic, this); - if (result != kDNSServiceErr_NoError) { - sdRef = NULL; - }*/ - //eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); - } + std::cout << "ENtry group callback: " << state << std::endl; + switch (state) { + case AVAHI_ENTRY_GROUP_ESTABLISHED : + // Domain is a hack! + eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>(DNSSDServiceID(name, "local", "_presence._tcp", 0))), shared_from_this()); + std::cout << "Entry group established" << std::endl; + break; + case AVAHI_ENTRY_GROUP_COLLISION : { + std::cout << "Entry group collision" << std::endl; + /*char *n; + n = avahi_alternative_service_name(name); + avahi_free(name); + name = n;*/ + break; + } + + case AVAHI_ENTRY_GROUP_FAILURE : + std::cout << "Entry group failure " << avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))) << std::endl; + break; + + case AVAHI_ENTRY_GROUP_UNCOMMITED: + case AVAHI_ENTRY_GROUP_REGISTERING: + ; + + /* + DNSServiceErrorType result = DNSServiceRegister( + &sdRef, 0, 0, name.c_str(), "_presence._tcp", NULL, NULL, port, + txtRecord.getSize(), txtRecord.getData(), + &AvahiRegisterQuery::handleServiceRegisteredStatic, this); + if (result != kDNSServiceErr_NoError) { + sdRef = NULL; + }*/ + //eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); + } } diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h index b47ed12..b780043 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h @@ -1,57 +1,57 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <avahi-client/publish.h> -#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h> namespace Swift { - class AvahiQuerier; + class AvahiQuerier; - class AvahiRegisterQuery : public DNSSDRegisterQuery, public AvahiQuery { - public: - AvahiRegisterQuery(const std::string& name, int port, const ByteArray& txtRecord, boost::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop) : AvahiQuery(querier, eventLoop), name(name), port(port), txtRecord(txtRecord), group(0) { - } + class AvahiRegisterQuery : public DNSSDRegisterQuery, public AvahiQuery { + public: + AvahiRegisterQuery(const std::string& name, unsigned short port, const ByteArray& txtRecord, std::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop) : AvahiQuery(querier, eventLoop), name(name), port(port), txtRecord(txtRecord), group(0) { + } - void registerService(); - void unregisterService(); - void updateServiceInfo(const ByteArray& txtRecord); + void registerService(); + void unregisterService(); + void updateServiceInfo(const ByteArray& txtRecord); - private: - void doRegisterService(); + private: + void doRegisterService(); - static void handleEntryGroupChange(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) { - static_cast<AvahiRegisterQuery*>(userdata)->handleEntryGroupChange(g, state); - } + static void handleEntryGroupChange(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) { + static_cast<AvahiRegisterQuery*>(userdata)->handleEntryGroupChange(g, state); + } - void handleEntryGroupChange(AvahiEntryGroup* g, AvahiEntryGroupState state); + void handleEntryGroupChange(AvahiEntryGroup* g, AvahiEntryGroupState state); /* - static void handleServiceRegisteredStatic(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) { - static_cast<AvahiRegisterQuery*>(context)->handleServiceRegistered(errorCode, name, regtype, domain); - } - - void handleServiceRegistered(DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) { - if (errorCode != kDNSServiceErr_NoError) { - eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); - } - else { - } - } - */ - - private: - std::string name; - int port; - ByteArray txtRecord; - AvahiEntryGroup* group; - }; + static void handleServiceRegisteredStatic(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) { + static_cast<AvahiRegisterQuery*>(context)->handleServiceRegistered(errorCode, name, regtype, domain); + } + + void handleServiceRegistered(DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) { + if (errorCode != kDNSServiceErr_NoError) { + eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); + } + else { + } + } + */ + + private: + std::string name; + unsigned short port; + ByteArray txtRecord; + AvahiEntryGroup* group; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.cpp index d9a1c5c..262add3 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.cpp @@ -1,22 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h> -#include <iostream> #include <boost/bind.hpp> +#include <netinet/in.h> + +#include <Swiften/Base/Log.h> + namespace Swift { -AvahiResolveHostnameQuery::AvahiResolveHostnameQuery(const std::string& hostname, int, boost::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop) : AvahiQuery(querier, eventLoop), hostname(hostname) { - std::cout << "Resolving hostname " << hostname << std::endl; +AvahiResolveHostnameQuery::AvahiResolveHostnameQuery(const std::string& hostname, int, std::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop) : AvahiQuery(querier, eventLoop), hostname(hostname) { + SWIFT_LOG(debug) << "Resolving hostname " << hostname; } void AvahiResolveHostnameQuery::run() { - eventLoop->postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>(HostAddress(hostname))), shared_from_this()); + eventLoop->postEvent(boost::bind(boost::ref(onHostnameResolved), HostAddress::fromString(hostname)), shared_from_this()); } } diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h index 5ee6346..33c425f 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h @@ -1,33 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + +#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h> #include <Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h> -#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/Network/HostAddress.h> -#include <netinet/in.h> - namespace Swift { - class AvahiQuerier; + class AvahiQuerier; - class AvahiResolveHostnameQuery : public DNSSDResolveHostnameQuery, public AvahiQuery { - public: - AvahiResolveHostnameQuery(const std::string& hostname, int, boost::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop); + class AvahiResolveHostnameQuery : public DNSSDResolveHostnameQuery, public AvahiQuery { + public: + AvahiResolveHostnameQuery(const std::string& hostname, int, std::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop); - void run(); + void run(); - void finish() { - } + void finish() { + } - private: - HostAddress hostAddress; - std::string hostname; - }; + private: + HostAddress hostAddress; + std::string hostname; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.cpp index ebd2329..a5e52b2 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.cpp @@ -1,65 +1,66 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h> -#include <boost/bind.hpp> #include <iostream> +#include <boost/bind.hpp> + #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h> namespace Swift { void AvahiResolveServiceQuery::start() { - std::cout << "Start resolving " << service.getName() << " " << service.getType() << " " << service.getDomain() << std::endl; - avahi_threaded_poll_lock(querier->getThreadedPoll()); - assert(!resolver); - resolver = avahi_service_resolver_new(querier->getClient(), service.getNetworkInterfaceID(), AVAHI_PROTO_UNSPEC, service.getName().c_str(), service.getType().c_str(), service.getDomain().c_str(), AVAHI_PROTO_UNSPEC, static_cast<AvahiLookupFlags>(0), handleServiceResolvedStatic, this); - if (!resolver) { - std::cout << "Error starting resolver" << std::endl; - eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this()); - } - avahi_threaded_poll_unlock(querier->getThreadedPoll()); + std::cout << "Start resolving " << service.getName() << " " << service.getType() << " " << service.getDomain() << std::endl; + avahi_threaded_poll_lock(querier->getThreadedPoll()); + assert(!resolver); + resolver = avahi_service_resolver_new(querier->getClient(), service.getNetworkInterfaceID(), AVAHI_PROTO_UNSPEC, service.getName().c_str(), service.getType().c_str(), service.getDomain().c_str(), AVAHI_PROTO_UNSPEC, static_cast<AvahiLookupFlags>(0), handleServiceResolvedStatic, this); + if (!resolver) { + std::cout << "Error starting resolver" << std::endl; + eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this()); + } + avahi_threaded_poll_unlock(querier->getThreadedPoll()); } void AvahiResolveServiceQuery::stop() { - std::cout << "Stop resolving" << std::endl; - avahi_threaded_poll_lock(querier->getThreadedPoll()); - avahi_service_resolver_free(resolver); - resolver = NULL; - avahi_threaded_poll_unlock(querier->getThreadedPoll()); + std::cout << "Stop resolving" << std::endl; + avahi_threaded_poll_lock(querier->getThreadedPoll()); + avahi_service_resolver_free(resolver); + resolver = NULL; + avahi_threaded_poll_unlock(querier->getThreadedPoll()); } void AvahiResolveServiceQuery::handleServiceResolved(AvahiServiceResolver* resolver, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent event, const char *name, const char * type, const char* domain, const char * /*host_name*/, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags) { - std::cout << "Resolve finished" << std::endl; - switch(event) { - case AVAHI_RESOLVER_FAILURE: - std::cout << "Resolve error " << avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(resolver))) << std::endl; - eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this()); - break; - case AVAHI_RESOLVER_FOUND: { - std::cout << "Success" << std::endl; - char a[AVAHI_ADDRESS_STR_MAX]; - avahi_address_snprint(a, sizeof(a), address); + std::cout << "Resolve finished" << std::endl; + switch(event) { + case AVAHI_RESOLVER_FAILURE: + std::cout << "Resolve error " << avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(resolver))) << std::endl; + eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this()); + break; + case AVAHI_RESOLVER_FOUND: { + std::cout << "Success" << std::endl; + char a[AVAHI_ADDRESS_STR_MAX]; + avahi_address_snprint(a, sizeof(a), address); - ByteArray txtRecord; - txtRecord.resize(1024); - avahi_string_list_serialize(txt, vecptr(txtRecord), txtRecord.size()); + ByteArray txtRecord; + txtRecord.resize(1024); + avahi_string_list_serialize(txt, vecptr(txtRecord), txtRecord.size()); - // FIXME: Probably not accurate - std::string fullname = std::string(name) + "." + std::string(type) + "." + std::string(domain) + "."; - std::cout << "Result: " << fullname << "->" << std::string(a) << ":" << port << std::endl; - eventLoop->postEvent( - boost::bind( - boost::ref(onServiceResolved), - Result(fullname, std::string(a), port, txtRecord)), - shared_from_this()); - break; - } - } + // FIXME: Probably not accurate + std::string fullname = std::string(name) + "." + std::string(type) + "." + std::string(domain) + "."; + std::cout << "Result: " << fullname << "->" << std::string(a) << ":" << port << std::endl; + eventLoop->postEvent( + boost::bind( + boost::ref(onServiceResolved), + Result(fullname, std::string(a), port, txtRecord)), + shared_from_this()); + break; + } + } } } diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h index a39d732..c05c73e 100644 --- a/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h +++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h @@ -1,39 +1,39 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <avahi-client/lookup.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/LinkLocal/DNSSD/Avahi/AvahiQuery.h> #include <Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h> #include <Swiften/LinkLocal/LinkLocalServiceInfo.h> -#include <Swiften/Base/ByteArray.h> -#include <Swiften/EventLoop/EventLoop.h> namespace Swift { - class AvahiQuerier; + class AvahiQuerier; - class AvahiResolveServiceQuery : public DNSSDResolveServiceQuery, public AvahiQuery { - public: - AvahiResolveServiceQuery(const DNSSDServiceID& service, boost::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop) : AvahiQuery(querier, eventLoop), service(service), resolver(NULL) { - } + class AvahiResolveServiceQuery : public DNSSDResolveServiceQuery, public AvahiQuery { + public: + AvahiResolveServiceQuery(const DNSSDServiceID& service, std::shared_ptr<AvahiQuerier> querier, EventLoop* eventLoop) : AvahiQuery(querier, eventLoop), service(service), resolver(NULL) { + } - void start(); - void stop(); + void start(); + void stop(); - private: - static void handleServiceResolvedStatic(AvahiServiceResolver* resolver, AvahiIfIndex interfaceIndex, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void* context) { - static_cast<AvahiResolveServiceQuery*>(context)->handleServiceResolved(resolver, interfaceIndex, protocol, event, name, type, domain, host_name, address, port, txt, flags); - } + private: + static void handleServiceResolvedStatic(AvahiServiceResolver* resolver, AvahiIfIndex interfaceIndex, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void* context) { + static_cast<AvahiResolveServiceQuery*>(context)->handleServiceResolved(resolver, interfaceIndex, protocol, event, name, type, domain, host_name, address, port, txt, flags); + } - void handleServiceResolved(AvahiServiceResolver* resolver, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent event, const char *name, const char * type, const char* domain, const char * /*host_name*/, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags); + void handleServiceResolved(AvahiServiceResolver* resolver, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent event, const char *name, const char * type, const char* domain, const char * /*host_name*/, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags); - private: - DNSSDServiceID service; - AvahiServiceResolver* resolver; - }; + private: + DNSSDServiceID service; + AvahiServiceResolver* resolver; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h index 52d6654..63f34db 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h @@ -1,62 +1,68 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <boost/numeric/conversion/cast.hpp> + +#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h> #include <Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h> -#include <Swiften/EventLoop/EventLoop.h> -#include <boost/numeric/conversion/cast.hpp> namespace Swift { - class BonjourQuerier; - - class BonjourBrowseQuery : public DNSSDBrowseQuery, public BonjourQuery { - public: - BonjourBrowseQuery(boost::shared_ptr<BonjourQuerier> q, EventLoop* eventLoop) : BonjourQuery(q, eventLoop) { - DNSServiceErrorType result = DNSServiceBrowse( - &sdRef, 0, 0, "_presence._tcp", 0, - &BonjourBrowseQuery::handleServiceDiscoveredStatic, this); - if (result != kDNSServiceErr_NoError) { - sdRef = NULL; - } - } - - void startBrowsing() { - if (!sdRef) { - eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this()); - } - else { - run(); - } - } - - void stopBrowsing() { - finish(); - } - - private: - static void handleServiceDiscoveredStatic(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain, void *context) { - static_cast<BonjourBrowseQuery*>(context)->handleServiceDiscovered(flags, interfaceIndex, errorCode, name, type, domain); - } - - void handleServiceDiscovered(DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain) { - if (errorCode != kDNSServiceErr_NoError) { - eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this()); - } - else { - //std::cout << "Discovered service: name:" << name << " domain:" << domain << " type: " << type << std::endl; - DNSSDServiceID service(name, domain, type, boost::numeric_cast<int>(interfaceIndex)); - if (flags & kDNSServiceFlagsAdd) { - eventLoop->postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this()); - } - else { - eventLoop->postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this()); - } - } - } - }; + class BonjourQuerier; + + class BonjourBrowseQuery : public DNSSDBrowseQuery, public BonjourQuery { + public: + BonjourBrowseQuery(std::shared_ptr<BonjourQuerier> q, EventLoop* eventLoop) : BonjourQuery(q, eventLoop) { + DNSServiceErrorType result = DNSServiceBrowse( + &sdRef, 0, 0, "_presence._tcp", nullptr, + &BonjourBrowseQuery::handleServiceDiscoveredStatic, this); + if (result != kDNSServiceErr_NoError) { + sdRef = nullptr; + } + } + + void startBrowsing() { + if (!sdRef) { + eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this()); + } + else { + run(); + } + } + + void stopBrowsing() { + finish(); + } + + private: + static void handleServiceDiscoveredStatic(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain, void *context) { + static_cast<BonjourBrowseQuery*>(context)->handleServiceDiscovered(flags, interfaceIndex, errorCode, name, type, domain); + } + + void handleServiceDiscovered(DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain) { + if (errorCode != kDNSServiceErr_NoError) { + eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this()); + } + else { + //std::cout << "Discovered service: name:" << name << " domain:" << domain << " type: " << type << std::endl; + try { + DNSSDServiceID service(name, domain, type, boost::numeric_cast<int>(interfaceIndex)); + if (flags & kDNSServiceFlagsAdd) { + eventLoop->postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this()); + } + else { + eventLoop->postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this()); + } + } + catch (...) { + eventLoop->postEvent(boost::bind(boost::ref(onError)), shared_from_this()); + } + } + } + }; } diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp index 530e066..551421e 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp @@ -1,136 +1,136 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h> -#include <unistd.h> -#include <sys/socket.h> #include <fcntl.h> +#include <sys/socket.h> +#include <unistd.h> +#include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/Log.h> #include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h> #include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h> -#include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h> #include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Base/Algorithm.h> +#include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h> namespace Swift { -BonjourQuerier::BonjourQuerier(EventLoop* eventLoop) : eventLoop(eventLoop), stopRequested(false), thread(0) { - int fds[2]; - int result = pipe(fds); - assert(result == 0); - (void) result; - interruptSelectReadSocket = fds[0]; - fcntl(interruptSelectReadSocket, F_SETFL, fcntl(interruptSelectReadSocket, F_GETFL)|O_NONBLOCK); - interruptSelectWriteSocket = fds[1]; +BonjourQuerier::BonjourQuerier(EventLoop* eventLoop) : eventLoop(eventLoop), stopRequested(false), thread(nullptr) { + int fds[2]; + int result = pipe(fds); + assert(result == 0); + (void) result; + interruptSelectReadSocket = fds[0]; + fcntl(interruptSelectReadSocket, F_SETFL, fcntl(interruptSelectReadSocket, F_GETFL)|O_NONBLOCK); + interruptSelectWriteSocket = fds[1]; } BonjourQuerier::~BonjourQuerier() { - assert(!thread); + assert(!thread); } -boost::shared_ptr<DNSSDBrowseQuery> BonjourQuerier::createBrowseQuery() { - return boost::shared_ptr<DNSSDBrowseQuery>(new BonjourBrowseQuery(shared_from_this(), eventLoop)); +std::shared_ptr<DNSSDBrowseQuery> BonjourQuerier::createBrowseQuery() { + return std::make_shared<BonjourBrowseQuery>(shared_from_this(), eventLoop); } -boost::shared_ptr<DNSSDRegisterQuery> BonjourQuerier::createRegisterQuery(const std::string& name, int port, const ByteArray& info) { - return boost::shared_ptr<DNSSDRegisterQuery>(new BonjourRegisterQuery(name, port, info, shared_from_this(), eventLoop)); +std::shared_ptr<DNSSDRegisterQuery> BonjourQuerier::createRegisterQuery(const std::string& name, unsigned short port, const ByteArray& info) { + return std::make_shared<BonjourRegisterQuery>(name, port, info, shared_from_this(), eventLoop); } -boost::shared_ptr<DNSSDResolveServiceQuery> BonjourQuerier::createResolveServiceQuery(const DNSSDServiceID& service) { - return boost::shared_ptr<DNSSDResolveServiceQuery>(new BonjourResolveServiceQuery(service, shared_from_this(), eventLoop)); +std::shared_ptr<DNSSDResolveServiceQuery> BonjourQuerier::createResolveServiceQuery(const DNSSDServiceID& service) { + return std::make_shared<BonjourResolveServiceQuery>(service, shared_from_this(), eventLoop); } -boost::shared_ptr<DNSSDResolveHostnameQuery> BonjourQuerier::createResolveHostnameQuery(const std::string& hostname, int interfaceIndex) { - return boost::shared_ptr<DNSSDResolveHostnameQuery>(new BonjourResolveHostnameQuery(hostname, interfaceIndex, shared_from_this(), eventLoop)); +std::shared_ptr<DNSSDResolveHostnameQuery> BonjourQuerier::createResolveHostnameQuery(const std::string& hostname, int interfaceIndex) { + return std::make_shared<BonjourResolveHostnameQuery>(hostname, interfaceIndex, shared_from_this(), eventLoop); } -void BonjourQuerier::addRunningQuery(boost::shared_ptr<BonjourQuery> query) { - { - boost::lock_guard<boost::mutex> lock(runningQueriesMutex); - runningQueries.push_back(query); - } - runningQueriesAvailableEvent.notify_one(); - interruptSelect(); +void BonjourQuerier::addRunningQuery(std::shared_ptr<BonjourQuery> query) { + { + std::lock_guard<std::mutex> lock(runningQueriesMutex); + runningQueries.push_back(query); + } + runningQueriesAvailableEvent.notify_one(); + interruptSelect(); } -void BonjourQuerier::removeRunningQuery(boost::shared_ptr<BonjourQuery> query) { - { - boost::lock_guard<boost::mutex> lock(runningQueriesMutex); - erase(runningQueries, query); - } +void BonjourQuerier::removeRunningQuery(std::shared_ptr<BonjourQuery> query) { + { + std::lock_guard<std::mutex> lock(runningQueriesMutex); + erase(runningQueries, query); + } } void BonjourQuerier::interruptSelect() { - char c = 0; - write(interruptSelectWriteSocket, &c, 1); + char c = 0; + write(interruptSelectWriteSocket, &c, 1); } void BonjourQuerier::start() { - assert(!thread); - thread = new boost::thread(boost::bind(&BonjourQuerier::run, shared_from_this())); + assert(!thread); + thread = new std::thread(boost::bind(&BonjourQuerier::run, shared_from_this())); } void BonjourQuerier::stop() { - if (thread) { - stopRequested = true; - assert(runningQueries.empty()); - runningQueriesAvailableEvent.notify_one(); - interruptSelect(); - thread->join(); - delete thread; - thread = NULL; - stopRequested = false; - } + if (thread) { + stopRequested = true; + assert(runningQueries.empty()); + runningQueriesAvailableEvent.notify_one(); + interruptSelect(); + thread->join(); + delete thread; + thread = nullptr; + stopRequested = false; + } } void BonjourQuerier::run() { - while (!stopRequested) { - fd_set fdSet; - int maxSocket; - { - boost::unique_lock<boost::mutex> lock(runningQueriesMutex); - if (runningQueries.empty()) { - runningQueriesAvailableEvent.wait(lock); - if (runningQueries.empty()) { - continue; - } - } - - // Run all running queries - FD_ZERO(&fdSet); - maxSocket = interruptSelectReadSocket; - FD_SET(interruptSelectReadSocket, &fdSet); - - foreach(const boost::shared_ptr<BonjourQuery>& query, runningQueries) { - int socketID = query->getSocketID(); - maxSocket = std::max(maxSocket, socketID); - FD_SET(socketID, &fdSet); - } - } - - if (select(maxSocket+1, &fdSet, NULL, NULL, 0) <= 0) { - continue; - } - - if (FD_ISSET(interruptSelectReadSocket, &fdSet)) { - char dummy; - while (read(interruptSelectReadSocket, &dummy, 1) > 0) {} - } - - { - boost::lock_guard<boost::mutex> lock(runningQueriesMutex); - foreach(boost::shared_ptr<BonjourQuery> query, runningQueries) { - if (FD_ISSET(query->getSocketID(), &fdSet)) { - query->processResult(); - } - } - } - } + while (!stopRequested) { + fd_set fdSet; + int maxSocket; + { + std::unique_lock<std::mutex> lock(runningQueriesMutex); + if (runningQueries.empty()) { + runningQueriesAvailableEvent.wait(lock); + if (runningQueries.empty()) { + continue; + } + } + + // Run all running queries + FD_ZERO(&fdSet); + maxSocket = interruptSelectReadSocket; + FD_SET(interruptSelectReadSocket, &fdSet); + + for (const auto& query : runningQueries) { + int socketID = query->getSocketID(); + maxSocket = std::max(maxSocket, socketID); + FD_SET(socketID, &fdSet); + } + } + + if (select(maxSocket+1, &fdSet, nullptr, nullptr, nullptr) <= 0) { + continue; + } + + if (FD_ISSET(interruptSelectReadSocket, &fdSet)) { + char dummy; + while (read(interruptSelectReadSocket, &dummy, 1) > 0) {} + } + + { + std::lock_guard<std::mutex> lock(runningQueriesMutex); + for (auto&& query : runningQueries) { + if (FD_ISSET(query->getSocketID(), &fdSet)) { + query->processResult(); + } + } + } + } } } diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h index 57fde49..6af1c1f 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h @@ -1,56 +1,55 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> #include <list> -#include <boost/thread/thread.hpp> -#include <boost/thread/mutex.hpp> +#include <memory> +#include <mutex> +#include <thread> -#include <Swiften/LinkLocal/DNSSD/DNSSDQuerier.h> -#include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDQuerier.h> namespace Swift { - class BonjourQuerier : - public DNSSDQuerier, - public boost::enable_shared_from_this<BonjourQuerier> { - public: - BonjourQuerier(EventLoop* eventLoop); - ~BonjourQuerier(); - - boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery(); - boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery( - const std::string& name, int port, const ByteArray& info); - boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery( - const DNSSDServiceID&); - boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery( - const std::string& hostname, int interfaceIndex); - - void start(); - void stop(); - - private: - friend class BonjourQuery; - - void addRunningQuery(boost::shared_ptr<BonjourQuery>); - void removeRunningQuery(boost::shared_ptr<BonjourQuery>); - void interruptSelect(); - void run(); - - private: - EventLoop* eventLoop; - bool stopRequested; - boost::thread* thread; - boost::mutex runningQueriesMutex; - std::list< boost::shared_ptr<BonjourQuery> > runningQueries; - int interruptSelectReadSocket; - int interruptSelectWriteSocket; - boost::condition_variable runningQueriesAvailableEvent; - }; + class BonjourQuerier : + public DNSSDQuerier, + public std::enable_shared_from_this<BonjourQuerier> { + public: + BonjourQuerier(EventLoop* eventLoop); + ~BonjourQuerier(); + + std::shared_ptr<DNSSDBrowseQuery> createBrowseQuery(); + std::shared_ptr<DNSSDRegisterQuery> createRegisterQuery( + const std::string& name, unsigned short port, const ByteArray& info); + std::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery( + const DNSSDServiceID&); + std::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery( + const std::string& hostname, int interfaceIndex); + + void start(); + void stop(); + + private: + friend class BonjourQuery; + + void addRunningQuery(std::shared_ptr<BonjourQuery>); + void removeRunningQuery(std::shared_ptr<BonjourQuery>); + void interruptSelect(); + void run(); + + private: + EventLoop* eventLoop; + bool stopRequested; + std::thread* thread; + std::mutex runningQueriesMutex; + std::list< std::shared_ptr<BonjourQuery> > runningQueries; + int interruptSelectReadSocket; + int interruptSelectWriteSocket; + std::condition_variable runningQueriesAvailableEvent; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.cpp b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.cpp index 9ff4b9f..b4448c7 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.cpp @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h> + #include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h> namespace Swift { -BonjourQuery::BonjourQuery(boost::shared_ptr<BonjourQuerier> q, EventLoop* eventLoop) : eventLoop(eventLoop), querier(q), sdRef(0) { +BonjourQuery::BonjourQuery(std::shared_ptr<BonjourQuerier> q, EventLoop* eventLoop) : eventLoop(eventLoop), querier(q), sdRef(nullptr) { } BonjourQuery::~BonjourQuery() { - DNSServiceRefDeallocate(sdRef); + DNSServiceRefDeallocate(sdRef); } void BonjourQuery::processResult() { - boost::lock_guard<boost::mutex> lock(sdRefMutex); - DNSServiceProcessResult(sdRef); + std::lock_guard<std::mutex> lock(sdRefMutex); + DNSServiceProcessResult(sdRef); } int BonjourQuery::getSocketID() const { - boost::lock_guard<boost::mutex> lock(sdRefMutex); - return DNSServiceRefSockFD(sdRef); + std::lock_guard<std::mutex> lock(sdRefMutex); + return DNSServiceRefSockFD(sdRef); } void BonjourQuery::run() { - querier->addRunningQuery(shared_from_this()); + querier->addRunningQuery(shared_from_this()); } void BonjourQuery::finish() { - querier->removeRunningQuery(shared_from_this()); + querier->removeRunningQuery(shared_from_this()); } } diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h index d91c57c..d3cebe4 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h @@ -1,40 +1,40 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> +#include <mutex> + #include <dns_sd.h> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/thread/mutex.hpp> #include <Swiften/EventLoop/EventOwner.h> namespace Swift { - class BonjourQuerier; - class EventLoop; - - class BonjourQuery : - public EventOwner, - public boost::enable_shared_from_this<BonjourQuery> { - public: - BonjourQuery(boost::shared_ptr<BonjourQuerier>, EventLoop* eventLoop); - virtual ~BonjourQuery(); - - void processResult(); - int getSocketID() const; - - protected: - void run(); - void finish(); - - protected: - EventLoop* eventLoop; - boost::shared_ptr<BonjourQuerier> querier; - mutable boost::mutex sdRefMutex; - DNSServiceRef sdRef; - }; + class BonjourQuerier; + class EventLoop; + + class BonjourQuery : + public EventOwner, + public std::enable_shared_from_this<BonjourQuery> { + public: + BonjourQuery(std::shared_ptr<BonjourQuerier>, EventLoop* eventLoop); + virtual ~BonjourQuery(); + + void processResult(); + int getSocketID() const; + + protected: + void run(); + void finish(); + + protected: + EventLoop* eventLoop; + std::shared_ptr<BonjourQuerier> querier; + mutable std::mutex sdRefMutex; + DNSServiceRef sdRef; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h index 1bec5f7..cc95d64 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h @@ -1,62 +1,79 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h> +#include <mutex> + +#include <boost/numeric/conversion/cast.hpp> + #include <Swiften/Base/ByteArray.h> #include <Swiften/EventLoop/EventLoop.h> -#include <boost/numeric/conversion/cast.hpp> +#include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h> namespace Swift { - class BonjourQuerier; - - class BonjourRegisterQuery : public DNSSDRegisterQuery, public BonjourQuery { - public: - BonjourRegisterQuery(const std::string& name, int port, const ByteArray& txtRecord, boost::shared_ptr<BonjourQuerier> querier, EventLoop* eventLoop) : BonjourQuery(querier, eventLoop) { - DNSServiceErrorType result = DNSServiceRegister( - &sdRef, 0, 0, name.c_str(), "_presence._tcp", NULL, NULL, boost::numeric_cast<unsigned short>(port), - boost::numeric_cast<unsigned short>(txtRecord.size()), vecptr(txtRecord), - &BonjourRegisterQuery::handleServiceRegisteredStatic, this); - if (result != kDNSServiceErr_NoError) { - sdRef = NULL; - } - } - - void registerService() { - if (sdRef) { - run(); - } - else { - eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); - } - } - - void unregisterService() { - finish(); - } - - void updateServiceInfo(const ByteArray& txtRecord) { - boost::lock_guard<boost::mutex> lock(sdRefMutex); - DNSServiceUpdateRecord(sdRef, NULL, 0, boost::numeric_cast<unsigned short>(txtRecord.size()), vecptr(txtRecord), 0); - } - - private: - static void handleServiceRegisteredStatic(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) { - static_cast<BonjourRegisterQuery*>(context)->handleServiceRegistered(errorCode, name, regtype, domain); - } - - void handleServiceRegistered(DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) { - if (errorCode != kDNSServiceErr_NoError) { - eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); - } - else { - eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>(DNSSDServiceID(name, domain, regtype, 0))), shared_from_this()); - } - } - }; + class BonjourQuerier; + + class BonjourRegisterQuery : public DNSSDRegisterQuery, public BonjourQuery { + public: + BonjourRegisterQuery(const std::string& name, unsigned short port, const ByteArray& txtRecord, std::shared_ptr<BonjourQuerier> querier, EventLoop* eventLoop) : BonjourQuery(querier, eventLoop) { + unsigned short recordSize = 0; + try { + recordSize = boost::numeric_cast<unsigned short>(txtRecord.size()); + } + catch (const boost::numeric::bad_numeric_cast&) { + SWIFT_LOG(warning) << "Bonjour TXT record is too long (" << txtRecord.size() << " bytes), not registring service"; + return; + } + DNSServiceErrorType result = DNSServiceRegister( + &sdRef, 0, 0, name.c_str(), "_presence._tcp", nullptr, nullptr, port, + recordSize, vecptr(txtRecord), + &BonjourRegisterQuery::handleServiceRegisteredStatic, this); + if (result != kDNSServiceErr_NoError) { + SWIFT_LOG(warning) << "Failed to register Bonjour service"; + sdRef = nullptr; + } + } + + void registerService() { + if (sdRef) { + run(); + } + else { + eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); + } + } + + void unregisterService() { + finish(); + } + + void updateServiceInfo(const ByteArray& txtRecord) { + std::lock_guard<std::mutex> lock(sdRefMutex); + try { + DNSServiceUpdateRecord(sdRef, nullptr, 0, boost::numeric_cast<unsigned short>(txtRecord.size()), vecptr(txtRecord), 0); + } + catch (const boost::numeric::bad_numeric_cast&) { + SWIFT_LOG(warning) << "Bonjour TXT record is too long (" << txtRecord.size() << " bytes), not updating service record"; + } + } + + private: + static void handleServiceRegisteredStatic(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) { + static_cast<BonjourRegisterQuery*>(context)->handleServiceRegistered(errorCode, name, regtype, domain); + } + + void handleServiceRegistered(DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) { + if (errorCode != kDNSServiceErr_NoError) { + eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); + } + else { + eventLoop->postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>(DNSSDServiceID(name, domain, regtype, 0))), shared_from_this()); + } + } + }; } diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h index 59d1af5..61f000e 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -18,55 +18,60 @@ #include <netinet/in.h> namespace Swift { - class BonjourQuerier; + class BonjourQuerier; - class BonjourResolveHostnameQuery : public DNSSDResolveHostnameQuery, public BonjourQuery { - public: - BonjourResolveHostnameQuery(const std::string& hostname, int interfaceIndex, boost::shared_ptr<BonjourQuerier> querier, EventLoop* eventLoop) : BonjourQuery(querier, eventLoop) { - DNSServiceErrorType result = DNSServiceGetAddrInfo( - &sdRef, 0, boost::numeric_cast<unsigned int>(interfaceIndex), kDNSServiceProtocol_IPv4, - hostname.c_str(), - &BonjourResolveHostnameQuery::handleHostnameResolvedStatic, this); - if (result != kDNSServiceErr_NoError) { - sdRef = NULL; - } - } + class BonjourResolveHostnameQuery : public DNSSDResolveHostnameQuery, public BonjourQuery { + public: + BonjourResolveHostnameQuery(const std::string& hostname, int interfaceIndex, std::shared_ptr<BonjourQuerier> querier, EventLoop* eventLoop) : BonjourQuery(querier, eventLoop) { + try { + DNSServiceErrorType result = DNSServiceGetAddrInfo( + &sdRef, 0, boost::numeric_cast<unsigned int>(interfaceIndex), kDNSServiceProtocol_IPv4, + hostname.c_str(), + &BonjourResolveHostnameQuery::handleHostnameResolvedStatic, this); + if (result != kDNSServiceErr_NoError) { + sdRef = nullptr; + } + } + catch (...) { + sdRef = nullptr; + } + } - //void DNSSDResolveHostnameQuery::run() { - void run() { - if (sdRef) { - BonjourQuery::run(); - } - else { - eventLoop->postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>()), shared_from_this()); - } - } + //void DNSSDResolveHostnameQuery::run() { + void run() { + if (sdRef) { + BonjourQuery::run(); + } + else { + eventLoop->postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>()), shared_from_this()); + } + } - void finish() { - BonjourQuery::finish(); - } + void finish() { + BonjourQuery::finish(); + } - private: - static void handleHostnameResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char*, const struct sockaddr *address, uint32_t, void *context) { - static_cast<BonjourResolveHostnameQuery*>(context)->handleHostnameResolved(errorCode, address); - } + private: + static void handleHostnameResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char*, const struct sockaddr *address, uint32_t, void *context) { + static_cast<BonjourResolveHostnameQuery*>(context)->handleHostnameResolved(errorCode, address); + } - void handleHostnameResolved(DNSServiceErrorType errorCode, const struct sockaddr *rawAddress) { - if (errorCode) { - eventLoop->postEvent( - boost::bind(boost::ref(onHostnameResolved), - boost::optional<HostAddress>()), - shared_from_this()); - } - else { - assert(rawAddress->sa_family == AF_INET); - const sockaddr_in* sa = reinterpret_cast<const sockaddr_in*>(rawAddress); - uint32_t address = ntohl(sa->sin_addr.s_addr); - eventLoop->postEvent(boost::bind( - boost::ref(onHostnameResolved), - HostAddress(reinterpret_cast<unsigned char*>(&address), 4)), - shared_from_this()); - } - } - }; + void handleHostnameResolved(DNSServiceErrorType errorCode, const struct sockaddr *rawAddress) { + if (errorCode) { + eventLoop->postEvent( + boost::bind(boost::ref(onHostnameResolved), + boost::optional<HostAddress>()), + shared_from_this()); + } + else { + assert(rawAddress->sa_family == AF_INET); + const sockaddr_in* sa = reinterpret_cast<const sockaddr_in*>(rawAddress); + uint32_t address = ntohl(sa->sin_addr.s_addr); + eventLoop->postEvent(boost::bind( + boost::ref(onHostnameResolved), + HostAddress(reinterpret_cast<unsigned char*>(&address), 4)), + shared_from_this()); + } + } + }; } diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h index 2eeac64..4baf87b 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h @@ -1,64 +1,71 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <boost/numeric/conversion/cast.hpp> + +#include <Swiften/Base/ByteArray.h> +#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h> #include <Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h> #include <Swiften/LinkLocal/LinkLocalServiceInfo.h> -#include <Swiften/Base/ByteArray.h> -#include <Swiften/EventLoop/EventLoop.h> namespace Swift { - class BonjourQuerier; + class BonjourQuerier; - class BonjourResolveServiceQuery : public DNSSDResolveServiceQuery, public BonjourQuery { - public: - BonjourResolveServiceQuery(const DNSSDServiceID& service, boost::shared_ptr<BonjourQuerier> querier, EventLoop* eventLoop) : BonjourQuery(querier, eventLoop) { - DNSServiceErrorType result = DNSServiceResolve( - &sdRef, 0, boost::numeric_cast<unsigned int>(service.getNetworkInterfaceID()), - service.getName().c_str(), service.getType().c_str(), - service.getDomain().c_str(), - &BonjourResolveServiceQuery::handleServiceResolvedStatic, this); - if (result != kDNSServiceErr_NoError) { - sdRef = NULL; - } - } + class BonjourResolveServiceQuery : public DNSSDResolveServiceQuery, public BonjourQuery { + public: + BonjourResolveServiceQuery(const DNSSDServiceID& service, std::shared_ptr<BonjourQuerier> querier, EventLoop* eventLoop) : BonjourQuery(querier, eventLoop) { + try { + DNSServiceErrorType result = DNSServiceResolve( + &sdRef, 0, boost::numeric_cast<unsigned int>(service.getNetworkInterfaceID()), + service.getName().c_str(), service.getType().c_str(), + service.getDomain().c_str(), + &BonjourResolveServiceQuery::handleServiceResolvedStatic, this); + if (result != kDNSServiceErr_NoError) { + sdRef = nullptr; + } + } + catch (...) { + sdRef = nullptr; + } + } - void start() { - if (sdRef) { - run(); - } - else { - eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this()); - } - } + void start() { + if (sdRef) { + run(); + } + else { + eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this()); + } + } - void stop() { - finish(); - } + void stop() { + finish(); + } - private: - static void handleServiceResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context) { - static_cast<BonjourResolveServiceQuery*>(context)->handleServiceResolved(errorCode, fullname, hosttarget, port, txtLen, txtRecord); - } + private: + static void handleServiceResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context) { + static_cast<BonjourResolveServiceQuery*>(context)->handleServiceResolved(errorCode, fullname, hosttarget, port, txtLen, txtRecord); + } - void handleServiceResolved(DNSServiceErrorType errorCode, const char* fullName, const char* host, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord) { - if (errorCode != kDNSServiceErr_NoError) { - eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this()); - } - else { - //std::cout << "Service resolved: name:" << fullName << " host:" << host << " port:" << port << std::endl; - eventLoop->postEvent( - boost::bind( - boost::ref(onServiceResolved), - Result(std::string(fullName), std::string(host), port, - createByteArray(reinterpret_cast<const char*>(txtRecord), txtLen))), - shared_from_this()); - } - } - }; + void handleServiceResolved(DNSServiceErrorType errorCode, const char* fullName, const char* host, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord) { + if (errorCode != kDNSServiceErr_NoError) { + eventLoop->postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this()); + } + else { + //std::cout << "Service resolved: name:" << fullName << " host:" << host << " port:" << port << std::endl; + eventLoop->postEvent( + boost::bind( + boost::ref(onServiceResolved), + Result(std::string(fullName), std::string(host), port, + createByteArray(reinterpret_cast<const char*>(txtRecord), txtLen))), + shared_from_this()); + } + } + }; } diff --git a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.cpp b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.cpp index 10edb0c..f92a386 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h> diff --git a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h index c2b3be7..f598be1 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h +++ b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h @@ -1,25 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> #include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> namespace Swift { - class DNSSDBrowseQuery { - public: - virtual ~DNSSDBrowseQuery(); + class DNSSDBrowseQuery { + public: + virtual ~DNSSDBrowseQuery(); - virtual void startBrowsing() = 0; - virtual void stopBrowsing() = 0; + virtual void startBrowsing() = 0; + virtual void stopBrowsing() = 0; - boost::signal<void (const DNSSDServiceID&)> onServiceAdded; - boost::signal<void (const DNSSDServiceID&)> onServiceRemoved; - boost::signal<void ()> onError; - }; + boost::signals2::signal<void (const DNSSDServiceID&)> onServiceAdded; + boost::signals2::signal<void (const DNSSDServiceID&)> onServiceRemoved; + boost::signals2::signal<void ()> onError; + }; } diff --git a/Swiften/LinkLocal/DNSSD/DNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.cpp index 0f32aa6..e8df884 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDQuerier.cpp +++ b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/DNSSDQuerier.h> diff --git a/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h index e6d548b..3924c05 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h +++ b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h @@ -1,35 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/ByteArray.h> namespace Swift { - class DNSSDServiceID; - class DNSSDBrowseQuery; - class DNSSDRegisterQuery; - class DNSSDResolveServiceQuery; - class DNSSDResolveHostnameQuery; + class DNSSDServiceID; + class DNSSDBrowseQuery; + class DNSSDRegisterQuery; + class DNSSDResolveServiceQuery; + class DNSSDResolveHostnameQuery; - class DNSSDQuerier { - public: - virtual ~DNSSDQuerier(); + class DNSSDQuerier { + public: + virtual ~DNSSDQuerier(); - virtual void start() = 0; - virtual void stop() = 0; + virtual void start() = 0; + virtual void stop() = 0; - virtual boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery() = 0; - virtual boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery( - const std::string& name, int port, const ByteArray& info) = 0; - virtual boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery( - const DNSSDServiceID&) = 0; - virtual boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery( - const std::string& hostname, int interfaceIndex) = 0; - }; + virtual std::shared_ptr<DNSSDBrowseQuery> createBrowseQuery() = 0; + virtual std::shared_ptr<DNSSDRegisterQuery> createRegisterQuery( + const std::string& name, unsigned short port, const ByteArray& info) = 0; + virtual std::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery( + const DNSSDServiceID&) = 0; + virtual std::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery( + const std::string& hostname, int interfaceIndex) = 0; + }; } diff --git a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.cpp b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.cpp index 9a807a4..8274bed 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h> diff --git a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h index e794a90..6639a85 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h +++ b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h @@ -1,26 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> #include <boost/optional.hpp> +#include <boost/signals2.hpp> -#include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> namespace Swift { - class DNSSDRegisterQuery { - public: - virtual ~DNSSDRegisterQuery(); + class DNSSDRegisterQuery { + public: + virtual ~DNSSDRegisterQuery(); - virtual void registerService() = 0; - virtual void unregisterService() = 0; - virtual void updateServiceInfo(const ByteArray& info) = 0; + virtual void registerService() = 0; + virtual void unregisterService() = 0; + virtual void updateServiceInfo(const ByteArray& info) = 0; - boost::signal<void (boost::optional<DNSSDServiceID>)> onRegisterFinished; - }; + boost::signals2::signal<void (boost::optional<DNSSDServiceID>)> onRegisterFinished; + }; } diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.cpp b/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.cpp index dd34e3d..b8b79ac 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h> diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h index ee8ffb9..f14c248 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h +++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h @@ -1,24 +1,24 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> #include <boost/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Network/HostAddress.h> namespace Swift { - class DNSSDResolveHostnameQuery { - public: - virtual ~DNSSDResolveHostnameQuery(); + class DNSSDResolveHostnameQuery { + public: + virtual ~DNSSDResolveHostnameQuery(); - virtual void run() = 0; - virtual void finish() = 0; + virtual void run() = 0; + virtual void finish() = 0; - boost::signal<void (const boost::optional<HostAddress>&)> onHostnameResolved; - }; + boost::signals2::signal<void (const boost::optional<HostAddress>&)> onHostnameResolved; + }; } diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.cpp b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.cpp index feb1712..060de7d 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h> diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h index c8d78aa..6416d69 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h +++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h @@ -1,34 +1,34 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> #include <boost/optional.hpp> +#include <boost/signals2.hpp> -#include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> namespace Swift { - class DNSSDResolveServiceQuery { - public: - struct Result { - Result(const std::string& fullName, const std::string& host, int port, const ByteArray& info) : - fullName(fullName), host(host), port(port), info(info) {} - std::string fullName; - std::string host; - int port; - ByteArray info; - }; + class DNSSDResolveServiceQuery { + public: + struct Result { + Result(const std::string& fullName, const std::string& host, unsigned short port, const ByteArray& info) : + fullName(fullName), host(host), port(port), info(info) {} + std::string fullName; + std::string host; + unsigned short port; + ByteArray info; + }; - virtual ~DNSSDResolveServiceQuery(); + virtual ~DNSSDResolveServiceQuery(); - virtual void start() = 0; - virtual void stop() = 0; + virtual void start() = 0; + virtual void stop() = 0; - boost::signal<void (const boost::optional<Result>&)> onServiceResolved; - }; + boost::signals2::signal<void (const boost::optional<Result>&)> onServiceResolved; + }; } diff --git a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp index 2f2784c..38d14c1 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp +++ b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> diff --git a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h index 6c36de0..5f8c2eb 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h +++ b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h @@ -1,73 +1,74 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> #include <string> +#include <Swiften/Base/API.h> + namespace Swift { - class SWIFTEN_API DNSSDServiceID { - public: - static const char* PresenceServiceType; + class SWIFTEN_API DNSSDServiceID { + public: + static const char* PresenceServiceType; - DNSSDServiceID( - const std::string& name, - const std::string& domain, - const std::string& type = PresenceServiceType, - int networkInterface = -1) : - name(name), - domain(domain), - type(type), - networkInterface(networkInterface) { - } + DNSSDServiceID( + const std::string& name, + const std::string& domain, + const std::string& type = PresenceServiceType, + int networkInterface = -1) : + name(name), + domain(domain), + type(type), + networkInterface(networkInterface) { + } - bool operator==(const DNSSDServiceID& o) const { - return name == o.name && domain == o.domain && type == o.type && (networkInterface != 0 && o.networkInterface != 0 ? networkInterface == o.networkInterface : true); - } + bool operator==(const DNSSDServiceID& o) const { + return name == o.name && domain == o.domain && type == o.type && (networkInterface != 0 && o.networkInterface != 0 ? networkInterface == o.networkInterface : true); + } - bool operator<(const DNSSDServiceID& o) const { - if (o.name == name) { - if (o.domain == domain) { - if (o.type == type) { - return networkInterface < o.networkInterface; - } - else { - return type < o.type; - } - } - else { - return domain < o.domain; - } - } - else { - return o.name < name; - } - } + bool operator<(const DNSSDServiceID& o) const { + if (o.name == name) { + if (o.domain == domain) { + if (o.type == type) { + return networkInterface < o.networkInterface; + } + else { + return type < o.type; + } + } + else { + return domain < o.domain; + } + } + else { + return o.name < name; + } + } - const std::string& getName() const { - return name; - } + const std::string& getName() const { + return name; + } - const std::string& getDomain() const { - return domain; - } + const std::string& getDomain() const { + return domain; + } - const std::string& getType() const { - return type; - } + const std::string& getType() const { + return type; + } - int getNetworkInterfaceID() const { - return networkInterface; - } + int getNetworkInterfaceID() const { + return networkInterface; + } - private: - std::string name; - std::string domain; - std::string type; - int networkInterface; - }; + private: + std::string name; + std::string domain; + std::string type; + int networkInterface; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h index b2a6d61..15d8128 100644 --- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h> #include <Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h> +#include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h> namespace Swift { - class FakeDNSSDQuerier; + class FakeDNSSDQuerier; - class FakeDNSSDBrowseQuery : public DNSSDBrowseQuery, public FakeDNSSDQuery { - public: - FakeDNSSDBrowseQuery(boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier) { - } + class FakeDNSSDBrowseQuery : public DNSSDBrowseQuery, public FakeDNSSDQuery { + public: + FakeDNSSDBrowseQuery(std::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier) { + } - void startBrowsing() { - run(); - } + void startBrowsing() { + run(); + } - void stopBrowsing() { - finish(); - } - }; + void stopBrowsing() { + finish(); + } + }; } diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp index 1ddeffa..3381a26 100644 --- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp @@ -1,21 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h> -#include <boost/bind.hpp> #include <iostream> -#include <Swiften/Base/foreach.h> +#include <boost/bind.hpp> + #include <Swiften/Base/Algorithm.h> +#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h> #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h> -#include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h> #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h> -#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h> namespace Swift { @@ -23,117 +23,117 @@ FakeDNSSDQuerier::FakeDNSSDQuerier(const std::string& domain, EventLoop* eventLo } FakeDNSSDQuerier::~FakeDNSSDQuerier() { - if (!runningQueries.empty()) { - std::cerr << "FakeDNSSDQuerier: Running queries not empty at destruction time" << std::endl; - } + if (!runningQueries.empty()) { + std::cerr << "FakeDNSSDQuerier: Running queries not empty at destruction time" << std::endl; + } } -boost::shared_ptr<DNSSDBrowseQuery> FakeDNSSDQuerier::createBrowseQuery() { - return boost::shared_ptr<DNSSDBrowseQuery>(new FakeDNSSDBrowseQuery(shared_from_this())); +std::shared_ptr<DNSSDBrowseQuery> FakeDNSSDQuerier::createBrowseQuery() { + return std::make_shared<FakeDNSSDBrowseQuery>(shared_from_this()); } -boost::shared_ptr<DNSSDRegisterQuery> FakeDNSSDQuerier::createRegisterQuery(const std::string& name, int port, const ByteArray& info) { - return boost::shared_ptr<DNSSDRegisterQuery>(new FakeDNSSDRegisterQuery(name, port, info, shared_from_this())); +std::shared_ptr<DNSSDRegisterQuery> FakeDNSSDQuerier::createRegisterQuery(const std::string& name, unsigned short port, const ByteArray& info) { + return std::make_shared<FakeDNSSDRegisterQuery>(name, port, info, shared_from_this()); } -boost::shared_ptr<DNSSDResolveServiceQuery> FakeDNSSDQuerier::createResolveServiceQuery(const DNSSDServiceID& service) { - return boost::shared_ptr<DNSSDResolveServiceQuery>(new FakeDNSSDResolveServiceQuery(service, shared_from_this())); +std::shared_ptr<DNSSDResolveServiceQuery> FakeDNSSDQuerier::createResolveServiceQuery(const DNSSDServiceID& service) { + return std::make_shared<FakeDNSSDResolveServiceQuery>(service, shared_from_this()); } -boost::shared_ptr<DNSSDResolveHostnameQuery> FakeDNSSDQuerier::createResolveHostnameQuery(const std::string& hostname, int interfaceIndex) { - return boost::shared_ptr<DNSSDResolveHostnameQuery>(new FakeDNSSDResolveHostnameQuery(hostname, interfaceIndex, shared_from_this())); +std::shared_ptr<DNSSDResolveHostnameQuery> FakeDNSSDQuerier::createResolveHostnameQuery(const std::string& hostname, int interfaceIndex) { + return std::make_shared<FakeDNSSDResolveHostnameQuery>(hostname, interfaceIndex, shared_from_this()); } -void FakeDNSSDQuerier::addRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query) { - runningQueries.push_back(query); - allQueriesEverRun.push_back(query); - if (boost::shared_ptr<FakeDNSSDBrowseQuery> browseQuery = boost::dynamic_pointer_cast<FakeDNSSDBrowseQuery>(query)) { - foreach(const DNSSDServiceID& service, services) { - eventLoop->postEvent(boost::bind(boost::ref(browseQuery->onServiceAdded), service), shared_from_this()); - } - } - else if (boost::shared_ptr<FakeDNSSDResolveServiceQuery> resolveQuery = boost::dynamic_pointer_cast<FakeDNSSDResolveServiceQuery>(query)) { - for(ServiceInfoMap::const_iterator i = serviceInfo.begin(); i != serviceInfo.end(); ++i) { - if (i->first == resolveQuery->service) { - eventLoop->postEvent(boost::bind(boost::ref(resolveQuery->onServiceResolved), i->second), shared_from_this()); - } - } - } - else if (boost::shared_ptr<FakeDNSSDRegisterQuery> registerQuery = boost::dynamic_pointer_cast<FakeDNSSDRegisterQuery>(query)) { - DNSSDServiceID service(registerQuery->name, domain); - eventLoop->postEvent(boost::bind(boost::ref(registerQuery->onRegisterFinished), service), shared_from_this()); - } - else if (boost::shared_ptr<FakeDNSSDResolveHostnameQuery> resolveHostnameQuery = boost::dynamic_pointer_cast<FakeDNSSDResolveHostnameQuery>(query)) { - std::map<std::string,boost::optional<HostAddress> >::const_iterator i = addresses.find(resolveHostnameQuery->hostname); - if (i != addresses.end()) { - eventLoop->postEvent( - boost::bind( - boost::ref(resolveHostnameQuery->onHostnameResolved), i->second), - shared_from_this()); - } - } +void FakeDNSSDQuerier::addRunningQuery(std::shared_ptr<FakeDNSSDQuery> query) { + runningQueries.push_back(query); + allQueriesEverRun.push_back(query); + if (std::shared_ptr<FakeDNSSDBrowseQuery> browseQuery = std::dynamic_pointer_cast<FakeDNSSDBrowseQuery>(query)) { + for (const auto& service : services) { + eventLoop->postEvent(boost::bind(boost::ref(browseQuery->onServiceAdded), service), shared_from_this()); + } + } + else if (std::shared_ptr<FakeDNSSDResolveServiceQuery> resolveQuery = std::dynamic_pointer_cast<FakeDNSSDResolveServiceQuery>(query)) { + for (const auto& i : serviceInfo) { + if (i.first == resolveQuery->service) { + eventLoop->postEvent(boost::bind(boost::ref(resolveQuery->onServiceResolved), i.second), shared_from_this()); + } + } + } + else if (std::shared_ptr<FakeDNSSDRegisterQuery> registerQuery = std::dynamic_pointer_cast<FakeDNSSDRegisterQuery>(query)) { + DNSSDServiceID service(registerQuery->name, domain); + eventLoop->postEvent(boost::bind(boost::ref(registerQuery->onRegisterFinished), service), shared_from_this()); + } + else if (std::shared_ptr<FakeDNSSDResolveHostnameQuery> resolveHostnameQuery = std::dynamic_pointer_cast<FakeDNSSDResolveHostnameQuery>(query)) { + std::map<std::string,boost::optional<HostAddress> >::const_iterator i = addresses.find(resolveHostnameQuery->hostname); + if (i != addresses.end()) { + eventLoop->postEvent( + boost::bind( + boost::ref(resolveHostnameQuery->onHostnameResolved), i->second), + shared_from_this()); + } + } } -void FakeDNSSDQuerier::removeRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query) { - erase(runningQueries, query); +void FakeDNSSDQuerier::removeRunningQuery(std::shared_ptr<FakeDNSSDQuery> query) { + erase(runningQueries, query); } void FakeDNSSDQuerier::addService(const DNSSDServiceID& id) { - services.insert(id); - foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) { - eventLoop->postEvent(boost::bind(boost::ref(query->onServiceAdded), id), shared_from_this()); - } + services.insert(id); + for (const auto& query : getQueries<FakeDNSSDBrowseQuery>()) { + eventLoop->postEvent(boost::bind(boost::ref(query->onServiceAdded), id), shared_from_this()); + } } void FakeDNSSDQuerier::removeService(const DNSSDServiceID& id) { - services.erase(id); - serviceInfo.erase(id); - foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) { - eventLoop->postEvent(boost::bind(boost::ref(query->onServiceRemoved), id), shared_from_this()); - } + services.erase(id); + serviceInfo.erase(id); + for (const auto& query : getQueries<FakeDNSSDBrowseQuery>()) { + eventLoop->postEvent(boost::bind(boost::ref(query->onServiceRemoved), id), shared_from_this()); + } } void FakeDNSSDQuerier::setServiceInfo(const DNSSDServiceID& id, const DNSSDResolveServiceQuery::Result& info) { - std::pair<ServiceInfoMap::iterator, bool> r = serviceInfo.insert(std::make_pair(id, info)); - if (!r.second) { - r.first->second = info; - } - foreach(const boost::shared_ptr<FakeDNSSDResolveServiceQuery>& query, getQueries<FakeDNSSDResolveServiceQuery>()) { - if (query->service == id) { - eventLoop->postEvent(boost::bind(boost::ref(query->onServiceResolved), info), shared_from_this()); - } - } -} - -bool FakeDNSSDQuerier::isServiceRegistered(const std::string& name, int port, const ByteArray& info) { - foreach(const boost::shared_ptr<FakeDNSSDRegisterQuery>& query, getQueries<FakeDNSSDRegisterQuery>()) { - if (query->name == name && query->port == port && query->info == info) { - return true; - } - } - return false; + std::pair<ServiceInfoMap::iterator, bool> r = serviceInfo.insert(std::make_pair(id, info)); + if (!r.second) { + r.first->second = info; + } + for (const auto& query : getQueries<FakeDNSSDResolveServiceQuery>()) { + if (query->service == id) { + eventLoop->postEvent(boost::bind(boost::ref(query->onServiceResolved), info), shared_from_this()); + } + } +} + +bool FakeDNSSDQuerier::isServiceRegistered(const std::string& name, unsigned short port, const ByteArray& info) { + for (const auto& query : getQueries<FakeDNSSDRegisterQuery>()) { + if (query->name == name && query->port == port && query->info == info) { + return true; + } + } + return false; } void FakeDNSSDQuerier::setBrowseError() { - foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) { - eventLoop->postEvent(boost::ref(query->onError), shared_from_this()); - } + for (const auto& query : getQueries<FakeDNSSDBrowseQuery>()) { + eventLoop->postEvent(boost::ref(query->onError), shared_from_this()); + } } void FakeDNSSDQuerier::setRegisterError() { - foreach(const boost::shared_ptr<FakeDNSSDRegisterQuery>& query, getQueries<FakeDNSSDRegisterQuery>()) { - eventLoop->postEvent(boost::bind(boost::ref(query->onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); - } + for (const auto& query : getQueries<FakeDNSSDRegisterQuery>()) { + eventLoop->postEvent(boost::bind(boost::ref(query->onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); + } } void FakeDNSSDQuerier::setAddress(const std::string& hostname, boost::optional<HostAddress> address) { - addresses[hostname] = address; - foreach(const boost::shared_ptr<FakeDNSSDResolveHostnameQuery>& query, getQueries<FakeDNSSDResolveHostnameQuery>()) { - if (query->hostname == hostname) { - eventLoop->postEvent(boost::bind( - boost::ref(query->onHostnameResolved), address), shared_from_this()); - } - } + addresses[hostname] = address; + for (const auto& query : getQueries<FakeDNSSDResolveHostnameQuery>()) { + if (query->hostname == hostname) { + eventLoop->postEvent(boost::bind( + boost::ref(query->onHostnameResolved), address), shared_from_this()); + } + } } } diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h index 9fc4608..07cb75c 100644 --- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h @@ -1,17 +1,16 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> #include <list> +#include <memory> #include <set> - #include <string> + #include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/EventLoop/EventOwner.h> @@ -20,78 +19,77 @@ #include <Swiften/Network/HostAddress.h> namespace Swift { - class FakeDNSSDQuery; - class FakeDNSSDBrowseQuery; - class EventLoop; + class FakeDNSSDQuery; + class EventLoop; - class SWIFTEN_API FakeDNSSDQuerier : - public DNSSDQuerier, - public EventOwner, - public boost::enable_shared_from_this<FakeDNSSDQuerier> { - public: - FakeDNSSDQuerier(const std::string& domain, EventLoop* eventLoop); - ~FakeDNSSDQuerier(); + class SWIFTEN_API FakeDNSSDQuerier : + public DNSSDQuerier, + public EventOwner, + public std::enable_shared_from_this<FakeDNSSDQuerier> { + public: + FakeDNSSDQuerier(const std::string& domain, EventLoop* eventLoop); + ~FakeDNSSDQuerier(); - void start() {} - void stop() {} + void start() {} + void stop() {} - void clearAllQueriesEverRun() { - allQueriesEverRun.clear(); - } + void clearAllQueriesEverRun() { + allQueriesEverRun.clear(); + } - boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery(); - boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery( - const std::string& name, int port, const ByteArray& info); - boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery( - const DNSSDServiceID&); - boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery( - const std::string& hostname, int interfaceIndex); + std::shared_ptr<DNSSDBrowseQuery> createBrowseQuery(); + std::shared_ptr<DNSSDRegisterQuery> createRegisterQuery( + const std::string& name, unsigned short port, const ByteArray& info); + std::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery( + const DNSSDServiceID&); + std::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery( + const std::string& hostname, int interfaceIndex); - void addRunningQuery(boost::shared_ptr<FakeDNSSDQuery>); - void removeRunningQuery(boost::shared_ptr<FakeDNSSDQuery>); + void addRunningQuery(std::shared_ptr<FakeDNSSDQuery>); + void removeRunningQuery(std::shared_ptr<FakeDNSSDQuery>); - void addService(const DNSSDServiceID& id); - void removeService(const DNSSDServiceID& id); - void setServiceInfo(const DNSSDServiceID& id, const DNSSDResolveServiceQuery::Result& info); - bool isServiceRegistered(const std::string& name, int port, const ByteArray& info); - void setAddress(const std::string& hostname, boost::optional<HostAddress> address); + void addService(const DNSSDServiceID& id); + void removeService(const DNSSDServiceID& id); + void setServiceInfo(const DNSSDServiceID& id, const DNSSDResolveServiceQuery::Result& info); + bool isServiceRegistered(const std::string& name, unsigned short port, const ByteArray& info); + void setAddress(const std::string& hostname, boost::optional<HostAddress> address); - void setBrowseError(); - void setRegisterError(); + void setBrowseError(); + void setRegisterError(); - public: - template<typename T> - std::vector< boost::shared_ptr<T> > getAllQueriesEverRun() const { - std::vector< boost::shared_ptr<T> > result; - for (QueryList::const_iterator i = allQueriesEverRun.begin(); i != allQueriesEverRun.end(); ++i) { - if (boost::shared_ptr<T> resultQuery = boost::dynamic_pointer_cast<T>(*i)) { - result.push_back(resultQuery); - } - } - return result; - } + public: + template<typename T> + std::vector< std::shared_ptr<T> > getAllQueriesEverRun() const { + std::vector< std::shared_ptr<T> > result; + for (const auto& i : allQueriesEverRun) { + if (std::shared_ptr<T> resultQuery = std::dynamic_pointer_cast<T>(i)) { + result.push_back(resultQuery); + } + } + return result; + } - private: - template<typename T> - std::vector< boost::shared_ptr<T> > getQueries() const { - std::vector< boost::shared_ptr<T> > result; - for (QueryList::const_iterator i = runningQueries.begin(); i != runningQueries.end(); ++i) { - if (boost::shared_ptr<T> resultQuery = boost::dynamic_pointer_cast<T>(*i)) { - result.push_back(resultQuery); - } - } - return result; - } + private: + template<typename T> + std::vector< std::shared_ptr<T> > getQueries() const { + std::vector< std::shared_ptr<T> > result; + for (const auto& runningQuerie : runningQueries) { + if (std::shared_ptr<T> resultQuery = std::dynamic_pointer_cast<T>(runningQuerie)) { + result.push_back(resultQuery); + } + } + return result; + } - private: - std::string domain; - EventLoop* eventLoop; - typedef std::list< boost::shared_ptr<FakeDNSSDQuery> > QueryList; - QueryList runningQueries; - QueryList allQueriesEverRun; - std::set<DNSSDServiceID> services; - typedef std::map<DNSSDServiceID,DNSSDResolveServiceQuery::Result> ServiceInfoMap; - ServiceInfoMap serviceInfo; - std::map<std::string, boost::optional<HostAddress> > addresses; - }; + private: + std::string domain; + EventLoop* eventLoop; + typedef std::list< std::shared_ptr<FakeDNSSDQuery> > QueryList; + QueryList runningQueries; + QueryList allQueriesEverRun; + std::set<DNSSDServiceID> services; + typedef std::map<DNSSDServiceID,DNSSDResolveServiceQuery::Result> ServiceInfoMap; + ServiceInfoMap serviceInfo; + std::map<std::string, boost::optional<HostAddress> > addresses; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp index 99f55fa..0e05968 100644 --- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp @@ -1,26 +1,27 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h> + #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h> namespace Swift { -FakeDNSSDQuery::FakeDNSSDQuery(boost::shared_ptr<FakeDNSSDQuerier> querier) : querier(querier) { +FakeDNSSDQuery::FakeDNSSDQuery(std::shared_ptr<FakeDNSSDQuerier> querier) : querier(querier) { } FakeDNSSDQuery::~FakeDNSSDQuery() { } void FakeDNSSDQuery::run() { - querier->addRunningQuery(shared_from_this()); + querier->addRunningQuery(shared_from_this()); } void FakeDNSSDQuery::finish() { - querier->removeRunningQuery(shared_from_this()); + querier->removeRunningQuery(shared_from_this()); } } diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h index b6d5c98..5d869d4 100644 --- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h @@ -1,31 +1,30 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <memory> #include <Swiften/EventLoop/EventOwner.h> namespace Swift { - class FakeDNSSDQuerier; + class FakeDNSSDQuerier; - class FakeDNSSDQuery : - public EventOwner, - public boost::enable_shared_from_this<FakeDNSSDQuery> { - public: - FakeDNSSDQuery(boost::shared_ptr<FakeDNSSDQuerier>); - virtual ~FakeDNSSDQuery(); - - protected: - void run(); - void finish(); - - protected: - boost::shared_ptr<FakeDNSSDQuerier> querier; - }; + class FakeDNSSDQuery : + public EventOwner, + public std::enable_shared_from_this<FakeDNSSDQuery> { + public: + FakeDNSSDQuery(std::shared_ptr<FakeDNSSDQuerier>); + virtual ~FakeDNSSDQuery(); + + protected: + void run(); + void finish(); + + protected: + std::shared_ptr<FakeDNSSDQuerier> querier; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h index c568f5b..ee6bb92 100644 --- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h @@ -1,38 +1,39 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h> -#include <Swiften/Base/ByteArray.h> #include <string> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h> +#include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h> + namespace Swift { - class FakeDNSSDQuerier; + class FakeDNSSDQuerier; - class FakeDNSSDRegisterQuery : public DNSSDRegisterQuery, public FakeDNSSDQuery { - public: - FakeDNSSDRegisterQuery(const std::string& name, int port, const ByteArray& info, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), name(name), port(port), info(info) { - } + class FakeDNSSDRegisterQuery : public DNSSDRegisterQuery, public FakeDNSSDQuery { + public: + FakeDNSSDRegisterQuery(const std::string& name, unsigned short port, const ByteArray& info, std::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), name(name), port(port), info(info) { + } - void registerService() { - run(); - } + void registerService() { + run(); + } - void updateServiceInfo(const ByteArray& i) { - info = i; - } + void updateServiceInfo(const ByteArray& i) { + info = i; + } - void unregisterService() { - finish(); - } + void unregisterService() { + finish(); + } - std::string name; - int port; - ByteArray info; - }; + std::string name; + unsigned short port; + ByteArray info; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h index aa427cc..60dc144 100644 --- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h @@ -1,33 +1,34 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> -#include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h> + #include <Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h> +#include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h> #include <Swiften/Network/HostAddress.h> namespace Swift { - class FakeDNSSDQuerier; + class FakeDNSSDQuerier; - class FakeDNSSDResolveHostnameQuery : public DNSSDResolveHostnameQuery, public FakeDNSSDQuery { - public: - FakeDNSSDResolveHostnameQuery(const std::string& hostname, int interfaceIndex, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), hostname(hostname), interfaceIndex(interfaceIndex) { - } + class FakeDNSSDResolveHostnameQuery : public DNSSDResolveHostnameQuery, public FakeDNSSDQuery { + public: + FakeDNSSDResolveHostnameQuery(const std::string& hostname, int interfaceIndex, std::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), hostname(hostname), interfaceIndex(interfaceIndex) { + } - void run() { - FakeDNSSDQuery::run(); - } + void run() { + FakeDNSSDQuery::run(); + } - void finish() { - FakeDNSSDQuery::finish(); - } + void finish() { + FakeDNSSDQuery::finish(); + } - std::string hostname; - int interfaceIndex; - }; + std::string hostname; + int interfaceIndex; + }; } diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h index 5c69843..8a02e7b 100644 --- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h @@ -1,31 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h> #include <Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h> +#include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h> #include <Swiften/LinkLocal/LinkLocalServiceInfo.h> namespace Swift { - class FakeDNSSDQuerier; + class FakeDNSSDQuerier; - class FakeDNSSDResolveServiceQuery : public DNSSDResolveServiceQuery, public FakeDNSSDQuery { - public: - FakeDNSSDResolveServiceQuery(const DNSSDServiceID& service, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), service(service) { - } + class FakeDNSSDResolveServiceQuery : public DNSSDResolveServiceQuery, public FakeDNSSDQuery { + public: + FakeDNSSDResolveServiceQuery(const DNSSDServiceID& service, std::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), service(service) { + } - void start() { - run(); - } + void start() { + run(); + } - void stop() { - finish(); - } + void stop() { + finish(); + } - DNSSDServiceID service; - }; + DNSSDServiceID service; + }; } diff --git a/Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.cpp b/Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.cpp index cc12573..e20326b 100644 --- a/Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.cpp +++ b/Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.h> @@ -18,21 +18,22 @@ namespace Swift { PlatformDNSSDQuerierFactory::PlatformDNSSDQuerierFactory(EventLoop* eventLoop) : eventLoop(eventLoop) { } -boost::shared_ptr<DNSSDQuerier> PlatformDNSSDQuerierFactory::createQuerier() { +std::shared_ptr<DNSSDQuerier> PlatformDNSSDQuerierFactory::createQuerier() { #if defined(HAVE_BONJOUR) - return boost::shared_ptr<DNSSDQuerier>(new BonjourQuerier(eventLoop)); + return std::make_shared<BonjourQuerier>(eventLoop); #elif defined(HAVE_AVAHI) - return boost::shared_ptr<DNSSDQuerier>(new AvahiQuerier(eventLoop)); + return std::make_shared<AvahiQuerier>(eventLoop); #else - return boost::shared_ptr<DNSSDQuerier>(); + (void)eventLoop; + return std::shared_ptr<DNSSDQuerier>(); #endif } bool PlatformDNSSDQuerierFactory::canCreate() { #if defined(HAVE_BONJOUR) || defined(HAVE_AVAHI) - return true; + return true; #else - return false; + return false; #endif } diff --git a/Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.h b/Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.h index 2eb21ed..68e10cf 100644 --- a/Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.h +++ b/Swiften/LinkLocal/DNSSD/PlatformDNSSDQuerierFactory.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> namespace Swift { - class DNSSDQuerier; - class EventLoop; + class DNSSDQuerier; + class EventLoop; - class SWIFTEN_API PlatformDNSSDQuerierFactory { - public: - PlatformDNSSDQuerierFactory(EventLoop* eventLoop); + class SWIFTEN_API PlatformDNSSDQuerierFactory { + public: + PlatformDNSSDQuerierFactory(EventLoop* eventLoop); - boost::shared_ptr<DNSSDQuerier> createQuerier(); + std::shared_ptr<DNSSDQuerier> createQuerier(); - bool canCreate(); + bool canCreate(); - private: - EventLoop* eventLoop; - }; + private: + EventLoop* eventLoop; + }; } diff --git a/Swiften/LinkLocal/IncomingLinkLocalSession.cpp b/Swiften/LinkLocal/IncomingLinkLocalSession.cpp index 610b28b..9d446a9 100644 --- a/Swiften/LinkLocal/IncomingLinkLocalSession.cpp +++ b/Swiften/LinkLocal/IncomingLinkLocalSession.cpp @@ -1,68 +1,69 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/IncomingLinkLocalSession.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Elements/IQ.h> #include <Swiften/Elements/ProtocolHeader.h> +#include <Swiften/Elements/StreamFeatures.h> #include <Swiften/Network/Connection.h> -#include <Swiften/StreamStack/StreamStack.h> #include <Swiften/StreamStack/ConnectionLayer.h> +#include <Swiften/StreamStack/StreamStack.h> #include <Swiften/StreamStack/XMPPLayer.h> -#include <Swiften/Elements/StreamFeatures.h> -#include <Swiften/Elements/IQ.h> namespace Swift { IncomingLinkLocalSession::IncomingLinkLocalSession( - const JID& localJID, - boost::shared_ptr<Connection> connection, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - XMLParserFactory* xmlParserFactory) : - Session(connection, payloadParserFactories, payloadSerializers, xmlParserFactory), - initialized(false) { - setLocalJID(localJID); + const JID& localJID, + std::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + XMLParserFactory* xmlParserFactory) : + Session(connection, payloadParserFactories, payloadSerializers, xmlParserFactory), + initialized(false) { + setLocalJID(localJID); } void IncomingLinkLocalSession::handleStreamStart(const ProtocolHeader& incomingHeader) { - setRemoteJID(JID(incomingHeader.getFrom())); - if (!getRemoteJID().isValid()) { - finishSession(); - return; - } + setRemoteJID(JID(incomingHeader.getFrom())); + if (!getRemoteJID().isValid()) { + finishSession(); + return; + } - ProtocolHeader header; - header.setFrom(getLocalJID()); - getXMPPLayer()->writeHeader(header); + ProtocolHeader header; + header.setFrom(getLocalJID()); + getXMPPLayer()->writeHeader(header); - if (incomingHeader.getVersion() == "1.0") { - getXMPPLayer()->writeElement(boost::make_shared<StreamFeatures>()); - } - else { - setInitialized(); - } + if (incomingHeader.getVersion() == "1.0") { + getXMPPLayer()->writeElement(std::make_shared<StreamFeatures>()); + } + else { + setInitialized(); + } } -void IncomingLinkLocalSession::handleElement(boost::shared_ptr<Element> element) { - boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element); - // If we get our first stanza before streamfeatures, our session is implicitly - // initialized - if (stanza && !isInitialized()) { - setInitialized(); - } - - onElementReceived(element); +void IncomingLinkLocalSession::handleElement(std::shared_ptr<ToplevelElement> element) { + std::shared_ptr<Stanza> stanza = std::dynamic_pointer_cast<Stanza>(element); + // If we get our first stanza before streamfeatures, our session is implicitly + // initialized + if (stanza && !isInitialized()) { + setInitialized(); + } + + onElementReceived(element); } void IncomingLinkLocalSession::setInitialized() { - initialized = true; - onSessionStarted(); + initialized = true; + onSessionStarted(); } diff --git a/Swiften/LinkLocal/IncomingLinkLocalSession.h b/Swiften/LinkLocal/IncomingLinkLocalSession.h index f00c166..9760bb7 100644 --- a/Swiften/LinkLocal/IncomingLinkLocalSession.h +++ b/Swiften/LinkLocal/IncomingLinkLocalSession.h @@ -1,44 +1,46 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> +#include <memory> -#include <Swiften/Session/Session.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> #include <Swiften/Network/Connection.h> +#include <Swiften/Session/Session.h> namespace Swift { - class ProtocolHeader; - class XMLParserFactory; - class Element; - class PayloadParserFactoryCollection; - class PayloadSerializerCollection; - - class IncomingLinkLocalSession : public Session { - public: - IncomingLinkLocalSession( - const JID& localJID, - boost::shared_ptr<Connection> connection, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - XMLParserFactory* xmlParserFactory); - - boost::signal<void ()> onSessionStarted; - - private: - void handleElement(boost::shared_ptr<Element>); - void handleStreamStart(const ProtocolHeader&); - void setInitialized(); - bool isInitialized() const { - return initialized; - } - - bool initialized; - }; + class ProtocolHeader; + class XMLParserFactory; + class ToplevelElement; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + + class SWIFTEN_API IncomingLinkLocalSession : public Session { + public: + IncomingLinkLocalSession( + const JID& localJID, + std::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + XMLParserFactory* xmlParserFactory); + + boost::signals2::signal<void ()> onSessionStarted; + + private: + void handleElement(std::shared_ptr<ToplevelElement>); + void handleStreamStart(const ProtocolHeader&); + void setInitialized(); + bool isInitialized() const { + return initialized; + } + + bool initialized; + }; } diff --git a/Swiften/LinkLocal/LinkLocalConnector.cpp b/Swiften/LinkLocal/LinkLocalConnector.cpp index af96e65..d961030 100644 --- a/Swiften/LinkLocal/LinkLocalConnector.cpp +++ b/Swiften/LinkLocal/LinkLocalConnector.cpp @@ -1,78 +1,78 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/LinkLocalConnector.h> #include <boost/bind.hpp> +#include <Swiften/LinkLocal/DNSSD/DNSSDQuerier.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/ConnectionFactory.h> #include <Swiften/Network/HostAddress.h> #include <Swiften/Network/HostAddressPort.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDQuerier.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h> namespace Swift { LinkLocalConnector::LinkLocalConnector( - const LinkLocalService& service, - boost::shared_ptr<DNSSDQuerier> querier, - boost::shared_ptr<Connection> connection) : - service(service), - querier(querier), - connection(connection) { + const LinkLocalService& service, + std::shared_ptr<DNSSDQuerier> querier, + std::shared_ptr<Connection> connection) : + service(service), + querier(querier), + connection(connection) { } LinkLocalConnector::~LinkLocalConnector() { - assert(!resolveQuery); + assert(!resolveQuery); } void LinkLocalConnector::connect() { - resolveQuery = querier->createResolveHostnameQuery( - service.getHostname(), - service.getID().getNetworkInterfaceID()); - resolveQueryHostNameResolvedConnection = resolveQuery->onHostnameResolved.connect(boost::bind( - &LinkLocalConnector::handleHostnameResolved, - boost::dynamic_pointer_cast<LinkLocalConnector>(shared_from_this()), - _1)); - resolveQuery->run(); + resolveQuery = querier->createResolveHostnameQuery( + service.getHostname(), + service.getID().getNetworkInterfaceID()); + resolveQueryHostNameResolvedConnection = resolveQuery->onHostnameResolved.connect(boost::bind( + &LinkLocalConnector::handleHostnameResolved, + std::dynamic_pointer_cast<LinkLocalConnector>(shared_from_this()), + _1)); + resolveQuery->run(); } void LinkLocalConnector::cancel() { - if (resolveQuery) { - resolveQuery->finish(); - resolveQueryHostNameResolvedConnection.disconnect(); - resolveQuery.reset(); - } - connectionConnectFinishedConnection.disconnect(); - connection->disconnect(); + if (resolveQuery) { + resolveQuery->finish(); + resolveQueryHostNameResolvedConnection.disconnect(); + resolveQuery.reset(); + } + connectionConnectFinishedConnection.disconnect(); + connection->disconnect(); } void LinkLocalConnector::handleHostnameResolved(const boost::optional<HostAddress>& address) { - resolveQuery->finish(); - resolveQueryHostNameResolvedConnection.disconnect(); - resolveQuery.reset(); - if (address) { - connectionConnectFinishedConnection = connection->onConnectFinished.connect( - boost::bind(&LinkLocalConnector::handleConnected, shared_from_this(), _1)); - connection->connect(HostAddressPort(*address, service.getPort())); - } - else { - onConnectFinished(true); - } + resolveQuery->finish(); + resolveQueryHostNameResolvedConnection.disconnect(); + resolveQuery.reset(); + if (address) { + connectionConnectFinishedConnection = connection->onConnectFinished.connect( + boost::bind(&LinkLocalConnector::handleConnected, shared_from_this(), _1)); + connection->connect(HostAddressPort(*address, service.getPort())); + } + else { + onConnectFinished(true); + } } void LinkLocalConnector::handleConnected(bool error) { - onConnectFinished(error); - assert(connectionConnectFinishedConnection.connected()); - connectionConnectFinishedConnection.disconnect(); + onConnectFinished(error); + assert(connectionConnectFinishedConnection.connected()); + connectionConnectFinishedConnection.disconnect(); } -void LinkLocalConnector::queueElement(boost::shared_ptr<Element> element) { - queuedElements.push_back(element); +void LinkLocalConnector::queueElement(std::shared_ptr<ToplevelElement> element) { + queuedElements.push_back(element); } diff --git a/Swiften/LinkLocal/LinkLocalConnector.h b/Swiften/LinkLocal/LinkLocalConnector.h index 52692ef..044b74f 100644 --- a/Swiften/LinkLocal/LinkLocalConnector.h +++ b/Swiften/LinkLocal/LinkLocalConnector.h @@ -1,66 +1,63 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> -#include <boost/enable_shared_from_this.hpp> +#include <memory> #include <vector> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Network/Connection.h> #include <Swiften/LinkLocal/LinkLocalService.h> +#include <Swiften/Network/Connection.h> namespace Swift { - class ConnectionFactory; - class HostAddress; - class Element; - class PayloadParserFactoryCollection; - class PayloadSerializerCollection; - class DNSSDQuerier; - class DNSSDResolveHostnameQuery; - - class SWIFTEN_API LinkLocalConnector : public boost::enable_shared_from_this<LinkLocalConnector> { - public: - LinkLocalConnector( - const LinkLocalService& service, - boost::shared_ptr<DNSSDQuerier> querier, - boost::shared_ptr<Connection> connection); - ~LinkLocalConnector(); - - const LinkLocalService& getService() const { - return service; - } - - void connect(); - void cancel(); - void queueElement(boost::shared_ptr<Element> element); - - const std::vector<boost::shared_ptr<Element> >& getQueuedElements() const { - return queuedElements; - } - - boost::shared_ptr<Connection> getConnection() const { - return connection; - } - - boost::signal<void (bool)> onConnectFinished; - - private: - void handleHostnameResolved(const boost::optional<HostAddress>& address); - void handleConnected(bool error); - - private: - LinkLocalService service; - boost::shared_ptr<DNSSDQuerier> querier; - boost::shared_ptr<DNSSDResolveHostnameQuery> resolveQuery; - boost::bsignals::connection resolveQueryHostNameResolvedConnection; - boost::shared_ptr<Connection> connection; - boost::bsignals::connection connectionConnectFinishedConnection; - std::vector<boost::shared_ptr<Element> > queuedElements; - }; + class DNSSDQuerier; + class DNSSDResolveHostnameQuery; + class HostAddress; + class ToplevelElement; + + class SWIFTEN_API LinkLocalConnector : public std::enable_shared_from_this<LinkLocalConnector> { + public: + LinkLocalConnector( + const LinkLocalService& service, + std::shared_ptr<DNSSDQuerier> querier, + std::shared_ptr<Connection> connection); + ~LinkLocalConnector(); + + const LinkLocalService& getService() const { + return service; + } + + void connect(); + void cancel(); + void queueElement(std::shared_ptr<ToplevelElement> element); + + const std::vector<std::shared_ptr<ToplevelElement> >& getQueuedElements() const { + return queuedElements; + } + + std::shared_ptr<Connection> getConnection() const { + return connection; + } + + boost::signals2::signal<void (bool)> onConnectFinished; + + private: + void handleHostnameResolved(const boost::optional<HostAddress>& address); + void handleConnected(bool error); + + private: + LinkLocalService service; + std::shared_ptr<DNSSDQuerier> querier; + std::shared_ptr<DNSSDResolveHostnameQuery> resolveQuery; + boost::signals2::connection resolveQueryHostNameResolvedConnection; + std::shared_ptr<Connection> connection; + boost::signals2::connection connectionConnectFinishedConnection; + std::vector<std::shared_ptr<ToplevelElement> > queuedElements; + }; } diff --git a/Swiften/LinkLocal/LinkLocalService.cpp b/Swiften/LinkLocal/LinkLocalService.cpp index 7c6538c..636362e 100644 --- a/Swiften/LinkLocal/LinkLocalService.cpp +++ b/Swiften/LinkLocal/LinkLocalService.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/LinkLocalService.h> @@ -9,25 +9,25 @@ namespace Swift { std::string LinkLocalService::getDescription() const { - LinkLocalServiceInfo info = getInfo(); - if (!info.getNick().empty()) { - return info.getNick(); - } - else if (!info.getFirstName().empty()) { - std::string result = info.getFirstName(); - if (!info.getLastName().empty()) { - result += " " + info.getLastName(); - } - return result; - } - else if (!info.getLastName().empty()) { - return info.getLastName(); - } - return getName(); + LinkLocalServiceInfo info = getInfo(); + if (!info.getNick().empty()) { + return info.getNick(); + } + else if (!info.getFirstName().empty()) { + std::string result = info.getFirstName(); + if (!info.getLastName().empty()) { + result += " " + info.getLastName(); + } + return result; + } + else if (!info.getLastName().empty()) { + return info.getLastName(); + } + return getName(); } JID LinkLocalService::getJID() const { - return JID(getName()); + return JID(getName()); } } diff --git a/Swiften/LinkLocal/LinkLocalService.h b/Swiften/LinkLocal/LinkLocalService.h index 56be9ef..c51f890 100644 --- a/Swiften/LinkLocal/LinkLocalService.h +++ b/Swiften/LinkLocal/LinkLocalService.h @@ -1,53 +1,54 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + #include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> #include <Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> #include <Swiften/LinkLocal/LinkLocalServiceInfo.h> namespace Swift { - class SWIFTEN_API LinkLocalService { - public: - LinkLocalService( - const DNSSDServiceID& id, - const DNSSDResolveServiceQuery::Result& info) : - id(id), - info(info) {} - - const DNSSDServiceID& getID() const { - return id; - } - - const std::string& getName() const { - return id.getName(); - } - - int getPort() const { - return info.port; - } - - const std::string& getHostname() const { - return info.host; - } - - LinkLocalServiceInfo getInfo() const { - return LinkLocalServiceInfo::createFromTXTRecord(info.info); - } - - std::string getDescription() const; - - JID getJID() const; - - private: - DNSSDServiceID id; - DNSSDResolveServiceQuery::Result info; - }; + class SWIFTEN_API LinkLocalService { + public: + LinkLocalService( + const DNSSDServiceID& id, + const DNSSDResolveServiceQuery::Result& info) : + id(id), + info(info) {} + + const DNSSDServiceID& getID() const { + return id; + } + + const std::string& getName() const { + return id.getName(); + } + + unsigned short getPort() const { + return info.port; + } + + const std::string& getHostname() const { + return info.host; + } + + LinkLocalServiceInfo getInfo() const { + return LinkLocalServiceInfo::createFromTXTRecord(info.info); + } + + std::string getDescription() const; + + JID getJID() const; + + private: + DNSSDServiceID id; + DNSSDResolveServiceQuery::Result info; + }; } diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp index 4b68a33..0498384 100644 --- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp +++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp @@ -1,155 +1,169 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/bind.hpp> +#include <Swiften/LinkLocal/LinkLocalServiceBrowser.h> + #include <iostream> -#include <Swiften/LinkLocal/LinkLocalServiceBrowser.h> +#include <boost/bind.hpp> + #include <Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h> #include <Swiften/Network/HostAddress.h> namespace Swift { -LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier) : querier(querier), haveError(false) { +LinkLocalServiceBrowser::LinkLocalServiceBrowser(std::shared_ptr<DNSSDQuerier> querier) : querier(querier), haveError(false) { } LinkLocalServiceBrowser::~LinkLocalServiceBrowser() { - if (isRunning()) { - std::cerr << "WARNING: LinkLocalServiceBrowser still running on destruction" << std::endl; - } + if (isRunning()) { + std::cerr << "WARNING: LinkLocalServiceBrowser still running on destruction" << std::endl; + } } void LinkLocalServiceBrowser::start() { - assert(!isRunning()); - haveError = false; - browseQuery = querier->createBrowseQuery(); - browseQuery->onServiceAdded.connect( - boost::bind(&LinkLocalServiceBrowser::handleServiceAdded, this, _1)); - browseQuery->onServiceRemoved.connect( - boost::bind(&LinkLocalServiceBrowser::handleServiceRemoved, this, _1)); - browseQuery->onError.connect( - boost::bind(&LinkLocalServiceBrowser::handleBrowseError, this)); - browseQuery->startBrowsing(); + assert(!isRunning()); + haveError = false; + browseQuery = querier->createBrowseQuery(); + browseQuery->onServiceAdded.connect( + boost::bind(&LinkLocalServiceBrowser::handleServiceAdded, this, _1)); + browseQuery->onServiceRemoved.connect( + boost::bind(&LinkLocalServiceBrowser::handleServiceRemoved, this, _1)); + browseQuery->onError.connect( + boost::bind(&LinkLocalServiceBrowser::handleBrowseError, this)); + browseQuery->startBrowsing(); } void LinkLocalServiceBrowser::stop() { - assert(isRunning()); - if (isRegistered()) { - unregisterService(); - } - for (ResolveQueryMap::const_iterator i = resolveQueries.begin(); i != resolveQueries.end(); ++i) { - i->second->stop(); - } - resolveQueries.clear(); - services.clear(); - browseQuery->stopBrowsing(); - browseQuery.reset(); - onStopped(haveError); + assert(isRunning()); + if (isRegistered()) { + unregisterService(); + } + for (ResolveQueryMap::const_iterator i = resolveQueries.begin(); i != resolveQueries.end(); ++i) { + i->second->stop(); + } + resolveQueries.clear(); + services.clear(); + browseQuery->stopBrowsing(); + browseQuery.reset(); + onStopped(haveError); } bool LinkLocalServiceBrowser::isRunning() const { - return browseQuery; + return !!browseQuery; } bool LinkLocalServiceBrowser::hasError() const { - return haveError; + return haveError; } bool LinkLocalServiceBrowser::isRegistered() const { - return registerQuery; + return !!registerQuery; } -void LinkLocalServiceBrowser::registerService(const std::string& name, int port, const LinkLocalServiceInfo& info) { - assert(!registerQuery); - registerQuery = querier->createRegisterQuery(name, port, info.toTXTRecord()); - registerQuery->onRegisterFinished.connect( - boost::bind(&LinkLocalServiceBrowser::handleRegisterFinished, this, _1)); - registerQuery->registerService(); +void LinkLocalServiceBrowser::registerService(const std::string& name, unsigned short port, const LinkLocalServiceInfo& info) { + assert(!registerQuery); + if (auto txtRecord = info.toTXTRecord()) { + registerQuery = querier->createRegisterQuery(name, port, *txtRecord); + registerQuery->onRegisterFinished.connect( + boost::bind(&LinkLocalServiceBrowser::handleRegisterFinished, this, _1)); + registerQuery->registerService(); + } + else { + haveError = true; + stop(); + } } void LinkLocalServiceBrowser::updateService(const LinkLocalServiceInfo& info) { - assert(registerQuery); - registerQuery->updateServiceInfo(info.toTXTRecord()); + assert(registerQuery); + if (auto txtRecord = info.toTXTRecord()) { + registerQuery->updateServiceInfo(*txtRecord); + } + else { + haveError = true; + stop(); + } } void LinkLocalServiceBrowser::unregisterService() { - assert(registerQuery); - registerQuery->unregisterService(); - registerQuery.reset(); - selfService.reset(); + assert(registerQuery); + registerQuery->unregisterService(); + registerQuery.reset(); + selfService.reset(); } std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const { - std::vector<LinkLocalService> result; - for (ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) { - result.push_back(LinkLocalService(i->first, i->second)); - } - return result; + std::vector<LinkLocalService> result; + for (const auto& service : services) { + result.push_back(LinkLocalService(service.first, service.second)); + } + return result; } void LinkLocalServiceBrowser::handleServiceAdded(const DNSSDServiceID& service) { - if (selfService && service == *selfService) { - return; - } + if (selfService && service == *selfService) { + return; + } - std::pair<ResolveQueryMap::iterator, bool> r = resolveQueries.insert(std::make_pair(service, boost::shared_ptr<DNSSDResolveServiceQuery>())); - if (r.second) { - // There was no existing query yet. Start a new query. - boost::shared_ptr<DNSSDResolveServiceQuery> resolveQuery = querier->createResolveServiceQuery(service); - resolveQuery->onServiceResolved.connect( - boost::bind(&LinkLocalServiceBrowser::handleServiceResolved, this, service, _1)); - r.first->second = resolveQuery; - resolveQuery->start(); - } + std::pair<ResolveQueryMap::iterator, bool> r = resolveQueries.insert(std::make_pair(service, std::shared_ptr<DNSSDResolveServiceQuery>())); + if (r.second) { + // There was no existing query yet. Start a new query. + std::shared_ptr<DNSSDResolveServiceQuery> resolveQuery = querier->createResolveServiceQuery(service); + resolveQuery->onServiceResolved.connect( + boost::bind(&LinkLocalServiceBrowser::handleServiceResolved, this, service, _1)); + r.first->second = resolveQuery; + resolveQuery->start(); + } } void LinkLocalServiceBrowser::handleServiceRemoved(const DNSSDServiceID& service) { - ResolveQueryMap::iterator i = resolveQueries.find(service); - if (i == resolveQueries.end()) { - // Can happen after an unregister(), when getting the old 'self' - // service remove notification. - return; - } - i->second->stop(); - resolveQueries.erase(i); - ServiceMap::iterator j = services.find(service); - assert(j != services.end()); - LinkLocalService linkLocalService(j->first, j->second); - services.erase(j); - onServiceRemoved(linkLocalService); + ResolveQueryMap::iterator i = resolveQueries.find(service); + if (i == resolveQueries.end()) { + // Can happen after an unregister(), when getting the old 'self' + // service remove notification. + return; + } + i->second->stop(); + resolveQueries.erase(i); + ServiceMap::iterator j = services.find(service); + assert(j != services.end()); + LinkLocalService linkLocalService(j->first, j->second); + services.erase(j); + onServiceRemoved(linkLocalService); } void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& service, const boost::optional<DNSSDResolveServiceQuery::Result>& result) { - if (result) { - std::pair<ServiceMap::iterator, bool> r = services.insert(std::make_pair(service, *result)); - if (r.second) { - onServiceAdded(LinkLocalService(r.first->first, r.first->second)); - } - else { - r.first->second = *result; - onServiceChanged(LinkLocalService(r.first->first, r.first->second)); - } - } + if (result) { + std::pair<ServiceMap::iterator, bool> r = services.insert(std::make_pair(service, *result)); + if (r.second) { + onServiceAdded(LinkLocalService(r.first->first, r.first->second)); + } + else { + r.first->second = *result; + onServiceChanged(LinkLocalService(r.first->first, r.first->second)); + } + } } void LinkLocalServiceBrowser::handleRegisterFinished(const boost::optional<DNSSDServiceID>& result) { - if (result) { - selfService = result; - onServiceRegistered(*result); - } - else { - haveError = true; - stop(); - } + if (result) { + selfService = result; + onServiceRegistered(*result); + } + else { + haveError = true; + stop(); + } } void LinkLocalServiceBrowser::handleBrowseError() { - haveError = true; - stop(); + haveError = true; + stop(); } } diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h index f9a12f3..bfcfc07 100644 --- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h +++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h @@ -1,75 +1,76 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> -#include <boost/optional.hpp> #include <map> +#include <memory> +#include <string> #include <vector> -#include <string> +#include <boost/optional.hpp> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> #include <Swiften/LinkLocal/DNSSD/DNSSDQuerier.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h> #include <Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h> #include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> #include <Swiften/LinkLocal/LinkLocalService.h> #include <Swiften/LinkLocal/LinkLocalServiceInfo.h> namespace Swift { - class SWIFTEN_API LinkLocalServiceBrowser { - public: - LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier); - ~LinkLocalServiceBrowser(); + class SWIFTEN_API LinkLocalServiceBrowser { + public: + LinkLocalServiceBrowser(std::shared_ptr<DNSSDQuerier> querier); + ~LinkLocalServiceBrowser(); - void start(); - void stop(); - bool isRunning() const; - bool hasError() const; + void start(); + void stop(); + bool isRunning() const; + bool hasError() const; - void registerService( - const std::string& name, - int port, - const LinkLocalServiceInfo& info = LinkLocalServiceInfo()); - void updateService( - const LinkLocalServiceInfo& info = LinkLocalServiceInfo()); - void unregisterService(); - bool isRegistered() const; + void registerService( + const std::string& name, + unsigned short port, + const LinkLocalServiceInfo& info = LinkLocalServiceInfo()); + void updateService( + const LinkLocalServiceInfo& info = LinkLocalServiceInfo()); + void unregisterService(); + bool isRegistered() const; - std::vector<LinkLocalService> getServices() const; + std::vector<LinkLocalService> getServices() const; - // FIXME: Ugly that we need this - boost::shared_ptr<DNSSDQuerier> getQuerier() const { - return querier; - } + // FIXME: Ugly that we need this + std::shared_ptr<DNSSDQuerier> getQuerier() const { + return querier; + } - boost::signal<void (const LinkLocalService&)> onServiceAdded; - boost::signal<void (const LinkLocalService&)> onServiceChanged; - boost::signal<void (const LinkLocalService&)> onServiceRemoved; - boost::signal<void (const DNSSDServiceID&)> onServiceRegistered; - boost::signal<void (bool)> onStopped; + boost::signals2::signal<void (const LinkLocalService&)> onServiceAdded; + boost::signals2::signal<void (const LinkLocalService&)> onServiceChanged; + boost::signals2::signal<void (const LinkLocalService&)> onServiceRemoved; + boost::signals2::signal<void (const DNSSDServiceID&)> onServiceRegistered; + boost::signals2::signal<void (bool)> onStopped; - private: - void handleServiceAdded(const DNSSDServiceID&); - void handleServiceRemoved(const DNSSDServiceID&); - void handleServiceResolved(const DNSSDServiceID& service, const boost::optional<DNSSDResolveServiceQuery::Result>& result); - void handleRegisterFinished(const boost::optional<DNSSDServiceID>&); - void handleBrowseError(); + private: + void handleServiceAdded(const DNSSDServiceID&); + void handleServiceRemoved(const DNSSDServiceID&); + void handleServiceResolved(const DNSSDServiceID& service, const boost::optional<DNSSDResolveServiceQuery::Result>& result); + void handleRegisterFinished(const boost::optional<DNSSDServiceID>&); + void handleBrowseError(); - private: - boost::shared_ptr<DNSSDQuerier> querier; - boost::optional<DNSSDServiceID> selfService; - boost::shared_ptr<DNSSDBrowseQuery> browseQuery; - boost::shared_ptr<DNSSDRegisterQuery> registerQuery; - typedef std::map<DNSSDServiceID, boost::shared_ptr<DNSSDResolveServiceQuery> > ResolveQueryMap; - ResolveQueryMap resolveQueries; - typedef std::map<DNSSDServiceID, DNSSDResolveServiceQuery::Result> ServiceMap; - ServiceMap services; - bool haveError; - }; + private: + std::shared_ptr<DNSSDQuerier> querier; + boost::optional<DNSSDServiceID> selfService; + std::shared_ptr<DNSSDBrowseQuery> browseQuery; + std::shared_ptr<DNSSDRegisterQuery> registerQuery; + typedef std::map<DNSSDServiceID, std::shared_ptr<DNSSDResolveServiceQuery> > ResolveQueryMap; + ResolveQueryMap resolveQueries; + typedef std::map<DNSSDServiceID, DNSSDResolveServiceQuery::Result> ServiceMap; + ServiceMap services; + bool haveError; + }; } diff --git a/Swiften/LinkLocal/LinkLocalServiceInfo.cpp b/Swiften/LinkLocal/LinkLocalServiceInfo.cpp index 7e18315..5e529fd 100644 --- a/Swiften/LinkLocal/LinkLocalServiceInfo.cpp +++ b/Swiften/LinkLocal/LinkLocalServiceInfo.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/LinkLocalServiceInfo.h> @@ -11,114 +11,127 @@ #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/Concat.h> +#include <Swiften/Base/Log.h> namespace Swift { -ByteArray LinkLocalServiceInfo::toTXTRecord() const { - ByteArray result(getEncoded("txtvers=1")); - if (!firstName.empty()) { - append(result, getEncoded("1st=" + firstName)); - } - if (!lastName.empty()) { - append(result, getEncoded("last=" + lastName)); - } - if (!email.empty()) { - append(result, getEncoded("email=" + email)); - } - if (jid.isValid()) { - append(result, getEncoded("jid=" + jid.toString())); - } - if (!message.empty()) { - append(result, getEncoded("msg=" + message)); - } - if (!nick.empty()) { - append(result, getEncoded("nick=" + nick)); - } - if (port) { - append(result, getEncoded("port.p2pj=" + std::string(boost::lexical_cast<std::string>(*port)))); - } +boost::optional<ByteArray> LinkLocalServiceInfo::toTXTRecord() const { + try { + ByteArray result(getEncoded("txtvers=1")); + if (!firstName.empty()) { + append(result, getEncoded("1st=" + firstName)); + } + if (!lastName.empty()) { + append(result, getEncoded("last=" + lastName)); + } + if (!email.empty()) { + append(result, getEncoded("email=" + email)); + } + if (jid.isValid()) { + append(result, getEncoded("jid=" + jid.toString())); + } + if (!message.empty()) { + append(result, getEncoded("msg=" + message)); + } + if (!nick.empty()) { + append(result, getEncoded("nick=" + nick)); + } + if (port) { + append(result, getEncoded("port.p2pj=" + std::string(std::to_string(*port)))); + } - switch (status) { - case Available: append(result, getEncoded("status=avail")); break; - case Away: append(result, getEncoded("status=away")); break; - case DND: append(result, getEncoded("status=dnd")); break; - } + switch (status) { + case Available: append(result, getEncoded("status=avail")); break; + case Away: append(result, getEncoded("status=away")); break; + case DND: append(result, getEncoded("status=dnd")); break; + } - return result; + return result; + } + catch (const std::exception& e) { + SWIFT_LOG(warning) << "Failed to create TXT record for link local service info: " << e.what(); + return boost::none; + } } ByteArray LinkLocalServiceInfo::getEncoded(const std::string& s) { - ByteArray sizeByte; - sizeByte.resize(1); - sizeByte[0] = boost::numeric_cast<unsigned char>(s.size()); - return concat(sizeByte, createByteArray(s)); + ByteArray sizeByte; + sizeByte.resize(1); + sizeByte[0] = boost::numeric_cast<unsigned char>(s.size()); + return concat(sizeByte, createByteArray(s)); } LinkLocalServiceInfo LinkLocalServiceInfo::createFromTXTRecord(const ByteArray& record) { - LinkLocalServiceInfo info; - size_t i = 0; - size_t recordCount = record.size(); - while (i < recordCount) { - std::pair<std::string,std::string> entry = readEntry(record, &i); - if (entry.first.empty()) { - break; - } - else if (entry.first == "1st") { - info.setFirstName(entry.second); - } - else if (entry.first == "last") { - info.setLastName(entry.second); - } - else if (entry.first == "email") { - info.setEMail(entry.second); - } - else if (entry.first == "jid") { - info.setJID(JID(entry.second)); - } - else if (entry.first == "msg") { - info.setMessage(entry.second); - } - else if (entry.first == "nick") { - info.setNick(entry.second); - } - else if (entry.first == "port.p2pj") { - info.setPort(boost::lexical_cast<int>(entry.second)); - } - else if (entry.first == "status") { - if (entry.second == "away") { - info.setStatus(Away); - } - else if (entry.second == "dnd") { - info.setStatus(DND); - } - } - } - return info; + LinkLocalServiceInfo info; + size_t i = 0; + size_t recordCount = record.size(); + while (i < recordCount) { + std::pair<std::string,std::string> entry = readEntry(record, &i); + if (entry.first.empty()) { + break; + } + else if (entry.first == "1st") { + info.setFirstName(entry.second); + } + else if (entry.first == "last") { + info.setLastName(entry.second); + } + else if (entry.first == "email") { + info.setEMail(entry.second); + } + else if (entry.first == "jid") { + info.setJID(JID(entry.second)); + } + else if (entry.first == "msg") { + info.setMessage(entry.second); + } + else if (entry.first == "nick") { + info.setNick(entry.second); + } + else if (entry.first == "port.p2pj") { + try { + info.setPort(boost::numeric_cast<unsigned short>(boost::lexical_cast<int>(entry.second))); + } + catch (const boost::bad_lexical_cast&) { + } + catch (const boost::numeric::bad_numeric_cast&) { + } + } + else if (entry.first == "status") { + if (entry.second == "away") { + info.setStatus(Away); + } + else if (entry.second == "dnd") { + info.setStatus(DND); + } + } + } + return info; } std::pair<std::string,std::string> LinkLocalServiceInfo::readEntry(const ByteArray& record, size_t* index) { - size_t& i = *index; - std::string key; - std::string value; + size_t& i = *index; + std::string key; + std::string value; - size_t entryEnd = i + 1 + record[i]; - ++i; - bool inKey = true; - while (i < entryEnd && i < record.size()) { - if (inKey) { - if (record[i] == '=') { - inKey = false; - } - else { - key += static_cast<char>(record[i]); - } - } - else { - value += static_cast<char>(record[i]); - } - ++i; - } - return std::make_pair(key, value); + size_t entryEnd = i + 1 + record[i]; + ++i; + bool inKey = true; + while (i < entryEnd && i < record.size()) { + if (inKey) { + if (record[i] == '=') { + inKey = false; + } + else { + key += static_cast<char>(record[i]); + } + } + else { + value += static_cast<char>(record[i]); + } + ++i; + } + return std::make_pair(key, value); } } diff --git a/Swiften/LinkLocal/LinkLocalServiceInfo.h b/Swiften/LinkLocal/LinkLocalServiceInfo.h index ac7b86f..adfd062 100644 --- a/Swiften/LinkLocal/LinkLocalServiceInfo.h +++ b/Swiften/LinkLocal/LinkLocalServiceInfo.h @@ -1,66 +1,67 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <string> + #include <boost/optional.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> -#include <string> #include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API LinkLocalServiceInfo { - public: - enum Status { Available, Away, DND }; + class SWIFTEN_API LinkLocalServiceInfo { + public: + enum Status { Available, Away, DND }; - LinkLocalServiceInfo() : status(Available) {} + LinkLocalServiceInfo() : status(Available) {} - const std::string& getFirstName() const { return firstName; } - void setFirstName(const std::string& f) { firstName = f; } + const std::string& getFirstName() const { return firstName; } + void setFirstName(const std::string& f) { firstName = f; } - const std::string& getLastName() const { return lastName; } - void setLastName(const std::string& l) { lastName = l; } + const std::string& getLastName() const { return lastName; } + void setLastName(const std::string& l) { lastName = l; } - const std::string& getEMail() const { return email; } - void setEMail(const std::string& e) { email = e; } + const std::string& getEMail() const { return email; } + void setEMail(const std::string& e) { email = e; } - const JID& getJID() const { return jid; } - void setJID(const JID& j) { jid = j; } + const JID& getJID() const { return jid; } + void setJID(const JID& j) { jid = j; } - const std::string& getMessage() const { return message; } - void setMessage(const std::string& m) { message = m; } + const std::string& getMessage() const { return message; } + void setMessage(const std::string& m) { message = m; } - const std::string& getNick() const { return nick; } - void setNick(const std::string& n) { nick = n; } + const std::string& getNick() const { return nick; } + void setNick(const std::string& n) { nick = n; } - Status getStatus() const { return status; } - void setStatus(Status s) { status = s; } + Status getStatus() const { return status; } + void setStatus(Status s) { status = s; } - boost::optional<int> getPort() const { return port; } - void setPort(int p) { port = p; } + boost::optional<unsigned short> getPort() const { return port; } + void setPort(unsigned short p) { port = p; } - ByteArray toTXTRecord() const; + boost::optional<ByteArray> toTXTRecord() const; - static LinkLocalServiceInfo createFromTXTRecord(const ByteArray& record); + static LinkLocalServiceInfo createFromTXTRecord(const ByteArray& record); - private: - static ByteArray getEncoded(const std::string&); - static std::pair<std::string,std::string> readEntry(const ByteArray&, size_t*); + private: + static ByteArray getEncoded(const std::string&); + static std::pair<std::string,std::string> readEntry(const ByteArray&, size_t*); - private: - std::string firstName; - std::string lastName; - std::string email; - JID jid; - std::string message; - std::string nick; - Status status; - boost::optional<int> port; - }; + private: + std::string firstName; + std::string lastName; + std::string email; + JID jid; + std::string message; + std::string nick; + Status status; + boost::optional<unsigned short> port; + }; } diff --git a/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp b/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp index 7a59715..a639ec5 100644 --- a/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp +++ b/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp @@ -1,52 +1,51 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/LinkLocal/OutgoingLinkLocalSession.h> #include <boost/bind.hpp> -#include <Swiften/Base/foreach.h> -#include <Swiften/StreamStack/XMPPLayer.h> +#include <Swiften/Elements/IQ.h> #include <Swiften/Elements/ProtocolHeader.h> #include <Swiften/Elements/StreamFeatures.h> -#include <Swiften/Elements/IQ.h> +#include <Swiften/StreamStack/XMPPLayer.h> namespace Swift { OutgoingLinkLocalSession::OutgoingLinkLocalSession( - const JID& localJID, - const JID& remoteJID, - boost::shared_ptr<Connection> connection, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - XMLParserFactory* xmlParserFactory) : - Session(connection, payloadParserFactories, payloadSerializers, xmlParserFactory) { - setLocalJID(localJID); - setRemoteJID(remoteJID); + const JID& localJID, + const JID& remoteJID, + std::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + XMLParserFactory* xmlParserFactory) : + Session(connection, payloadParserFactories, payloadSerializers, xmlParserFactory) { + setLocalJID(localJID); + setRemoteJID(remoteJID); } void OutgoingLinkLocalSession::handleSessionStarted() { - ProtocolHeader header; - header.setFrom(getLocalJID()); - getXMPPLayer()->writeHeader(header); + ProtocolHeader header; + header.setFrom(getLocalJID()); + getXMPPLayer()->writeHeader(header); } void OutgoingLinkLocalSession::handleStreamStart(const ProtocolHeader&) { - foreach(const boost::shared_ptr<Element>& stanza, queuedElements_) { - sendElement(stanza); - } - queuedElements_.clear(); + for (const auto& stanza : queuedElements_) { + sendElement(stanza); + } + queuedElements_.clear(); } -void OutgoingLinkLocalSession::handleElement(boost::shared_ptr<Element> element) { - onElementReceived(element); +void OutgoingLinkLocalSession::handleElement(std::shared_ptr<ToplevelElement> element) { + onElementReceived(element); } -void OutgoingLinkLocalSession::queueElement(boost::shared_ptr<Element> element) { - queuedElements_.push_back(element); +void OutgoingLinkLocalSession::queueElement(std::shared_ptr<ToplevelElement> element) { + queuedElements_.push_back(element); } diff --git a/Swiften/LinkLocal/OutgoingLinkLocalSession.h b/Swiften/LinkLocal/OutgoingLinkLocalSession.h index b97f2bf..93f8c9d 100644 --- a/Swiften/LinkLocal/OutgoingLinkLocalSession.h +++ b/Swiften/LinkLocal/OutgoingLinkLocalSession.h @@ -1,44 +1,44 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> -#include <boost/enable_shared_from_this.hpp> +#include <memory> #include <vector> -#include <Swiften/Session/Session.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> +#include <Swiften/Session/Session.h> namespace Swift { - class ConnectionFactory; - class XMLParserFactory; - class Element; - class PayloadParserFactoryCollection; - class PayloadSerializerCollection; - - class OutgoingLinkLocalSession : public Session { - public: - OutgoingLinkLocalSession( - const JID& localJID, - const JID& remoteJID, - boost::shared_ptr<Connection> connection, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - XMLParserFactory* xmlParserFactory); - - void queueElement(boost::shared_ptr<Element> element); - - private: - void handleSessionStarted(); - void handleElement(boost::shared_ptr<Element>); - void handleStreamStart(const ProtocolHeader&); - - private: - std::vector<boost::shared_ptr<Element> > queuedElements_; - }; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + class ToplevelElement; + class XMLParserFactory; + + class SWIFTEN_API OutgoingLinkLocalSession : public Session { + public: + OutgoingLinkLocalSession( + const JID& localJID, + const JID& remoteJID, + std::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + XMLParserFactory* xmlParserFactory); + + void queueElement(std::shared_ptr<ToplevelElement> element); + + private: + void handleSessionStarted(); + void handleElement(std::shared_ptr<ToplevelElement>); + void handleStreamStart(const ProtocolHeader&); + + private: + std::vector<std::shared_ptr<ToplevelElement> > queuedElements_; + }; } diff --git a/Swiften/LinkLocal/SConscript b/Swiften/LinkLocal/SConscript index 29ea692..697037a 100644 --- a/Swiften/LinkLocal/SConscript +++ b/Swiften/LinkLocal/SConscript @@ -4,39 +4,39 @@ myenv = swiften_env.Clone() myenv.MergeFlags(swiften_env.get("BONJOUR_FLAGS", "")) sources = [ - "DNSSD/DNSSDBrowseQuery.cpp", - "DNSSD/DNSSDQuerier.cpp", - "DNSSD/DNSSDRegisterQuery.cpp", - "DNSSD/DNSSDResolveHostnameQuery.cpp", - "DNSSD/DNSSDResolveServiceQuery.cpp", - "DNSSD/DNSSDServiceID.cpp", - "DNSSD/Fake/FakeDNSSDQuerier.cpp", - "DNSSD/Fake/FakeDNSSDQuery.cpp", - "DNSSD/PlatformDNSSDQuerierFactory.cpp", - "IncomingLinkLocalSession.cpp", - "LinkLocalConnector.cpp", - "LinkLocalService.cpp", - "LinkLocalServiceBrowser.cpp", - "LinkLocalServiceInfo.cpp", - "OutgoingLinkLocalSession.cpp", - ] + "DNSSD/DNSSDBrowseQuery.cpp", + "DNSSD/DNSSDQuerier.cpp", + "DNSSD/DNSSDRegisterQuery.cpp", + "DNSSD/DNSSDResolveHostnameQuery.cpp", + "DNSSD/DNSSDResolveServiceQuery.cpp", + "DNSSD/DNSSDServiceID.cpp", + "DNSSD/Fake/FakeDNSSDQuerier.cpp", + "DNSSD/Fake/FakeDNSSDQuery.cpp", + "DNSSD/PlatformDNSSDQuerierFactory.cpp", + "IncomingLinkLocalSession.cpp", + "LinkLocalConnector.cpp", + "LinkLocalService.cpp", + "LinkLocalServiceBrowser.cpp", + "LinkLocalServiceInfo.cpp", + "OutgoingLinkLocalSession.cpp", + ] if myenv.get("HAVE_BONJOUR", 0) : - myenv.Append(CPPDEFINES = "HAVE_BONJOUR") - sources += [ - "DNSSD/Bonjour/BonjourQuerier.cpp", - "DNSSD/Bonjour/BonjourQuery.cpp", - ] + myenv.Append(CPPDEFINES = "HAVE_BONJOUR") + sources += [ + "DNSSD/Bonjour/BonjourQuerier.cpp", + "DNSSD/Bonjour/BonjourQuery.cpp", + ] elif myenv.get("HAVE_AVAHI", 0) : - myenv.Append(CPPDEFINES = ["HAVE_AVAHI"]) - sources += [ - "DNSSD/Avahi/AvahiQuerier.cpp", - "DNSSD/Avahi/AvahiQuery.cpp", - "DNSSD/Avahi/AvahiResolveHostnameQuery.cpp", - "DNSSD/Avahi/AvahiResolveServiceQuery.cpp", - "DNSSD/Avahi/AvahiRegisterQuery.cpp", - "DNSSD/Avahi/AvahiBrowseQuery.cpp", - ] + myenv.Append(CPPDEFINES = ["HAVE_AVAHI"]) + sources += [ + "DNSSD/Avahi/AvahiQuerier.cpp", + "DNSSD/Avahi/AvahiQuery.cpp", + "DNSSD/Avahi/AvahiResolveHostnameQuery.cpp", + "DNSSD/Avahi/AvahiResolveServiceQuery.cpp", + "DNSSD/Avahi/AvahiRegisterQuery.cpp", + "DNSSD/Avahi/AvahiBrowseQuery.cpp", + ] objects = myenv.SwiftenObject(sources) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalConnectorTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalConnectorTest.cpp index dd5e884..59cf996 100644 --- a/Swiften/LinkLocal/UnitTest/LinkLocalConnectorTest.cpp +++ b/Swiften/LinkLocal/UnitTest/LinkLocalConnectorTest.cpp @@ -1,143 +1,145 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> - -#include <Swiften/LinkLocal/LinkLocalConnector.h> -#include <Swiften/LinkLocal/LinkLocalService.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h> -#include <Swiften/EventLoop/DummyEventLoop.h> +#include <Swiften/LinkLocal/LinkLocalConnector.h> +#include <Swiften/LinkLocal/LinkLocalService.h> #include <Swiften/Network/FakeConnection.h> using namespace Swift; class LinkLocalConnectorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(LinkLocalConnectorTest); - CPPUNIT_TEST(testConnect); - CPPUNIT_TEST(testConnect_UnableToResolve); - CPPUNIT_TEST(testConnect_UnableToConnect); - CPPUNIT_TEST(testCancel_DuringResolve); - CPPUNIT_TEST(testCancel_DuringConnect); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - eventLoop = new DummyEventLoop(); - querier = boost::make_shared<FakeDNSSDQuerier>("rabbithole.local", eventLoop); - connection = boost::make_shared<FakeConnection>(eventLoop); - connectFinished = false; - } - - void tearDown() { - querier->clearAllQueriesEverRun(); - delete eventLoop; - } - - void testConnect() { - boost::shared_ptr<LinkLocalConnector> - testling(createConnector("rabbithole.local", 1234)); - querier->setAddress("rabbithole.local", HostAddress("192.168.1.1")); - - testling->connect(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(connectFinished); - CPPUNIT_ASSERT(!connectError); - CPPUNIT_ASSERT(connection->connectedTo); - CPPUNIT_ASSERT_EQUAL(std::string(connection->connectedTo->getAddress().toString()), std::string("192.168.1.1")); - CPPUNIT_ASSERT_EQUAL(connection->connectedTo->getPort(), 1234); - } - - void testConnect_UnableToResolve() { - boost::shared_ptr<LinkLocalConnector> - testling(createConnector("rabbithole.local", 1234)); - querier->setAddress("rabbithole.local", boost::optional<HostAddress>()); - - testling->connect(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(connectFinished); - CPPUNIT_ASSERT(connectError); - CPPUNIT_ASSERT(!connection->connectedTo); - } - - void testConnect_UnableToConnect() { - boost::shared_ptr<LinkLocalConnector> - testling(createConnector("rabbithole.local", 1234)); - querier->setAddress("rabbithole.local", HostAddress("192.168.1.1")); - connection->setError(Connection::ReadError); - - testling->connect(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(connectFinished); - CPPUNIT_ASSERT(connectError); - CPPUNIT_ASSERT(!connection->connectedTo); - } - - void testCancel_DuringResolve() { - boost::shared_ptr<LinkLocalConnector> - testling(createConnector("rabbithole.local", 1234)); - testling->connect(); - eventLoop->processEvents(); - CPPUNIT_ASSERT(!connectFinished); - - testling->cancel(); - eventLoop->processEvents(); - querier->setAddress("rabbithole.local", HostAddress("192.168.1.1")); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(FakeConnection::Disconnected == connection->state); - } - - void testCancel_DuringConnect() { - boost::shared_ptr<LinkLocalConnector> - testling(createConnector("rabbithole.local", 1234)); - querier->setAddress("rabbithole.local", HostAddress("192.168.1.1")); - connection->setDelayConnect(); - testling->connect(); - eventLoop->processEvents(); - CPPUNIT_ASSERT(FakeConnection::Connecting == connection->state); - - testling->cancel(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(FakeConnection::Disconnected == connection->state); - } - - private: - boost::shared_ptr<LinkLocalConnector> createConnector(const std::string& hostname, int port) { - LinkLocalService service( - DNSSDServiceID("myname", "local."), - DNSSDResolveServiceQuery::Result( - "myname._presence._tcp.local", hostname, port, - LinkLocalServiceInfo().toTXTRecord())); - boost::shared_ptr<LinkLocalConnector> result( - new LinkLocalConnector(service, querier, connection)); - result->onConnectFinished.connect( - boost::bind(&LinkLocalConnectorTest::handleConnected, this, _1)); - return result; - } - - void handleConnected(bool e) { - connectFinished = true; - connectError = e; - } - - private: - DummyEventLoop* eventLoop; - boost::shared_ptr<FakeDNSSDQuerier> querier; - boost::shared_ptr<FakeConnection> connection; - bool connectFinished; - bool connectError; + CPPUNIT_TEST_SUITE(LinkLocalConnectorTest); + CPPUNIT_TEST(testConnect); + CPPUNIT_TEST(testConnect_UnableToResolve); + CPPUNIT_TEST(testConnect_UnableToConnect); + CPPUNIT_TEST(testCancel_DuringResolve); + CPPUNIT_TEST(testCancel_DuringConnect); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + eventLoop = new DummyEventLoop(); + querier = std::make_shared<FakeDNSSDQuerier>("rabbithole.local", eventLoop); + connection = std::make_shared<FakeConnection>(eventLoop); + connectFinished = false; + } + + void tearDown() { + querier->clearAllQueriesEverRun(); + delete eventLoop; + } + + void testConnect() { + std::shared_ptr<LinkLocalConnector> + testling(createConnector("rabbithole.local", 1234)); + querier->setAddress("rabbithole.local", HostAddress::fromString("192.168.1.1").get()); + + testling->connect(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(connectFinished); + CPPUNIT_ASSERT(!connectError); + CPPUNIT_ASSERT(connection->connectedTo); + CPPUNIT_ASSERT_EQUAL(std::string(connection->connectedTo->getAddress().toString()), std::string("192.168.1.1")); + CPPUNIT_ASSERT_EQUAL(connection->connectedTo->getPort(), static_cast<unsigned short>(1234)); + } + + void testConnect_UnableToResolve() { + std::shared_ptr<LinkLocalConnector> + testling(createConnector("rabbithole.local", 1234)); + querier->setAddress("rabbithole.local", boost::optional<HostAddress>()); + + testling->connect(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(connectFinished); + CPPUNIT_ASSERT(connectError); + CPPUNIT_ASSERT(!connection->connectedTo); + } + + void testConnect_UnableToConnect() { + std::shared_ptr<LinkLocalConnector> + testling(createConnector("rabbithole.local", 1234)); + querier->setAddress("rabbithole.local", HostAddress::fromString("192.168.1.1").get()); + connection->setError(Connection::ReadError); + + testling->connect(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(connectFinished); + CPPUNIT_ASSERT(connectError); + CPPUNIT_ASSERT(!connection->connectedTo); + } + + void testCancel_DuringResolve() { + std::shared_ptr<LinkLocalConnector> + testling(createConnector("rabbithole.local", 1234)); + testling->connect(); + eventLoop->processEvents(); + CPPUNIT_ASSERT(!connectFinished); + + testling->cancel(); + eventLoop->processEvents(); + querier->setAddress("rabbithole.local", HostAddress::fromString("192.168.1.1").get()); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(FakeConnection::Disconnected == connection->state); + } + + void testCancel_DuringConnect() { + std::shared_ptr<LinkLocalConnector> + testling(createConnector("rabbithole.local", 1234)); + querier->setAddress("rabbithole.local", HostAddress::fromString("192.168.1.1").get()); + connection->setDelayConnect(); + testling->connect(); + eventLoop->processEvents(); + CPPUNIT_ASSERT(FakeConnection::Connecting == connection->state); + + testling->cancel(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(FakeConnection::Disconnected == connection->state); + } + + private: + std::shared_ptr<LinkLocalConnector> createConnector(const std::string& hostname, unsigned short port) { + auto txtRecord = LinkLocalServiceInfo().toTXTRecord(); + CPPUNIT_ASSERT(txtRecord); + LinkLocalService service( + DNSSDServiceID("myname", "local."), + DNSSDResolveServiceQuery::Result( + "myname._presence._tcp.local", hostname, port, + *txtRecord)); + std::shared_ptr<LinkLocalConnector> result( + new LinkLocalConnector(service, querier, connection)); + result->onConnectFinished.connect( + boost::bind(&LinkLocalConnectorTest::handleConnected, this, _1)); + return result; + } + + void handleConnected(bool e) { + connectFinished = true; + connectError = e; + } + + private: + DummyEventLoop* eventLoop; + std::shared_ptr<FakeDNSSDQuerier> querier; + std::shared_ptr<FakeConnection> connection; + bool connectFinished; + bool connectError; }; CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalConnectorTest); diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp index 93deea5..3491634 100644 --- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp +++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp @@ -1,412 +1,424 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <map> +#include <memory> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <map> -#include <Swiften/LinkLocal/LinkLocalServiceBrowser.h> -#include <Swiften/LinkLocal/LinkLocalService.h> -#include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h> +#include <Swiften/LinkLocal/DNSSD/DNSSDServiceID.h> #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h> #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h> -#include <Swiften/EventLoop/DummyEventLoop.h> +#include <Swiften/LinkLocal/LinkLocalService.h> +#include <Swiften/LinkLocal/LinkLocalServiceBrowser.h> using namespace Swift; class LinkLocalServiceBrowserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(LinkLocalServiceBrowserTest); - CPPUNIT_TEST(testConstructor); - CPPUNIT_TEST(testStart); - CPPUNIT_TEST(testServiceAdded); - CPPUNIT_TEST(testServiceAdded_NoServiceInfo); - CPPUNIT_TEST(testServiceAdded_RegisteredService); - CPPUNIT_TEST(testServiceAdded_UnregisteredService); - CPPUNIT_TEST(testServiceAdded_Twice); - CPPUNIT_TEST(testServiceChanged); - CPPUNIT_TEST(testServiceRemoved); - CPPUNIT_TEST(testServiceRemoved_UnregisteredService); - CPPUNIT_TEST(testError_BrowseErrorAfterStart); - CPPUNIT_TEST(testError_BrowseErrorAfterResolve); - CPPUNIT_TEST(testRegisterService); - CPPUNIT_TEST(testRegisterService_Error); - CPPUNIT_TEST(testRegisterService_Reregister); - CPPUNIT_TEST(testUpdateService); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - eventLoop = new DummyEventLoop(); - querier = boost::make_shared<FakeDNSSDQuerier>("wonderland.lit", eventLoop); - aliceServiceID = new DNSSDServiceID("alice", "wonderland.lit"); - aliceServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.wonderland.lit", "xmpp.wonderland.lit", 1234, LinkLocalServiceInfo().toTXTRecord()); - testServiceID = new DNSSDServiceID("foo", "bar.local"); - testServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.bar.local", "xmpp.bar.local", 1234, LinkLocalServiceInfo().toTXTRecord()); - testServiceInfo2 = new DNSSDResolveServiceQuery::Result("_presence.tcp.bar.local", "xmpp.foo.local", 2345, LinkLocalServiceInfo().toTXTRecord()); - errorStopReceived = false; - normalStopReceived = false; - } - - void tearDown() { - querier->clearAllQueriesEverRun(); - addedServices.clear(); - removedServices.clear(); - changedServices.clear(); - - delete aliceServiceID; - delete aliceServiceInfo; - delete testServiceInfo2; - delete testServiceInfo; - delete testServiceID; - delete eventLoop; - } - - void testConstructor() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - - CPPUNIT_ASSERT(!testling->isRunning()); - CPPUNIT_ASSERT(!testling->hasError()); - } - - void testStart() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - - CPPUNIT_ASSERT(testling->isRunning()); - CPPUNIT_ASSERT(!testling->hasError()); - - testling->stop(); - } - - void testServiceAdded() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - eventLoop->processEvents(); - - querier->setServiceInfo(*testServiceID,*testServiceInfo); - querier->addService(*testServiceID); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); - CPPUNIT_ASSERT(addedServices[0].getID() == *testServiceID); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size())); - std::vector<LinkLocalService> services = testling->getServices(); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size())); - CPPUNIT_ASSERT(*testServiceID == services[0].getID()); - CPPUNIT_ASSERT(testServiceInfo->port == services[0].getPort()); - CPPUNIT_ASSERT(testServiceInfo->host == services[0].getHostname()); - - testling->stop(); - } - - void testServiceAdded_NoServiceInfo() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - eventLoop->processEvents(); - - querier->addService(*testServiceID); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size())); - - testling->stop(); - } - - void testServiceAdded_RegisteredService() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - eventLoop->processEvents(); - - testling->registerService("alice", 1234, LinkLocalServiceInfo()); - eventLoop->processEvents(); - querier->setServiceInfo(*aliceServiceID, *aliceServiceInfo); - querier->addService(*aliceServiceID); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size())); - - testling->stop(); - } - - void testServiceAdded_UnregisteredService() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - eventLoop->processEvents(); - testling->registerService("alice", 1234, LinkLocalServiceInfo()); - eventLoop->processEvents(); - testling->unregisterService(); - eventLoop->processEvents(); - - querier->setServiceInfo(*aliceServiceID, *aliceServiceInfo); - querier->addService(*aliceServiceID); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); - CPPUNIT_ASSERT(addedServices[0].getID() == *aliceServiceID); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size())); - std::vector<LinkLocalService> services = testling->getServices(); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size())); - CPPUNIT_ASSERT(*aliceServiceID == services[0].getID()); - CPPUNIT_ASSERT(aliceServiceInfo->port == services[0].getPort()); - CPPUNIT_ASSERT(aliceServiceInfo->host == services[0].getHostname()); - - testling->stop(); - } - - void testServiceRemoved_UnregisteredService() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - eventLoop->processEvents(); - testling->registerService("alice", 1234, LinkLocalServiceInfo()); - eventLoop->processEvents(); - testling->unregisterService(); - eventLoop->processEvents(); - - querier->removeService(*aliceServiceID); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size())); - - testling->stop(); - } - - void testServiceAdded_Twice() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - eventLoop->processEvents(); - - querier->setServiceInfo(*testServiceID,*testServiceInfo); - querier->addService(*testServiceID); - querier->addService(*testServiceID); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(querier->getAllQueriesEverRun<FakeDNSSDResolveServiceQuery>().size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); - CPPUNIT_ASSERT(addedServices[0].getID() == *testServiceID); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size())); - std::vector<LinkLocalService> services = testling->getServices(); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size())); - CPPUNIT_ASSERT(*testServiceID == services[0].getID()); - CPPUNIT_ASSERT(testServiceInfo->port == services[0].getPort()); - CPPUNIT_ASSERT(testServiceInfo->host == services[0].getHostname()); - - testling->stop(); - } - - - void testServiceChanged() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - querier->setServiceInfo(*testServiceID,*testServiceInfo); - querier->addService(*testServiceID); - eventLoop->processEvents(); - - querier->setServiceInfo(*testServiceID,*testServiceInfo2); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changedServices.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size())); - CPPUNIT_ASSERT(changedServices[0].getID() == *testServiceID); - std::vector<LinkLocalService> services = testling->getServices(); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size())); - CPPUNIT_ASSERT(*testServiceID == services[0].getID()); - CPPUNIT_ASSERT(testServiceInfo2->port == services[0].getPort()); - CPPUNIT_ASSERT(testServiceInfo2->host == services[0].getHostname()); - - testling->stop(); - } - - void testServiceRemoved() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - querier->setServiceInfo(*testServiceID,*testServiceInfo); - querier->addService(*testServiceID); - eventLoop->processEvents(); - - querier->removeService(*testServiceID); - eventLoop->processEvents(); - querier->setServiceInfo(*testServiceID,*testServiceInfo2); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(removedServices.size())); - CPPUNIT_ASSERT(removedServices[0].getID() == *testServiceID); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size())); - - testling->stop(); - } - - void testError_BrowseErrorAfterStart() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - - querier->setBrowseError(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(!testling->isRunning()); - CPPUNIT_ASSERT(testling->hasError()); - CPPUNIT_ASSERT(errorStopReceived); - } - - void testError_BrowseErrorAfterResolve() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - querier->setServiceInfo(*testServiceID,*testServiceInfo); - querier->addService(*testServiceID); - eventLoop->processEvents(); - - querier->setBrowseError(); - eventLoop->processEvents(); - querier->setServiceInfo(*testServiceID,*testServiceInfo2); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(!testling->isRunning()); - CPPUNIT_ASSERT(testling->hasError()); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); - CPPUNIT_ASSERT(errorStopReceived); - } - - void testRegisterService() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - eventLoop->processEvents(); - - LinkLocalServiceInfo info; - info.setFirstName("Foo"); - testling->registerService("foo@bar", 1234, info); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(querier->isServiceRegistered("foo@bar", 1234, info.toTXTRecord())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(registeredServices.size())); - CPPUNIT_ASSERT(registeredServices[0] == DNSSDServiceID("foo@bar", "wonderland.lit")); - testling->stop(); - } - - void testRegisterService_Error() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - LinkLocalServiceInfo info; - testling->registerService("foo@bar", 1234, info); - eventLoop->processEvents(); - - querier->setRegisterError(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(!testling->isRunning()); - CPPUNIT_ASSERT(testling->hasError()); - CPPUNIT_ASSERT(errorStopReceived); - CPPUNIT_ASSERT(!querier->isServiceRegistered("foo@bar", 1234, info.toTXTRecord())); - } - - void testRegisterService_Reregister() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - eventLoop->processEvents(); - LinkLocalServiceInfo info; - info.setFirstName("Foo"); - testling->registerService("foo@bar", 1234, info); - eventLoop->processEvents(); - testling->unregisterService(); - eventLoop->processEvents(); - - info.setFirstName("Bar"); - testling->registerService("bar@baz", 3456, info); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(querier->isServiceRegistered("bar@baz", 3456, info.toTXTRecord())); - - testling->stop(); - } - - void testUpdateService() { - boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); - testling->start(); - eventLoop->processEvents(); - - LinkLocalServiceInfo info; - info.setFirstName("Foo"); - testling->registerService("foo@bar", 1234, info); - eventLoop->processEvents(); - info.setFirstName("Bar"); - testling->updateService(info); - - CPPUNIT_ASSERT(querier->isServiceRegistered("foo@bar", 1234, info.toTXTRecord())); - - testling->stop(); - } - - private: - boost::shared_ptr<LinkLocalServiceBrowser> createTestling() { - boost::shared_ptr<LinkLocalServiceBrowser> testling( - new LinkLocalServiceBrowser(querier)); - testling->onServiceAdded.connect(boost::bind( - &LinkLocalServiceBrowserTest::handleServiceAdded, this, _1)); - testling->onServiceChanged.connect(boost::bind( - &LinkLocalServiceBrowserTest::handleServiceChanged, this, _1)); - testling->onServiceRemoved.connect(boost::bind( - &LinkLocalServiceBrowserTest::handleServiceRemoved, this, _1)); - testling->onServiceRegistered.connect(boost::bind( - &LinkLocalServiceBrowserTest::handleServiceRegistered, this, _1)); - testling->onStopped.connect(boost::bind( - &LinkLocalServiceBrowserTest::handleStopped, this, _1)); - return testling; - } - - void handleServiceAdded(const LinkLocalService& service) { - addedServices.push_back(service); - } - - void handleServiceRemoved(const LinkLocalService& service) { - removedServices.push_back(service); - } - - void handleServiceChanged(const LinkLocalService& service) { - changedServices.push_back(service); - } - - void handleServiceRegistered(const DNSSDServiceID& service) { - registeredServices.push_back(service); - } - - void handleStopped(bool error) { - CPPUNIT_ASSERT(!errorStopReceived); - CPPUNIT_ASSERT(!normalStopReceived); - if (error) { - errorStopReceived = true; - } - else { - normalStopReceived = true; - } - } - - private: - DummyEventLoop* eventLoop; - boost::shared_ptr<FakeDNSSDQuerier> querier; - std::vector<LinkLocalService> addedServices; - std::vector<LinkLocalService> changedServices; - std::vector<LinkLocalService> removedServices; - std::vector<DNSSDServiceID> registeredServices; - DNSSDServiceID* aliceServiceID; - DNSSDResolveServiceQuery::Result* aliceServiceInfo; - DNSSDServiceID* testServiceID; - DNSSDResolveServiceQuery::Result* testServiceInfo; - DNSSDResolveServiceQuery::Result* testServiceInfo2; - bool errorStopReceived; - bool normalStopReceived; + CPPUNIT_TEST_SUITE(LinkLocalServiceBrowserTest); + CPPUNIT_TEST(testConstructor); + CPPUNIT_TEST(testStart); + CPPUNIT_TEST(testServiceAdded); + CPPUNIT_TEST(testServiceAdded_NoServiceInfo); + CPPUNIT_TEST(testServiceAdded_RegisteredService); + CPPUNIT_TEST(testServiceAdded_UnregisteredService); + CPPUNIT_TEST(testServiceAdded_Twice); + CPPUNIT_TEST(testServiceChanged); + CPPUNIT_TEST(testServiceRemoved); + CPPUNIT_TEST(testServiceRemoved_UnregisteredService); + CPPUNIT_TEST(testError_BrowseErrorAfterStart); + CPPUNIT_TEST(testError_BrowseErrorAfterResolve); + CPPUNIT_TEST(testRegisterService); + CPPUNIT_TEST(testRegisterService_Error); + CPPUNIT_TEST(testRegisterService_Reregister); + CPPUNIT_TEST(testUpdateService); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + eventLoop = new DummyEventLoop(); + querier = std::make_shared<FakeDNSSDQuerier>("wonderland.lit", eventLoop); + aliceServiceID = new DNSSDServiceID("alice", "wonderland.lit"); + auto txtRecord = LinkLocalServiceInfo().toTXTRecord(); + CPPUNIT_ASSERT(txtRecord); + aliceServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.wonderland.lit", "xmpp.wonderland.lit", 1234, *txtRecord); + testServiceID = new DNSSDServiceID("foo", "bar.local"); + testServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.bar.local", "xmpp.bar.local", 1234, *txtRecord); + testServiceInfo2 = new DNSSDResolveServiceQuery::Result("_presence.tcp.bar.local", "xmpp.foo.local", 2345, *txtRecord); + errorStopReceived = false; + normalStopReceived = false; + } + + void tearDown() { + querier->clearAllQueriesEverRun(); + addedServices.clear(); + removedServices.clear(); + changedServices.clear(); + + delete aliceServiceID; + delete aliceServiceInfo; + delete testServiceInfo2; + delete testServiceInfo; + delete testServiceID; + delete eventLoop; + } + + void testConstructor() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + + CPPUNIT_ASSERT(!testling->isRunning()); + CPPUNIT_ASSERT(!testling->hasError()); + } + + void testStart() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + + CPPUNIT_ASSERT(testling->isRunning()); + CPPUNIT_ASSERT(!testling->hasError()); + + testling->stop(); + } + + void testServiceAdded() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + eventLoop->processEvents(); + + querier->setServiceInfo(*testServiceID,*testServiceInfo); + querier->addService(*testServiceID); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); + CPPUNIT_ASSERT(addedServices[0].getID() == *testServiceID); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size())); + std::vector<LinkLocalService> services = testling->getServices(); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size())); + CPPUNIT_ASSERT(*testServiceID == services[0].getID()); + CPPUNIT_ASSERT(testServiceInfo->port == services[0].getPort()); + CPPUNIT_ASSERT(testServiceInfo->host == services[0].getHostname()); + + testling->stop(); + } + + void testServiceAdded_NoServiceInfo() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + eventLoop->processEvents(); + + querier->addService(*testServiceID); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size())); + + testling->stop(); + } + + void testServiceAdded_RegisteredService() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + eventLoop->processEvents(); + + testling->registerService("alice", 1234, LinkLocalServiceInfo()); + eventLoop->processEvents(); + querier->setServiceInfo(*aliceServiceID, *aliceServiceInfo); + querier->addService(*aliceServiceID); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size())); + + testling->stop(); + } + + void testServiceAdded_UnregisteredService() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + eventLoop->processEvents(); + testling->registerService("alice", 1234, LinkLocalServiceInfo()); + eventLoop->processEvents(); + testling->unregisterService(); + eventLoop->processEvents(); + + querier->setServiceInfo(*aliceServiceID, *aliceServiceInfo); + querier->addService(*aliceServiceID); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); + CPPUNIT_ASSERT(addedServices[0].getID() == *aliceServiceID); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size())); + std::vector<LinkLocalService> services = testling->getServices(); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size())); + CPPUNIT_ASSERT(*aliceServiceID == services[0].getID()); + CPPUNIT_ASSERT(aliceServiceInfo->port == services[0].getPort()); + CPPUNIT_ASSERT(aliceServiceInfo->host == services[0].getHostname()); + + testling->stop(); + } + + void testServiceRemoved_UnregisteredService() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + eventLoop->processEvents(); + testling->registerService("alice", 1234, LinkLocalServiceInfo()); + eventLoop->processEvents(); + testling->unregisterService(); + eventLoop->processEvents(); + + querier->removeService(*aliceServiceID); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size())); + + testling->stop(); + } + + void testServiceAdded_Twice() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + eventLoop->processEvents(); + + querier->setServiceInfo(*testServiceID,*testServiceInfo); + querier->addService(*testServiceID); + querier->addService(*testServiceID); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(querier->getAllQueriesEverRun<FakeDNSSDResolveServiceQuery>().size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); + CPPUNIT_ASSERT(addedServices[0].getID() == *testServiceID); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size())); + std::vector<LinkLocalService> services = testling->getServices(); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size())); + CPPUNIT_ASSERT(*testServiceID == services[0].getID()); + CPPUNIT_ASSERT(testServiceInfo->port == services[0].getPort()); + CPPUNIT_ASSERT(testServiceInfo->host == services[0].getHostname()); + + testling->stop(); + } + + + void testServiceChanged() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + querier->setServiceInfo(*testServiceID,*testServiceInfo); + querier->addService(*testServiceID); + eventLoop->processEvents(); + + querier->setServiceInfo(*testServiceID,*testServiceInfo2); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changedServices.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size())); + CPPUNIT_ASSERT(changedServices[0].getID() == *testServiceID); + std::vector<LinkLocalService> services = testling->getServices(); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size())); + CPPUNIT_ASSERT(*testServiceID == services[0].getID()); + CPPUNIT_ASSERT(testServiceInfo2->port == services[0].getPort()); + CPPUNIT_ASSERT(testServiceInfo2->host == services[0].getHostname()); + + testling->stop(); + } + + void testServiceRemoved() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + querier->setServiceInfo(*testServiceID,*testServiceInfo); + querier->addService(*testServiceID); + eventLoop->processEvents(); + + querier->removeService(*testServiceID); + eventLoop->processEvents(); + querier->setServiceInfo(*testServiceID,*testServiceInfo2); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(removedServices.size())); + CPPUNIT_ASSERT(removedServices[0].getID() == *testServiceID); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size())); + + testling->stop(); + } + + void testError_BrowseErrorAfterStart() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + + querier->setBrowseError(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(!testling->isRunning()); + CPPUNIT_ASSERT(testling->hasError()); + CPPUNIT_ASSERT(errorStopReceived); + } + + void testError_BrowseErrorAfterResolve() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + querier->setServiceInfo(*testServiceID,*testServiceInfo); + querier->addService(*testServiceID); + eventLoop->processEvents(); + + querier->setBrowseError(); + eventLoop->processEvents(); + querier->setServiceInfo(*testServiceID,*testServiceInfo2); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(!testling->isRunning()); + CPPUNIT_ASSERT(testling->hasError()); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); + CPPUNIT_ASSERT(errorStopReceived); + } + + void testRegisterService() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + eventLoop->processEvents(); + + LinkLocalServiceInfo info; + info.setFirstName("Foo"); + testling->registerService("foo@bar", 1234, info); + eventLoop->processEvents(); + + auto txtRecord = info.toTXTRecord(); + CPPUNIT_ASSERT(txtRecord); + CPPUNIT_ASSERT(querier->isServiceRegistered("foo@bar", 1234, *txtRecord)); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(registeredServices.size())); + CPPUNIT_ASSERT(registeredServices[0] == DNSSDServiceID("foo@bar", "wonderland.lit")); + testling->stop(); + } + + void testRegisterService_Error() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + LinkLocalServiceInfo info; + testling->registerService("foo@bar", 1234, info); + eventLoop->processEvents(); + + querier->setRegisterError(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(!testling->isRunning()); + CPPUNIT_ASSERT(testling->hasError()); + CPPUNIT_ASSERT(errorStopReceived); + auto txtRecord = info.toTXTRecord(); + CPPUNIT_ASSERT(txtRecord); + CPPUNIT_ASSERT(!querier->isServiceRegistered("foo@bar", 1234, *txtRecord)); + } + + void testRegisterService_Reregister() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + eventLoop->processEvents(); + LinkLocalServiceInfo info; + info.setFirstName("Foo"); + testling->registerService("foo@bar", 1234, info); + eventLoop->processEvents(); + testling->unregisterService(); + eventLoop->processEvents(); + + info.setFirstName("Bar"); + testling->registerService("bar@baz", 3456, info); + eventLoop->processEvents(); + + auto txtRecord = info.toTXTRecord(); + CPPUNIT_ASSERT(txtRecord); + CPPUNIT_ASSERT(querier->isServiceRegistered("bar@baz", 3456, *txtRecord)); + + testling->stop(); + } + + void testUpdateService() { + std::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + testling->start(); + eventLoop->processEvents(); + + LinkLocalServiceInfo info; + info.setFirstName("Foo"); + testling->registerService("foo@bar", 1234, info); + eventLoop->processEvents(); + info.setFirstName("Bar"); + testling->updateService(info); + + auto txtRecord = info.toTXTRecord(); + CPPUNIT_ASSERT(txtRecord); + CPPUNIT_ASSERT(querier->isServiceRegistered("foo@bar", 1234, *txtRecord)); + + testling->stop(); + } + + private: + std::shared_ptr<LinkLocalServiceBrowser> createTestling() { + std::shared_ptr<LinkLocalServiceBrowser> testling( + new LinkLocalServiceBrowser(querier)); + testling->onServiceAdded.connect(boost::bind( + &LinkLocalServiceBrowserTest::handleServiceAdded, this, _1)); + testling->onServiceChanged.connect(boost::bind( + &LinkLocalServiceBrowserTest::handleServiceChanged, this, _1)); + testling->onServiceRemoved.connect(boost::bind( + &LinkLocalServiceBrowserTest::handleServiceRemoved, this, _1)); + testling->onServiceRegistered.connect(boost::bind( + &LinkLocalServiceBrowserTest::handleServiceRegistered, this, _1)); + testling->onStopped.connect(boost::bind( + &LinkLocalServiceBrowserTest::handleStopped, this, _1)); + return testling; + } + + void handleServiceAdded(const LinkLocalService& service) { + addedServices.push_back(service); + } + + void handleServiceRemoved(const LinkLocalService& service) { + removedServices.push_back(service); + } + + void handleServiceChanged(const LinkLocalService& service) { + changedServices.push_back(service); + } + + void handleServiceRegistered(const DNSSDServiceID& service) { + registeredServices.push_back(service); + } + + void handleStopped(bool error) { + CPPUNIT_ASSERT(!errorStopReceived); + CPPUNIT_ASSERT(!normalStopReceived); + if (error) { + errorStopReceived = true; + } + else { + normalStopReceived = true; + } + } + + private: + DummyEventLoop* eventLoop; + std::shared_ptr<FakeDNSSDQuerier> querier; + std::vector<LinkLocalService> addedServices; + std::vector<LinkLocalService> changedServices; + std::vector<LinkLocalService> removedServices; + std::vector<DNSSDServiceID> registeredServices; + DNSSDServiceID* aliceServiceID; + DNSSDResolveServiceQuery::Result* aliceServiceInfo; + DNSSDServiceID* testServiceID; + DNSSDResolveServiceQuery::Result* testServiceInfo; + DNSSDResolveServiceQuery::Result* testServiceInfo2; + bool errorStopReceived; + bool normalStopReceived; }; CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceBrowserTest); diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp index 314b46a..35cb1b4 100644 --- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp +++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp @@ -1,72 +1,83 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/LinkLocal/LinkLocalServiceInfo.h> using namespace Swift; class LinkLocalServiceInfoTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(LinkLocalServiceInfoTest); - CPPUNIT_TEST(testGetTXTRecord); - CPPUNIT_TEST(testCreateFromTXTRecord); - CPPUNIT_TEST(testCreateFromTXTRecord_InvalidSize); - CPPUNIT_TEST(testGetTXTRecordCreateFromTXTRecord_RoundTrip); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(LinkLocalServiceInfoTest); + CPPUNIT_TEST(testGetTXTRecord); + CPPUNIT_TEST(testCreateFromTXTRecord); + CPPUNIT_TEST(testCreateFromTXTRecord_InvalidSize); + CPPUNIT_TEST(testGetTXTRecordCreateFromTXTRecord_RoundTrip); + CPPUNIT_TEST_SUITE_END(); + + public: + void testGetTXTRecord() { + LinkLocalServiceInfo info; + info.setFirstName("Remko"); + info.setLastName("Tron\xc3\xe7on"); + info.setStatus(LinkLocalServiceInfo::Away); - public: - void testGetTXTRecord() { - LinkLocalServiceInfo info; - info.setFirstName("Remko"); - info.setLastName("Tron\xc3\xe7on"); - info.setStatus(LinkLocalServiceInfo::Away); + auto txtRecord = info.toTXTRecord(); + CPPUNIT_ASSERT(txtRecord); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x09txtvers=1\x09" + std::string("1st=Remko\x0dlast=Tron\xc3\xe7on\x0bstatus=away")), *txtRecord); + } - CPPUNIT_ASSERT_EQUAL(createByteArray("\x09txtvers=1\x09" + std::string("1st=Remko\x0dlast=Tron\xc3\xe7on\x0bstatus=away")), info.toTXTRecord()); - } + void testCreateFromTXTRecord() { + LinkLocalServiceInfo info = LinkLocalServiceInfo::createFromTXTRecord(createByteArray("\x09txtvers=1\x09" + std::string("1st=Remko\x0dlast=Tron\xc3\xe7on\x0bstatus=away"))); - void testCreateFromTXTRecord() { - LinkLocalServiceInfo info = LinkLocalServiceInfo::createFromTXTRecord(createByteArray("\x09txtvers=1\x09" + std::string("1st=Remko\x0dlast=Tron\xc3\xe7on\x0bstatus=away"))); + CPPUNIT_ASSERT_EQUAL(std::string("Remko"), info.getFirstName()); + CPPUNIT_ASSERT_EQUAL(std::string("Tron\xc3\xe7on"), info.getLastName()); + CPPUNIT_ASSERT_EQUAL(LinkLocalServiceInfo::Away, info.getStatus()); + } - CPPUNIT_ASSERT_EQUAL(std::string("Remko"), info.getFirstName()); - CPPUNIT_ASSERT_EQUAL(std::string("Tron\xc3\xe7on"), info.getLastName()); - CPPUNIT_ASSERT_EQUAL(LinkLocalServiceInfo::Away, info.getStatus()); - } + void testCreateFromTXTRecord_InvalidSize() { + LinkLocalServiceInfo info = LinkLocalServiceInfo::createFromTXTRecord(createByteArray("\x10last=a")); - void testCreateFromTXTRecord_InvalidSize() { - LinkLocalServiceInfo info = LinkLocalServiceInfo::createFromTXTRecord(createByteArray("\x10last=a")); + CPPUNIT_ASSERT_EQUAL(std::string("a"), info.getLastName()); + } - CPPUNIT_ASSERT_EQUAL(std::string("a"), info.getLastName()); - } + void testGetTXTRecordCreateFromTXTRecord_RoundTrip() { + LinkLocalServiceInfo info; + info.setFirstName("Remko"); + info.setLastName("Tron\xc3\xe7on"); + info.setEMail("remko-email@swift.im"); + info.setJID(JID("remko-jid@swift.im")); + info.setMessage("I'm busy"); + info.setNick("el-tramo"); + info.setStatus(LinkLocalServiceInfo::DND); + info.setPort(1234); - void testGetTXTRecordCreateFromTXTRecord_RoundTrip() { - LinkLocalServiceInfo info; - info.setFirstName("Remko"); - info.setLastName("Tron\xc3\xe7on"); - info.setEMail("remko-email@swift.im"); - info.setJID(JID("remko-jid@swift.im")); - info.setMessage("I'm busy"); - info.setNick("el-tramo"); - info.setStatus(LinkLocalServiceInfo::DND); - info.setPort(1234); + auto txtRecord = info.toTXTRecord(); + CPPUNIT_ASSERT(txtRecord); + LinkLocalServiceInfo info2 = LinkLocalServiceInfo::createFromTXTRecord(*txtRecord); + CPPUNIT_ASSERT_EQUAL(info.getFirstName(), info2.getFirstName()); + CPPUNIT_ASSERT_EQUAL(info.getLastName(), info2.getLastName()); + CPPUNIT_ASSERT_EQUAL(info.getEMail(), info2.getEMail()); + CPPUNIT_ASSERT_EQUAL(info.getJID(), info2.getJID()); + CPPUNIT_ASSERT_EQUAL(info.getMessage(), info2.getMessage()); + CPPUNIT_ASSERT_EQUAL(info.getNick(), info2.getNick()); + CPPUNIT_ASSERT(info.getStatus() == info2.getStatus()); + CPPUNIT_ASSERT(info.getPort() == info2.getPort()); + } - LinkLocalServiceInfo info2 = LinkLocalServiceInfo::createFromTXTRecord(info.toTXTRecord()); - CPPUNIT_ASSERT_EQUAL(info.getFirstName(), info2.getFirstName()); - CPPUNIT_ASSERT_EQUAL(info.getLastName(), info2.getLastName()); - CPPUNIT_ASSERT_EQUAL(info.getEMail(), info2.getEMail()); - CPPUNIT_ASSERT_EQUAL(info.getJID(), info2.getJID()); - CPPUNIT_ASSERT_EQUAL(info.getMessage(), info2.getMessage()); - CPPUNIT_ASSERT_EQUAL(info.getNick(), info2.getNick()); - CPPUNIT_ASSERT(info.getStatus() == info2.getStatus()); - CPPUNIT_ASSERT(info.getPort() == info2.getPort()); - } + void testToTXTRecordWithInvalidParameter() { + LinkLocalServiceInfo info; + info.setFirstName(std::string(256, 'x')); + auto txtRecord = info.toTXTRecord(); + CPPUNIT_ASSERT(!txtRecord); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceInfoTest); diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceTest.cpp index 2e3e1bb..cb5f40a 100644 --- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceTest.cpp +++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -12,57 +12,59 @@ using namespace Swift; class LinkLocalServiceTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(LinkLocalServiceTest); - CPPUNIT_TEST(testGetDescription_WithNick); - CPPUNIT_TEST(testGetDescription_WithFirstName); - CPPUNIT_TEST(testGetDescription_WithLastName); - CPPUNIT_TEST(testGetDescription_WithFirstAndLastName); - CPPUNIT_TEST(testGetDescription_NoInfo); - CPPUNIT_TEST_SUITE_END(); - - public: - void testGetDescription_WithNick() { - LinkLocalService testling = createService("alice@wonderland", "Alice", "Alice In", "Wonderland"); - - CPPUNIT_ASSERT_EQUAL(std::string("Alice"), testling.getDescription()); - } - - void testGetDescription_WithFirstName() { - LinkLocalService testling = createService("alice@wonderland", "", "Alice In"); - - CPPUNIT_ASSERT_EQUAL(std::string("Alice In"), testling.getDescription()); - } - - void testGetDescription_WithLastName() { - LinkLocalService testling = createService("alice@wonderland", "", "", "Wonderland"); - - CPPUNIT_ASSERT_EQUAL(std::string("Wonderland"), testling.getDescription()); - } - - void testGetDescription_WithFirstAndLastName() { - LinkLocalService testling = createService("alice@wonderland", "", "Alice In", "Wonderland"); - - CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland"), testling.getDescription()); - } - - void testGetDescription_NoInfo() { - LinkLocalService testling = createService("alice@wonderland"); - - CPPUNIT_ASSERT_EQUAL(std::string("alice@wonderland"), testling.getDescription()); - } - - private: - LinkLocalService createService(const std::string& name, const std::string& nickName = std::string(), const std::string& firstName = std::string(), const std::string& lastName = std::string()) { - DNSSDServiceID service(name, "local."); - LinkLocalServiceInfo info; - info.setFirstName(firstName); - info.setLastName(lastName); - info.setNick(nickName); - return LinkLocalService(service, - DNSSDResolveServiceQuery::Result( - name + "._presence._tcp.local", "rabbithole.local", 1234, - info.toTXTRecord())); - } + CPPUNIT_TEST_SUITE(LinkLocalServiceTest); + CPPUNIT_TEST(testGetDescription_WithNick); + CPPUNIT_TEST(testGetDescription_WithFirstName); + CPPUNIT_TEST(testGetDescription_WithLastName); + CPPUNIT_TEST(testGetDescription_WithFirstAndLastName); + CPPUNIT_TEST(testGetDescription_NoInfo); + CPPUNIT_TEST_SUITE_END(); + + public: + void testGetDescription_WithNick() { + LinkLocalService testling = createService("alice@wonderland", "Alice", "Alice In", "Wonderland"); + + CPPUNIT_ASSERT_EQUAL(std::string("Alice"), testling.getDescription()); + } + + void testGetDescription_WithFirstName() { + LinkLocalService testling = createService("alice@wonderland", "", "Alice In"); + + CPPUNIT_ASSERT_EQUAL(std::string("Alice In"), testling.getDescription()); + } + + void testGetDescription_WithLastName() { + LinkLocalService testling = createService("alice@wonderland", "", "", "Wonderland"); + + CPPUNIT_ASSERT_EQUAL(std::string("Wonderland"), testling.getDescription()); + } + + void testGetDescription_WithFirstAndLastName() { + LinkLocalService testling = createService("alice@wonderland", "", "Alice In", "Wonderland"); + + CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland"), testling.getDescription()); + } + + void testGetDescription_NoInfo() { + LinkLocalService testling = createService("alice@wonderland"); + + CPPUNIT_ASSERT_EQUAL(std::string("alice@wonderland"), testling.getDescription()); + } + + private: + LinkLocalService createService(const std::string& name, const std::string& nickName = std::string(), const std::string& firstName = std::string(), const std::string& lastName = std::string()) { + DNSSDServiceID service(name, "local."); + LinkLocalServiceInfo info; + info.setFirstName(firstName); + info.setLastName(lastName); + info.setNick(nickName); + auto txtRecord = info.toTXTRecord(); + CPPUNIT_ASSERT(txtRecord); + return LinkLocalService(service, + DNSSDResolveServiceQuery::Result( + name + "._presence._tcp.local", "rabbithole.local", 1234, + *txtRecord)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceTest); diff --git a/Swiften/MIX/MIX.cpp b/Swiften/MIX/MIX.cpp new file mode 100644 index 0000000..f3e3d69 --- /dev/null +++ b/Swiften/MIX/MIX.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/MIX/MIX.h> + +namespace Swift { + +MIX::~MIX() { +} + +} diff --git a/Swiften/MIX/MIX.h b/Swiften/MIX/MIX.h new file mode 100644 index 0000000..1398a6e --- /dev/null +++ b/Swiften/MIX/MIX.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <memory> +#include <string> +#include <unordered_set> + +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/MIXJoin.h> +#include <Swiften/Elements/MIXLeave.h> +#include <Swiften/Elements/MIXUpdateSubscription.h> +#include <Swiften/Elements/MIXUserPreference.h> +#include <Swiften/Elements/ErrorPayload.h> + +namespace Swift { + class SWIFTEN_API MIX { + public: + using ref = std::shared_ptr<MIX>; + + public: + virtual ~MIX(); + + /** + * Join a MIX channel and subscribe to nodes. + */ + virtual void joinChannel(const std::unordered_set<std::string>& nodes) = 0; + + /** + * Join Channel with a set of preferences. + */ + virtual void joinChannelWithPreferences(const std::unordered_set<std::string>& nodes, Form::ref form) = 0; + + /** + * Update subscription of nodes. + */ + virtual void updateSubscription(const std::unordered_set<std::string>& nodes) = 0; + + /** + * Leave a MIX channel and unsubcribe nodes. + */ + virtual void leaveChannel() = 0; + + /** + * Request a configuration form for updating preferences. + */ + virtual void requestPreferencesForm() = 0; + + /** + * Update preferences after requesting preference form. + */ + virtual void updatePreferences(Form::ref form) = 0; + + public: + boost::signals2::signal<void (MIXJoin::ref /* joinResponse */, ErrorPayload::ref /* joinError */)> onJoinResponse; + boost::signals2::signal<void (MIXLeave::ref /* leaveResponse */, ErrorPayload::ref /* leaveError */)> onLeaveResponse; + boost::signals2::signal<void (MIXUpdateSubscription::ref /* updateResponse */, ErrorPayload::ref /* updateError */)> onSubscriptionUpdateResponse; + boost::signals2::signal<void (Form::ref /* preferencesForm */, ErrorPayload::ref /* failedConfiguration */)> onPreferencesFormResponse; + boost::signals2::signal<void (MIXUserPreference::ref /* userPreferenceResponse */, ErrorPayload::ref /* failedUpdate */)> onPreferencesUpdateResponse; + }; +} diff --git a/Swiften/MIX/MIXImpl.cpp b/Swiften/MIX/MIXImpl.cpp new file mode 100644 index 0000000..cd3eb21 --- /dev/null +++ b/Swiften/MIX/MIXImpl.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/MIX/MIXImpl.h> + +#include <Swiften/Client/StanzaChannel.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Queries/IQRouter.h> + +namespace Swift { + +MIXImpl::MIXImpl(const JID& ownJID, const JID& channelJID, IQRouter* iqRouter) : ownJID_(ownJID), channelJID_(channelJID), iqRouter_(iqRouter) { + +} + +MIXImpl::~MIXImpl() { + +} + +void MIXImpl::joinChannel(const std::unordered_set<std::string>& nodes) { + joinChannelWithPreferences(nodes, nullptr); +} + +void MIXImpl::joinChannelWithPreferences(const std::unordered_set<std::string>& nodes, Form::ref form) { + auto joinPayload = std::make_shared<MIXJoin>(); + joinPayload->setChannel(channelJID_); + for (auto node : nodes) { + joinPayload->addSubscription(node); + } + if (form) { + joinPayload->setForm(form); + } + auto request = std::make_shared<GenericRequest<MIXJoin>>(IQ::Set, getJID(), joinPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MIXImpl::handleJoinResponse, this, _1, _2)); + request->send(); +} + +void MIXImpl::handleJoinResponse(MIXJoin::ref payload, ErrorPayload::ref error) { + onJoinResponse(payload, error); +} + +void MIXImpl::updateSubscription(const std::unordered_set<std::string>& nodes) { + auto updateSubscriptionPayload = std::make_shared<MIXUpdateSubscription>(); + updateSubscriptionPayload->setSubscriptions(nodes); + auto request = std::make_shared<GenericRequest<MIXUpdateSubscription>>(IQ::Set, channelJID_, updateSubscriptionPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MIXImpl::handleUpdateSubscriptionResponse, this, _1, _2)); + request->send(); +} + +void MIXImpl::handleUpdateSubscriptionResponse(MIXUpdateSubscription::ref payload, ErrorPayload::ref error) { + onSubscriptionUpdateResponse(payload, error); +} + +void MIXImpl::leaveChannel() { + auto leavePayload = std::make_shared<MIXLeave>(); + leavePayload->setChannel(channelJID_); + auto request = std::make_shared<GenericRequest<MIXLeave>>(IQ::Set, getJID(), leavePayload, iqRouter_); + request->onResponse.connect(boost::bind(&MIXImpl::handleLeaveResponse, this, _1, _2)); + request->send(); +} + +void MIXImpl::handleLeaveResponse(MIXLeave::ref payload, ErrorPayload::ref error) { + onLeaveResponse(payload, error); +} + +void MIXImpl::requestPreferencesForm() { + auto prefPayload = std::make_shared<MIXUserPreference>(); + auto request = std::make_shared<GenericRequest<MIXUserPreference>>(IQ::Get, channelJID_, prefPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MIXImpl::handlePreferencesFormReceived, this, _1, _2)); + request->send(); +} + +void MIXImpl::handlePreferencesFormReceived(MIXUserPreference::ref payload, ErrorPayload::ref error) { + Form::ref form = nullptr; + if (payload) { + form = payload->getData(); + } + onPreferencesFormResponse(form, error); +} + +void MIXImpl::handlePreferencesResultReceived(MIXUserPreference::ref payload, ErrorPayload::ref error) { + onPreferencesUpdateResponse(payload, error); +} + +void MIXImpl::updatePreferences(Form::ref form) { + auto prefPayload = std::make_shared<MIXUserPreference>(); + prefPayload->setData(form); + auto request = std::make_shared<GenericRequest<MIXUserPreference>>(IQ::Set, channelJID_, prefPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MIXImpl::handlePreferencesResultReceived, this, _1, _2)); + request->send(); +} + +} diff --git a/Swiften/MIX/MIXImpl.h b/Swiften/MIX/MIXImpl.h new file mode 100644 index 0000000..4da7a62 --- /dev/null +++ b/Swiften/MIX/MIXImpl.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + + /* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/MIX/MIX.h> + +namespace Swift { + class StanzaChannel; + class IQRouter; + + class SWIFTEN_API MIXImpl : public MIX { + public: + using ref = std::shared_ptr<MIXImpl>; + + public: + MIXImpl(const JID& ownJID, const JID& channelJID, IQRouter* iqRouter); + virtual ~MIXImpl() override; + + /** + * Returns the (bare) JID of the user. + */ + virtual JID getJID() const { + return ownJID_.toBare(); + } + + /** + * Returns the JID of MIX channel. + */ + virtual JID getChannelJID() const { + return channelJID_; + } + + virtual void joinChannel(const std::unordered_set<std::string>& nodes) override; + + virtual void joinChannelWithPreferences(const std::unordered_set<std::string>& nodes, Form::ref form) override; + + virtual void updateSubscription(const std::unordered_set<std::string>& nodes) override; + + virtual void leaveChannel() override; + + virtual void requestPreferencesForm() override; + + virtual void updatePreferences(Form::ref form) override; + + private: + void handleJoinResponse(MIXJoin::ref, ErrorPayload::ref); + void handleLeaveResponse(MIXLeave::ref, ErrorPayload::ref); + void handleUpdateSubscriptionResponse(MIXUpdateSubscription::ref, ErrorPayload::ref); + void handlePreferencesFormReceived(MIXUserPreference::ref, ErrorPayload::ref); + void handlePreferencesResultReceived(MIXUserPreference::ref /*payload*/, ErrorPayload::ref error); + + private: + JID ownJID_; + JID channelJID_; + IQRouter* iqRouter_; + }; +} diff --git a/Swiften/MIX/UnitTest/MIXImplTest.cpp b/Swiften/MIX/UnitTest/MIXImplTest.cpp new file mode 100644 index 0000000..05dde17 --- /dev/null +++ b/Swiften/MIX/UnitTest/MIXImplTest.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <boost/bind.hpp> + +#include <Swiften/Elements/FormField.h> +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/MIX/MIXImpl.h> +#include <Swiften/Queries/IQRouter.h> + +using namespace Swift; + +class MIXImplTest : public ::testing::Test { + + protected: + void SetUp() { + ownJID_ = JID("hag66@shakespeare.example/UUID-a1j/7533"); + channelJID_ = JID("coven@mix.shakespeare.example"); + channel_ = new DummyStanzaChannel(); + router_ = new IQRouter(channel_); + successfulJoins_ = 0; + } + + void TearDown() { + delete router_; + delete channel_; + } + + MIX::ref createMIXClient() { + auto mix = std::make_shared<MIXImpl>(ownJID_, channelJID_, router_); + mix->onJoinResponse.connect(boost::bind(&MIXImplTest::handleJoin, this, _1, _2)); + mix->onLeaveResponse.connect(boost::bind(&MIXImplTest::handleLeave, this, _1, _2)); + mix->onSubscriptionUpdateResponse.connect(boost::bind(&MIXImplTest::handleSubscriptionUpdate, this, _1, _2)); + mix->onPreferencesFormResponse.connect(boost::bind(&MIXImplTest::handlePreferencesForm, this, _1, _2)); + return mix; + } + + void handleJoin(MIXJoin::ref joinPayload, ErrorPayload::ref error) { + if (joinPayload) { + ASSERT_FALSE(error); + ASSERT_TRUE(joinPayload->getJID()); + ASSERT_EQ(*joinPayload->getJID(), JID("123456#coven@mix.shakespeare.example")); + if (joinPayload->getForm()) { + preferenceForm_ = joinPayload->getForm(); + } + ++successfulJoins_; + subscribedNodes_ = joinPayload->getSubscriptions(); + } + } + + void handleLeave(MIXLeave::ref leavePayload, ErrorPayload::ref error) { + ASSERT_TRUE(leavePayload); + ASSERT_FALSE(error); + ASSERT_EQ(static_cast<int>(0), subscribedNodes_.size()); + } + + void handleSubscriptionUpdate(MIXUpdateSubscription::ref payload, ErrorPayload::ref error) { + ASSERT_TRUE(payload); + ASSERT_FALSE(error); + if (payload) { + for (auto node : payload->getSubscriptions()) { + subscribedNodes_.insert(node); + } + } + } + + void handlePreferencesForm(Form::ref form, ErrorPayload::ref error) { + ASSERT_FALSE(error); + if (form) { + preferenceForm_ = form; + } + } + + IQ::ref createJoinResult(const std::unordered_set<std::string>& nodes, Form::ref form) { + auto joinResultPayload = std::make_shared<MIXJoin>(); + for (auto node : nodes) { + joinResultPayload->addSubscription(node); + } + if (form) { + joinResultPayload->setForm(form); + } + joinResultPayload->setJID(JID("123456#coven@mix.shakespeare.example")); + return IQ::createResult(ownJID_, channel_->sentStanzas[0]->getTo(), channel_->sentStanzas[0]->getID(), joinResultPayload); + } + + IQ::ref createLeaveResult() { + auto leaveResultPayload = std::make_shared<MIXLeave>(); + return IQ::createResult(ownJID_, channel_->sentStanzas[0]->getTo(), channel_->sentStanzas[0]->getID(), leaveResultPayload); + } + + IQ::ref createError() { + return IQ::createError(ownJID_, channel_->sentStanzas[0]->getTo(), channel_->sentStanzas[0]->getID()); + } + + bool hasSubscription(const std::string& value) { + return std::find(subscribedNodes_.begin(), subscribedNodes_.end(), value) != subscribedNodes_.end(); + } + + JID ownJID_; + JID channelJID_; + DummyStanzaChannel* channel_; + IQRouter* router_; + int successfulJoins_; + Form::ref preferenceForm_; + std::unordered_set<std::string> subscribedNodes_; +}; + +TEST_F(MIXImplTest, testJoinError) { + MIX::ref testling = createMIXClient(); + testling->joinChannel(std::unordered_set<std::string>()); + + ASSERT_EQ(1, static_cast<int>(channel_->sentStanzas.size())); + ASSERT_TRUE(channel_->isRequestAtIndex<MIXJoin>(0, ownJID_.toBare(), IQ::Set)); + + auto iq = channel_->getStanzaAtIndex<IQ>(0); + ASSERT_TRUE(iq); + ASSERT_TRUE(iq->getPayload<MIXJoin>()); + ASSERT_FALSE(iq->getPayload<MIXJoin>()->getForm()); + ASSERT_EQ(static_cast<size_t>(0), iq->getPayload<MIXJoin>()->getSubscriptions().size()); + + channel_->onIQReceived(createError()); + ASSERT_EQ(static_cast<int>(0), successfulJoins_); + ASSERT_EQ(static_cast<int>(0), subscribedNodes_.size()); +} + +TEST_F(MIXImplTest, testJoinWithAllSubscriptions) { + MIX::ref testling = createMIXClient(); + std::unordered_set<std::string> nodes; + nodes.insert(std::string("urn:xmpp:mix:nodes:messages")); + nodes.insert(std::string("urn:xmpp:mix:nodes:presence")); + nodes.insert(std::string("urn:xmpp:mix:nodes:participants")); + nodes.insert(std::string("urn:xmpp:mix:nodes:config")); + + testling->joinChannel(nodes); + + ASSERT_EQ(1, static_cast<int>(channel_->sentStanzas.size())); + ASSERT_TRUE(channel_->isRequestAtIndex<MIXJoin>(0, ownJID_.toBare(), IQ::Set)); + + auto iq = channel_->getStanzaAtIndex<IQ>(0); + ASSERT_TRUE(iq); + ASSERT_TRUE(iq->getPayload<MIXJoin>()); + ASSERT_FALSE(iq->getPayload<MIXJoin>()->getForm()); + ASSERT_EQ(static_cast<size_t>(4), iq->getPayload<MIXJoin>()->getSubscriptions().size()); + + channel_->onIQReceived(createJoinResult(nodes, nullptr)); + ASSERT_EQ(static_cast<int>(1), successfulJoins_); + ASSERT_EQ(static_cast<int>(4), subscribedNodes_.size()); +} + +TEST_F(MIXImplTest, testJoinWithSomeSubscriptions) { + MIX::ref testling = createMIXClient(); + std::unordered_set<std::string> nodes; + nodes.insert(std::string("urn:xmpp:mix:nodes:messages")); + nodes.insert(std::string("urn:xmpp:mix:nodes:presence")); + nodes.insert(std::string("urn:xmpp:mix:nodes:participants")); + nodes.insert(std::string("urn:xmpp:mix:nodes:config")); + + testling->joinChannel(nodes); + + ASSERT_EQ(1, static_cast<int>(channel_->sentStanzas.size())); + ASSERT_TRUE(channel_->isRequestAtIndex<MIXJoin>(0, ownJID_.toBare(), IQ::Set)); + + auto iq = channel_->getStanzaAtIndex<IQ>(0); + ASSERT_TRUE(iq); + ASSERT_TRUE(iq->getPayload<MIXJoin>()); + ASSERT_FALSE(iq->getPayload<MIXJoin>()->getForm()); + ASSERT_EQ(static_cast<size_t>(4), iq->getPayload<MIXJoin>()->getSubscriptions().size()); + + std::unordered_set<std::string> subscribedTo; + subscribedTo.insert(std::string("urn:xmpp:mix:nodes:messages")); + + channel_->onIQReceived(createJoinResult(subscribedTo, nullptr)); + ASSERT_EQ(static_cast<int>(1), successfulJoins_); + ASSERT_EQ(static_cast<int>(1), subscribedNodes_.size()); + ASSERT_TRUE(hasSubscription(std::string("urn:xmpp:mix:nodes:messages"))); +} + +TEST_F(MIXImplTest, testLeaveChannel) { + MIX::ref testling = createMIXClient(); + testling->leaveChannel(); + ASSERT_EQ(1, static_cast<int>(channel_->sentStanzas.size())); + ASSERT_TRUE(channel_->isRequestAtIndex<MIXLeave>(0, ownJID_.toBare(), IQ::Set)); + + auto iq = channel_->getStanzaAtIndex<IQ>(0); + ASSERT_TRUE(iq); + ASSERT_TRUE(iq->getPayload<MIXLeave>()); + ASSERT_TRUE(iq->getPayload<MIXLeave>()->getChannel()); + + channel_->onIQReceived(createLeaveResult()); +} + +TEST_F(MIXImplTest, testUpdateSubscription) { + MIX::ref testling = createMIXClient(); + std::unordered_set<std::string> nodes; + nodes.insert(std::string("urn:xmpp:mix:nodes:messages")); + nodes.insert(std::string("urn:xmpp:mix:nodes:presence")); + + testling->joinChannel(nodes); + + ASSERT_EQ(1, static_cast<int>(channel_->sentStanzas.size())); + ASSERT_TRUE(channel_->isRequestAtIndex<MIXJoin>(0, ownJID_.toBare(), IQ::Set)); + + channel_->onIQReceived(createJoinResult(nodes, nullptr)); + ASSERT_EQ(static_cast<int>(1), successfulJoins_); + ASSERT_EQ(static_cast<int>(2), subscribedNodes_.size()); + + nodes.clear(); + nodes.insert(std::string("urn:xmpp:mix:nodes:participants")); + nodes.insert(std::string("urn:xmpp:mix:nodes:config")); + + testling->updateSubscription(nodes); + + ASSERT_EQ(2, static_cast<int>(channel_->sentStanzas.size())); + ASSERT_TRUE(channel_->isRequestAtIndex<MIXUpdateSubscription>(1, channelJID_, IQ::Set)); + + // fake response + auto subscriptionUpdate = std::make_shared<MIXUpdateSubscription>(); + subscriptionUpdate->setSubscriptions(nodes); + subscriptionUpdate->setJID(JID("hag66@shakespeare.example")); + auto response = IQ::createResult(ownJID_, channel_->sentStanzas[1]->getTo(), channel_->sentStanzas[1]->getID(), subscriptionUpdate); + + channel_->onIQReceived(response); + ASSERT_EQ(static_cast<int>(4), subscribedNodes_.size()); + ASSERT_TRUE(hasSubscription(std::string("urn:xmpp:mix:nodes:participants"))); + ASSERT_TRUE(hasSubscription(std::string("urn:xmpp:mix:nodes:config"))); + ASSERT_TRUE(hasSubscription(std::string("urn:xmpp:mix:nodes:messages"))); +} + +TEST_F(MIXImplTest, testJoinWithPreference) { + MIX::ref testling = createMIXClient(); + std::unordered_set<std::string> nodes; + nodes.insert(std::string("urn:xmpp:mix:nodes:messages")); + nodes.insert(std::string("urn:xmpp:mix:nodes:presence")); + + auto parameters = std::make_shared<Form>(); + parameters->setType(Form::Type::SubmitType); + + auto fieldType = std::make_shared<FormField>(FormField::HiddenType); + fieldType->setName("FORM_TYPE"); + fieldType->addValue("urn:xmpp:mix:0"); + parameters->addField(fieldType); + + auto fieldJIDVisibility = std::make_shared<FormField>(); + fieldJIDVisibility->setName("JID Visibility"); + fieldJIDVisibility->addValue("never"); + parameters->addField(fieldJIDVisibility); + + testling->joinChannelWithPreferences(nodes, parameters); + + ASSERT_EQ(1, static_cast<int>(channel_->sentStanzas.size())); + ASSERT_TRUE(channel_->isRequestAtIndex<MIXJoin>(0, ownJID_.toBare(), IQ::Set)); + + //fake response + auto responseForm = std::make_shared<Form>(); + responseForm->setType(Form::Type::ResultType); + + auto fieldTypeResponse = std::make_shared<FormField>(FormField::HiddenType); + fieldTypeResponse->setName("FORM_TYPE"); + fieldTypeResponse->addValue("urn:xmpp:mix:0"); + responseForm->addField(fieldTypeResponse); + + auto fieldJIDVisibilityResponse = std::make_shared<FormField>(); + fieldJIDVisibilityResponse->setName("JID Visibility"); + fieldJIDVisibilityResponse->addValue("never"); + responseForm->addField(fieldJIDVisibilityResponse); + + auto fieldprivateMessagesResponse = std::make_shared<FormField>(); + fieldprivateMessagesResponse->setName("Private Messages"); + fieldprivateMessagesResponse->addValue("allow"); + responseForm->addField(fieldprivateMessagesResponse); + + auto vCardResponse = std::make_shared<FormField>(); + vCardResponse->setName("vCard"); + vCardResponse->addValue("block"); + responseForm->addField(vCardResponse); + + channel_->onIQReceived(createJoinResult(nodes, responseForm)); + ASSERT_EQ(static_cast<int>(1), successfulJoins_); + ASSERT_EQ(static_cast<int>(2), subscribedNodes_.size()); + ASSERT_TRUE(preferenceForm_); + + ASSERT_TRUE(preferenceForm_->getField("JID Visibility")); + ASSERT_EQ(std::string("never"), preferenceForm_->getField("JID Visibility")->getTextSingleValue()); +} + +TEST_F(MIXImplTest, preferenceFormRequest) { + MIX::ref testling = createMIXClient(); + testling->requestPreferencesForm(); + + ASSERT_EQ(1, static_cast<int>(channel_->sentStanzas.size())); + ASSERT_TRUE(channel_->isRequestAtIndex<MIXUserPreference>(0, channelJID_, IQ::Get)); + + //fake response + auto responseForm = std::make_shared<Form>(); + responseForm->setType(Form::Type::FormType); + + auto fieldTypeResponse = std::make_shared<FormField>(FormField::HiddenType); + fieldTypeResponse->setName("FORM_TYPE"); + fieldTypeResponse->addValue("urn:xmpp:mix:0"); + responseForm->addField(fieldTypeResponse); + + auto preferenceResponse = std::make_shared<MIXUserPreference>(); + preferenceResponse->setData(responseForm); + + channel_->onIQReceived(IQ::createResult(ownJID_, channel_->sentStanzas[0]->getTo(), channel_->sentStanzas[0]->getID(), preferenceResponse)); + ASSERT_TRUE(preferenceForm_); +} diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp index f85cf8d..e9b742c 100644 --- a/Swiften/MUC/MUC.cpp +++ b/Swiften/MUC/MUC.cpp @@ -1,430 +1,14 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/MUC/MUC.h> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> - -#include <Swiften/Base/foreach.h> -#include <Swiften/Presence/DirectedPresenceSender.h> -#include <Swiften/Client/StanzaChannel.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Elements/Form.h> -#include <Swiften/Elements/Message.h> -#include <Swiften/Elements/IQ.h> -#include <Swiften/Elements/MUCUserPayload.h> -#include <Swiften/Elements/MUCAdminPayload.h> -#include <Swiften/Elements/MUCPayload.h> -#include <Swiften/Elements/MUCDestroyPayload.h> -#include <Swiften/Elements/MUCInvitationPayload.h> -#include <Swiften/MUC/MUCRegistry.h> -#include <Swiften/Queries/GenericRequest.h> - namespace Swift { -typedef std::pair<std::string, MUCOccupant> StringMUCOccupantPair; - -MUC::MUC(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, const JID &muc, MUCRegistry* mucRegistry) : ownMUCJID(muc), stanzaChannel(stanzaChannel), iqRouter_(iqRouter), presenceSender(presenceSender), mucRegistry(mucRegistry), createAsReservedIfNew(false), unlocking(false), isUnlocked_(false) { - scopedConnection_ = stanzaChannel->onPresenceReceived.connect(boost::bind(&MUC::handleIncomingPresence, this, _1)); -} - -//FIXME: discover reserved nickname - -/** - * Join the MUC with default context. - */ -void MUC::joinAs(const std::string &nick) { - joinSince_ = boost::posix_time::not_a_date_time; - internalJoin(nick); -} - -/** - * Set the password used for entering the room. - */ -void MUC::setPassword(const boost::optional<std::string>& newPassword) { - password = newPassword; -} - -/** - * Join the MUC with context since date. - */ -void MUC::joinWithContextSince(const std::string &nick, const boost::posix_time::ptime& since) { - joinSince_ = since; - internalJoin(nick); -} - -std::map<std::string, MUCOccupant> MUC::getOccupants() const { - return occupants; -} - -void MUC::internalJoin(const std::string &nick) { - //TODO: history request - joinComplete_ = false; - joinSucceeded_ = false; - - mucRegistry->addMUC(getJID()); - - ownMUCJID = JID(ownMUCJID.getNode(), ownMUCJID.getDomain(), nick); - - Presence::ref joinPresence = boost::make_shared<Presence>(*presenceSender->getLastSentUndirectedPresence()); - assert(joinPresence->getType() == Presence::Available); - joinPresence->setTo(ownMUCJID); - MUCPayload::ref mucPayload = boost::make_shared<MUCPayload>(); - if (joinSince_ != boost::posix_time::not_a_date_time) { - mucPayload->setSince(joinSince_); - } - if (password) { - mucPayload->setPassword(*password); - } - joinPresence->addPayload(mucPayload); - - presenceSender->sendPresence(joinPresence); -} - -void MUC::part() { - presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); - mucRegistry->removeMUC(getJID()); -} - -void MUC::handleUserLeft(LeavingType type) { - std::map<std::string,MUCOccupant>::iterator i = occupants.find(ownMUCJID.getResource()); - if (i != occupants.end()) { - MUCOccupant me = i->second; - occupants.erase(i); - onOccupantLeft(me, type, ""); - } - occupants.clear(); - joinComplete_ = false; - joinSucceeded_ = false; - isUnlocked_ = false; - presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); -} - -void MUC::handleIncomingPresence(Presence::ref presence) { - if (!isFromMUC(presence->getFrom())) { - return; - } - - MUCUserPayload::ref mucPayload; - foreach (MUCUserPayload::ref payload, presence->getPayloads<MUCUserPayload>()) { - if (!payload->getItems().empty() || !payload->getStatusCodes().empty()) { - mucPayload = payload; - } - } - - // On the first incoming presence, check if our join has succeeded - // (i.e. we start getting non-error presence from the MUC) or not - if (!joinSucceeded_) { - if (presence->getType() == Presence::Error) { - std::string reason; - onJoinFailed(presence->getPayload<ErrorPayload>()); - return; - } - else { - joinSucceeded_ = true; - presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); - } - } - - std::string nick = presence->getFrom().getResource(); - if (nick.empty()) { - return; - } - MUCOccupant::Role role(MUCOccupant::NoRole); - MUCOccupant::Affiliation affiliation(MUCOccupant::NoAffiliation); - boost::optional<JID> realJID; - if (mucPayload && mucPayload->getItems().size() > 0) { - role = mucPayload->getItems()[0].role ? mucPayload->getItems()[0].role.get() : MUCOccupant::NoRole; - affiliation = mucPayload->getItems()[0].affiliation ? mucPayload->getItems()[0].affiliation.get() : MUCOccupant::NoAffiliation; - realJID = mucPayload->getItems()[0].realJID; - } - - //100 is non-anonymous - //TODO: 100 may also be specified in a <message/> - //170 is room logging to http - //TODO: Nick changes - if (presence->getType() == Presence::Unavailable) { - LeavingType type = LeavePart; - if (mucPayload) { - if (boost::dynamic_pointer_cast<MUCDestroyPayload>(mucPayload->getPayload())) { - type = LeaveDestroy; - } - else foreach (MUCUserPayload::StatusCode status, mucPayload->getStatusCodes()) { - if (status.code == 307) { - type = LeaveKick; - } - else if (status.code == 301) { - type = LeaveBan; - } - else if (status.code == 321) { - type = LeaveNotMember; - } - } - } - - if (presence->getFrom() == ownMUCJID) { - handleUserLeft(type); - return; - } - else { - std::map<std::string,MUCOccupant>::iterator i = occupants.find(nick); - if (i != occupants.end()) { - //TODO: part type - MUCOccupant occupant = i->second; - occupants.erase(i); - onOccupantLeft(occupant, type, ""); - } - } - } - else if (presence->getType() == Presence::Available) { - std::map<std::string, MUCOccupant>::iterator it = occupants.find(nick); - MUCOccupant occupant(nick, role, affiliation); - bool isJoin = true; - if (realJID) { - occupant.setRealJID(realJID.get()); - } - if (it != occupants.end()) { - isJoin = false; - MUCOccupant oldOccupant = it->second; - if (oldOccupant.getRole() != role) { - onOccupantRoleChanged(nick, occupant, oldOccupant.getRole()); - } - if (oldOccupant.getAffiliation() != affiliation) { - onOccupantAffiliationChanged(nick, affiliation, oldOccupant.getAffiliation()); - } - occupants.erase(it); - } - std::pair<std::map<std::string, MUCOccupant>::iterator, bool> result = occupants.insert(std::make_pair(nick, occupant)); - if (isJoin) { - onOccupantJoined(result.first->second); - } - onOccupantPresenceChange(presence); - } - if (mucPayload && !joinComplete_) { - bool isLocked = false; - foreach (MUCUserPayload::StatusCode status, mucPayload->getStatusCodes()) { - if (status.code == 110) { - /* Simply knowing this is your presence is enough, 210 doesn't seem to be necessary. */ - joinComplete_ = true; - if (ownMUCJID != presence->getFrom()) { - presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); - ownMUCJID = presence->getFrom(); - presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); - } - onJoinComplete(getOwnNick()); - } - if (status.code == 201) { - isLocked = true; - /* Room is created and locked */ - /* Currently deal with this by making an instant room */ - if (ownMUCJID != presence->getFrom()) { - presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); - ownMUCJID = presence->getFrom(); - presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); - } - if (createAsReservedIfNew) { - unlocking = true; - requestConfigurationForm(); - } - else { - MUCOwnerPayload::ref mucPayload(new MUCOwnerPayload()); - presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); - mucPayload->setPayload(boost::make_shared<Form>(Form::SubmitType)); - GenericRequest<MUCOwnerPayload>* request = new GenericRequest<MUCOwnerPayload>(IQ::Set, getJID(), mucPayload, iqRouter_); - request->onResponse.connect(boost::bind(&MUC::handleCreationConfigResponse, this, _1, _2)); - request->send(); - } - } - } - if (!isLocked && !isUnlocked_ && (presence->getFrom() == ownMUCJID)) { - isUnlocked_ = true; - onUnlocked(); - } - } -} - -void MUC::handleCreationConfigResponse(MUCOwnerPayload::ref /*unused*/, ErrorPayload::ref error) { - unlocking = false; - if (error) { - presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); - onJoinFailed(error); - } else { - onJoinComplete(getOwnNick()); /* Previously, this wasn't needed here, as the presence duplication bug caused an emit elsewhere. */ - isUnlocked_ = true; - onUnlocked(); - } -} - -bool MUC::hasOccupant(const std::string& nick) { - return occupants.find(nick) != occupants.end(); -} - -const MUCOccupant& MUC::getOccupant(const std::string& nick) { - return occupants.find(nick)->second; -} - -void MUC::kickOccupant(const JID& jid) { - changeOccupantRole(jid, MUCOccupant::NoRole); -} - -/** - * Call with the room JID, not the real JID. - */ -void MUC::changeOccupantRole(const JID& jid, MUCOccupant::Role role) { - MUCAdminPayload::ref mucPayload = boost::make_shared<MUCAdminPayload>(); - MUCItem item; - item.role = role; - item.nick = jid.getResource(); - mucPayload->addItem(item); - GenericRequest<MUCAdminPayload>* request = new GenericRequest<MUCAdminPayload>(IQ::Set, getJID(), mucPayload, iqRouter_); - request->onResponse.connect(boost::bind(&MUC::handleOccupantRoleChangeResponse, this, _1, _2, jid, role)); - request->send(); - -} - -void MUC::handleOccupantRoleChangeResponse(MUCAdminPayload::ref /*unused*/, ErrorPayload::ref error, const JID& jid, MUCOccupant::Role role) { - if (error) { - onRoleChangeFailed(error, jid, role); - } -} - -void MUC::requestAffiliationList(MUCOccupant::Affiliation affiliation) { - MUCAdminPayload::ref mucPayload = boost::make_shared<MUCAdminPayload>(); - MUCItem item; - item.affiliation = affiliation; - mucPayload->addItem(item); - GenericRequest<MUCAdminPayload>* request = new GenericRequest<MUCAdminPayload>(IQ::Get, getJID(), mucPayload, iqRouter_); - request->onResponse.connect(boost::bind(&MUC::handleAffiliationListResponse, this, _1, _2, affiliation)); - request->send(); -} - -/** - * Must be called with the real JID, not the room JID. - */ -void MUC::changeAffiliation(const JID& jid, MUCOccupant::Affiliation affiliation) { - MUCAdminPayload::ref mucPayload = boost::make_shared<MUCAdminPayload>(); - MUCItem item; - item.affiliation = affiliation; - item.realJID = jid.toBare(); - mucPayload->addItem(item); - GenericRequest<MUCAdminPayload>* request = new GenericRequest<MUCAdminPayload>(IQ::Set, getJID(), mucPayload, iqRouter_); - request->onResponse.connect(boost::bind(&MUC::handleAffiliationChangeResponse, this, _1, _2, jid, affiliation)); - request->send(); -} - -void MUC::handleAffiliationListResponse(MUCAdminPayload::ref payload, ErrorPayload::ref error, MUCOccupant::Affiliation affiliation) { - if (error) { - onAffiliationListFailed(error); - } - else { - std::vector<JID> jids; - foreach (MUCItem item, payload->getItems()) { - if (item.realJID) { - jids.push_back(*item.realJID); - } - } - onAffiliationListReceived(affiliation, jids); - } -} - -void MUC::handleAffiliationChangeResponse(MUCAdminPayload::ref /*unused*/, ErrorPayload::ref error, const JID& jid, MUCOccupant::Affiliation affiliation) { - if (error) { - onAffiliationChangeFailed(error, jid, affiliation); - } -} - -void MUC::changeSubject(const std::string& subject) { - Message::ref message = boost::make_shared<Message>(); - message->setSubject(subject); - message->setType(Message::Groupchat); - message->setTo(ownMUCJID.toBare()); - stanzaChannel->sendMessage(message); -} - -void MUC::requestConfigurationForm() { - MUCOwnerPayload::ref mucPayload(new MUCOwnerPayload()); - GenericRequest<MUCOwnerPayload>* request = new GenericRequest<MUCOwnerPayload>(IQ::Get, getJID(), mucPayload, iqRouter_); - request->onResponse.connect(boost::bind(&MUC::handleConfigurationFormReceived, this, _1, _2)); - request->send(); +MUC::~MUC() { } -void MUC::cancelConfigureRoom() { - MUCOwnerPayload::ref mucPayload(new MUCOwnerPayload()); - mucPayload->setPayload(boost::make_shared<Form>(Form::CancelType)); - GenericRequest<MUCOwnerPayload>* request = new GenericRequest<MUCOwnerPayload>(IQ::Set, getJID(), mucPayload, iqRouter_); - request->send(); -} - -void MUC::handleConfigurationFormReceived(MUCOwnerPayload::ref payload, ErrorPayload::ref error) { - Form::ref form; - if (payload) { - form = payload->getForm(); - } - if (error || !form) { - onConfigurationFailed(error); - } else { - onConfigurationFormReceived(form); - } -} - -void MUC::handleConfigurationResultReceived(MUCOwnerPayload::ref /*payload*/, ErrorPayload::ref error) { - if (error) { - onConfigurationFailed(error); - } -} - -void MUC::configureRoom(Form::ref form) { - MUCOwnerPayload::ref mucPayload(new MUCOwnerPayload()); - mucPayload->setPayload(form); - GenericRequest<MUCOwnerPayload>* request = new GenericRequest<MUCOwnerPayload>(IQ::Set, getJID(), mucPayload, iqRouter_); - if (unlocking) { - request->onResponse.connect(boost::bind(&MUC::handleCreationConfigResponse, this, _1, _2)); - } - else { - request->onResponse.connect(boost::bind(&MUC::handleConfigurationResultReceived, this, _1, _2)); - } - request->send(); -} - -void MUC::destroyRoom() { - MUCOwnerPayload::ref mucPayload = boost::make_shared<MUCOwnerPayload>(); - MUCDestroyPayload::ref mucDestroyPayload = boost::make_shared<MUCDestroyPayload>(); - mucPayload->setPayload(mucDestroyPayload); - GenericRequest<MUCOwnerPayload>* request = new GenericRequest<MUCOwnerPayload>(IQ::Set, getJID(), mucPayload, iqRouter_); - request->onResponse.connect(boost::bind(&MUC::handleConfigurationResultReceived, this, _1, _2)); - request->send(); -} - -void MUC::invitePerson(const JID& person, const std::string& reason, bool isImpromptu, bool isReuseChat) { - Message::ref message = boost::make_shared<Message>(); - message->setTo(person); - message->setType(Message::Normal); - MUCInvitationPayload::ref invite = boost::make_shared<MUCInvitationPayload>(); - invite->setReason(reason); - invite->setJID(ownMUCJID.toBare()); - invite->setIsImpromptu(isImpromptu); - invite->setIsContinuation(isReuseChat); - message->addPayload(invite); - stanzaChannel->sendMessage(message); -} - -//TODO: Invites(direct/mediated) - -//TODO: requesting membership - -//TODO: get member list - -//TODO: request voice - -//TODO: moderator use cases - -//TODO: Admin use cases - -//TODO: Owner use cases - } diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h index 6a0ab75..d61f369 100644 --- a/Swiften/MUC/MUC.h +++ b/Swiften/MUC/MUC.h @@ -1,137 +1,96 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/JID/JID.h> -#include <Swiften/Base/API.h> +#include <map> +#include <memory> #include <string> + +#include <boost/signals2.hpp> +#include <boost/signals2/connection.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/MUCAdminPayload.h> +#include <Swiften/Elements/MUCOccupant.h> +#include <Swiften/Elements/MUCOwnerPayload.h> #include <Swiften/Elements/Message.h> #include <Swiften/Elements/Presence.h> -#include <Swiften/Elements/MUCOccupant.h> +#include <Swiften/JID/JID.h> #include <Swiften/MUC/MUCRegistry.h> -#include <Swiften/Elements/MUCOwnerPayload.h> -#include <Swiften/Elements/MUCAdminPayload.h> -#include <Swiften/Elements/Form.h> - -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> -#include <boost/signals/connection.hpp> - -#include <map> namespace Swift { - class StanzaChannel; - class IQRouter; - class DirectedPresenceSender; - - class SWIFTEN_API MUC { - public: - typedef boost::shared_ptr<MUC> ref; - - enum JoinResult { JoinSucceeded, JoinFailed }; - enum LeavingType { LeavePart, LeaveKick, LeaveBan, LeaveDestroy, LeaveNotMember, Disconnect }; - - public: - MUC(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, const JID &muc, MUCRegistry* mucRegistry); + class SWIFTEN_API MUC { + public: + typedef std::shared_ptr<MUC> ref; - /** - * Returns the (bare) JID of the MUC. - */ - JID getJID() const { - return ownMUCJID.toBare(); - } + enum JoinResult { JoinSucceeded, JoinFailed }; + enum LeavingType { LeavePart, LeaveKick, LeaveBan, LeaveDestroy, LeaveNotMember, Disconnect }; - /** - * Returns if the room is unlocked and other people can join the room. - * @return True if joinable by others; false otherwise. - */ - bool isUnlocked() const { - return isUnlocked_; - } + public: + virtual ~MUC(); - void joinAs(const std::string &nick); - void joinWithContextSince(const std::string &nick, const boost::posix_time::ptime& since); - /*void queryRoomInfo(); */ - /*void queryRoomItems(); */ - std::string getCurrentNick(); - std::map<std::string, MUCOccupant> getOccupants() const; - void part(); - void handleIncomingMessage(Message::ref message); - /** Expose public so it can be called when e.g. user goes offline */ - void handleUserLeft(LeavingType); - /** Get occupant information*/ - const MUCOccupant& getOccupant(const std::string& nick); - bool hasOccupant(const std::string& nick); - void kickOccupant(const JID& jid); - void changeOccupantRole(const JID& jid, MUCOccupant::Role role); - void requestAffiliationList(MUCOccupant::Affiliation); - void changeAffiliation(const JID& jid, MUCOccupant::Affiliation affiliation); - void changeSubject(const std::string& subject); - void requestConfigurationForm(); - void configureRoom(Form::ref); - void cancelConfigureRoom(); - void destroyRoom(); - /** Send an invite for the person to join the MUC */ - void invitePerson(const JID& person, const std::string& reason = "", bool isImpromptu = false, bool isReuseChat = false); - void setCreateAsReservedIfNew() {createAsReservedIfNew = true;} - void setPassword(const boost::optional<std::string>& password); - - public: - boost::signal<void (const std::string& /*nick*/)> onJoinComplete; - boost::signal<void (ErrorPayload::ref)> onJoinFailed; - boost::signal<void (ErrorPayload::ref, const JID&, MUCOccupant::Role)> onRoleChangeFailed; - boost::signal<void (ErrorPayload::ref, const JID&, MUCOccupant::Affiliation)> onAffiliationChangeFailed; - boost::signal<void (ErrorPayload::ref)> onConfigurationFailed; - boost::signal<void (ErrorPayload::ref)> onAffiliationListFailed; - boost::signal<void (Presence::ref)> onOccupantPresenceChange; - boost::signal<void (const std::string&, const MUCOccupant& /*now*/, const MUCOccupant::Role& /*old*/)> onOccupantRoleChanged; - boost::signal<void (const std::string&, const MUCOccupant::Affiliation& /*new*/, const MUCOccupant::Affiliation& /*old*/)> onOccupantAffiliationChanged; - boost::signal<void (const MUCOccupant&)> onOccupantJoined; - boost::signal<void (const MUCOccupant&, LeavingType, const std::string& /*reason*/)> onOccupantLeft; - boost::signal<void (Form::ref)> onConfigurationFormReceived; - boost::signal<void (MUCOccupant::Affiliation, const std::vector<JID>&)> onAffiliationListReceived; - boost::signal<void ()> onUnlocked; - /* boost::signal<void (const MUCInfo&)> onInfoResult; */ - /* boost::signal<void (const blah&)> onItemsResult; */ - + /** + * Returns the (bare) JID of the MUC. + */ + virtual JID getJID() const = 0; - private: - bool isFromMUC(const JID& j) const { - return ownMUCJID.equals(j, JID::WithoutResource); - } + /** + * Returns if the room is unlocked and other people can join the room. + * @return True if joinable by others; false otherwise. + */ + virtual bool isUnlocked() const = 0; - const std::string& getOwnNick() const { - return ownMUCJID.getResource(); - } + virtual void joinAs(const std::string &nick) = 0; + virtual void joinWithContextSince(const std::string &nick, const boost::posix_time::ptime& since) = 0; + /*virtual void queryRoomInfo(); */ + /*virtual void queryRoomItems(); */ + /*virtual std::string getCurrentNick() = 0; */ + virtual std::map<std::string, MUCOccupant> getOccupants() const = 0; + virtual void changeNickname(const std::string& newNickname) = 0; + virtual void part() = 0; + /*virtual void handleIncomingMessage(Message::ref message) = 0; */ + /** Expose public so it can be called when e.g. user goes offline */ + virtual void handleUserLeft(LeavingType) = 0; + /** Get occupant information*/ + virtual const MUCOccupant& getOccupant(const std::string& nick) = 0; + virtual bool hasOccupant(const std::string& nick) = 0; + virtual void kickOccupant(const JID& jid) = 0; + virtual void changeOccupantRole(const JID& jid, MUCOccupant::Role role) = 0; + virtual void requestAffiliationList(MUCOccupant::Affiliation) = 0; + virtual void changeAffiliation(const JID& jid, MUCOccupant::Affiliation affiliation) = 0; + virtual void changeSubject(const std::string& subject) = 0; + virtual void requestConfigurationForm() = 0; + virtual void configureRoom(Form::ref) = 0; + virtual void cancelConfigureRoom() = 0; + virtual void destroyRoom() = 0; + /** Send an invite for the person to join the MUC */ + virtual void invitePerson(const JID& person, const std::string& reason = "", bool isImpromptu = false, bool isReuseChat = false) = 0; + virtual void setCreateAsReservedIfNew() = 0; + virtual void setPassword(const boost::optional<std::string>& password) = 0; - private: - void handleIncomingPresence(Presence::ref presence); - void internalJoin(const std::string& nick); - void handleCreationConfigResponse(MUCOwnerPayload::ref, ErrorPayload::ref); - void handleOccupantRoleChangeResponse(MUCAdminPayload::ref, ErrorPayload::ref, const JID&, MUCOccupant::Role); - void handleAffiliationChangeResponse(MUCAdminPayload::ref, ErrorPayload::ref, const JID&, MUCOccupant::Affiliation); - void handleAffiliationListResponse(MUCAdminPayload::ref, ErrorPayload::ref, MUCOccupant::Affiliation); - void handleConfigurationFormReceived(MUCOwnerPayload::ref, ErrorPayload::ref); - void handleConfigurationResultReceived(MUCOwnerPayload::ref, ErrorPayload::ref); + public: + boost::signals2::signal<void (const std::string& /*nick*/)> onJoinComplete; + boost::signals2::signal<void (ErrorPayload::ref)> onJoinFailed; + boost::signals2::signal<void (ErrorPayload::ref, const JID&, MUCOccupant::Role)> onRoleChangeFailed; + boost::signals2::signal<void (ErrorPayload::ref, const JID&, MUCOccupant::Affiliation)> onAffiliationChangeFailed; + boost::signals2::signal<void (ErrorPayload::ref)> onConfigurationFailed; + boost::signals2::signal<void (ErrorPayload::ref)> onAffiliationListFailed; + boost::signals2::signal<void (Presence::ref)> onOccupantPresenceChange; + boost::signals2::signal<void (const std::string&, const MUCOccupant& /*now*/, const MUCOccupant::Role& /*old*/)> onOccupantRoleChanged; + boost::signals2::signal<void (const std::string&, const MUCOccupant::Affiliation& /*new*/, const MUCOccupant::Affiliation& /*old*/)> onOccupantAffiliationChanged; + boost::signals2::signal<void (const MUCOccupant&)> onOccupantJoined; + boost::signals2::signal<void (const std::string& /*oldNickname*/, const std::string& /*newNickname*/ )> onOccupantNicknameChanged; + boost::signals2::signal<void (const MUCOccupant&, LeavingType, const std::string& /*reason*/)> onOccupantLeft; + boost::signals2::signal<void (Form::ref)> onConfigurationFormReceived; + boost::signals2::signal<void (MUCOccupant::Affiliation, const std::vector<JID>&)> onAffiliationListReceived; + boost::signals2::signal<void ()> onUnlocked; + /* boost::signals2::signal<void (const MUCInfo&)> onInfoResult; */ + /* boost::signals2::signal<void (const blah&)> onItemsResult; */ - private: - JID ownMUCJID; - StanzaChannel* stanzaChannel; - IQRouter* iqRouter_; - DirectedPresenceSender* presenceSender; - MUCRegistry* mucRegistry; - std::map<std::string, MUCOccupant> occupants; - bool joinSucceeded_; - bool joinComplete_; - boost::bsignals::scoped_connection scopedConnection_; - boost::posix_time::ptime joinSince_; - bool createAsReservedIfNew; - bool unlocking; - bool isUnlocked_; - boost::optional<std::string> password; - }; + }; } diff --git a/Swiften/MUC/MUCBookmark.h b/Swiften/MUC/MUCBookmark.h index 3c28bdb..92050f1 100644 --- a/Swiften/MUC/MUCBookmark.h +++ b/Swiften/MUC/MUCBookmark.h @@ -1,88 +1,90 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <string> + #include <boost/optional.hpp> -#include <string> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Storage.h> +#include <Swiften/JID/JID.h> namespace Swift { - class MUCBookmark { - public: - MUCBookmark(const Storage::Room& room) { - name_ = room.name; - room_ = room.jid; - nick_ = room.nick; - password_ = room.password; - autojoin_ = room.autoJoin; - } - - MUCBookmark(const JID& room, const std::string& bookmarkName) : room_(room), name_(bookmarkName), autojoin_(false) { - } - - void setAutojoin(bool enabled) { - autojoin_ = enabled; - } - - bool getAutojoin() const { - return autojoin_; - } - - void setNick(const boost::optional<std::string>& nick) { - nick_ = nick; - } - - void setPassword(const boost::optional<std::string>& password) { - password_ = password; - } - - const boost::optional<std::string>& getNick() const { - return nick_; - } - - const boost::optional<std::string>& getPassword() const { - return password_; - } - - const std::string& getName() const { - return name_; - } - - const JID& getRoom() const { - return room_; - } - - bool operator==(const MUCBookmark& rhs) const { - /* FIXME: not checking passwords for equality - which might make sense, perhaps */ - return rhs.room_ == room_ && rhs.name_ == name_ && rhs.nick_ == nick_ /*&& rhs.password_ == password_*/ && rhs.autojoin_ == autojoin_; - } - - Storage::Room toStorage() const { - Storage::Room room; - room.name = name_; - room.jid = room_; - if (nick_) { - room.nick = *nick_; - } - if (password_) { - room.password = *password_; - } - room.autoJoin = autojoin_; - return room; - } - - private: - JID room_; - std::string name_; - boost::optional<std::string> nick_; - boost::optional<std::string> password_; - bool autojoin_; - }; + class SWIFTEN_API MUCBookmark { + public: + MUCBookmark(const Storage::Room& room) { + name_ = room.name; + room_ = room.jid; + nick_ = room.nick; + password_ = room.password; + autojoin_ = room.autoJoin; + } + + MUCBookmark(const JID& room, const std::string& bookmarkName) : room_(room), name_(bookmarkName), autojoin_(false) { + } + + void setAutojoin(bool enabled) { + autojoin_ = enabled; + } + + bool getAutojoin() const { + return autojoin_; + } + + void setNick(const boost::optional<std::string>& nick) { + nick_ = nick; + } + + void setPassword(const boost::optional<std::string>& password) { + password_ = password; + } + + const boost::optional<std::string>& getNick() const { + return nick_; + } + + const boost::optional<std::string>& getPassword() const { + return password_; + } + + const std::string& getName() const { + return name_; + } + + const JID& getRoom() const { + return room_; + } + + bool operator==(const MUCBookmark& rhs) const { + /* FIXME: not checking passwords for equality - which might make sense, perhaps */ + return rhs.room_ == room_ && rhs.name_ == name_ && rhs.nick_ == nick_ /*&& rhs.password_ == password_*/ && rhs.autojoin_ == autojoin_; + } + + Storage::Room toStorage() const { + Storage::Room room; + room.name = name_; + room.jid = room_; + if (nick_) { + room.nick = *nick_; + } + if (password_) { + room.password = *password_; + } + room.autoJoin = autojoin_; + return room; + } + + private: + JID room_; + std::string name_; + boost::optional<std::string> nick_; + boost::optional<std::string> password_; + bool autojoin_; + }; } diff --git a/Swiften/MUC/MUCBookmarkManager.cpp b/Swiften/MUC/MUCBookmarkManager.cpp index 8a63745..e0922ae 100644 --- a/Swiften/MUC/MUCBookmarkManager.cpp +++ b/Swiften/MUC/MUCBookmarkManager.cpp @@ -1,121 +1,146 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include "MUCBookmarkManager.h" +#include <Swiften/MUC/MUCBookmarkManager.h> + +#include <algorithm> +#include <memory> #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <iostream> -#include <Swiften/Base/foreach.h> #include <Swiften/Queries/IQRouter.h> #include <Swiften/Queries/Requests/GetPrivateStorageRequest.h> #include <Swiften/Queries/Requests/SetPrivateStorageRequest.h> - namespace Swift { MUCBookmarkManager::MUCBookmarkManager(IQRouter* iqRouter) { - iqRouter_ = iqRouter; - ready_ = false; - GetPrivateStorageRequest<Storage>::ref request = GetPrivateStorageRequest<Storage>::create(iqRouter_); - request->onResponse.connect(boost::bind(&MUCBookmarkManager::handleBookmarksReceived, this, _1, _2)); - request->send(); + iqRouter_ = iqRouter; + ready_ = false; + GetPrivateStorageRequest<Storage>::ref request = GetPrivateStorageRequest<Storage>::create(iqRouter_); + request->onResponse.connect(boost::bind(&MUCBookmarkManager::handleBookmarksReceived, this, _1, _2)); + request->send(); } -void MUCBookmarkManager::handleBookmarksReceived(boost::shared_ptr<Storage> payload, ErrorPayload::ref error) { - if (error) { - return; - } - - ready_ = true; - onBookmarksReady(); - - storage = payload; - - std::vector<MUCBookmark> receivedBookmarks; - foreach (Storage::Room room, payload->getRooms()) { - receivedBookmarks.push_back(MUCBookmark(room)); - } - - std::vector<MUCBookmark> newBookmarks; - foreach (const MUCBookmark& oldBookmark, bookmarks_) { - if (containsEquivalent(receivedBookmarks, oldBookmark)) { - newBookmarks.push_back(oldBookmark); - } else { - onBookmarkRemoved(oldBookmark); - } - } - - foreach (const MUCBookmark& newBookmark, receivedBookmarks) { - if (!containsEquivalent(bookmarks_, newBookmark)) { - newBookmarks.push_back(newBookmark); - onBookmarkAdded(newBookmark); - } - } - bookmarks_ = newBookmarks; +void MUCBookmarkManager::handleBookmarksReceived(std::shared_ptr<Storage> payload, ErrorPayload::ref error) { + if (error || !payload) { + return; + } + + ready_ = true; + handlingReceivedBookmarks_ = true; + onBookmarksReady(); + + storage_ = payload; + + std::vector<MUCBookmark> receivedBookmarks; + for (const auto& room : payload->getRooms()) { + receivedBookmarks.push_back(MUCBookmark(room)); + } + + std::vector<MUCBookmark> newBookmarks; + for (const auto& oldBookmark : bookmarks_) { + if (containsEquivalent(receivedBookmarks, oldBookmark)) { + newBookmarks.push_back(oldBookmark); + } else { + onBookmarkRemoved(oldBookmark); + } + } + std::vector<MUCBookmark> newAddedBookmarksToBeSignaled; + for (const auto& newBookmark : receivedBookmarks) { + if (!containsEquivalent(bookmarks_, newBookmark)) { + newBookmarks.push_back(newBookmark); + //If the bookmark does not exist in bookmark manager, after emmiting the signal, chatsmanager will try to join the room, if the bookmark has autojoin to true. + //The bookmark is not yet available in bookmark manager, therefore a new bookmark will be created which will be lost when newBookmarks replace bookmarks. + newAddedBookmarksToBeSignaled.push_back(newBookmark); + } + } + bookmarks_ = newBookmarks; + for (auto bookmark : newAddedBookmarksToBeSignaled) { + onBookmarkAdded(bookmark); + } + + handlingReceivedBookmarks_ = false; } bool MUCBookmarkManager::containsEquivalent(const std::vector<MUCBookmark>& list, const MUCBookmark& bookmark) { - return std::find(list.begin(), list.end(), bookmark) != list.end(); + return std::find_if(list.begin(), list.end(), [&](const MUCBookmark& val) { return bookmark.getRoom() == val.getRoom(); }) != list.end(); } void MUCBookmarkManager::replaceBookmark(const MUCBookmark& oldBookmark, const MUCBookmark& newBookmark) { - if (!ready_) return; - for (size_t i = 0; i < bookmarks_.size(); i++) { - if (bookmarks_[i] == oldBookmark) { - bookmarks_[i] = newBookmark; - flush(); - onBookmarkRemoved(oldBookmark); - onBookmarkAdded(newBookmark); - return; - } - } + if (!ready_) return; + for (auto& bookmark : bookmarks_) { + if (bookmark == oldBookmark) { + bookmark = newBookmark; + flush(); + onBookmarkRemoved(oldBookmark); + onBookmarkAdded(newBookmark); + return; + } + } } void MUCBookmarkManager::addBookmark(const MUCBookmark& bookmark) { - if (!ready_) return; - bookmarks_.push_back(bookmark); - onBookmarkAdded(bookmark); - flush(); + if (!ready_) return; + if (auto found = lookupBookmark(bookmark.getRoom())) { + if (found != bookmark) { + replaceBookmark(found.get(), bookmark); + } + } + else { + bookmarks_.push_back(bookmark); + onBookmarkAdded(bookmark); + } + flush(); } void MUCBookmarkManager::removeBookmark(const MUCBookmark& bookmark) { - if (!ready_) return; - std::vector<MUCBookmark>::iterator it; - for (it = bookmarks_.begin(); it != bookmarks_.end(); ++it) { - if ((*it) == bookmark) { - bookmarks_.erase(it); - onBookmarkRemoved(bookmark); - break; - } - } - flush(); + if (!ready_) return; + std::vector<MUCBookmark>::iterator it; + for (it = bookmarks_.begin(); it != bookmarks_.end(); ++it) { + if ((*it) == bookmark) { + bookmarks_.erase(it); + onBookmarkRemoved(bookmark); + break; + } + } + flush(); } void MUCBookmarkManager::flush() { - if (!storage) { - storage = boost::make_shared<Storage>(); - } - // Update the storage element - storage->clearRooms(); - foreach(const MUCBookmark& bookmark, bookmarks_) { - storage->addRoom(bookmark.toStorage()); - } - - // Send an iq to save the storage element - SetPrivateStorageRequest<Storage>::ref request = SetPrivateStorageRequest<Storage>::create(storage, iqRouter_); - // FIXME: We should care about the result - //request->onResponse.connect(boost::bind(&MUCBookmarkManager::handleBookmarksSet, this, _1, _2)); - request->send(); + if (handlingReceivedBookmarks_) { + return; + } + if (!storage_) { + storage_ = std::make_shared<Storage>(); + } + // Update the storage element + storage_->clearRooms(); + for (const auto& bookmark : bookmarks_) { + storage_->addRoom(bookmark.toStorage()); + } + + // Send an iq to save the storage element + SetPrivateStorageRequest<Storage>::ref request = SetPrivateStorageRequest<Storage>::create(storage_, iqRouter_); + // FIXME: We should care about the result + //request->onResponse.connect(boost::bind(&MUCBookmarkManager::handleBookmarksSet, this, _1, _2)); + request->send(); } const std::vector<MUCBookmark>& MUCBookmarkManager::getBookmarks() const { - return bookmarks_; + return bookmarks_; +} + +boost::optional<MUCBookmark> MUCBookmarkManager::lookupBookmark(const JID& bookmarkJID) const { + auto bookmarkIterator = std::find_if(bookmarks_.begin(), bookmarks_.end(), [&](const MUCBookmark& val) { return bookmarkJID == val.getRoom(); }); + if (bookmarkIterator != bookmarks_.end()) { + return *bookmarkIterator; + } + return boost::none; } } diff --git a/Swiften/MUC/MUCBookmarkManager.h b/Swiften/MUC/MUCBookmarkManager.h index 667caa4..1ef227d 100644 --- a/Swiften/MUC/MUCBookmarkManager.h +++ b/Swiften/MUC/MUCBookmarkManager.h @@ -1,52 +1,53 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <vector> -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> #include <boost/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/MUC/MUCBookmark.h> -#include <Swiften/Elements/Storage.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/Storage.h> +#include <Swiften/MUC/MUCBookmark.h> namespace Swift { - class IQRouter; - - class SWIFTEN_API MUCBookmarkManager { - public: - MUCBookmarkManager(IQRouter* iqRouter); - - void addBookmark(const MUCBookmark& bookmark); - void removeBookmark(const MUCBookmark& bookmark); - void replaceBookmark(const MUCBookmark& oldBookmark, const MUCBookmark& newBookmark); - - const std::vector<MUCBookmark>& getBookmarks() const; - - public: - boost::signal<void (const MUCBookmark&)> onBookmarkAdded; - boost::signal<void (const MUCBookmark&)> onBookmarkRemoved; - /** - * When server bookmarks are ready to be used (request response has been received). - */ - boost::signal<void ()> onBookmarksReady; - - private: - bool containsEquivalent(const std::vector<MUCBookmark>& list, const MUCBookmark& bookmark); - void handleBookmarksReceived(boost::shared_ptr<Storage> payload, ErrorPayload::ref error); - void flush(); - - private: - bool ready_; - std::vector<MUCBookmark> bookmarks_; - IQRouter* iqRouter_; - boost::shared_ptr<Storage> storage; - }; + class IQRouter; + + class SWIFTEN_API MUCBookmarkManager { + public: + MUCBookmarkManager(IQRouter* iqRouter); + + void addBookmark(const MUCBookmark& bookmark); + void removeBookmark(const MUCBookmark& bookmark); + void replaceBookmark(const MUCBookmark& oldBookmark, const MUCBookmark& newBookmark); + const std::vector<MUCBookmark>& getBookmarks() const; + boost::optional<MUCBookmark> lookupBookmark(const JID& bookmarkJID) const; + + public: + boost::signals2::signal<void (const MUCBookmark&)> onBookmarkAdded; + boost::signals2::signal<void (const MUCBookmark&)> onBookmarkRemoved; + /** + * When server bookmarks are ready to be used (request response has been received). + */ + boost::signals2::signal<void ()> onBookmarksReady; + + private: + bool containsEquivalent(const std::vector<MUCBookmark>& list, const MUCBookmark& bookmark); + void handleBookmarksReceived(std::shared_ptr<Storage> payload, ErrorPayload::ref error); + void flush(); + + private: + bool ready_; + bool handlingReceivedBookmarks_; + std::vector<MUCBookmark> bookmarks_; + IQRouter* iqRouter_; + std::shared_ptr<Storage> storage_; + }; } diff --git a/Swiften/MUC/MUCImpl.cpp b/Swiften/MUC/MUCImpl.cpp new file mode 100644 index 0000000..d2b33f3 --- /dev/null +++ b/Swiften/MUC/MUCImpl.cpp @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/MUC/MUCImpl.h> + +#include <memory> + +#include <boost/bind.hpp> + +#include <Swiften/Client/StanzaChannel.h> +#include <Swiften/Elements/CapsInfo.h> +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/MUCAdminPayload.h> +#include <Swiften/Elements/MUCDestroyPayload.h> +#include <Swiften/Elements/MUCInvitationPayload.h> +#include <Swiften/Elements/MUCPayload.h> +#include <Swiften/Elements/MUCUserPayload.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/MUC/MUCRegistry.h> +#include <Swiften/Presence/DirectedPresenceSender.h> +#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Queries/IQRouter.h> + +namespace Swift { + +typedef std::pair<std::string, MUCOccupant> StringMUCOccupantPair; + +MUCImpl::MUCImpl(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, const JID &muc, MUCRegistry* mucRegistry) : ownMUCJID(muc), stanzaChannel(stanzaChannel), iqRouter_(iqRouter), presenceSender(presenceSender), mucRegistry(mucRegistry) { + scopedConnection_ = stanzaChannel->onPresenceReceived.connect(boost::bind(&MUCImpl::handleIncomingPresence, this, _1)); +} + +MUCImpl::~MUCImpl() +{ +} + +//FIXME: discover reserved nickname + +/** + * Join the MUC with default context. + */ +void MUCImpl::joinAs(const std::string &nick) { + joinSince_ = boost::posix_time::not_a_date_time; + internalJoin(nick); +} + +/** + * Set the password used for entering the room. + */ +void MUCImpl::setPassword(const boost::optional<std::string>& newPassword) { + password = newPassword; +} + +/** + * Join the MUC with context since date. + */ +void MUCImpl::joinWithContextSince(const std::string &nick, const boost::posix_time::ptime& since) { + joinSince_ = since; + internalJoin(nick); +} + +std::map<std::string, MUCOccupant> MUCImpl::getOccupants() const { + return occupants; +} + +bool MUCImpl::isEqualExceptID(const Presence& lhs, const Presence& rhs) { + bool isEqual = false; + if (lhs.getFrom() == rhs.getFrom() && lhs.getTo() == rhs.getTo() && lhs.getStatus() == rhs.getStatus() && lhs.getShow() == rhs.getShow()) { + CapsInfo::ref lhsCaps = lhs.getPayload<CapsInfo>(); + CapsInfo::ref rhsCaps = rhs.getPayload<CapsInfo>(); + + if (!!lhsCaps && !!rhsCaps) { + isEqual = (*lhsCaps == *rhsCaps); + } + else { + isEqual = (!lhsCaps && !rhsCaps); + } + } + return isEqual; +} + +void MUCImpl::internalJoin(const std::string &nick) { + //TODO: history request + joinComplete_ = false; + joinSucceeded_ = false; + + mucRegistry->addMUC(getJID()); + + ownMUCJID = JID(ownMUCJID.getNode(), ownMUCJID.getDomain(), nick); + + Presence::ref joinPresence = presenceSender->getLastSentUndirectedPresence() ? (*presenceSender->getLastSentUndirectedPresence())->clone() : std::make_shared<Presence>(); + assert(joinPresence->getType() == Presence::Available); + joinPresence->setTo(ownMUCJID); + MUCPayload::ref mucPayload = std::make_shared<MUCPayload>(); + if (joinSince_ != boost::posix_time::not_a_date_time) { + mucPayload->setSince(joinSince_); + } + if (password) { + mucPayload->setPassword(*password); + } + joinPresence->addPayload(mucPayload); + joinRequestPresence_ = joinPresence; + presenceSender->sendPresence(joinPresence); +} + +void MUCImpl::changeNickname(const std::string& newNickname) { + Presence::ref changeNicknamePresence = std::make_shared<Presence>(); + changeNicknamePresence->setTo(ownMUCJID.toBare().toString() + std::string("/") + newNickname); + presenceSender->sendPresence(changeNicknamePresence); +} + +void MUCImpl::part() { + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); + mucRegistry->removeMUC(getJID()); +} + +void MUCImpl::handleUserLeft(LeavingType type) { + std::map<std::string,MUCOccupant>::iterator i = occupants.find(ownMUCJID.getResource()); + if (i != occupants.end()) { + MUCOccupant me = i->second; + occupants.erase(i); + onOccupantLeft(me, type, ""); + } + occupants.clear(); + joinComplete_ = false; + joinSucceeded_ = false; + isUnlocked_ = false; + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); +} + +void MUCImpl::handleIncomingPresence(Presence::ref presence) { + if (!isFromMUC(presence->getFrom())) { + return; + } + + MUCUserPayload::ref mucPayload; + for (MUCUserPayload::ref payload : presence->getPayloads<MUCUserPayload>()) { + if (!payload->getItems().empty() || !payload->getStatusCodes().empty()) { + mucPayload = payload; + } + } + + // On the first incoming presence, check if our join has succeeded + // (i.e. we start getting non-error presence from the MUC) or not + if (!joinSucceeded_) { + if (presence->getType() == Presence::Error) { + onJoinFailed(presence->getPayload<ErrorPayload>()); + return; + } + else if (presence->getType() == Presence::Available) { + joinSucceeded_ = true; + presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); + if (presenceSender->getLastSentUndirectedPresence() && !isEqualExceptID(**(presenceSender->getLastSentUndirectedPresence()), *joinRequestPresence_)) { + // our presence changed between join request and join complete, send current presence to MUC + Presence::ref latestPresence = std::make_shared<Presence>(**presenceSender->getLastSentUndirectedPresence()); + latestPresence->setTo(ownMUCJID); + presenceSender->sendPresence(latestPresence); + } + } + else if (presence->getType() == Presence::Unavailable) { + onJoinFailed(std::shared_ptr<ErrorPayload>()); + return; + } + } + + std::string nick = presence->getFrom().getResource(); + if (nick.empty()) { + return; + } + MUCOccupant::Role role(MUCOccupant::NoRole); + MUCOccupant::Affiliation affiliation(MUCOccupant::NoAffiliation); + boost::optional<JID> realJID; + if (mucPayload && mucPayload->getItems().size() > 0) { + role = mucPayload->getItems()[0].role ? mucPayload->getItems()[0].role.get() : MUCOccupant::NoRole; + affiliation = mucPayload->getItems()[0].affiliation ? mucPayload->getItems()[0].affiliation.get() : MUCOccupant::NoAffiliation; + realJID = mucPayload->getItems()[0].realJID; + } + + //100 is non-anonymous + //TODO: 100 may also be specified in a <message/> + //170 is room logging to http + //TODO: Nick changes + if (presence->getType() == Presence::Unavailable) { + LeavingType type = LeavePart; + boost::optional<std::string> newNickname; + if (mucPayload) { + if (std::dynamic_pointer_cast<MUCDestroyPayload>(mucPayload->getPayload())) { + type = LeaveDestroy; + } + else { + for (MUCUserPayload::StatusCode status : mucPayload->getStatusCodes()) { + if (status.code == 307) { + type = LeaveKick; + } + else if (status.code == 301) { + type = LeaveBan; + } + else if (status.code == 321) { + type = LeaveNotMember; + } + else if (status.code == 303) { + if (mucPayload->getItems().size() == 1) { + newNickname = mucPayload->getItems()[0].nick; + } + } + } + } + } + if (newNickname) { + std::map<std::string,MUCOccupant>::iterator i = occupants.find(nick); + if (i != occupants.end()) { + MUCOccupant occupant = i->second; + occupants.erase(i); + occupant.setNick(newNickname.get()); + occupants.insert(std::make_pair(newNickname.get(), occupant)); + onOccupantNicknameChanged(nick, newNickname.get()); + } + } + else { + if (presence->getFrom() == ownMUCJID) { + handleUserLeft(type); + return; + } + else { + std::map<std::string,MUCOccupant>::iterator i = occupants.find(nick); + if (i != occupants.end()) { + //TODO: part type + MUCOccupant occupant = i->second; + occupants.erase(i); + onOccupantLeft(occupant, type, ""); + } + } + } + } + else if (presence->getType() == Presence::Available) { + std::map<std::string, MUCOccupant>::iterator it = occupants.find(nick); + MUCOccupant occupant(nick, role, affiliation); + bool isJoin = true; + if (realJID) { + occupant.setRealJID(realJID.get()); + } + if (it != occupants.end()) { + isJoin = false; + MUCOccupant oldOccupant = it->second; + if (oldOccupant.getRole() != role) { + onOccupantRoleChanged(nick, occupant, oldOccupant.getRole()); + } + if (oldOccupant.getAffiliation() != affiliation) { + onOccupantAffiliationChanged(nick, affiliation, oldOccupant.getAffiliation()); + } + occupants.erase(it); + } + std::pair<std::map<std::string, MUCOccupant>::iterator, bool> result = occupants.insert(std::make_pair(nick, occupant)); + if (isJoin) { + onOccupantJoined(result.first->second); + } + onOccupantPresenceChange(presence); + + if (mucPayload && !joinComplete_) { + bool isLocked = false; + for (MUCUserPayload::StatusCode status : mucPayload->getStatusCodes()) { + if (status.code == 110) { + /* Simply knowing this is your presence is enough, 210 doesn't seem to be necessary. */ + joinComplete_ = true; + if (ownMUCJID != presence->getFrom()) { + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); + ownMUCJID = presence->getFrom(); + presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); + } + } + // MUC status 201: a new room has been created + if (status.code == 201) { + isLocked = true; + /* Room is created and locked */ + /* Currently deal with this by making an instant room */ + if (ownMUCJID != presence->getFrom()) { + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); + ownMUCJID = presence->getFrom(); + presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); + } + if (createAsReservedIfNew) { + unlocking = true; + requestConfigurationForm(); + } + else { + // Accept default room configuration and create an instant room http://xmpp.org/extensions/xep-0045.html#createroom-instant + MUCOwnerPayload::ref mucPayload(new MUCOwnerPayload()); + presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); + mucPayload->setPayload(std::make_shared<Form>(Form::SubmitType)); + std::shared_ptr< GenericRequest<MUCOwnerPayload> > request = std::make_shared< GenericRequest<MUCOwnerPayload> >(IQ::Set, getJID(), mucPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MUCImpl::handleCreationConfigResponse, this, _1, _2)); + request->send(); + } + } + } + + if (joinComplete_ && !isLocked) { + assert(hasOccupant(getOwnNick())); + onJoinComplete(getOwnNick()); + } + if (!isLocked && !isUnlocked_ && (presence->getFrom() == ownMUCJID)) { + isUnlocked_ = true; + onUnlocked(); + } + } + } +} + +void MUCImpl::handleCreationConfigResponse(MUCOwnerPayload::ref /*unused*/, ErrorPayload::ref error) { + unlocking = false; + if (error) { + presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence); + onJoinFailed(error); + } else { + onJoinComplete(getOwnNick()); /* Previously, this wasn't needed here, as the presence duplication bug caused an emit elsewhere. */ + isUnlocked_ = true; + onUnlocked(); + } +} + +bool MUCImpl::hasOccupant(const std::string& nick) { + return occupants.find(nick) != occupants.end(); +} + +const MUCOccupant& MUCImpl::getOccupant(const std::string& nick) { + return occupants.find(nick)->second; +} + +void MUCImpl::kickOccupant(const JID& jid) { + changeOccupantRole(jid, MUCOccupant::NoRole); +} + +/** + * Call with the room JID, not the real JID. + */ +void MUCImpl::changeOccupantRole(const JID& jid, MUCOccupant::Role role) { + MUCAdminPayload::ref mucPayload = std::make_shared<MUCAdminPayload>(); + MUCItem item; + item.role = role; + item.nick = jid.getResource(); + mucPayload->addItem(item); + std::shared_ptr<GenericRequest<MUCAdminPayload> > request = std::make_shared<GenericRequest<MUCAdminPayload> >(IQ::Set, getJID(), mucPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MUCImpl::handleOccupantRoleChangeResponse, this, _1, _2, jid, role)); + request->send(); + +} + +void MUCImpl::handleOccupantRoleChangeResponse(MUCAdminPayload::ref /*unused*/, ErrorPayload::ref error, const JID& jid, MUCOccupant::Role role) { + if (error) { + onRoleChangeFailed(error, jid, role); + } +} + +void MUCImpl::requestAffiliationList(MUCOccupant::Affiliation affiliation) { + MUCAdminPayload::ref mucPayload = std::make_shared<MUCAdminPayload>(); + MUCItem item; + item.affiliation = affiliation; + mucPayload->addItem(item); + std::shared_ptr<GenericRequest<MUCAdminPayload> > request = std::make_shared< GenericRequest<MUCAdminPayload> >(IQ::Get, getJID(), mucPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MUCImpl::handleAffiliationListResponse, this, _1, _2, affiliation)); + request->send(); +} + +/** + * Must be called with the real JID, not the room JID. + */ +void MUCImpl::changeAffiliation(const JID& jid, MUCOccupant::Affiliation affiliation) { + MUCAdminPayload::ref mucPayload = std::make_shared<MUCAdminPayload>(); + MUCItem item; + item.affiliation = affiliation; + item.realJID = jid; + mucPayload->addItem(item); + std::shared_ptr<GenericRequest<MUCAdminPayload> > request = std::make_shared<GenericRequest<MUCAdminPayload> >(IQ::Set, getJID(), mucPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MUCImpl::handleAffiliationChangeResponse, this, _1, _2, jid, affiliation)); + request->send(); +} + +void MUCImpl::handleAffiliationListResponse(MUCAdminPayload::ref payload, ErrorPayload::ref error, MUCOccupant::Affiliation affiliation) { + if (error) { + onAffiliationListFailed(error); + } + else { + std::vector<JID> jids; + for (MUCItem item : payload->getItems()) { + if (item.realJID) { + jids.push_back(*item.realJID); + } + } + onAffiliationListReceived(affiliation, jids); + } +} + +void MUCImpl::handleAffiliationChangeResponse(MUCAdminPayload::ref /*unused*/, ErrorPayload::ref error, const JID& jid, MUCOccupant::Affiliation affiliation) { + if (error) { + onAffiliationChangeFailed(error, jid, affiliation); + } +} + +void MUCImpl::changeSubject(const std::string& subject) { + Message::ref message = std::make_shared<Message>(); + message->setSubject(subject); + message->setType(Message::Groupchat); + message->setTo(ownMUCJID.toBare()); + stanzaChannel->sendMessage(message); +} + +void MUCImpl::requestConfigurationForm() { + MUCOwnerPayload::ref mucPayload(new MUCOwnerPayload()); + std::shared_ptr<GenericRequest<MUCOwnerPayload> > request = std::make_shared<GenericRequest<MUCOwnerPayload> >(IQ::Get, getJID(), mucPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MUCImpl::handleConfigurationFormReceived, this, _1, _2)); + request->send(); +} + +void MUCImpl::cancelConfigureRoom() { + MUCOwnerPayload::ref mucPayload(new MUCOwnerPayload()); + mucPayload->setPayload(std::make_shared<Form>(Form::CancelType)); + std::shared_ptr<GenericRequest<MUCOwnerPayload> > request = std::make_shared<GenericRequest<MUCOwnerPayload> >(IQ::Set, getJID(), mucPayload, iqRouter_); + request->send(); +} + +void MUCImpl::handleConfigurationFormReceived(MUCOwnerPayload::ref payload, ErrorPayload::ref error) { + Form::ref form; + if (payload) { + form = payload->getForm(); + } + if (error || !form) { + onConfigurationFailed(error); + } else { + onConfigurationFormReceived(form); + } +} + +void MUCImpl::handleConfigurationResultReceived(MUCOwnerPayload::ref /*payload*/, ErrorPayload::ref error) { + if (error) { + onConfigurationFailed(error); + } +} + +void MUCImpl::configureRoom(Form::ref form) { + MUCOwnerPayload::ref mucPayload(new MUCOwnerPayload()); + mucPayload->setPayload(form); + std::shared_ptr<GenericRequest<MUCOwnerPayload> > request = std::make_shared<GenericRequest<MUCOwnerPayload> >(IQ::Set, getJID(), mucPayload, iqRouter_); + if (unlocking) { + request->onResponse.connect(boost::bind(&MUCImpl::handleCreationConfigResponse, this, _1, _2)); + } + else { + request->onResponse.connect(boost::bind(&MUCImpl::handleConfigurationResultReceived, this, _1, _2)); + } + request->send(); +} + +void MUCImpl::destroyRoom() { + MUCOwnerPayload::ref mucPayload = std::make_shared<MUCOwnerPayload>(); + MUCDestroyPayload::ref mucDestroyPayload = std::make_shared<MUCDestroyPayload>(); + mucPayload->setPayload(mucDestroyPayload); + std::shared_ptr< GenericRequest<MUCOwnerPayload> > request = std::make_shared<GenericRequest<MUCOwnerPayload> >(IQ::Set, getJID(), mucPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MUCImpl::handleConfigurationResultReceived, this, _1, _2)); + request->send(); +} + +void MUCImpl::invitePerson(const JID& person, const std::string& reason, bool isImpromptu, bool isReuseChat) { + Message::ref message = std::make_shared<Message>(); + message->setTo(person); + message->setType(Message::Normal); + MUCInvitationPayload::ref invite = std::make_shared<MUCInvitationPayload>(); + invite->setReason(reason); + invite->setJID(ownMUCJID.toBare()); + invite->setIsImpromptu(isImpromptu); + invite->setIsContinuation(isReuseChat); + message->addPayload(invite); + stanzaChannel->sendMessage(message); +} + +//TODO: Invites(direct/mediated) + +//TODO: requesting membership + +//TODO: get member list + +//TODO: request voice + +//TODO: moderator use cases + +//TODO: Admin use cases + +//TODO: Owner use cases + +} diff --git a/Swiften/MUC/MUCImpl.h b/Swiften/MUC/MUCImpl.h new file mode 100644 index 0000000..1c02dee --- /dev/null +++ b/Swiften/MUC/MUCImpl.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <map> +#include <memory> +#include <string> + +#include <boost/signals2.hpp> +#include <boost/signals2/connection.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/MUCAdminPayload.h> +#include <Swiften/Elements/MUCOccupant.h> +#include <Swiften/Elements/MUCOwnerPayload.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/JID/JID.h> +#include <Swiften/MUC/MUC.h> +#include <Swiften/MUC/MUCRegistry.h> + +namespace Swift { + class StanzaChannel; + class IQRouter; + class DirectedPresenceSender; + + class SWIFTEN_API MUCImpl : public MUC { + public: + typedef std::shared_ptr<MUCImpl> ref; + + public: + MUCImpl(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, const JID &muc, MUCRegistry* mucRegistry); + virtual ~MUCImpl(); + + /** + * Returns the (bare) JID of the MUC. + */ + virtual JID getJID() const { + return ownMUCJID.toBare(); + } + + /** + * Returns if the room is unlocked and other people can join the room. + * @return True if joinable by others; false otherwise. + */ + virtual bool isUnlocked() const { + return isUnlocked_; + } + + virtual void joinAs(const std::string &nick); + virtual void joinWithContextSince(const std::string &nick, const boost::posix_time::ptime& since); + /*virtual void queryRoomInfo(); */ + /*virtual void queryRoomItems(); */ + /*virtual std::string getCurrentNick(); */ + virtual std::map<std::string, MUCOccupant> getOccupants() const; + + /** + * Send a new presence to the MUC indicating a nickname change. Any custom status the user had in the is cleared. + * @param newNickname The nickname to change to. + */ + virtual void changeNickname(const std::string& newNickname); + virtual void part(); + /*virtual void handleIncomingMessage(Message::ref message); */ + /** Expose public so it can be called when e.g. user goes offline */ + virtual void handleUserLeft(LeavingType); + /** Get occupant information*/ + virtual const MUCOccupant& getOccupant(const std::string& nick); + virtual bool hasOccupant(const std::string& nick); + virtual void kickOccupant(const JID& jid); + virtual void changeOccupantRole(const JID& jid, MUCOccupant::Role role); + virtual void requestAffiliationList(MUCOccupant::Affiliation); + virtual void changeAffiliation(const JID& jid, MUCOccupant::Affiliation affiliation); + virtual void changeSubject(const std::string& subject); + virtual void requestConfigurationForm(); + virtual void configureRoom(Form::ref); + virtual void cancelConfigureRoom(); + virtual void destroyRoom(); + /** Send an invite for the person to join the MUC */ + virtual void invitePerson(const JID& person, const std::string& reason = "", bool isImpromptu = false, bool isReuseChat = false); + virtual void setCreateAsReservedIfNew() {createAsReservedIfNew = true;} + virtual void setPassword(const boost::optional<std::string>& password); + + private: + bool isFromMUC(const JID& j) const { + return ownMUCJID.equals(j, JID::WithoutResource); + } + + const std::string& getOwnNick() const { + return ownMUCJID.getResource(); + } + + /** + * This function compares two Presence elements for equality based on to, from, status, show and entity capability information. + * @return True if equal; else otherwise. + */ + static bool isEqualExceptID(const Presence& lhs, const Presence& rhs); + + private: + void handleIncomingPresence(Presence::ref presence); + void internalJoin(const std::string& nick); + void handleCreationConfigResponse(MUCOwnerPayload::ref, ErrorPayload::ref); + void handleOccupantRoleChangeResponse(MUCAdminPayload::ref, ErrorPayload::ref, const JID&, MUCOccupant::Role); + void handleAffiliationChangeResponse(MUCAdminPayload::ref, ErrorPayload::ref, const JID&, MUCOccupant::Affiliation); + void handleAffiliationListResponse(MUCAdminPayload::ref, ErrorPayload::ref, MUCOccupant::Affiliation); + void handleConfigurationFormReceived(MUCOwnerPayload::ref, ErrorPayload::ref); + void handleConfigurationResultReceived(MUCOwnerPayload::ref, ErrorPayload::ref); + + private: + JID ownMUCJID; + StanzaChannel* stanzaChannel; + IQRouter* iqRouter_; + DirectedPresenceSender* presenceSender; + MUCRegistry* mucRegistry; + std::map<std::string, MUCOccupant> occupants; + bool joinSucceeded_ = false; + bool joinComplete_ = false; + boost::signals2::scoped_connection scopedConnection_; + boost::posix_time::ptime joinSince_; + bool createAsReservedIfNew = false; + bool unlocking = false; + bool isUnlocked_ = false; + boost::optional<std::string> password; + Presence::ref joinRequestPresence_; + }; +} diff --git a/Swiften/MUC/MUCManager.cpp b/Swiften/MUC/MUCManager.cpp index 6e9b820..81e5cd5 100644 --- a/Swiften/MUC/MUCManager.cpp +++ b/Swiften/MUC/MUCManager.cpp @@ -1,18 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/MUC/MUCManager.h> +#include <Swiften/MUC/MUCImpl.h> + namespace Swift { MUCManager::MUCManager(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, MUCRegistry* mucRegistry) : stanzaChannel(stanzaChannel), iqRouter(iqRouter), presenceSender(presenceSender), mucRegistry(mucRegistry) { } MUC::ref MUCManager::createMUC(const JID& jid) { - return MUC::ref(new MUC(stanzaChannel, iqRouter, presenceSender, jid, mucRegistry)); + return std::make_shared<MUCImpl>(stanzaChannel, iqRouter, presenceSender, jid, mucRegistry); } } diff --git a/Swiften/MUC/MUCManager.h b/Swiften/MUC/MUCManager.h index cf9000b..c1f0f61 100644 --- a/Swiften/MUC/MUCManager.h +++ b/Swiften/MUC/MUCManager.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,21 +10,21 @@ #include <Swiften/MUC/MUC.h> namespace Swift { - class IQRouter; - class StanzaChannel; - class DirectedPresenceSender; - class MUCRegistry; + class IQRouter; + class StanzaChannel; + class DirectedPresenceSender; + class MUCRegistry; - class SWIFTEN_API MUCManager { - public: - MUCManager(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, MUCRegistry* mucRegistry); + class SWIFTEN_API MUCManager { + public: + MUCManager(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, MUCRegistry* mucRegistry); - MUC::ref createMUC(const JID&); + MUC::ref createMUC(const JID&); - private: - StanzaChannel* stanzaChannel; - IQRouter* iqRouter; - DirectedPresenceSender* presenceSender; - MUCRegistry* mucRegistry; - }; + private: + StanzaChannel* stanzaChannel; + IQRouter* iqRouter; + DirectedPresenceSender* presenceSender; + MUCRegistry* mucRegistry; + }; } diff --git a/Swiften/MUC/MUCRegistry.cpp b/Swiften/MUC/MUCRegistry.cpp index f4d061e..9315173 100644 --- a/Swiften/MUC/MUCRegistry.cpp +++ b/Swiften/MUC/MUCRegistry.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/MUC/MUCRegistry.h> @@ -14,15 +14,15 @@ MUCRegistry::~MUCRegistry() { } bool MUCRegistry::isMUC(const JID& j) const { - return std::find(mucs.begin(), mucs.end(), j) != mucs.end(); + return std::find(mucs.begin(), mucs.end(), j) != mucs.end(); } void MUCRegistry::addMUC(const JID& j) { - mucs.push_back(j); + mucs.push_back(j); } void MUCRegistry::removeMUC(const JID& j) { - erase(mucs, j); + erase(mucs, j); } diff --git a/Swiften/MUC/MUCRegistry.h b/Swiften/MUC/MUCRegistry.h index 6ad1b89..aa341e4 100644 --- a/Swiften/MUC/MUCRegistry.h +++ b/Swiften/MUC/MUCRegistry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -12,17 +12,17 @@ #include <Swiften/JID/JID.h> namespace Swift { - class JID; + class JID; - class SWIFTEN_API MUCRegistry { - public: - ~MUCRegistry(); + class SWIFTEN_API MUCRegistry { + public: + virtual ~MUCRegistry(); - bool isMUC(const JID& j) const; - void addMUC(const JID& j); - void removeMUC(const JID& j); + bool isMUC(const JID& j) const; + void addMUC(const JID& j); + void removeMUC(const JID& j); - private: - std::vector<JID> mucs; - }; + private: + std::vector<JID> mucs; + }; } diff --git a/Swiften/MUC/UnitTest/MUCTest.cpp b/Swiften/MUC/UnitTest/MUCTest.cpp index 427e938..115787e 100644 --- a/Swiften/MUC/UnitTest/MUCTest.cpp +++ b/Swiften/MUC/UnitTest/MUCTest.cpp @@ -1,193 +1,277 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/bind.hpp> -#include <Swiften/MUC/MUC.h> #include <Swiften/Client/DummyStanzaChannel.h> -#include <Swiften/Presence/StanzaChannelPresenceSender.h> -#include <Swiften/Presence/DirectedPresenceSender.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Elements/MUCUserPayload.h> +#include <Swiften/Elements/CapsInfo.h> #include <Swiften/Elements/MUCOwnerPayload.h> +#include <Swiften/Elements/MUCUserPayload.h> #include <Swiften/Elements/VCard.h> -#include <Swiften/Elements/CapsInfo.h> - +#include <Swiften/MUC/MUCImpl.h> +#include <Swiften/Presence/DirectedPresenceSender.h> +#include <Swiften/Presence/StanzaChannelPresenceSender.h> +#include <Swiften/Queries/IQRouter.h> using namespace Swift; class MUCTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(MUCTest); - CPPUNIT_TEST(testJoin); - CPPUNIT_TEST(testJoin_ChangePresenceDuringJoinDoesNotSendPresenceBeforeJoinSuccess); - CPPUNIT_TEST(testJoin_ChangePresenceDuringJoinResendsPresenceAfterJoinSuccess); - CPPUNIT_TEST(testCreateInstant); - CPPUNIT_TEST(testReplicateBug); - /*CPPUNIT_TEST(testJoin_Success); - CPPUNIT_TEST(testJoin_Fail);*/ - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - channel = new DummyStanzaChannel(); - router = new IQRouter(channel); - mucRegistry = new MUCRegistry(); - stanzaChannelPresenceSender = new StanzaChannelPresenceSender(channel); - presenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender); - } - - void tearDown() { - delete presenceSender; - delete stanzaChannelPresenceSender; - delete mucRegistry; - delete router; - delete channel; - } - - void testJoin() { - MUC::ref testling = createMUC(JID("foo@bar.com")); - testling->joinAs("Alice"); - - CPPUNIT_ASSERT(mucRegistry->isMUC(JID("foo@bar.com"))); - Presence::ref p = channel->getStanzaAtIndex<Presence>(0); - CPPUNIT_ASSERT(p); - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/Alice"), p->getTo()); - } - - void testJoin_ChangePresenceDuringJoinDoesNotSendPresenceBeforeJoinSuccess() { - MUC::ref testling = createMUC(JID("foo@bar.com")); - testling->joinAs("Alice"); - - presenceSender->sendPresence(Presence::create("Test")); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel->sentStanzas.size())); - } - - void testJoin_ChangePresenceDuringJoinResendsPresenceAfterJoinSuccess() { - MUC::ref testling = createMUC(JID("foo@bar.com")); - testling->joinAs("Alice"); - - presenceSender->sendPresence(Presence::create("Test")); - receivePresence(JID("foo@bar.com/Rabbit"), "Here"); - - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(channel->sentStanzas.size())); - Presence::ref p = channel->getStanzaAtIndex<Presence>(2); - CPPUNIT_ASSERT(p); - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/Alice"), p->getTo()); - CPPUNIT_ASSERT_EQUAL(std::string("Test"), p->getStatus()); - } - - void testCreateInstant() { - MUC::ref testling = createMUC(JID("rabbithole@wonderland.lit")); - testling->joinAs("Alice"); - Presence::ref serverRespondsLocked = boost::make_shared<Presence>(); - serverRespondsLocked->setFrom(JID("rabbithole@wonderland.lit/Alice")); - MUCUserPayload::ref mucPayload(new MUCUserPayload()); - MUCItem myItem; - myItem.affiliation = MUCOccupant::Owner; - myItem.role = MUCOccupant::Moderator; - mucPayload->addItem(myItem); - mucPayload->addStatusCode(MUCUserPayload::StatusCode(110)); - mucPayload->addStatusCode(MUCUserPayload::StatusCode(201)); - serverRespondsLocked->addPayload(mucPayload); - channel->onPresenceReceived(serverRespondsLocked); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel->sentStanzas.size())); - IQ::ref iq = channel->getStanzaAtIndex<IQ>(1); - CPPUNIT_ASSERT(iq); - CPPUNIT_ASSERT(iq->getPayload<MUCOwnerPayload>()); - CPPUNIT_ASSERT(iq->getPayload<MUCOwnerPayload>()->getForm()); - CPPUNIT_ASSERT_EQUAL(Form::SubmitType, iq->getPayload<MUCOwnerPayload>()->getForm()->getType()); - } - - void testReplicateBug() { - Presence::ref initialPresence = boost::make_shared<Presence>(); - initialPresence->setStatus(""); - VCard::ref vcard = boost::make_shared<VCard>(); - vcard->setPhoto(createByteArray("15c30080ae98ec48be94bf0e191d43edd06e500a")); - initialPresence->addPayload(vcard); - CapsInfo::ref caps = boost::make_shared<CapsInfo>(); - caps->setNode("http://swift.im"); - caps->setVersion("p2UP0DrcVgKM6jJqYN/B92DKK0o="); - initialPresence->addPayload(caps); - channel->sendPresence(initialPresence); - - MUC::ref testling = createMUC(JID("test@rooms.swift.im")); - testling->joinAs("Test"); - Presence::ref serverRespondsLocked = boost::make_shared<Presence>(); - serverRespondsLocked->setFrom(JID("test@rooms.swift.im/Test")); - serverRespondsLocked->setTo(JID("test@swift.im/6913d576d55f0b67")); - serverRespondsLocked->addPayload(vcard); - serverRespondsLocked->addPayload(caps); - serverRespondsLocked->setStatus(""); - MUCUserPayload::ref mucPayload(new MUCUserPayload()); - MUCItem myItem; - myItem.affiliation = MUCOccupant::Owner; - myItem.role = MUCOccupant::Moderator; - mucPayload->addItem(myItem); - mucPayload->addStatusCode(MUCUserPayload::StatusCode(201)); - serverRespondsLocked->addPayload(mucPayload); - channel->onPresenceReceived(serverRespondsLocked); - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(channel->sentStanzas.size())); - IQ::ref iq = channel->getStanzaAtIndex<IQ>(2); - CPPUNIT_ASSERT(iq); - CPPUNIT_ASSERT(iq->getPayload<MUCOwnerPayload>()); - CPPUNIT_ASSERT(iq->getPayload<MUCOwnerPayload>()->getForm()); - CPPUNIT_ASSERT_EQUAL(Form::SubmitType, iq->getPayload<MUCOwnerPayload>()->getForm()->getType()); - } - - /*void testJoin_Success() { - MUC::ref testling = createMUC(JID("foo@bar.com")); - testling->onJoinFinished.connect(boost::bind(&MUCTest::handleJoinFinished, this, _1, _2)); - testling->joinAs("Alice"); - receivePresence(JID("foo@bar.com/Rabbit"), "Here"); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(joinResults.size())); - CPPUNIT_ASSERT_EQUAL(std::string("Alice"), joinResults[0].nick); - CPPUNIT_ASSERT(joinResults[0].error); - } - - void testJoin_Fail() { - //CPPUNIT_ASSERT(!mucRegistry->isMUC(JID("foo@bar.com"))); - }*/ - - private: - MUC::ref createMUC(const JID& jid) { - return boost::make_shared<MUC>(channel, router, presenceSender, jid, mucRegistry); - } - - void handleJoinFinished(const std::string& nick, ErrorPayload::ref error) { - JoinResult r; - r.nick = nick; - r.error = error; - joinResults.push_back(r); - } - - void receivePresence(const JID& jid, const std::string& status) { - Presence::ref p = Presence::create(status); - p->setFrom(jid); - //MUCUserPayload::ref mucUserPayload = boost::make_shared<MUCUserPayload>(); - //mucUserPayload->addItem(item); - //p->addPayload(mucUserPayload); - channel->onPresenceReceived(p); - } - - private: - DummyStanzaChannel* channel; - IQRouter* router; - MUCRegistry* mucRegistry; - StanzaChannelPresenceSender* stanzaChannelPresenceSender; - DirectedPresenceSender* presenceSender; - struct JoinResult { - std::string nick; - ErrorPayload::ref error; - }; - std::vector<JoinResult> joinResults; + CPPUNIT_TEST_SUITE(MUCTest); + CPPUNIT_TEST(testJoin); + CPPUNIT_TEST(testJoin_ChangePresenceDuringJoinDoesNotSendPresenceBeforeJoinSuccess); + CPPUNIT_TEST(testJoin_ChangePresenceDuringJoinResendsPresenceAfterJoinSuccess); + CPPUNIT_TEST(testJoin_NoPresenceChangeDuringJoinDoesNotResendAfterJoinSuccess); + CPPUNIT_TEST(testCreateInstant); + CPPUNIT_TEST(testReplicateBug); + CPPUNIT_TEST(testNicknameChange); + /*CPPUNIT_TEST(testJoin_Success); + CPPUNIT_TEST(testJoin_Fail);*/ + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + channel = new DummyStanzaChannel(); + router = new IQRouter(channel); + mucRegistry = new MUCRegistry(); + stanzaChannelPresenceSender = new StanzaChannelPresenceSender(channel); + presenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender); + nickChanges = 0; + } + + void tearDown() { + delete presenceSender; + delete stanzaChannelPresenceSender; + delete mucRegistry; + delete router; + delete channel; + } + + void testJoin() { + MUC::ref testling = createMUC(JID("foo@bar.com")); + testling->joinAs("Alice"); + + CPPUNIT_ASSERT(mucRegistry->isMUC(JID("foo@bar.com"))); + Presence::ref p = channel->getStanzaAtIndex<Presence>(0); + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/Alice"), p->getTo()); + } + + void testJoin_ChangePresenceDuringJoinDoesNotSendPresenceBeforeJoinSuccess() { + MUC::ref testling = createMUC(JID("foo@bar.com")); + testling->joinAs("Alice"); + + presenceSender->sendPresence(Presence::create("Test")); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel->sentStanzas.size())); + } + + void testJoin_ChangePresenceDuringJoinResendsPresenceAfterJoinSuccess() { + MUC::ref testling = createMUC(JID("foo@bar.com")); + testling->joinAs("Alice"); + + presenceSender->sendPresence(Presence::create("Test")); + receivePresence(JID("foo@bar.com/Rabbit"), "Here"); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(channel->sentStanzas.size())); + Presence::ref p = channel->getStanzaAtIndex<Presence>(2); + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/Alice"), p->getTo()); + CPPUNIT_ASSERT_EQUAL(std::string("Test"), p->getStatus()); + } + + void testJoin_NoPresenceChangeDuringJoinDoesNotResendAfterJoinSuccess() { + MUC::ref testling = createMUC(JID("foo@bar.com")); + testling->joinAs("Alice"); + + receivePresence(JID("foo@bar.com/Rabbit"), "Here"); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); + Presence::ref p = channel->getStanzaAtIndex<Presence>(0); + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/Alice"), p->getTo()); + CPPUNIT_ASSERT_EQUAL(std::string(""), p->getStatus()); + } + + void testCreateInstant() { + MUC::ref testling = createMUC(JID("rabbithole@wonderland.lit")); + testling->joinAs("Alice"); + Presence::ref serverRespondsLocked = std::make_shared<Presence>(); + serverRespondsLocked->setFrom(JID("rabbithole@wonderland.lit/Alice")); + MUCUserPayload::ref mucPayload(new MUCUserPayload()); + MUCItem myItem; + myItem.affiliation = MUCOccupant::Owner; + myItem.role = MUCOccupant::Moderator; + mucPayload->addItem(myItem); + mucPayload->addStatusCode(MUCUserPayload::StatusCode(110)); + mucPayload->addStatusCode(MUCUserPayload::StatusCode(201)); + serverRespondsLocked->addPayload(mucPayload); + channel->onPresenceReceived(serverRespondsLocked); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel->sentStanzas.size())); + IQ::ref iq = channel->getStanzaAtIndex<IQ>(1); + CPPUNIT_ASSERT(iq); + CPPUNIT_ASSERT(iq->getPayload<MUCOwnerPayload>()); + CPPUNIT_ASSERT(iq->getPayload<MUCOwnerPayload>()->getForm()); + CPPUNIT_ASSERT_EQUAL(Form::SubmitType, iq->getPayload<MUCOwnerPayload>()->getForm()->getType()); + } + + void testReplicateBug() { + Presence::ref initialPresence = std::make_shared<Presence>(); + initialPresence->setStatus(""); + VCard::ref vcard = std::make_shared<VCard>(); + vcard->setPhoto(createByteArray("15c30080ae98ec48be94bf0e191d43edd06e500a")); + initialPresence->addPayload(vcard); + CapsInfo::ref caps = std::make_shared<CapsInfo>(); + caps->setNode("http://swift.im"); + caps->setVersion("p2UP0DrcVgKM6jJqYN/B92DKK0o="); + initialPresence->addPayload(caps); + channel->sendPresence(initialPresence); + + MUC::ref testling = createMUC(JID("test@rooms.swift.im")); + testling->joinAs("Test"); + Presence::ref serverRespondsLocked = std::make_shared<Presence>(); + serverRespondsLocked->setFrom(JID("test@rooms.swift.im/Test")); + serverRespondsLocked->setTo(JID("test@swift.im/6913d576d55f0b67")); + serverRespondsLocked->addPayload(vcard); + serverRespondsLocked->addPayload(caps); + serverRespondsLocked->setStatus(""); + MUCUserPayload::ref mucPayload(new MUCUserPayload()); + MUCItem myItem; + myItem.affiliation = MUCOccupant::Owner; + myItem.role = MUCOccupant::Moderator; + mucPayload->addItem(myItem); + mucPayload->addStatusCode(MUCUserPayload::StatusCode(201)); + serverRespondsLocked->addPayload(mucPayload); + channel->onPresenceReceived(serverRespondsLocked); + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(channel->sentStanzas.size())); + IQ::ref iq = channel->getStanzaAtIndex<IQ>(2); + CPPUNIT_ASSERT(iq); + CPPUNIT_ASSERT(iq->getPayload<MUCOwnerPayload>()); + CPPUNIT_ASSERT(iq->getPayload<MUCOwnerPayload>()->getForm()); + CPPUNIT_ASSERT_EQUAL(Form::SubmitType, iq->getPayload<MUCOwnerPayload>()->getForm()->getType()); + } + + void testNicknameChange() { + MUC::ref testling = createMUC(JID("foo@bar.com")); + // Join as Rabbit + testling->joinAs("Rabbit"); + + // Rabbit joins + Presence::ref rabbitJoins = std::make_shared<Presence>(); + rabbitJoins->setTo("test@swift.im/6913d576d55f0b67"); + rabbitJoins->setFrom(testling->getJID().toString() + "/Rabbit"); + channel->onPresenceReceived(rabbitJoins); + CPPUNIT_ASSERT_EQUAL(true, testling->hasOccupant("Rabbit")); + + // Alice joins + Presence::ref aliceJoins = std::make_shared<Presence>(); + aliceJoins->setTo("test@swift.im/6913d576d55f0b67"); + aliceJoins->setFrom(testling->getJID().toString() + "/Alice"); + channel->onPresenceReceived(aliceJoins); + CPPUNIT_ASSERT_EQUAL(true, testling->hasOccupant("Alice")); + + // Change nick to Dodo + testling->changeNickname("Dodo"); + Presence::ref stanza = channel->getStanzaAtIndex<Presence>(1); + CPPUNIT_ASSERT(stanza); + CPPUNIT_ASSERT_EQUAL(std::string("Dodo"), stanza->getTo().getResource()); + + // Alice changes nick to Alice2 + stanza = std::make_shared<Presence>(); + stanza->setFrom(JID("foo@bar.com/Alice")); + stanza->setTo(JID(router->getJID())); + stanza->setType(Presence::Unavailable); + MUCUserPayload::ref mucPayload(new MUCUserPayload()); + MUCItem myItem; + myItem.affiliation = MUCOccupant::Member; + myItem.nick = "Alice2"; + myItem.role = MUCOccupant::Participant; + mucPayload->addItem(myItem); + mucPayload->addStatusCode(303); + stanza->addPayload(mucPayload); + channel->onPresenceReceived(stanza); + CPPUNIT_ASSERT_EQUAL(1, nickChanges); + CPPUNIT_ASSERT_EQUAL(false, testling->hasOccupant("Alice")); + CPPUNIT_ASSERT_EQUAL(true, testling->hasOccupant("Alice2")); + + // We (Rabbit) change nick to Robot + stanza = std::make_shared<Presence>(); + stanza->setFrom(JID("foo@bar.com/Rabbit")); + stanza->setTo(JID(router->getJID())); + stanza->setType(Presence::Unavailable); + mucPayload = MUCUserPayload::ref(new MUCUserPayload()); + myItem.affiliation = MUCOccupant::Member; + myItem.nick = "Robot"; + myItem.role = MUCOccupant::Participant; + mucPayload->addItem(myItem); + mucPayload->addStatusCode(303); + stanza->addPayload(mucPayload); + channel->onPresenceReceived(stanza); + CPPUNIT_ASSERT_EQUAL(2, nickChanges); + CPPUNIT_ASSERT_EQUAL(false, testling->hasOccupant("Rabbit")); + CPPUNIT_ASSERT_EQUAL(true, testling->hasOccupant("Robot")); + } + + /*void testJoin_Success() { + MUC::ref testling = createMUC(JID("foo@bar.com")); + testling->onJoinFinished.connect(boost::bind(&MUCTest::handleJoinFinished, this, _1, _2)); + testling->joinAs("Alice"); + receivePresence(JID("foo@bar.com/Rabbit"), "Here"); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(joinResults.size())); + CPPUNIT_ASSERT_EQUAL(std::string("Alice"), joinResults[0].nick); + CPPUNIT_ASSERT(joinResults[0].error); + } + + void testJoin_Fail() { + //CPPUNIT_ASSERT(!mucRegistry->isMUC(JID("foo@bar.com"))); + }*/ + + private: + MUC::ref createMUC(const JID& jid) { + MUC::ref muc = std::make_shared<MUCImpl>(channel, router, presenceSender, jid, mucRegistry); + muc->onOccupantNicknameChanged.connect(boost::bind(&MUCTest::handleOccupantNicknameChanged, this, _1, _2)); + return muc; + } + + void handleJoinFinished(const std::string& nick, ErrorPayload::ref error) { + JoinResult r; + r.nick = nick; + r.error = error; + joinResults.push_back(r); + } + + void receivePresence(const JID& jid, const std::string& status) { + Presence::ref p = Presence::create(status); + p->setFrom(jid); + //MUCUserPayload::ref mucUserPayload = std::make_shared<MUCUserPayload>(); + //mucUserPayload->addItem(item); + //p->addPayload(mucUserPayload); + channel->onPresenceReceived(p); + } + + void handleOccupantNicknameChanged(const std::string&, const std::string&) { + nickChanges++; + } + + private: + DummyStanzaChannel* channel; + IQRouter* router; + MUCRegistry* mucRegistry; + StanzaChannelPresenceSender* stanzaChannelPresenceSender; + DirectedPresenceSender* presenceSender; + struct JoinResult { + std::string nick; + ErrorPayload::ref error; + }; + std::vector<JoinResult> joinResults; + int nickChanges; }; CPPUNIT_TEST_SUITE_REGISTRATION(MUCTest); diff --git a/Swiften/MUC/UnitTest/MockMUC.cpp b/Swiften/MUC/UnitTest/MockMUC.cpp new file mode 100644 index 0000000..d9bf348 --- /dev/null +++ b/Swiften/MUC/UnitTest/MockMUC.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/MUC/UnitTest/MockMUC.h> + +namespace Swift { + +MockMUC::MockMUC(const JID &muc) +: ownMUCJID(muc) +, newSubjectSet_("") +{ +} + +MockMUC::~MockMUC() { +} + +void MockMUC::insertOccupant(const MUCOccupant& occupant) +{ + occupants_.insert(std::make_pair(occupant.getNick(), occupant)); + onOccupantJoined(occupant); +} + +const MUCOccupant& MockMUC::getOccupant(const std::string& nick) { + return occupants_.find(nick)->second; +} + +bool MockMUC::hasOccupant(const std::string& nick) { + return occupants_.find(nick) != occupants_.end(); +} + +void MockMUC::changeAffiliation(const JID &jid, MUCOccupant::Affiliation newAffilation) { + std::map<std::string, MUCOccupant>::iterator i = occupants_.find(jid.getResource()); + if (i != occupants_.end()) { + const MUCOccupant old = i->second; + i->second = MUCOccupant(old.getNick(), old.getRole(), newAffilation); + onOccupantAffiliationChanged(i->first, newAffilation, old.getAffiliation()); + } +} + +void MockMUC::changeOccupantRole(const JID &jid, MUCOccupant::Role newRole) { + std::map<std::string, MUCOccupant>::iterator i = occupants_.find(jid.getResource()); + if (i != occupants_.end()) { + const MUCOccupant old = i->second; + i->second = MUCOccupant(old.getNick(), newRole, old.getAffiliation()); + onOccupantRoleChanged(i->first, i->second, old.getRole()); + } +} +void MockMUC::changeSubject(const std::string& newSubject) { + newSubjectSet_ = newSubject; +} + +} diff --git a/Swiften/MUC/UnitTest/MockMUC.h b/Swiften/MUC/UnitTest/MockMUC.h new file mode 100644 index 0000000..39b0f1a --- /dev/null +++ b/Swiften/MUC/UnitTest/MockMUC.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <map> +#include <memory> +#include <string> + +#include <boost/signals2.hpp> +#include <boost/signals2/connection.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/MUCAdminPayload.h> +#include <Swiften/Elements/MUCOccupant.h> +#include <Swiften/Elements/MUCOwnerPayload.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/JID/JID.h> +#include <Swiften/MUC/MUC.h> +#include <Swiften/MUC/MUCRegistry.h> + +namespace Swift { + class SWIFTEN_API MockMUC : public MUC{ + public: + typedef std::shared_ptr<MockMUC> ref; + + public: + MockMUC(const JID &muc); + virtual ~MockMUC(); + + /** + * Cause a user to appear to have entered the room. For testing only. + */ + void insertOccupant(const MUCOccupant& occupant); + + /** + * Returns the (bare) JID of the MUC. + */ + virtual JID getJID() const { + return ownMUCJID.toBare(); + } + /** + * Returns if the room is unlocked and other people can join the room. + * @return True if joinable by others; false otherwise. + */ + virtual bool isUnlocked() const { return true; } + + virtual void joinAs(const std::string&) {} + virtual void joinWithContextSince(const std::string&, const boost::posix_time::ptime&) {} + /*virtual void queryRoomInfo(); */ + /*virtual void queryRoomItems(); */ + /*virtual std::string getCurrentNick() = 0; */ + virtual std::map<std::string, MUCOccupant> getOccupants() const { return occupants_; } + virtual void changeNickname(const std::string&) { } + virtual void part() {} + /*virtual void handleIncomingMessage(Message::ref message) = 0; */ + /** Expose public so it can be called when e.g. user goes offline */ + virtual void handleUserLeft(LeavingType) {} + /** Get occupant information*/ + virtual const MUCOccupant& getOccupant(const std::string&); + virtual bool hasOccupant(const std::string&); + virtual void kickOccupant(const JID&) {} + virtual void changeOccupantRole(const JID&, MUCOccupant::Role); + virtual void requestAffiliationList(MUCOccupant::Affiliation) {} + virtual void changeAffiliation(const JID&, MUCOccupant::Affiliation); + virtual void changeSubject(const std::string&); + virtual void requestConfigurationForm() {} + virtual void configureRoom(Form::ref) {} + virtual void cancelConfigureRoom() {} + virtual void destroyRoom() {} + /** Send an invite for the person to join the MUC */ + virtual void invitePerson(const JID&, const std::string&, bool, bool) {} + virtual void setCreateAsReservedIfNew() {} + virtual void setPassword(const boost::optional<std::string>&) {} + + protected: + virtual bool isFromMUC(const JID& j) const { + return ownMUCJID.equals(j, JID::WithoutResource); + } + + virtual const std::string& getOwnNick() const { + return ownMUCJID.getResource(); + } + + private: + JID ownMUCJID; + std::map<std::string, MUCOccupant> occupants_; + + public: + std::string newSubjectSet_; + }; +} diff --git a/Swiften/Network/BOSHConnection.cpp b/Swiften/Network/BOSHConnection.cpp index 23772eb..1312a3e 100644 --- a/Swiften/Network/BOSHConnection.cpp +++ b/Swiften/Network/BOSHConnection.cpp @@ -5,295 +5,392 @@ */ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/BOSHConnection.h> +#include <string> +#include <thread> + #include <boost/bind.hpp> -#include <boost/thread.hpp> #include <boost/lexical_cast.hpp> -#include <string> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Concat.h> #include <Swiften/Base/Log.h> #include <Swiften/Base/String.h> -#include <Swiften/Base/Concat.h> -#include <Swiften/Base/ByteArray.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Parser/BOSHBodyExtractor.h> +#include <Swiften/StreamStack/DummyStreamLayer.h> +#include <Swiften/StreamStack/TLSLayer.h> +#include <Swiften/TLS/TLSContext.h> +#include <Swiften/TLS/TLSContextFactory.h> +#include <Swiften/TLS/TLSOptions.h> namespace Swift { -BOSHConnection::BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory) - : boshURL_(boshURL), - connector_(connector), - parserFactory_(parserFactory), - sid_(), - waitingForStartResponse_(false), - pending_(false), - connectionReady_(false) +BOSHConnection::BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory, TLSContextFactory* tlsContextFactory, const TLSOptions& tlsOptions) + : boshURL_(boshURL), + connector_(connector), + parserFactory_(parserFactory), + sid_(), + waitingForStartResponse_(false), + rid_(~0ULL), + pending_(false), + connectionReady_(false) { + if (boshURL_.getScheme() == "https") { + auto tlsContext = tlsContextFactory->createTLSContext(tlsOptions); + tlsLayer_ = std::make_shared<TLSLayer>(std::move(tlsContext)); + // The following dummyLayer_ is needed as the TLSLayer will pass the decrypted data to its parent layer. + // The dummyLayer_ will serve as the parent layer. + dummyLayer_ = std::make_shared<DummyStreamLayer>(tlsLayer_.get()); + } } BOSHConnection::~BOSHConnection() { - cancelConnector(); - if (connection_) { - connection_->onDataRead.disconnect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1)); - connection_->onDisconnected.disconnect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1)); - } - disconnect(); + cancelConnector(); + if (connection_) { + connection_->onDataRead.disconnect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1)); + connection_->onDisconnected.disconnect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1)); + } + BOSHConnection::disconnect(); } void BOSHConnection::connect() { - connector_->onConnectFinished.connect(boost::bind(&BOSHConnection::handleConnectFinished, shared_from_this(), _1)); - connector_->start(); + connector_->onConnectFinished.connect(boost::bind(&BOSHConnection::handleConnectFinished, shared_from_this(), _1)); + connector_->start(); } void BOSHConnection::cancelConnector() { - if (connector_) { - connector_->onConnectFinished.disconnect(boost::bind(&BOSHConnection::handleConnectFinished, shared_from_this(), _1)); - connector_->stop(); - connector_.reset(); - } + if (connector_) { + connector_->onConnectFinished.disconnect(boost::bind(&BOSHConnection::handleConnectFinished, shared_from_this(), _1)); + connector_->stop(); + connector_.reset(); + } +} + +void BOSHConnection::handleTLSConnected() { + SWIFT_LOG(debug); + onConnectFinished(false); +} + +void BOSHConnection::handleTLSApplicationDataRead(const SafeByteArray& data) { + SWIFT_LOG(debug); + handleDataRead(std::make_shared<SafeByteArray>(data)); +} + +void BOSHConnection::handleTLSNetowrkDataWriteRequest(const SafeByteArray& data) { + SWIFT_LOG(debug); + connection_->write(data); +} + +void BOSHConnection::handleRawDataRead(std::shared_ptr<SafeByteArray> data) { + SWIFT_LOG(debug); + tlsLayer_->handleDataRead(*data.get()); +} + +void BOSHConnection::handleTLSError(std::shared_ptr<TLSError> error) { + SWIFT_LOG(debug) << (error ? error->getMessage() : "Unknown TLS error"); +} + +void BOSHConnection::writeData(const SafeByteArray& data) { + if (tlsLayer_) { + tlsLayer_->writeData(data); + } + else { + connection_->write(data); + } } void BOSHConnection::disconnect() { - if (connection_) { - connection_->disconnect(); - sid_ = ""; - } - else { - /* handleDisconnected takes care of the connector_ as well */ - handleDisconnected(boost::optional<Connection::Error>()); - } + if (connection_) { + connection_->disconnect(); + sid_ = ""; + } + else { + /* handleDisconnected takes care of the connector_ as well */ + handleDisconnected(boost::optional<Connection::Error>()); + } } void BOSHConnection::restartStream() { - write(createSafeByteArray(""), true, false); + write(createSafeByteArray(""), true, false); +} + +bool BOSHConnection::setClientCertificate(CertificateWithKey::ref cert) { + if (tlsLayer_) { + SWIFT_LOG(debug) << "set client certificate"; + return tlsLayer_->setClientCertificate(cert); + } + else { + return false; + } +} + +Certificate::ref BOSHConnection::getPeerCertificate() const { + Certificate::ref peerCertificate; + if (tlsLayer_) { + peerCertificate = tlsLayer_->getPeerCertificate(); + } + return peerCertificate; +} + +std::vector<Certificate::ref> BOSHConnection::getPeerCertificateChain() const { + std::vector<Certificate::ref> peerCertificateChain; + if (tlsLayer_) { + peerCertificateChain = tlsLayer_->getPeerCertificateChain(); + } + return peerCertificateChain; +} + +CertificateVerificationError::ref BOSHConnection::getPeerCertificateVerificationError() const { + CertificateVerificationError::ref verificationError; + if (tlsLayer_) { + verificationError = tlsLayer_->getPeerCertificateVerificationError(); + } + return verificationError; } void BOSHConnection::terminateStream() { - write(createSafeByteArray(""), false, true); + write(createSafeByteArray(""), false, true); } void BOSHConnection::write(const SafeByteArray& data) { - write(data, false, false); + write(data, false, false); } std::pair<SafeByteArray, size_t> BOSHConnection::createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, unsigned long long rid, const std::string& sid, const URL& boshURL) { - size_t size; - std::stringstream content; - SafeByteArray contentTail = createSafeByteArray("</body>"); - std::stringstream header; - - content << "<body rid='" << rid << "' sid='" << sid << "'"; - if (streamRestart) { - content << " xmpp:restart='true' xmlns:xmpp='urn:xmpp:xbosh'"; - } - if (terminate) { - content << " type='terminate'"; - } - content << " xmlns='http://jabber.org/protocol/httpbind'>"; - - SafeByteArray safeContent = createSafeByteArray(content.str()); - safeContent.insert(safeContent.end(), data.begin(), data.end()); - safeContent.insert(safeContent.end(), contentTail.begin(), contentTail.end()); - - size = safeContent.size(); - - header << "POST " << boshURL.getPath() << " HTTP/1.1\r\n" - << "Host: " << boshURL.getHost(); - if (boshURL.getPort()) { - header << ":" << *boshURL.getPort(); - } - header << "\r\n" - // << "Accept-Encoding: deflate\r\n" - << "Content-Type: text/xml; charset=utf-8\r\n" - << "Content-Length: " << size << "\r\n\r\n"; - - SafeByteArray safeHeader = createSafeByteArray(header.str()); - safeHeader.insert(safeHeader.end(), safeContent.begin(), safeContent.end()); - - return std::pair<SafeByteArray, size_t>(safeHeader, size); + size_t size; + std::stringstream content; + SafeByteArray contentTail = createSafeByteArray("</body>"); + std::stringstream header; + + content << "<body rid='" << rid << "' sid='" << sid << "'"; + if (streamRestart) { + content << " xmpp:restart='true' xmlns:xmpp='urn:xmpp:xbosh'"; + } + if (terminate) { + content << " type='terminate'"; + } + content << " xmlns='http://jabber.org/protocol/httpbind'>"; + + SafeByteArray safeContent = createSafeByteArray(content.str()); + safeContent.insert(safeContent.end(), data.begin(), data.end()); + safeContent.insert(safeContent.end(), contentTail.begin(), contentTail.end()); + + size = safeContent.size(); + + header << "POST " << boshURL.getPath() << " HTTP/1.1\r\n" + << "Host: " << boshURL.getHost(); + if (boshURL.getPort()) { + header << ":" << *boshURL.getPort(); + } + header << "\r\n" + // << "Accept-Encoding: deflate\r\n" + << "Content-Type: text/xml; charset=utf-8\r\n" + << "Content-Length: " << size << "\r\n\r\n"; + + SafeByteArray safeHeader = createSafeByteArray(header.str()); + safeHeader.insert(safeHeader.end(), safeContent.begin(), safeContent.end()); + + return std::pair<SafeByteArray, size_t>(safeHeader, size); } void BOSHConnection::write(const SafeByteArray& data, bool streamRestart, bool terminate) { - assert(connectionReady_); - assert(!sid_.empty()); + assert(connectionReady_); + assert(!sid_.empty()); - SafeByteArray safeHeader = createHTTPRequest(data, streamRestart, terminate, rid_, sid_, boshURL_).first; + SafeByteArray safeHeader = createHTTPRequest(data, streamRestart, terminate, rid_, sid_, boshURL_).first; - onBOSHDataWritten(safeHeader); - connection_->write(safeHeader); - pending_ = true; + onBOSHDataWritten(safeHeader); + writeData(safeHeader); + pending_ = true; - SWIFT_LOG(debug) << "write data: " << safeByteArrayToString(safeHeader) << std::endl; + SWIFT_LOG(debug) << "write data: " << safeByteArrayToString(safeHeader); } void BOSHConnection::handleConnectFinished(Connection::ref connection) { - cancelConnector(); - connectionReady_ = connection; - if (connectionReady_) { - connection_ = connection; - connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1)); - connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1)); - } - onConnectFinished(!connectionReady_); + cancelConnector(); + connectionReady_ = !!connection; + if (connectionReady_) { + connection_ = connection; + if (tlsLayer_) { + connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleRawDataRead, shared_from_this(), _1)); + connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1)); + + tlsLayer_->getContext()->onDataForNetwork.connect(boost::bind(&BOSHConnection::handleTLSNetowrkDataWriteRequest, shared_from_this(), _1)); + tlsLayer_->getContext()->onDataForApplication.connect(boost::bind(&BOSHConnection::handleTLSApplicationDataRead, shared_from_this(), _1)); + tlsLayer_->onConnected.connect(boost::bind(&BOSHConnection::handleTLSConnected, shared_from_this())); + tlsLayer_->onError.connect(boost::bind(&BOSHConnection::handleTLSError, shared_from_this(), _1)); + tlsLayer_->connect(); + } + else { + connection_->onDataRead.connect(boost::bind(&BOSHConnection::handleDataRead, shared_from_this(), _1)); + connection_->onDisconnected.connect(boost::bind(&BOSHConnection::handleDisconnected, shared_from_this(), _1)); + } + } + + if (!connectionReady_ || !tlsLayer_) { + onConnectFinished(!connectionReady_); + } } void BOSHConnection::startStream(const std::string& to, unsigned long long rid) { - assert(connectionReady_); - // Session Creation Request - std::stringstream content; - std::stringstream header; - - content << "<body content='text/xml; charset=utf-8'" - << " hold='1'" - << " to='" << to << "'" - << " rid='" << rid << "'" - << " ver='1.6'" - << " wait='60'" /* FIXME: we probably want this configurable*/ - // << " ack='0'" FIXME: support acks - << " xml:lang='en'" - << " xmlns:xmpp='urn:xmpp:bosh'" - << " xmpp:version='1.0'" - << " xmlns='http://jabber.org/protocol/httpbind' />"; - - std::string contentString = content.str(); - - header << "POST " << boshURL_.getPath() << " HTTP/1.1\r\n" - << "Host: " << boshURL_.getHost(); - if (boshURL_.getPort()) { - header << ":" << *boshURL_.getPort(); - } - header << "\r\n" - // << "Accept-Encoding: deflate\r\n" - << "Content-Type: text/xml; charset=utf-8\r\n" - << "Content-Length: " << contentString.size() << "\r\n\r\n" - << contentString; - - waitingForStartResponse_ = true; - SafeByteArray safeHeader = createSafeByteArray(header.str()); - onBOSHDataWritten(safeHeader); - connection_->write(safeHeader); - SWIFT_LOG(debug) << "write stream header: " << safeByteArrayToString(safeHeader) << std::endl; + assert(connectionReady_); + // Session Creation Request + std::stringstream content; + std::stringstream header; + + content << "<body content='text/xml; charset=utf-8'" + << " hold='1'" + << " to='" << to << "'" + << " rid='" << rid << "'" + << " ver='1.6'" + << " wait='60'" /* FIXME: we probably want this configurable*/ + // << " ack='0'" FIXME: support acks + << " xml:lang='en'" + << " xmlns:xmpp='urn:xmpp:bosh'" + << " xmpp:version='1.0'" + << " xmlns='http://jabber.org/protocol/httpbind' />"; + + std::string contentString = content.str(); + + header << "POST " << boshURL_.getPath() << " HTTP/1.1\r\n" + << "Host: " << boshURL_.getHost(); + if (boshURL_.getPort()) { + header << ":" << *boshURL_.getPort(); + } + header << "\r\n" + // << "Accept-Encoding: deflate\r\n" + << "Content-Type: text/xml; charset=utf-8\r\n" + << "Content-Length: " << contentString.size() << "\r\n\r\n" + << contentString; + + waitingForStartResponse_ = true; + SafeByteArray safeHeader = createSafeByteArray(header.str()); + onBOSHDataWritten(safeHeader); + writeData(safeHeader); + SWIFT_LOG(debug) << "write stream header: " << safeByteArrayToString(safeHeader); } -void BOSHConnection::handleDataRead(boost::shared_ptr<SafeByteArray> data) { - onBOSHDataRead(*data); - buffer_ = concat(buffer_, *data); - std::string response = safeByteArrayToString(buffer_); - if (response.find("\r\n\r\n") == std::string::npos) { - onBOSHDataRead(createSafeByteArray("[[Previous read incomplete, pending]]")); - return; - } - - std::string httpCode = response.substr(response.find(" ") + 1, 3); - if (httpCode != "200") { - onHTTPError(httpCode); - return; - } - - BOSHBodyExtractor parser(parserFactory_, createByteArray(response.substr(response.find("\r\n\r\n") + 4))); - if (parser.getBody()) { - if (parser.getBody()->attributes.getAttribute("type") == "terminate") { - BOSHError::Type errorType = parseTerminationCondition(parser.getBody()->attributes.getAttribute("condition")); - onSessionTerminated(errorType == BOSHError::NoError ? boost::shared_ptr<BOSHError>() : boost::make_shared<BOSHError>(errorType)); - } - buffer_.clear(); - if (waitingForStartResponse_) { - waitingForStartResponse_ = false; - sid_ = parser.getBody()->attributes.getAttribute("sid"); - std::string requestsString = parser.getBody()->attributes.getAttribute("requests"); - size_t requests = 2; - if (!requestsString.empty()) { - try { - requests = boost::lexical_cast<size_t>(requestsString); - } - catch (const boost::bad_lexical_cast&) { - } - } - onSessionStarted(sid_, requests); - } - SafeByteArray payload = createSafeByteArray(parser.getBody()->content); - /* Say we're good to go again, so don't add anything after here in the method */ - pending_ = false; - onXMPPDataRead(payload); - } +void BOSHConnection::handleDataRead(std::shared_ptr<SafeByteArray> data) { + onBOSHDataRead(*data); + buffer_ = concat(buffer_, *data); + std::string response = safeByteArrayToString(buffer_); + if (response.find("\r\n\r\n") == std::string::npos) { + onBOSHDataRead(createSafeByteArray("[[Previous read incomplete, pending]]")); + return; + } + + std::string httpCode = response.substr(response.find(" ") + 1, 3); + if (httpCode != "200") { + onHTTPError(httpCode); + return; + } + + BOSHBodyExtractor parser(parserFactory_, createByteArray(response.substr(response.find("\r\n\r\n") + 4))); + if (parser.getBody()) { + if (parser.getBody()->attributes.getAttribute("type") == "terminate") { + BOSHError::Type errorType = parseTerminationCondition(parser.getBody()->attributes.getAttribute("condition")); + onSessionTerminated(errorType == BOSHError::NoError ? std::shared_ptr<BOSHError>() : std::make_shared<BOSHError>(errorType)); + return; + } + buffer_.clear(); + if (waitingForStartResponse_) { + waitingForStartResponse_ = false; + sid_ = parser.getBody()->attributes.getAttribute("sid"); + std::string requestsString = parser.getBody()->attributes.getAttribute("requests"); + size_t requests = 2; + if (!requestsString.empty()) { + try { + requests = boost::lexical_cast<size_t>(requestsString); + } + catch (const boost::bad_lexical_cast&) { + } + } + onSessionStarted(sid_, requests); + } + SafeByteArray payload = createSafeByteArray(parser.getBody()->content); + /* Say we're good to go again, so don't add anything after here in the method */ + pending_ = false; + onXMPPDataRead(payload); + } } BOSHError::Type BOSHConnection::parseTerminationCondition(const std::string& text) { - BOSHError::Type condition = BOSHError::UndefinedCondition; - if (text == "bad-request") { - condition = BOSHError::BadRequest; - } - else if (text == "host-gone") { - condition = BOSHError::HostGone; - } - else if (text == "host-unknown") { - condition = BOSHError::HostUnknown; - } - else if (text == "improper-addressing") { - condition = BOSHError::ImproperAddressing; - } - else if (text == "internal-server-error") { - condition = BOSHError::InternalServerError; - } - else if (text == "item-not-found") { - condition = BOSHError::ItemNotFound; - } - else if (text == "other-request") { - condition = BOSHError::OtherRequest; - } - else if (text == "policy-violation") { - condition = BOSHError::PolicyViolation; - } - else if (text == "remote-connection-failed") { - condition = BOSHError::RemoteConnectionFailed; - } - else if (text == "remote-stream-error") { - condition = BOSHError::RemoteStreamError; - } - else if (text == "see-other-uri") { - condition = BOSHError::SeeOtherURI; - } - else if (text == "system-shutdown") { - condition = BOSHError::SystemShutdown; - } - else if (text == "") { - condition = BOSHError::NoError; - } - return condition; + BOSHError::Type condition = BOSHError::UndefinedCondition; + if (text == "bad-request") { + condition = BOSHError::BadRequest; + } + else if (text == "host-gone") { + condition = BOSHError::HostGone; + } + else if (text == "host-unknown") { + condition = BOSHError::HostUnknown; + } + else if (text == "improper-addressing") { + condition = BOSHError::ImproperAddressing; + } + else if (text == "internal-server-error") { + condition = BOSHError::InternalServerError; + } + else if (text == "item-not-found") { + condition = BOSHError::ItemNotFound; + } + else if (text == "other-request") { + condition = BOSHError::OtherRequest; + } + else if (text == "policy-violation") { + condition = BOSHError::PolicyViolation; + } + else if (text == "remote-connection-failed") { + condition = BOSHError::RemoteConnectionFailed; + } + else if (text == "remote-stream-error") { + condition = BOSHError::RemoteStreamError; + } + else if (text == "see-other-uri") { + condition = BOSHError::SeeOtherURI; + } + else if (text == "system-shutdown") { + condition = BOSHError::SystemShutdown; + } + else if (text == "") { + condition = BOSHError::NoError; + } + return condition; } const std::string& BOSHConnection::getSID() { - return sid_; + return sid_; } void BOSHConnection::setRID(unsigned long long rid) { - rid_ = rid; + rid_ = rid; } void BOSHConnection::setSID(const std::string& sid) { - sid_ = sid; + sid_ = sid; } void BOSHConnection::handleDisconnected(const boost::optional<Connection::Error>& error) { - cancelConnector(); - onDisconnected(error); - sid_ = ""; - connectionReady_ = false; + cancelConnector(); + onDisconnected(error ? true : false); + sid_ = ""; + connectionReady_ = false; } bool BOSHConnection::isReadyToSend() { - /* Without pipelining you need to not send more without first receiving the response */ - /* With pipelining you can. Assuming we can't, here */ - return connectionReady_ && !pending_ && !waitingForStartResponse_ && !sid_.empty(); + /* Without pipelining you need to not send more without first receiving the response */ + /* With pipelining you can. Assuming we can't, here */ + return connectionReady_ && !pending_ && !waitingForStartResponse_ && !sid_.empty(); } } diff --git a/Swiften/Network/BOSHConnection.h b/Swiften/Network/BOSHConnection.h index 01341cc..f0a946a 100644 --- a/Swiften/Network/BOSHConnection.h +++ b/Swiften/Network/BOSHConnection.h @@ -5,104 +5,115 @@ */ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/enable_shared_from_this.hpp> +#include <memory> #include <Swiften/Base/API.h> +#include <Swiften/Base/Error.h> +#include <Swiften/Base/String.h> +#include <Swiften/Base/URL.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/Connector.h> #include <Swiften/Network/HostAddressPort.h> -#include <Swiften/Base/String.h> -#include <Swiften/Base/URL.h> -#include <Swiften/Base/Error.h> #include <Swiften/Session/SessionStream.h> - -namespace boost { - class thread; - namespace system { - class error_code; - } -} +#include <Swiften/TLS/TLSError.h> class BOSHConnectionTest; namespace Swift { - class XMLParserFactory; - class TLSContextFactory; - - class SWIFTEN_API BOSHError : public SessionStream::SessionStreamError { - public: - enum Type {BadRequest, HostGone, HostUnknown, ImproperAddressing, - InternalServerError, ItemNotFound, OtherRequest, PolicyViolation, - RemoteConnectionFailed, RemoteStreamError, SeeOtherURI, SystemShutdown, UndefinedCondition, - NoError}; - BOSHError(Type type) : SessionStream::SessionStreamError(SessionStream::SessionStreamError::ConnectionReadError), type(type) {} - Type getType() {return type;} - typedef boost::shared_ptr<BOSHError> ref; - private: - Type type; - - }; - - - class SWIFTEN_API BOSHConnection : public boost::enable_shared_from_this<BOSHConnection> { - public: - typedef boost::shared_ptr<BOSHConnection> ref; - static ref create(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory) { - return ref(new BOSHConnection(boshURL, connector, parserFactory)); - } - virtual ~BOSHConnection(); - virtual void connect(); - virtual void disconnect(); - virtual void write(const SafeByteArray& data); - - const std::string& getSID(); - void setRID(unsigned long long rid); - void setSID(const std::string& sid); - void startStream(const std::string& to, unsigned long long rid); - void terminateStream(); - bool isReadyToSend(); - void restartStream(); - - - boost::signal<void (bool /* error */)> onConnectFinished; - boost::signal<void (bool /* error */)> onDisconnected; - boost::signal<void (BOSHError::ref)> onSessionTerminated; - boost::signal<void (const std::string& /*sid*/, size_t /*requests*/)> onSessionStarted; - boost::signal<void (const SafeByteArray&)> onXMPPDataRead; - boost::signal<void (const SafeByteArray&)> onBOSHDataRead; - boost::signal<void (const SafeByteArray&)> onBOSHDataWritten; - boost::signal<void (const std::string&)> onHTTPError; - - private: - friend class ::BOSHConnectionTest; - - BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory); - - static std::pair<SafeByteArray, size_t> createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, unsigned long long rid, const std::string& sid, const URL& boshURL); - void handleConnectFinished(Connection::ref); - void handleDataRead(boost::shared_ptr<SafeByteArray> data); - void handleDisconnected(const boost::optional<Connection::Error>& error); - void write(const SafeByteArray& data, bool streamRestart, bool terminate); /* FIXME: refactor */ - BOSHError::Type parseTerminationCondition(const std::string& text); - void cancelConnector(); - - URL boshURL_; - Connector::ref connector_; - XMLParserFactory* parserFactory_; - boost::shared_ptr<Connection> connection_; - std::string sid_; - bool waitingForStartResponse_; - unsigned long long rid_; - SafeByteArray buffer_; - bool pending_; - bool connectionReady_; - }; + class XMLParserFactory; + class TLSContextFactory; + class TLSLayer; + class TLSOptions; + class HighLayer; + + class SWIFTEN_API BOSHError : public SessionStream::SessionStreamError { + public: + enum Type { + BadRequest, HostGone, HostUnknown, ImproperAddressing, + InternalServerError, ItemNotFound, OtherRequest, PolicyViolation, + RemoteConnectionFailed, RemoteStreamError, SeeOtherURI, SystemShutdown, UndefinedCondition, + NoError}; + + BOSHError(Type type) : SessionStream::SessionStreamError(SessionStream::SessionStreamError::ConnectionReadError), type(type) {} + Type getType() const {return type;} + typedef std::shared_ptr<BOSHError> ref; + + private: + Type type; + }; + + class SWIFTEN_API BOSHConnection : public std::enable_shared_from_this<BOSHConnection> { + public: + typedef std::shared_ptr<BOSHConnection> ref; + static ref create(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory, TLSContextFactory* tlsContextFactory, const TLSOptions& tlsOptions) { + return ref(new BOSHConnection(boshURL, connector, parserFactory, tlsContextFactory, tlsOptions)); + } + virtual ~BOSHConnection(); + virtual void connect(); + virtual void disconnect(); + virtual void write(const SafeByteArray& data); + + const std::string& getSID(); + void setRID(unsigned long long rid); + void setSID(const std::string& sid); + void startStream(const std::string& to, unsigned long long rid); + void terminateStream(); + bool isReadyToSend(); + void restartStream(); + + bool setClientCertificate(CertificateWithKey::ref cert); + Certificate::ref getPeerCertificate() const; + std::vector<Certificate::ref> getPeerCertificateChain() const; + CertificateVerificationError::ref getPeerCertificateVerificationError() const; + + boost::signals2::signal<void (bool /* error */)> onConnectFinished; + boost::signals2::signal<void (bool /* error */)> onDisconnected; + boost::signals2::signal<void (BOSHError::ref)> onSessionTerminated; + boost::signals2::signal<void (const std::string& /*sid*/, size_t /*requests*/)> onSessionStarted; + boost::signals2::signal<void (const SafeByteArray&)> onXMPPDataRead; + boost::signals2::signal<void (const SafeByteArray&)> onBOSHDataRead; + boost::signals2::signal<void (const SafeByteArray&)> onBOSHDataWritten; + boost::signals2::signal<void (const std::string&)> onHTTPError; + + private: + friend class ::BOSHConnectionTest; + + BOSHConnection(const URL& boshURL, Connector::ref connector, XMLParserFactory* parserFactory, TLSContextFactory* tlsContextFactory, const TLSOptions& tlsOptions); + + static std::pair<SafeByteArray, size_t> createHTTPRequest(const SafeByteArray& data, bool streamRestart, bool terminate, unsigned long long rid, const std::string& sid, const URL& boshURL); + void handleConnectFinished(Connection::ref); + void handleDataRead(std::shared_ptr<SafeByteArray> data); + void handleDisconnected(const boost::optional<Connection::Error>& error); + void write(const SafeByteArray& data, bool streamRestart, bool terminate); /* FIXME: refactor */ + BOSHError::Type parseTerminationCondition(const std::string& text); + void cancelConnector(); + + void handleTLSConnected(); + void handleTLSApplicationDataRead(const SafeByteArray& data); + void handleTLSNetowrkDataWriteRequest(const SafeByteArray& data); + void handleRawDataRead(std::shared_ptr<SafeByteArray> data); + void handleTLSError(std::shared_ptr<TLSError> error); + void writeData(const SafeByteArray& data); + + URL boshURL_; + Connector::ref connector_; + XMLParserFactory* parserFactory_; + std::shared_ptr<Connection> connection_; + std::shared_ptr<HighLayer> dummyLayer_; + std::shared_ptr<TLSLayer> tlsLayer_; + std::string sid_; + bool waitingForStartResponse_; + unsigned long long rid_; + SafeByteArray buffer_; + bool pending_; + bool connectionReady_; + }; } diff --git a/Swiften/Network/BOSHConnectionPool.cpp b/Swiften/Network/BOSHConnectionPool.cpp index 4517ffb..3a79a16 100644 --- a/Swiften/Network/BOSHConnectionPool.cpp +++ b/Swiften/Network/BOSHConnectionPool.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/BOSHConnectionPool.h> @@ -10,258 +10,292 @@ #include <boost/bind.hpp> #include <boost/lexical_cast.hpp> -#include <Swiften/Base/foreach.h> +#include <Swiften/Base/Log.h> #include <Swiften/Base/SafeString.h> -#include <Swiften/Network/TLSConnectionFactory.h> -#include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h> #include <Swiften/Network/CachingDomainNameResolver.h> +#include <Swiften/Network/HTTPConnectProxiedConnectionFactory.h> namespace Swift { -BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, DomainNameResolver* realResolver, ConnectionFactory* connectionFactoryParameter, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& to, unsigned long long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword) : - boshURL(boshURL), - connectionFactory(connectionFactoryParameter), - xmlParserFactory(parserFactory), - timerFactory(timerFactory), - rid(initialRID), - pendingTerminate(false), - to(to), - requestLimit(2), - restartCount(0), - pendingRestart(false) { - - if (!boshHTTPConnectProxyURL.isEmpty()) { - if (boshHTTPConnectProxyURL.getScheme() == "https") { - connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory); - myConnectionFactories.push_back(connectionFactory); - } - connectionFactory = new HTTPConnectProxiedConnectionFactory(realResolver, connectionFactory, timerFactory, boshHTTPConnectProxyURL.getHost(), URL::getPortOrDefaultPort(boshHTTPConnectProxyURL), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword); - } - if (boshURL.getScheme() == "https") { - connectionFactory = new TLSConnectionFactory(tlsFactory, connectionFactory); - myConnectionFactories.push_back(connectionFactory); - } - resolver = new CachingDomainNameResolver(realResolver, eventLoop); - createConnection(); +BOSHConnectionPool::BOSHConnectionPool(const URL& boshURL, DomainNameResolver* realResolver, ConnectionFactory* connectionFactoryParameter, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& to, unsigned long long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword, const TLSOptions& tlsOptions, std::shared_ptr<HTTPTrafficFilter> trafficFilter) : + boshURL(boshURL), + connectionFactory(connectionFactoryParameter), + xmlParserFactory(parserFactory), + timerFactory(timerFactory), + rid(initialRID), + pendingTerminate(false), + to(to), + requestLimit(2), + restartCount(0), + pendingRestart(false), + tlsContextFactory_(tlsFactory), + tlsOptions_(tlsOptions) { + + if (!boshHTTPConnectProxyURL.isEmpty()) { + connectionFactory = new HTTPConnectProxiedConnectionFactory(realResolver, connectionFactory, timerFactory, boshHTTPConnectProxyURL.getHost(), URL::getPortOrDefaultPort(boshHTTPConnectProxyURL), boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword, trafficFilter); + } + resolver = new CachingDomainNameResolver(realResolver, eventLoop); } BOSHConnectionPool::~BOSHConnectionPool() { - /* Don't do a normal close here. Instead kill things forcibly, as close() or writeFooter() will already have been called */ - std::vector<BOSHConnection::ref> connectionCopies = connections; - foreach (BOSHConnection::ref connection, connectionCopies) { - if (connection) { - destroyConnection(connection); - connection->disconnect(); - } - } - foreach (ConnectionFactory* factory, myConnectionFactories) { - delete factory; - } - delete resolver; + /* Don't do a normal close here. Instead kill things forcibly, as close() or writeFooter() will already have been called */ + std::vector<BOSHConnection::ref> connectionCopies = connections; + for (auto&& connection : connectionCopies) { + if (connection) { + destroyConnection(connection); + connection->disconnect(); + } + } + for (auto factory : myConnectionFactories) { + delete factory; + } + delete resolver; } void BOSHConnectionPool::write(const SafeByteArray& data) { - dataQueue.push_back(data); - tryToSendQueuedData(); + dataQueue.push_back(data); + tryToSendQueuedData(); } void BOSHConnectionPool::handleDataRead(const SafeByteArray& data) { - onXMPPDataRead(data); - tryToSendQueuedData(); /* Will rebalance the connections */ + onXMPPDataRead(data); + tryToSendQueuedData(); /* Will rebalance the connections */ } void BOSHConnectionPool::restartStream() { - BOSHConnection::ref connection = getSuitableConnection(); - if (connection) { - pendingRestart = false; - rid++; - connection->setRID(rid); - connection->restartStream(); - restartCount++; - } - else { - pendingRestart = true; - } + BOSHConnection::ref connection = getSuitableConnection(); + if (connection) { + pendingRestart = false; + rid++; + connection->setRID(rid); + connection->restartStream(); + restartCount++; + } + else { + pendingRestart = true; + } +} + +void BOSHConnectionPool::setTLSCertificate(CertificateWithKey::ref certWithKey) { + clientCertificate = certWithKey; +} + +bool BOSHConnectionPool::isTLSEncrypted() const { + return !pinnedCertificateChain_.empty(); +} + +Certificate::ref BOSHConnectionPool::getPeerCertificate() const { + Certificate::ref peerCertificate; + if (!pinnedCertificateChain_.empty()) { + peerCertificate = pinnedCertificateChain_[0]; + } + return peerCertificate; +} + +std::vector<Certificate::ref> BOSHConnectionPool::getPeerCertificateChain() const { + return pinnedCertificateChain_; +} + +std::shared_ptr<CertificateVerificationError> BOSHConnectionPool::getPeerCertificateVerificationError() const { + return lastVerificationError_; } void BOSHConnectionPool::writeFooter() { - pendingTerminate = true; - tryToSendQueuedData(); + pendingTerminate = true; + tryToSendQueuedData(); +} + +void BOSHConnectionPool::open() { + createConnection(); } void BOSHConnectionPool::close() { - if (!sid.empty()) { - writeFooter(); - } - else { - pendingTerminate = true; - std::vector<BOSHConnection::ref> connectionCopies = connections; - foreach (BOSHConnection::ref connection, connectionCopies) { - if (connection) { - connection->disconnect(); - } - } - } + if (!sid.empty()) { + writeFooter(); + } + else { + pendingTerminate = true; + std::vector<BOSHConnection::ref> connectionCopies = connections; + for (auto&& connection : connectionCopies) { + if (connection) { + connection->disconnect(); + } + } + } } void BOSHConnectionPool::handleSessionStarted(const std::string& sessionID, size_t requests) { - sid = sessionID; - requestLimit = requests; - onSessionStarted(); + sid = sessionID; + requestLimit = requests; + onSessionStarted(); } void BOSHConnectionPool::handleConnectFinished(bool error, BOSHConnection::ref connection) { - if (error) { - onSessionTerminated(boost::make_shared<BOSHError>(BOSHError::UndefinedCondition)); - /*TODO: We can probably manage to not terminate the stream here and use the rid/ack retry - * logic to just swallow the error and try again (some number of tries). - */ - } - else { - if (sid.empty()) { - connection->startStream(to, rid); - } - if (pendingRestart) { - restartStream(); - } - tryToSendQueuedData(); - } + if (error) { + onSessionTerminated(std::make_shared<BOSHError>(BOSHError::UndefinedCondition)); + /*TODO: We can probably manage to not terminate the stream here and use the rid/ack retry + * logic to just swallow the error and try again (some number of tries). + */ + } + else { + if (connection->getPeerCertificate() && pinnedCertificateChain_.empty()) { + pinnedCertificateChain_ = connection->getPeerCertificateChain(); + } + if (!pinnedCertificateChain_.empty()) { + lastVerificationError_ = connection->getPeerCertificateVerificationError(); + onTLSConnectionEstablished(); + } + + if (sid.empty()) { + connection->startStream(to, rid); + } + if (pendingRestart) { + restartStream(); + } + tryToSendQueuedData(); + } } BOSHConnection::ref BOSHConnectionPool::getSuitableConnection() { - BOSHConnection::ref suitableConnection; - foreach (BOSHConnection::ref connection, connections) { - if (connection->isReadyToSend()) { - suitableConnection = connection; - break; - } - } - - if (!suitableConnection && connections.size() < requestLimit) { - /* This is not a suitable connection because it won't have yet connected and added TLS if needed. */ - BOSHConnection::ref newConnection = createConnection(); - newConnection->setSID(sid); - } - assert(connections.size() <= requestLimit); - assert((!suitableConnection) || suitableConnection->isReadyToSend()); - return suitableConnection; + BOSHConnection::ref suitableConnection; + for (auto&& connection : connections) { + if (connection->isReadyToSend()) { + suitableConnection = connection; + break; + } + } + + if (!suitableConnection && connections.size() < requestLimit) { + /* This is not a suitable connection because it won't have yet connected and added TLS if needed. */ + BOSHConnection::ref newConnection = createConnection(); + newConnection->setSID(sid); + } + assert(connections.size() <= requestLimit); + assert((!suitableConnection) || suitableConnection->isReadyToSend()); + return suitableConnection; } void BOSHConnectionPool::tryToSendQueuedData() { - if (sid.empty()) { - /* If we've not got as far as stream start yet, pend */ - return; - } - - BOSHConnection::ref suitableConnection = getSuitableConnection(); - bool toSend = !dataQueue.empty(); - if (suitableConnection) { - if (toSend) { - rid++; - suitableConnection->setRID(rid); - SafeByteArray data; - foreach (const SafeByteArray& datum, dataQueue) { - data.insert(data.end(), datum.begin(), datum.end()); - } - suitableConnection->write(data); - dataQueue.clear(); - } - else if (pendingTerminate) { - rid++; - suitableConnection->setRID(rid); - suitableConnection->terminateStream(); - sid = ""; - close(); - } - } - if (!pendingTerminate) { - /* Ensure there's always a session waiting to read data for us */ - bool pending = false; - foreach (BOSHConnection::ref connection, connections) { - if (connection && !connection->isReadyToSend()) { - pending = true; - } - } - if (!pending) { - if (restartCount >= 1) { - /* Don't open a second connection until we've restarted the stream twice - i.e. we've authed and resource bound.*/ - if (suitableConnection) { - rid++; - suitableConnection->setRID(rid); - suitableConnection->write(createSafeByteArray("")); - } - else { - /* My thought process I went through when writing this, to aid anyone else confused why this can happen... - * - * What to do here? I think this isn't possible. - If you didn't have two connections, suitable would have made one. - If you have two connections and neither is suitable, pending would be true. - If you have a non-pending connection, it's suitable. - - If I decide to do something here, remove assert above. - - Ah! Yes, because there's a period between creating the connection and it being connected. */ - } - } - } - } + if (sid.empty()) { + /* If we've not got as far as stream start yet, pend */ + return; + } + + BOSHConnection::ref suitableConnection = getSuitableConnection(); + bool toSend = !dataQueue.empty(); + if (suitableConnection) { + if (toSend) { + rid++; + suitableConnection->setRID(rid); + SafeByteArray data; + for (const auto& datum : dataQueue) { + data.insert(data.end(), datum.begin(), datum.end()); + } + suitableConnection->write(data); + dataQueue.clear(); + } + else if (pendingTerminate) { + rid++; + suitableConnection->setRID(rid); + suitableConnection->terminateStream(); + sid = ""; + close(); + } + } + if (!pendingTerminate) { + /* Ensure there's always a session waiting to read data for us */ + bool pending = false; + for (auto&& connection : connections) { + if (connection && !connection->isReadyToSend()) { + pending = true; + } + } + if (!pending) { + if (restartCount >= 1) { + /* Don't open a second connection until we've restarted the stream twice - i.e. we've authed and resource bound.*/ + if (suitableConnection) { + rid++; + suitableConnection->setRID(rid); + suitableConnection->write(createSafeByteArray("")); + } + else { + /* My thought process I went through when writing this, to aid anyone else confused why this can happen... + * + * What to do here? I think this isn't possible. + If you didn't have two connections, suitable would have made one. + If you have two connections and neither is suitable, pending would be true. + If you have a non-pending connection, it's suitable. + + If I decide to do something here, remove assert above. + + Ah! Yes, because there's a period between creating the connection and it being connected. */ + } + } + } + } } void BOSHConnectionPool::handleHTTPError(const std::string& /*errorCode*/) { - handleSessionTerminated(boost::make_shared<BOSHError>(BOSHError::UndefinedCondition)); + handleSessionTerminated(std::make_shared<BOSHError>(BOSHError::UndefinedCondition)); } void BOSHConnectionPool::handleConnectionDisconnected(bool/* error*/, BOSHConnection::ref connection) { - destroyConnection(connection); - if (pendingTerminate && sid.empty() && connections.empty()) { - handleSessionTerminated(BOSHError::ref()); - } - //else if (error) { - // handleSessionTerminated(boost::make_shared<BOSHError>(BOSHError::UndefinedCondition)); - //} - else { - /* We might have just freed up a connection slot to send with */ - tryToSendQueuedData(); - } + destroyConnection(connection); + if (pendingTerminate && sid.empty() && connections.empty()) { + handleSessionTerminated(BOSHError::ref()); + } + //else if (error) { + // handleSessionTerminated(std::make_shared<BOSHError>(BOSHError::UndefinedCondition)); + //} + else { + /* We might have just freed up a connection slot to send with */ + tryToSendQueuedData(); + } } -boost::shared_ptr<BOSHConnection> BOSHConnectionPool::createConnection() { - Connector::ref connector = Connector::create(boshURL.getHost(), URL::getPortOrDefaultPort(boshURL), false, resolver, connectionFactory, timerFactory); - BOSHConnection::ref connection = BOSHConnection::create(boshURL, connector, xmlParserFactory); - connection->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPool::handleDataRead, this, _1)); - connection->onSessionStarted.connect(boost::bind(&BOSHConnectionPool::handleSessionStarted, this, _1, _2)); - connection->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPool::handleBOSHDataRead, this, _1)); - connection->onBOSHDataWritten.connect(boost::bind(&BOSHConnectionPool::handleBOSHDataWritten, this, _1)); - connection->onDisconnected.connect(boost::bind(&BOSHConnectionPool::handleConnectionDisconnected, this, _1, connection)); - connection->onConnectFinished.connect(boost::bind(&BOSHConnectionPool::handleConnectFinished, this, _1, connection)); - connection->onSessionTerminated.connect(boost::bind(&BOSHConnectionPool::handleSessionTerminated, this, _1)); - connection->onHTTPError.connect(boost::bind(&BOSHConnectionPool::handleHTTPError, this, _1)); - connection->connect(); - connections.push_back(connection); - return connection; +std::shared_ptr<BOSHConnection> BOSHConnectionPool::createConnection() { + Connector::ref connector = Connector::create(boshURL.getHost(), URL::getPortOrDefaultPort(boshURL), boost::optional<std::string>(), resolver, connectionFactory, timerFactory); + BOSHConnection::ref connection = BOSHConnection::create(boshURL, connector, xmlParserFactory, tlsContextFactory_, tlsOptions_); + connection->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPool::handleDataRead, this, _1)); + connection->onSessionStarted.connect(boost::bind(&BOSHConnectionPool::handleSessionStarted, this, _1, _2)); + connection->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPool::handleBOSHDataRead, this, _1)); + connection->onBOSHDataWritten.connect(boost::bind(&BOSHConnectionPool::handleBOSHDataWritten, this, _1)); + connection->onDisconnected.connect(boost::bind(&BOSHConnectionPool::handleConnectionDisconnected, this, _1, connection)); + connection->onConnectFinished.connect(boost::bind(&BOSHConnectionPool::handleConnectFinished, this, _1, connection)); + connection->onSessionTerminated.connect(boost::bind(&BOSHConnectionPool::handleSessionTerminated, this, _1)); + connection->onHTTPError.connect(boost::bind(&BOSHConnectionPool::handleHTTPError, this, _1)); + + if (boshURL.getScheme() == "https") { + bool success = connection->setClientCertificate(clientCertificate); + SWIFT_LOG(debug) << "setClientCertificate, success: " << success; + } + + connection->connect(); + connections.push_back(connection); + return connection; } -void BOSHConnectionPool::destroyConnection(boost::shared_ptr<BOSHConnection> connection) { - connections.erase(std::remove(connections.begin(), connections.end(), connection), connections.end()); - connection->onXMPPDataRead.disconnect(boost::bind(&BOSHConnectionPool::handleDataRead, this, _1)); - connection->onSessionStarted.disconnect(boost::bind(&BOSHConnectionPool::handleSessionStarted, this, _1, _2)); - connection->onBOSHDataRead.disconnect(boost::bind(&BOSHConnectionPool::handleBOSHDataRead, this, _1)); - connection->onBOSHDataWritten.disconnect(boost::bind(&BOSHConnectionPool::handleBOSHDataWritten, this, _1)); - connection->onDisconnected.disconnect(boost::bind(&BOSHConnectionPool::handleConnectionDisconnected, this, _1, connection)); - connection->onConnectFinished.disconnect(boost::bind(&BOSHConnectionPool::handleConnectFinished, this, _1, connection)); - connection->onSessionTerminated.disconnect(boost::bind(&BOSHConnectionPool::handleSessionTerminated, this, _1)); - connection->onHTTPError.disconnect(boost::bind(&BOSHConnectionPool::handleHTTPError, this, _1)); +void BOSHConnectionPool::destroyConnection(std::shared_ptr<BOSHConnection> connection) { + connections.erase(std::remove(connections.begin(), connections.end(), connection), connections.end()); + connection->onXMPPDataRead.disconnect(boost::bind(&BOSHConnectionPool::handleDataRead, this, _1)); + connection->onSessionStarted.disconnect(boost::bind(&BOSHConnectionPool::handleSessionStarted, this, _1, _2)); + connection->onBOSHDataRead.disconnect(boost::bind(&BOSHConnectionPool::handleBOSHDataRead, this, _1)); + connection->onBOSHDataWritten.disconnect(boost::bind(&BOSHConnectionPool::handleBOSHDataWritten, this, _1)); + connection->onDisconnected.disconnect(boost::bind(&BOSHConnectionPool::handleConnectionDisconnected, this, _1, connection)); + connection->onConnectFinished.disconnect(boost::bind(&BOSHConnectionPool::handleConnectFinished, this, _1, connection)); + connection->onSessionTerminated.disconnect(boost::bind(&BOSHConnectionPool::handleSessionTerminated, this, _1)); + connection->onHTTPError.disconnect(boost::bind(&BOSHConnectionPool::handleHTTPError, this, _1)); } void BOSHConnectionPool::handleSessionTerminated(BOSHError::ref error) { - onSessionTerminated(error); + onSessionTerminated(error); } void BOSHConnectionPool::handleBOSHDataRead(const SafeByteArray& data) { - onBOSHDataRead(data); + onBOSHDataRead(data); } void BOSHConnectionPool::handleBOSHDataWritten(const SafeByteArray& data) { - onBOSHDataWritten(data); + onBOSHDataWritten(data); } } diff --git a/Swiften/Network/BOSHConnectionPool.h b/Swiften/Network/BOSHConnectionPool.h index de707e8..a6956fa 100644 --- a/Swiften/Network/BOSHConnectionPool.h +++ b/Swiften/Network/BOSHConnectionPool.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ @@ -12,59 +12,77 @@ #include <Swiften/Base/API.h> #include <Swiften/Base/SafeString.h> #include <Swiften/Network/BOSHConnection.h> +#include <Swiften/TLS/CertificateWithKey.h> +#include <Swiften/TLS/TLSOptions.h> namespace Swift { - class HTTPConnectProxiedConnectionFactory; - class TLSConnectionFactory; - class CachingDomainNameResolver; - class EventLoop; + class CachingDomainNameResolver; + class EventLoop; + class HTTPTrafficFilter; + class TLSContextFactory; + class CachingDomainNameResolver; + class EventLoop; - class SWIFTEN_API BOSHConnectionPool : public boost::bsignals::trackable { - public: - BOSHConnectionPool(const URL& boshURL, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& to, unsigned long long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword); - ~BOSHConnectionPool(); - void write(const SafeByteArray& data); - void writeFooter(); - void close(); - void restartStream(); + class SWIFTEN_API BOSHConnectionPool : public boost::signals2::trackable { + public: + BOSHConnectionPool(const URL& boshURL, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, XMLParserFactory* parserFactory, TLSContextFactory* tlsFactory, TimerFactory* timerFactory, EventLoop* eventLoop, const std::string& to, unsigned long long initialRID, const URL& boshHTTPConnectProxyURL, const SafeString& boshHTTPConnectProxyAuthID, const SafeString& boshHTTPConnectProxyAuthPassword, const TLSOptions& tlsOptions, std::shared_ptr<HTTPTrafficFilter> trafficFilter = std::shared_ptr<HTTPTrafficFilter>()); + ~BOSHConnectionPool(); - boost::signal<void (BOSHError::ref)> onSessionTerminated; - boost::signal<void ()> onSessionStarted; - boost::signal<void (const SafeByteArray&)> onXMPPDataRead; - boost::signal<void (const SafeByteArray&)> onBOSHDataRead; - boost::signal<void (const SafeByteArray&)> onBOSHDataWritten; + void open(); + void write(const SafeByteArray& data); + void writeFooter(); + void close(); + void restartStream(); - private: - void handleDataRead(const SafeByteArray& data); - void handleSessionStarted(const std::string& sid, size_t requests); - void handleBOSHDataRead(const SafeByteArray& data); - void handleBOSHDataWritten(const SafeByteArray& data); - void handleSessionTerminated(BOSHError::ref condition); - void handleConnectFinished(bool, BOSHConnection::ref connection); - void handleConnectionDisconnected(bool error, BOSHConnection::ref connection); - void handleHTTPError(const std::string& errorCode); + void setTLSCertificate(CertificateWithKey::ref certWithKey); + bool isTLSEncrypted() const; + Certificate::ref getPeerCertificate() const; + std::vector<Certificate::ref> getPeerCertificateChain() const; + std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; - private: - BOSHConnection::ref createConnection(); - void destroyConnection(BOSHConnection::ref connection); - void tryToSendQueuedData(); - BOSHConnection::ref getSuitableConnection(); + boost::signals2::signal<void ()> onTLSConnectionEstablished; + boost::signals2::signal<void (BOSHError::ref)> onSessionTerminated; + boost::signals2::signal<void ()> onSessionStarted; + boost::signals2::signal<void (const SafeByteArray&)> onXMPPDataRead; + boost::signals2::signal<void (const SafeByteArray&)> onBOSHDataRead; + boost::signals2::signal<void (const SafeByteArray&)> onBOSHDataWritten; - private: - URL boshURL; - ConnectionFactory* connectionFactory; - XMLParserFactory* xmlParserFactory; - TimerFactory* timerFactory; - std::vector<BOSHConnection::ref> connections; - std::string sid; - unsigned long long rid; - std::vector<SafeByteArray> dataQueue; - bool pendingTerminate; - std::string to; - size_t requestLimit; - int restartCount; - bool pendingRestart; - std::vector<ConnectionFactory*> myConnectionFactories; - CachingDomainNameResolver* resolver; - }; + private: + void handleDataRead(const SafeByteArray& data); + void handleSessionStarted(const std::string& sid, size_t requests); + void handleBOSHDataRead(const SafeByteArray& data); + void handleBOSHDataWritten(const SafeByteArray& data); + void handleSessionTerminated(BOSHError::ref condition); + void handleConnectFinished(bool, BOSHConnection::ref connection); + void handleConnectionDisconnected(bool error, BOSHConnection::ref connection); + void handleHTTPError(const std::string& errorCode); + + private: + BOSHConnection::ref createConnection(); + void destroyConnection(BOSHConnection::ref connection); + void tryToSendQueuedData(); + BOSHConnection::ref getSuitableConnection(); + + private: + URL boshURL; + ConnectionFactory* connectionFactory; + XMLParserFactory* xmlParserFactory; + TimerFactory* timerFactory; + std::vector<BOSHConnection::ref> connections; + std::string sid; + unsigned long long rid; + std::vector<SafeByteArray> dataQueue; + bool pendingTerminate; + std::string to; + size_t requestLimit; + int restartCount; + bool pendingRestart; + std::vector<ConnectionFactory*> myConnectionFactories; + CachingDomainNameResolver* resolver; + CertificateWithKey::ref clientCertificate; + TLSContextFactory* tlsContextFactory_; + TLSOptions tlsOptions_; + std::vector<std::shared_ptr<Certificate> > pinnedCertificateChain_; + std::shared_ptr<CertificateVerificationError> lastVerificationError_; + }; } diff --git a/Swiften/Network/BoostConnection.cpp b/Swiften/Network/BoostConnection.cpp index 5137c3c..6ae6bf6 100644 --- a/Swiften/Network/BoostConnection.cpp +++ b/Swiften/Network/BoostConnection.cpp @@ -1,28 +1,27 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/BoostConnection.h> -#include <iostream> -#include <string> #include <algorithm> -#include <boost/bind.hpp> -#include <boost/thread.hpp> +#include <memory> +#include <mutex> +#include <string> + #include <boost/asio/placeholders.hpp> #include <boost/asio/write.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/numeric/conversion/cast.hpp> +#include <boost/bind.hpp> -#include <Swiften/Base/Log.h> #include <Swiften/Base/Algorithm.h> -#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/Base/ByteArray.h> -#include <Swiften/Network/HostAddressPort.h> -#include <Swiften/Base/sleep.h> +#include <Swiften/Base/Log.h> #include <Swiften/Base/SafeAllocator.h> +#include <Swiften/Base/sleep.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/Network/HostAddressPort.h> namespace Swift { @@ -32,141 +31,147 @@ static const size_t BUFFER_SIZE = 4096; // A reference-counted non-modifiable buffer class. class SharedBuffer { - public: - SharedBuffer(const SafeByteArray& data) : - data_(new std::vector<char, SafeAllocator<char> >(data.begin(), data.end())), - buffer_(boost::asio::buffer(*data_)) { - } - - // ConstBufferSequence requirements. - typedef boost::asio::const_buffer value_type; - typedef const boost::asio::const_buffer* const_iterator; - const boost::asio::const_buffer* begin() const { return &buffer_; } - const boost::asio::const_buffer* end() const { return &buffer_ + 1; } - - private: - boost::shared_ptr< std::vector<char, SafeAllocator<char> > > data_; - boost::asio::const_buffer buffer_; + public: + SharedBuffer(const SafeByteArray& data) : + data_(new std::vector<char, SafeAllocator<char> >(data.begin(), data.end())), + buffer_(boost::asio::buffer(*data_)) { + } + + // ConstBufferSequence requirements. + typedef boost::asio::const_buffer value_type; + typedef const boost::asio::const_buffer* const_iterator; + const boost::asio::const_buffer* begin() const { return &buffer_; } + const boost::asio::const_buffer* end() const { return &buffer_ + 1; } + + private: + std::shared_ptr< std::vector<char, SafeAllocator<char> > > data_; + boost::asio::const_buffer buffer_; }; // ----------------------------------------------------------------------------- -BoostConnection::BoostConnection(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : - eventLoop(eventLoop), ioService(ioService), socket_(*ioService), writing_(false), closeSocketAfterNextWrite_(false) { +BoostConnection::BoostConnection(std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : + eventLoop(eventLoop), ioService(ioService), socket_(*ioService), writing_(false), closeSocketAfterNextWrite_(false) { } BoostConnection::~BoostConnection() { } void BoostConnection::listen() { - doRead(); + doRead(); } void BoostConnection::connect(const HostAddressPort& addressPort) { - boost::asio::ip::tcp::endpoint endpoint( - boost::asio::ip::address::from_string(addressPort.getAddress().toString()), boost::numeric_cast<unsigned short>(addressPort.getPort())); - socket_.async_connect( - endpoint, - boost::bind(&BoostConnection::handleConnectFinished, shared_from_this(), boost::asio::placeholders::error)); + boost::asio::ip::tcp::endpoint endpoint( + boost::asio::ip::address::from_string(addressPort.getAddress().toString()), addressPort.getPort()); + socket_.async_connect( + endpoint, + boost::bind(&BoostConnection::handleConnectFinished, shared_from_this(), boost::asio::placeholders::error)); } void BoostConnection::disconnect() { - //MainEventLoop::removeEventsFromOwner(shared_from_this()); - - // Mac OS X apparently exhibits a problem where closing a socket during a write could potentially go into uninterruptable sleep. - // See e.g. http://bugs.python.org/issue7401 - // We therefore wait until any pending write finishes, which hopefully should fix our hang on exit during close(). - boost::lock_guard<boost::mutex> lock(writeMutex_); - if (writing_) { - closeSocketAfterNextWrite_ = true; - } else { - closeSocket(); - } + //MainEventLoop::removeEventsFromOwner(shared_from_this()); + + // Mac OS X apparently exhibits a problem where closing a socket during a write could potentially go into uninterruptable sleep. + // See e.g. http://bugs.python.org/issue7401 + // We therefore wait until any pending write finishes, which hopefully should fix our hang on exit during close(). + std::lock_guard<std::mutex> lock(writeMutex_); + if (writing_) { + closeSocketAfterNextWrite_ = true; + } else { + closeSocket(); + } } void BoostConnection::closeSocket() { - boost::system::error_code errorCode; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, errorCode); - socket_.close(); + std::lock_guard<std::mutex> lock(readCloseMutex_); + boost::system::error_code errorCode; + socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, errorCode); + socket_.close(); } void BoostConnection::write(const SafeByteArray& data) { - boost::lock_guard<boost::mutex> lock(writeMutex_); - if (!writing_) { - writing_ = true; - doWrite(data); - } - else { - append(writeQueue_, data); - } + std::lock_guard<std::mutex> lock(writeMutex_); + if (!writing_) { + writing_ = true; + doWrite(data); + } + else { + append(writeQueue_, data); + } } void BoostConnection::doWrite(const SafeByteArray& data) { - boost::asio::async_write(socket_, SharedBuffer(data), - boost::bind(&BoostConnection::handleDataWritten, shared_from_this(), boost::asio::placeholders::error)); + boost::asio::async_write(socket_, SharedBuffer(data), + boost::bind(&BoostConnection::handleDataWritten, shared_from_this(), boost::asio::placeholders::error)); } void BoostConnection::handleConnectFinished(const boost::system::error_code& error) { - SWIFT_LOG(debug) << "Connect finished: " << error << std::endl; - if (!error) { - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), false), shared_from_this()); - doRead(); - } - else if (error != boost::asio::error::operation_aborted) { - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), true), shared_from_this()); - } + SWIFT_LOG(debug) << "Connect finished: " << error; + if (!error) { + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), false), shared_from_this()); + doRead(); + } + else if (error != boost::asio::error::operation_aborted) { + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), true), shared_from_this()); + } } void BoostConnection::doRead() { - readBuffer_ = boost::make_shared<SafeByteArray>(BUFFER_SIZE); - socket_.async_read_some( - boost::asio::buffer(*readBuffer_), - boost::bind(&BoostConnection::handleSocketRead, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + readBuffer_ = std::make_shared<SafeByteArray>(BUFFER_SIZE); + std::lock_guard<std::mutex> lock(readCloseMutex_); + socket_.async_read_some( + boost::asio::buffer(*readBuffer_), + boost::bind(&BoostConnection::handleSocketRead, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void BoostConnection::handleSocketRead(const boost::system::error_code& error, size_t bytesTransferred) { - SWIFT_LOG(debug) << "Socket read " << error << std::endl; - if (!error) { - readBuffer_->resize(bytesTransferred); - eventLoop->postEvent(boost::bind(boost::ref(onDataRead), readBuffer_), shared_from_this()); - doRead(); - } - else if (/*error == boost::asio::error::eof ||*/ error == boost::asio::error::operation_aborted) { - eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), boost::optional<Error>()), shared_from_this()); - } - else { - eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), ReadError), shared_from_this()); - } + SWIFT_LOG(debug) << "Socket read " << error; + if (!error) { + readBuffer_->resize(bytesTransferred); + eventLoop->postEvent(boost::bind(boost::ref(onDataRead), readBuffer_), shared_from_this()); + doRead(); + } + else if (/*error == boost::asio::error::eof ||*/ error == boost::asio::error::operation_aborted) { + eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), boost::optional<Error>()), shared_from_this()); + } + else { + eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), ReadError), shared_from_this()); + } } void BoostConnection::handleDataWritten(const boost::system::error_code& error) { - SWIFT_LOG(debug) << "Data written " << error << std::endl; - if (!error) { - eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); - } - else if (/*error == boost::asio::error::eof || */error == boost::asio::error::operation_aborted) { - eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), boost::optional<Error>()), shared_from_this()); - } - else { - eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), WriteError), shared_from_this()); - } - { - boost::lock_guard<boost::mutex> lock(writeMutex_); - if (writeQueue_.empty()) { - writing_ = false; - if (closeSocketAfterNextWrite_) { - closeSocket(); - } - } - else { - doWrite(writeQueue_); - writeQueue_.clear(); - } - } + SWIFT_LOG(debug) << "Data written " << error; + if (!error) { + eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); + } + else if (/*error == boost::asio::error::eof || */error == boost::asio::error::operation_aborted) { + eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), boost::optional<Error>()), shared_from_this()); + } + else { + eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), WriteError), shared_from_this()); + } + { + std::lock_guard<std::mutex> lock(writeMutex_); + if (writeQueue_.empty()) { + writing_ = false; + if (closeSocketAfterNextWrite_) { + closeSocket(); + } + } + else { + doWrite(writeQueue_); + writeQueue_.clear(); + } + } } HostAddressPort BoostConnection::getLocalAddress() const { - return HostAddressPort(socket_.local_endpoint()); + return HostAddressPort(socket_.local_endpoint()); +} + +HostAddressPort BoostConnection::getRemoteAddress() const { + return HostAddressPort(socket_.remote_endpoint()); } diff --git a/Swiften/Network/BoostConnection.h b/Swiften/Network/BoostConnection.h index 636853a..c77b933 100644 --- a/Swiften/Network/BoostConnection.h +++ b/Swiften/Network/BoostConnection.h @@ -1,70 +1,75 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> +#include <mutex> + #include <boost/asio/io_service.hpp> #include <boost/asio/ip/tcp.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/thread/mutex.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Network/Connection.h> -#include <Swiften/EventLoop/EventOwner.h> #include <Swiften/Base/SafeByteArray.h> - -namespace boost { - class thread; - namespace system { - class error_code; - } -} +#include <Swiften/EventLoop/EventOwner.h> +#include <Swiften/Network/Connection.h> +#include <Swiften/TLS/Certificate.h> +#include <Swiften/TLS/CertificateVerificationError.h> +#include <Swiften/TLS/CertificateWithKey.h> namespace Swift { - class EventLoop; - - class SWIFTEN_API BoostConnection : public Connection, public EventOwner, public boost::enable_shared_from_this<BoostConnection> { - public: - typedef boost::shared_ptr<BoostConnection> ref; - - ~BoostConnection(); - - static ref create(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) { - return ref(new BoostConnection(ioService, eventLoop)); - } - - virtual void listen(); - virtual void connect(const HostAddressPort& address); - virtual void disconnect(); - virtual void write(const SafeByteArray& data); - - boost::asio::ip::tcp::socket& getSocket() { - return socket_; - } - - HostAddressPort getLocalAddress() const; - - private: - BoostConnection(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); - - void handleConnectFinished(const boost::system::error_code& error); - void handleSocketRead(const boost::system::error_code& error, size_t bytesTransferred); - void handleDataWritten(const boost::system::error_code& error); - void doRead(); - void doWrite(const SafeByteArray& data); - void closeSocket(); - - private: - EventLoop* eventLoop; - boost::shared_ptr<boost::asio::io_service> ioService; - boost::asio::ip::tcp::socket socket_; - boost::shared_ptr<SafeByteArray> readBuffer_; - boost::mutex writeMutex_; - bool writing_; - SafeByteArray writeQueue_; - bool closeSocketAfterNextWrite_; - }; + class EventLoop; + + class SWIFTEN_API BoostConnection : public Connection, public EventOwner, public std::enable_shared_from_this<BoostConnection> { + public: + typedef std::shared_ptr<BoostConnection> ref; + + virtual ~BoostConnection(); + + static ref create(std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) { + return ref(new BoostConnection(ioService, eventLoop)); + } + + virtual void listen(); + virtual void connect(const HostAddressPort& address); + virtual void disconnect(); + virtual void write(const SafeByteArray& data); + + boost::asio::ip::tcp::socket& getSocket() { + return socket_; + } + + virtual HostAddressPort getLocalAddress() const; + virtual HostAddressPort getRemoteAddress() const; + + bool setClientCertificate(CertificateWithKey::ref cert); + + Certificate::ref getPeerCertificate() const; + std::vector<Certificate::ref> getPeerCertificateChain() const; + std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; + + private: + BoostConnection(std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); + + void handleConnectFinished(const boost::system::error_code& error); + void handleSocketRead(const boost::system::error_code& error, size_t bytesTransferred); + void handleDataWritten(const boost::system::error_code& error); + void doRead(); + void doWrite(const SafeByteArray& data); + void closeSocket(); + + private: + EventLoop* eventLoop; + std::shared_ptr<boost::asio::io_service> ioService; + boost::asio::ip::tcp::socket socket_; + std::shared_ptr<SafeByteArray> readBuffer_; + std::mutex writeMutex_; + bool writing_; + SafeByteArray writeQueue_; + bool closeSocketAfterNextWrite_; + std::mutex readCloseMutex_; + }; } diff --git a/Swiften/Network/BoostConnectionFactory.cpp b/Swiften/Network/BoostConnectionFactory.cpp index d5f9fad..9ec30f5 100644 --- a/Swiften/Network/BoostConnectionFactory.cpp +++ b/Swiften/Network/BoostConnectionFactory.cpp @@ -1,19 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/BoostConnectionFactory.h> + #include <Swiften/Network/BoostConnection.h> namespace Swift { -BoostConnectionFactory::BoostConnectionFactory(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : ioService(ioService), eventLoop(eventLoop) { +BoostConnectionFactory::BoostConnectionFactory(std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : ioService(ioService), eventLoop(eventLoop) { } -boost::shared_ptr<Connection> BoostConnectionFactory::createConnection() { - return BoostConnection::create(ioService, eventLoop); +std::shared_ptr<Connection> BoostConnectionFactory::createConnection() { + return BoostConnection::create(ioService, eventLoop); } } diff --git a/Swiften/Network/BoostConnectionFactory.h b/Swiften/Network/BoostConnectionFactory.h index c0a105b..eef0b45 100644 --- a/Swiften/Network/BoostConnectionFactory.h +++ b/Swiften/Network/BoostConnectionFactory.h @@ -1,27 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/asio/io_service.hpp> -#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Base/API.h> #include <Swiften/Network/BoostConnection.h> +#include <Swiften/Network/ConnectionFactory.h> namespace Swift { - class BoostConnection; - - class BoostConnectionFactory : public ConnectionFactory { - public: - BoostConnectionFactory(boost::shared_ptr<boost::asio::io_service>, EventLoop* eventLoop); + class SWIFTEN_API BoostConnectionFactory : public ConnectionFactory { + public: + BoostConnectionFactory(std::shared_ptr<boost::asio::io_service>, EventLoop* eventLoop); - virtual boost::shared_ptr<Connection> createConnection(); + virtual std::shared_ptr<Connection> createConnection(); - private: - boost::shared_ptr<boost::asio::io_service> ioService; - EventLoop* eventLoop; - }; + private: + std::shared_ptr<boost::asio::io_service> ioService; + EventLoop* eventLoop; + }; } diff --git a/Swiften/Network/BoostConnectionServer.cpp b/Swiften/Network/BoostConnectionServer.cpp index c90b554..dc05172 100644 --- a/Swiften/Network/BoostConnectionServer.cpp +++ b/Swiften/Network/BoostConnectionServer.cpp @@ -1,103 +1,112 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/BoostConnectionServer.h> -#include <boost/bind.hpp> -#include <boost/system/system_error.hpp> +#include <boost/asio/ip/v6_only.hpp> #include <boost/asio/placeholders.hpp> +#include <boost/bind.hpp> #include <boost/numeric/conversion/cast.hpp> #include <boost/optional.hpp> +#include <boost/system/error_code.hpp> +#include <boost/system/system_error.hpp> +#include <Swiften/Base/Log.h> #include <Swiften/EventLoop/EventLoop.h> namespace Swift { -BoostConnectionServer::BoostConnectionServer(int port, boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : port_(port), ioService_(ioService), eventLoop(eventLoop), acceptor_(NULL) { +BoostConnectionServer::BoostConnectionServer(unsigned short port, std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : port_(port), ioService_(ioService), eventLoop(eventLoop), acceptor_(nullptr) { } -BoostConnectionServer::BoostConnectionServer(const HostAddress &address, int port, boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : address_(address), port_(port), ioService_(ioService), eventLoop(eventLoop), acceptor_(NULL) { +BoostConnectionServer::BoostConnectionServer(const HostAddress &address, unsigned short port, std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : address_(address), port_(port), ioService_(ioService), eventLoop(eventLoop), acceptor_(nullptr) { } void BoostConnectionServer::start() { - boost::optional<Error> error = tryStart(); - if (error) { - eventLoop->postEvent(boost::bind(boost::ref(onStopped), *error), shared_from_this()); - } + boost::optional<Error> error = tryStart(); + if (error) { + eventLoop->postEvent(boost::bind(boost::ref(onStopped), *error), shared_from_this()); + } } boost::optional<BoostConnectionServer::Error> BoostConnectionServer::tryStart() { - try { - assert(!acceptor_); - if (address_.isValid()) { - acceptor_ = new boost::asio::ip::tcp::acceptor( - *ioService_, - boost::asio::ip::tcp::endpoint(address_.getRawAddress(), boost::numeric_cast<unsigned short>(port_))); - } - else { - acceptor_ = new boost::asio::ip::tcp::acceptor( - *ioService_, - boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), boost::numeric_cast<unsigned short>(port_))); - } - acceptNextConnection(); - } - catch (const boost::system::system_error& e) { - if (e.code() == boost::asio::error::address_in_use) { - return Conflict; - } - else { - return UnknownError; - } - } - return boost::optional<Error>(); + try { + assert(!acceptor_); + boost::asio::ip::tcp::endpoint endpoint; + if (address_.isValid()) { + endpoint = boost::asio::ip::tcp::endpoint(address_.getRawAddress(), port_); + } + else { + endpoint = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), port_); + } + acceptor_ = new boost::asio::ip::tcp::acceptor(*ioService_, endpoint); + if (endpoint.protocol() == boost::asio::ip::tcp::v6()) { + boost::system::error_code ec; + acceptor_->set_option(boost::asio::ip::v6_only(false), ec); + SWIFT_LOG_ASSERT(ec, warning) << "IPv4/IPv6 dual-stack support is not supported on this platform."; + } + acceptNextConnection(); + } + catch (const boost::system::system_error& e) { + if (e.code() == boost::asio::error::address_in_use) { + return Conflict; + } + else { + return UnknownError; + } + } + catch (const boost::numeric::bad_numeric_cast&) { + return UnknownError; + } + return boost::optional<Error>(); } void BoostConnectionServer::stop() { - stop(boost::optional<Error>()); + stop(boost::optional<Error>()); } void BoostConnectionServer::stop(boost::optional<Error> e) { - if (acceptor_) { - acceptor_->close(); - delete acceptor_; - acceptor_ = NULL; - } - eventLoop->postEvent(boost::bind(boost::ref(onStopped), e), shared_from_this()); + if (acceptor_) { + acceptor_->close(); + delete acceptor_; + acceptor_ = nullptr; + } + eventLoop->postEvent(boost::bind(boost::ref(onStopped), e), shared_from_this()); } void BoostConnectionServer::acceptNextConnection() { - BoostConnection::ref newConnection(BoostConnection::create(ioService_, eventLoop)); - acceptor_->async_accept(newConnection->getSocket(), - boost::bind(&BoostConnectionServer::handleAccept, shared_from_this(), newConnection, boost::asio::placeholders::error)); + BoostConnection::ref newConnection(BoostConnection::create(ioService_, eventLoop)); + acceptor_->async_accept(newConnection->getSocket(), + boost::bind(&BoostConnectionServer::handleAccept, shared_from_this(), newConnection, boost::asio::placeholders::error)); } -void BoostConnectionServer::handleAccept(boost::shared_ptr<BoostConnection> newConnection, const boost::system::error_code& error) { - if (error) { - eventLoop->postEvent( - boost::bind( - &BoostConnectionServer::stop, shared_from_this(), UnknownError), - shared_from_this()); - } - else { - eventLoop->postEvent( - boost::bind(boost::ref(onNewConnection), newConnection), - shared_from_this()); - newConnection->listen(); - acceptNextConnection(); - } +void BoostConnectionServer::handleAccept(std::shared_ptr<BoostConnection> newConnection, const boost::system::error_code& error) { + if (error) { + eventLoop->postEvent( + boost::bind( + &BoostConnectionServer::stop, shared_from_this(), UnknownError), + shared_from_this()); + } + else { + eventLoop->postEvent( + boost::bind(boost::ref(onNewConnection), newConnection), + shared_from_this()); + newConnection->listen(); + acceptNextConnection(); + } } HostAddressPort BoostConnectionServer::getAddressPort() const { - if (acceptor_) { - return HostAddressPort(acceptor_->local_endpoint()); - } - else { - return HostAddressPort(); - } + if (acceptor_) { + return HostAddressPort(acceptor_->local_endpoint()); + } + else { + return HostAddressPort(); + } } } diff --git a/Swiften/Network/BoostConnectionServer.h b/Swiften/Network/BoostConnectionServer.h index 3ad0450..917d638 100644 --- a/Swiften/Network/BoostConnectionServer.h +++ b/Swiften/Network/BoostConnectionServer.h @@ -1,57 +1,57 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/asio/io_service.hpp> #include <boost/asio/ip/tcp.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <boost/optional/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/EventLoop/EventOwner.h> #include <Swiften/Network/BoostConnection.h> #include <Swiften/Network/ConnectionServer.h> -#include <Swiften/EventLoop/EventOwner.h> -#include <boost/optional/optional_fwd.hpp> namespace Swift { - class SWIFTEN_API BoostConnectionServer : public ConnectionServer, public EventOwner, public boost::enable_shared_from_this<BoostConnectionServer> { - public: - typedef boost::shared_ptr<BoostConnectionServer> ref; + class SWIFTEN_API BoostConnectionServer : public ConnectionServer, public EventOwner, public std::enable_shared_from_this<BoostConnectionServer> { + public: + typedef std::shared_ptr<BoostConnectionServer> ref; - static ref create(int port, boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) { - return ref(new BoostConnectionServer(port, ioService, eventLoop)); - } + static ref create(unsigned short port, std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) { + return ref(new BoostConnectionServer(port, ioService, eventLoop)); + } - static ref create(const HostAddress &address, int port, boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) { - return ref(new BoostConnectionServer(address, port, ioService, eventLoop)); - } + static ref create(const HostAddress &address, unsigned short port, std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) { + return ref(new BoostConnectionServer(address, port, ioService, eventLoop)); + } - virtual boost::optional<Error> tryStart(); // FIXME: This should become the new start - virtual void start(); - virtual void stop(); + virtual boost::optional<Error> tryStart(); // FIXME: This should become the new start + virtual void start(); + virtual void stop(); - virtual HostAddressPort getAddressPort() const; + virtual HostAddressPort getAddressPort() const; - boost::signal<void (boost::optional<Error>)> onStopped; + boost::signals2::signal<void (boost::optional<Error>)> onStopped; - private: - BoostConnectionServer(int port, boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); - BoostConnectionServer(const HostAddress &address, int port, boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); + private: + BoostConnectionServer(unsigned short port, std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); + BoostConnectionServer(const HostAddress &address, unsigned short port, std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); - void stop(boost::optional<Error> e); - void acceptNextConnection(); - void handleAccept(boost::shared_ptr<BoostConnection> newConnection, const boost::system::error_code& error); + void stop(boost::optional<Error> e); + void acceptNextConnection(); + void handleAccept(std::shared_ptr<BoostConnection> newConnection, const boost::system::error_code& error); - private: - HostAddress address_; - int port_; - boost::shared_ptr<boost::asio::io_service> ioService_; - EventLoop* eventLoop; - boost::asio::ip::tcp::acceptor* acceptor_; - }; + private: + HostAddress address_; + unsigned short port_; + std::shared_ptr<boost::asio::io_service> ioService_; + EventLoop* eventLoop; + boost::asio::ip::tcp::acceptor* acceptor_; + }; } diff --git a/Swiften/Network/BoostConnectionServerFactory.cpp b/Swiften/Network/BoostConnectionServerFactory.cpp index 04c614e..6936453 100644 --- a/Swiften/Network/BoostConnectionServerFactory.cpp +++ b/Swiften/Network/BoostConnectionServerFactory.cpp @@ -4,20 +4,27 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Network/BoostConnectionServerFactory.h> + #include <Swiften/Network/BoostConnectionServer.h> namespace Swift { -BoostConnectionServerFactory::BoostConnectionServerFactory(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : ioService(ioService), eventLoop(eventLoop) { +BoostConnectionServerFactory::BoostConnectionServerFactory(std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : ioService(ioService), eventLoop(eventLoop) { } -boost::shared_ptr<ConnectionServer> BoostConnectionServerFactory::createConnectionServer(int port) { - return BoostConnectionServer::create(port, ioService, eventLoop); +std::shared_ptr<ConnectionServer> BoostConnectionServerFactory::createConnectionServer(unsigned short port) { + return BoostConnectionServer::create(port, ioService, eventLoop); } -boost::shared_ptr<ConnectionServer> BoostConnectionServerFactory::createConnectionServer(const Swift::HostAddress &hostAddress, int port) { - return BoostConnectionServer::create(hostAddress, port, ioService, eventLoop); +std::shared_ptr<ConnectionServer> BoostConnectionServerFactory::createConnectionServer(const Swift::HostAddress &hostAddress, unsigned short port) { + return BoostConnectionServer::create(hostAddress, port, ioService, eventLoop); } } diff --git a/Swiften/Network/BoostConnectionServerFactory.h b/Swiften/Network/BoostConnectionServerFactory.h index 9132b5c..956132b 100644 --- a/Swiften/Network/BoostConnectionServerFactory.h +++ b/Swiften/Network/BoostConnectionServerFactory.h @@ -4,26 +4,33 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <boost/asio/io_service.hpp> -#include <Swiften/Network/ConnectionServerFactory.h> +#include <Swiften/Base/API.h> #include <Swiften/Network/BoostConnectionServer.h> +#include <Swiften/Network/ConnectionServerFactory.h> namespace Swift { - class ConnectionServer; + class ConnectionServer; - class BoostConnectionServerFactory : public ConnectionServerFactory { - public: - BoostConnectionServerFactory(boost::shared_ptr<boost::asio::io_service>, EventLoop* eventLoop); + class SWIFTEN_API BoostConnectionServerFactory : public ConnectionServerFactory { + public: + BoostConnectionServerFactory(std::shared_ptr<boost::asio::io_service>, EventLoop* eventLoop); - virtual boost::shared_ptr<ConnectionServer> createConnectionServer(int port); + virtual std::shared_ptr<ConnectionServer> createConnectionServer(unsigned short port); - virtual boost::shared_ptr<ConnectionServer> createConnectionServer(const Swift::HostAddress &hostAddress, int port); + virtual std::shared_ptr<ConnectionServer> createConnectionServer(const Swift::HostAddress &hostAddress, unsigned short port); - private: - boost::shared_ptr<boost::asio::io_service> ioService; - EventLoop* eventLoop; - }; + private: + std::shared_ptr<boost::asio::io_service> ioService; + EventLoop* eventLoop; + }; } diff --git a/Swiften/Network/BoostIOServiceThread.cpp b/Swiften/Network/BoostIOServiceThread.cpp index c98a653..756e660 100644 --- a/Swiften/Network/BoostIOServiceThread.cpp +++ b/Swiften/Network/BoostIOServiceThread.cpp @@ -1,29 +1,39 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/BoostIOServiceThread.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + +#include <boost/bind.hpp> namespace Swift { -BoostIOServiceThread::BoostIOServiceThread() { - ioService_ = boost::make_shared<boost::asio::io_service>(); - thread_ = new boost::thread(boost::bind(&BoostIOServiceThread::doRun, this)); +BoostIOServiceThread::BoostIOServiceThread(std::shared_ptr<boost::asio::io_service> ioService) { + if (!!ioService) { + ioService_ = ioService; + thread_ = nullptr; + } + else { + ioService_ = std::make_shared<boost::asio::io_service>(); + thread_ = new std::thread(boost::bind(&BoostIOServiceThread::doRun, this)); + } } BoostIOServiceThread::~BoostIOServiceThread() { - ioService_->stop(); - thread_->join(); - delete thread_; + if (thread_) { + ioService_->stop(); + thread_->join(); + delete thread_; + } } void BoostIOServiceThread::doRun() { - boost::asio::io_service::work work(*ioService_); - ioService_->run(); + boost::asio::io_service::work work(*ioService_); + ioService_->run(); } } diff --git a/Swiften/Network/BoostIOServiceThread.h b/Swiften/Network/BoostIOServiceThread.h index d1a5f37..b9183fd 100644 --- a/Swiften/Network/BoostIOServiceThread.h +++ b/Swiften/Network/BoostIOServiceThread.h @@ -1,32 +1,41 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> +#include <thread> + #include <boost/asio/io_service.hpp> -#include <boost/thread/thread.hpp> -#include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API BoostIOServiceThread { - public: - BoostIOServiceThread(); - ~BoostIOServiceThread(); - - boost::shared_ptr<boost::asio::io_service> getIOService() const { - return ioService_; - } - - private: - void doRun(); - - private: - boost::shared_ptr<boost::asio::io_service> ioService_; - boost::thread* thread_; - }; + class SWIFTEN_API BoostIOServiceThread { + public: + /** + * Construct the object. + * @param ioService If this optional parameter is provided, the behaviour + * of this class changes completely - it no longer spawns its own thread + * and instead acts as a simple wrapper of the io_service. Use this if + * you are re-using an io_service from elsewhere (particularly if you + * are using the BoostASIOEventLoop). + */ + BoostIOServiceThread(std::shared_ptr<boost::asio::io_service> ioService = std::shared_ptr<boost::asio::io_service>()); + ~BoostIOServiceThread(); + + std::shared_ptr<boost::asio::io_service> getIOService() const { + return ioService_; + } + + private: + void doRun(); + + private: + std::shared_ptr<boost::asio::io_service> ioService_; + std::thread* thread_; + }; } diff --git a/Swiften/Network/BoostNetworkFactories.cpp b/Swiften/Network/BoostNetworkFactories.cpp index 72e826a..13a7960 100644 --- a/Swiften/Network/BoostNetworkFactories.cpp +++ b/Swiften/Network/BoostNetworkFactories.cpp @@ -1,24 +1,24 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/BoostNetworkFactories.h> -#include <Swiften/Network/BoostTimerFactory.h> -#include <Swiften/Network/BoostConnectionFactory.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/IDN/IDNConverter.h> +#include <Swiften/IDN/PlatformIDNConverter.h> +#include <Swiften/Network/BoostConnectionFactory.h> #include <Swiften/Network/BoostConnectionServerFactory.h> -#include <Swiften/Network/PlatformNATTraversalWorker.h> -#include <Swiften/Parser/PlatformXMLParserFactory.h> +#include <Swiften/Network/BoostTimerFactory.h> #include <Swiften/Network/NullNATTraverser.h> +#include <Swiften/Network/PlatformNATTraversalWorker.h> #include <Swiften/Network/PlatformNetworkEnvironment.h> -#include <Swiften/TLS/PlatformTLSFactories.h> #include <Swiften/Network/PlatformProxyProvider.h> -#include <Swiften/IDN/PlatformIDNConverter.h> -#include <Swiften/IDN/IDNConverter.h> -#include <Swiften/Crypto/PlatformCryptoProvider.h> -#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Parser/PlatformXMLParserFactory.h> +#include <Swiften/TLS/PlatformTLSFactories.h> #ifdef USE_UNBOUND #include <Swiften/Network/UnboundDomainNameResolver.h> @@ -28,45 +28,44 @@ namespace Swift { -BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop) : eventLoop(eventLoop){ - timerFactory = new BoostTimerFactory(ioServiceThread.getIOService(), eventLoop); - connectionFactory = new BoostConnectionFactory(ioServiceThread.getIOService(), eventLoop); - connectionServerFactory = new BoostConnectionServerFactory(ioServiceThread.getIOService(), eventLoop); +BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop, std::shared_ptr<boost::asio::io_service> ioService) : ioServiceThread(ioService), eventLoop(eventLoop) { + timerFactory = new BoostTimerFactory(ioServiceThread.getIOService(), eventLoop); + connectionFactory = new BoostConnectionFactory(ioServiceThread.getIOService(), eventLoop); + connectionServerFactory = new BoostConnectionServerFactory(ioServiceThread.getIOService(), eventLoop); #ifdef SWIFT_EXPERIMENTAL_FT - natTraverser = new PlatformNATTraversalWorker(eventLoop); + natTraverser = new PlatformNATTraversalWorker(eventLoop); #else - natTraverser = new NullNATTraverser(eventLoop); + natTraverser = new NullNATTraverser(eventLoop); #endif - networkEnvironment = new PlatformNetworkEnvironment(); - xmlParserFactory = new PlatformXMLParserFactory(); - tlsFactories = new PlatformTLSFactories(); - proxyProvider = new PlatformProxyProvider(); - idnConverter = PlatformIDNConverter::create(); + networkEnvironment = new PlatformNetworkEnvironment(); + xmlParserFactory = new PlatformXMLParserFactory(); + tlsFactories = new PlatformTLSFactories(); + proxyProvider = new PlatformProxyProvider(); + idnConverter = PlatformIDNConverter::create(); #ifdef USE_UNBOUND - // TODO: What to do about idnConverter. - domainNameResolver = new UnboundDomainNameResolver(ioServiceThread.getIOService(), eventLoop); + // TODO: What to do about idnConverter. + domainNameResolver = new UnboundDomainNameResolver(idnConverter.get(), ioServiceThread.getIOService(), eventLoop); #else - domainNameResolver = new PlatformDomainNameResolver(idnConverter, eventLoop); + domainNameResolver = new PlatformDomainNameResolver(idnConverter.get(), eventLoop); #endif - cryptoProvider = PlatformCryptoProvider::create(); + cryptoProvider = PlatformCryptoProvider::create(); } BoostNetworkFactories::~BoostNetworkFactories() { - delete cryptoProvider; - delete domainNameResolver; - delete idnConverter; - delete proxyProvider; - delete tlsFactories; - delete xmlParserFactory; - delete networkEnvironment; - delete natTraverser; - delete connectionServerFactory; - delete connectionFactory; - delete timerFactory; + delete cryptoProvider; + delete domainNameResolver; + delete proxyProvider; + delete tlsFactories; + delete xmlParserFactory; + delete networkEnvironment; + delete natTraverser; + delete connectionServerFactory; + delete connectionFactory; + delete timerFactory; } TLSContextFactory* BoostNetworkFactories::getTLSContextFactory() const { - return tlsFactories->getTLSContextFactory(); + return tlsFactories->getTLSContextFactory(); } } diff --git a/Swiften/Network/BoostNetworkFactories.h b/Swiften/Network/BoostNetworkFactories.h index 9c3bab1..33a3584 100644 --- a/Swiften/Network/BoostNetworkFactories.h +++ b/Swiften/Network/BoostNetworkFactories.h @@ -1,89 +1,95 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Base/Override.h> -#include <Swiften/Network/NetworkFactories.h> #include <Swiften/Network/BoostIOServiceThread.h> +#include <Swiften/Network/NetworkFactories.h> namespace Swift { - class EventLoop; - class NATTraverser; - class PlatformTLSFactories; - - class SWIFTEN_API BoostNetworkFactories : public NetworkFactories { - public: - BoostNetworkFactories(EventLoop* eventLoop); - ~BoostNetworkFactories(); - - virtual TimerFactory* getTimerFactory() const SWIFTEN_OVERRIDE { - return timerFactory; - } - - virtual ConnectionFactory* getConnectionFactory() const SWIFTEN_OVERRIDE { - return connectionFactory; - } - - BoostIOServiceThread* getIOServiceThread() { - return &ioServiceThread; - } - - DomainNameResolver* getDomainNameResolver() const SWIFTEN_OVERRIDE { - return domainNameResolver; - } - - ConnectionServerFactory* getConnectionServerFactory() const SWIFTEN_OVERRIDE { - return connectionServerFactory; - } - - NetworkEnvironment* getNetworkEnvironment() const SWIFTEN_OVERRIDE { - return networkEnvironment; - } - - NATTraverser* getNATTraverser() const SWIFTEN_OVERRIDE { - return natTraverser; - } - - virtual XMLParserFactory* getXMLParserFactory() const SWIFTEN_OVERRIDE { - return xmlParserFactory; - } - - virtual TLSContextFactory* getTLSContextFactory() const SWIFTEN_OVERRIDE; - - virtual ProxyProvider* getProxyProvider() const SWIFTEN_OVERRIDE { - return proxyProvider; - } - - virtual EventLoop* getEventLoop() const SWIFTEN_OVERRIDE { - return eventLoop; - } - - virtual IDNConverter* getIDNConverter() const SWIFTEN_OVERRIDE { - return idnConverter; - } - - virtual CryptoProvider* getCryptoProvider() const SWIFTEN_OVERRIDE { - return cryptoProvider; - } - - private: - BoostIOServiceThread ioServiceThread; - TimerFactory* timerFactory; - ConnectionFactory* connectionFactory; - DomainNameResolver* domainNameResolver; - ConnectionServerFactory* connectionServerFactory; - NATTraverser* natTraverser; - NetworkEnvironment* networkEnvironment; - XMLParserFactory* xmlParserFactory; - PlatformTLSFactories* tlsFactories; - ProxyProvider* proxyProvider; - EventLoop* eventLoop; - IDNConverter* idnConverter; - CryptoProvider* cryptoProvider; - }; + class EventLoop; + class NATTraverser; + class PlatformTLSFactories; + + class SWIFTEN_API BoostNetworkFactories : public NetworkFactories { + public: + /** + * Construct the network factories, using the provided EventLoop. + * @param ioService If this optional parameter is provided, it will be + * used for the construction of the BoostIOServiceThread. + */ + BoostNetworkFactories(EventLoop* eventLoop, std::shared_ptr<boost::asio::io_service> ioService = std::shared_ptr<boost::asio::io_service>()); + virtual ~BoostNetworkFactories() override; + + virtual TimerFactory* getTimerFactory() const override { + return timerFactory; + } + + virtual ConnectionFactory* getConnectionFactory() const override { + return connectionFactory; + } + + BoostIOServiceThread* getIOServiceThread() { + return &ioServiceThread; + } + + DomainNameResolver* getDomainNameResolver() const override { + return domainNameResolver; + } + + ConnectionServerFactory* getConnectionServerFactory() const override { + return connectionServerFactory; + } + + NetworkEnvironment* getNetworkEnvironment() const override { + return networkEnvironment; + } + + NATTraverser* getNATTraverser() const override { + return natTraverser; + } + + virtual XMLParserFactory* getXMLParserFactory() const override { + return xmlParserFactory; + } + + virtual TLSContextFactory* getTLSContextFactory() const override; + + virtual ProxyProvider* getProxyProvider() const override { + return proxyProvider; + } + + virtual EventLoop* getEventLoop() const override { + return eventLoop; + } + + virtual IDNConverter* getIDNConverter() const override { + return idnConverter.get(); + } + + virtual CryptoProvider* getCryptoProvider() const override { + return cryptoProvider; + } + + private: + BoostIOServiceThread ioServiceThread; + TimerFactory* timerFactory; + ConnectionFactory* connectionFactory; + DomainNameResolver* domainNameResolver; + ConnectionServerFactory* connectionServerFactory; + NATTraverser* natTraverser; + NetworkEnvironment* networkEnvironment; + XMLParserFactory* xmlParserFactory; + PlatformTLSFactories* tlsFactories; + ProxyProvider* proxyProvider; + EventLoop* eventLoop; + std::unique_ptr<IDNConverter> idnConverter; + CryptoProvider* cryptoProvider; + }; } diff --git a/Swiften/Network/BoostTimer.cpp b/Swiften/Network/BoostTimer.cpp index bf042d6..a177504 100644 --- a/Swiften/Network/BoostTimer.cpp +++ b/Swiften/Network/BoostTimer.cpp @@ -1,40 +1,62 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/BoostTimer.h> -#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/asio.hpp> #include <boost/bind.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> #include <Swiften/EventLoop/EventLoop.h> namespace Swift { -BoostTimer::BoostTimer(int milliseconds, boost::shared_ptr<boost::asio::io_service> service, EventLoop* eventLoop) : - timeout(milliseconds), ioService(service), timer(*service), eventLoop(eventLoop) { +BoostTimer::BoostTimer(int milliseconds, std::shared_ptr<boost::asio::io_service> service, EventLoop* eventLoop) : + timeout(milliseconds), ioService(service), eventLoop(eventLoop), shuttingDown(false) { + timer.reset(new boost::asio::deadline_timer(*service)); +} + +BoostTimer::~BoostTimer() { + { + std::unique_lock<std::mutex> lockTimer(timerMutex); + timer.reset(); + } } void BoostTimer::start() { - timer.expires_from_now(boost::posix_time::milliseconds(timeout)); - timer.async_wait(boost::bind(&BoostTimer::handleTimerTick, shared_from_this(), boost::asio::placeholders::error)); + { + std::unique_lock<std::mutex> lockTimer(timerMutex); + shuttingDown = false; + timer->expires_from_now(boost::posix_time::milliseconds(timeout)); + timer->async_wait(boost::bind(&BoostTimer::handleTimerTick, shared_from_this(), boost::asio::placeholders::error)); + } } void BoostTimer::stop() { - timer.cancel(); - eventLoop->removeEventsFromOwner(shared_from_this()); + { + std::unique_lock<std::mutex> lockTimer(timerMutex); + shuttingDown = true; + timer->cancel(); + eventLoop->removeEventsFromOwner(shared_from_this()); + } } void BoostTimer::handleTimerTick(const boost::system::error_code& error) { - if (error) { - assert(error == boost::asio::error::operation_aborted); - } - else { - eventLoop->postEvent(boost::bind(boost::ref(onTick)), shared_from_this()); - } + if (error) { + assert(error == boost::asio::error::operation_aborted); + } + else { + { + std::unique_lock<std::mutex> lockTimer(timerMutex); + if (shuttingDown) { + return; + } + eventLoop->postEvent(boost::bind(boost::ref(onTick)), shared_from_this()); + } + } } } diff --git a/Swiften/Network/BoostTimer.h b/Swiften/Network/BoostTimer.h index bfe631b..68ae28c 100644 --- a/Swiften/Network/BoostTimer.h +++ b/Swiften/Network/BoostTimer.h @@ -1,41 +1,49 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/asio/io_service.hpp> +#include <memory> +#include <mutex> + #include <boost/asio/deadline_timer.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/scoped_ptr.hpp> +#include <Swiften/Base/API.h> #include <Swiften/EventLoop/EventOwner.h> #include <Swiften/Network/Timer.h> namespace Swift { - class EventLoop; + class EventLoop; + + class SWIFTEN_API BoostTimer : public Timer, public EventOwner, public std::enable_shared_from_this<BoostTimer> { + public: + typedef std::shared_ptr<BoostTimer> ref; - class BoostTimer : public Timer, public EventOwner, public boost::enable_shared_from_this<BoostTimer> { - public: - typedef boost::shared_ptr<BoostTimer> ref; + virtual ~BoostTimer(); - static ref create(int milliseconds, boost::shared_ptr<boost::asio::io_service> service, EventLoop* eventLoop) { - return ref(new BoostTimer(milliseconds, service, eventLoop)); - } + static ref create(int milliseconds, std::shared_ptr<boost::asio::io_service> service, EventLoop* eventLoop) { + return ref(new BoostTimer(milliseconds, service, eventLoop)); + } - virtual void start(); - virtual void stop(); + virtual void start(); + virtual void stop(); - private: - BoostTimer(int milliseconds, boost::shared_ptr<boost::asio::io_service> service, EventLoop* eventLoop); + private: + BoostTimer(int milliseconds, std::shared_ptr<boost::asio::io_service> service, EventLoop* eventLoop); - void handleTimerTick(const boost::system::error_code& error); + void handleTimerTick(const boost::system::error_code& error); - private: - int timeout; - boost::shared_ptr<boost::asio::io_service> ioService; - boost::asio::deadline_timer timer; - EventLoop* eventLoop; - }; + private: + int timeout; + std::shared_ptr<boost::asio::io_service> ioService; + boost::scoped_ptr<boost::asio::deadline_timer> timer; + std::mutex timerMutex; + EventLoop* eventLoop; + bool shuttingDown; + }; } diff --git a/Swiften/Network/BoostTimerFactory.cpp b/Swiften/Network/BoostTimerFactory.cpp index c0bdb56..ffa9b30 100644 --- a/Swiften/Network/BoostTimerFactory.cpp +++ b/Swiften/Network/BoostTimerFactory.cpp @@ -1,19 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/BoostTimerFactory.h> + #include <Swiften/Network/BoostTimer.h> namespace Swift { -BoostTimerFactory::BoostTimerFactory(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : ioService(ioService), eventLoop(eventLoop) { +BoostTimerFactory::BoostTimerFactory(std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : ioService(ioService), eventLoop(eventLoop) { } -boost::shared_ptr<Timer> BoostTimerFactory::createTimer(int milliseconds) { - return BoostTimer::create(milliseconds, ioService, eventLoop); +std::shared_ptr<Timer> BoostTimerFactory::createTimer(int milliseconds) { + return BoostTimer::create(milliseconds, ioService, eventLoop); } } diff --git a/Swiften/Network/BoostTimerFactory.h b/Swiften/Network/BoostTimerFactory.h index 6093db0..1e2139b 100644 --- a/Swiften/Network/BoostTimerFactory.h +++ b/Swiften/Network/BoostTimerFactory.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/asio/io_service.hpp> -#include <Swiften/Network/TimerFactory.h> +#include <Swiften/Base/API.h> #include <Swiften/Network/BoostTimer.h> +#include <Swiften/Network/TimerFactory.h> namespace Swift { - class BoostTimer; - class EventLoop; + class EventLoop; - class BoostTimerFactory : public TimerFactory { - public: - BoostTimerFactory(boost::shared_ptr<boost::asio::io_service>, EventLoop* eventLoop); + class SWIFTEN_API BoostTimerFactory : public TimerFactory { + public: + BoostTimerFactory(std::shared_ptr<boost::asio::io_service>, EventLoop* eventLoop); - virtual boost::shared_ptr<Timer> createTimer(int milliseconds); + virtual std::shared_ptr<Timer> createTimer(int milliseconds); - private: - boost::shared_ptr<boost::asio::io_service> ioService; - EventLoop* eventLoop; - }; + private: + std::shared_ptr<boost::asio::io_service> ioService; + EventLoop* eventLoop; + }; } diff --git a/Swiften/Network/CachingDomainNameResolver.cpp b/Swiften/Network/CachingDomainNameResolver.cpp index 4cf8286..8846e09 100644 --- a/Swiften/Network/CachingDomainNameResolver.cpp +++ b/Swiften/Network/CachingDomainNameResolver.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/CachingDomainNameResolver.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> namespace Swift { @@ -17,14 +17,14 @@ CachingDomainNameResolver::~CachingDomainNameResolver() { } -DomainNameServiceQuery::ref CachingDomainNameResolver::createServiceQuery(const std::string& name) { - //TODO: Cache - return realResolver->createServiceQuery(name); +DomainNameServiceQuery::ref CachingDomainNameResolver::createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) { + //TODO: Cache + return realResolver->createServiceQuery(serviceLookupPrefix, domain); } DomainNameAddressQuery::ref CachingDomainNameResolver::createAddressQuery(const std::string& name) { - //TODO: Cache - return realResolver->createAddressQuery(name); + //TODO: Cache + return realResolver->createAddressQuery(name); } } diff --git a/Swiften/Network/CachingDomainNameResolver.h b/Swiften/Network/CachingDomainNameResolver.h index 66b4d68..9339a77 100644 --- a/Swiften/Network/CachingDomainNameResolver.h +++ b/Swiften/Network/CachingDomainNameResolver.h @@ -1,13 +1,14 @@ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Network/DomainNameResolver.h> #include <Swiften/Network/StaticDomainNameResolver.h> @@ -15,17 +16,17 @@ * FIXME: Does not do any caching yet. */ namespace Swift { - class EventLoop; + class EventLoop; - class CachingDomainNameResolver : public DomainNameResolver { - public: - CachingDomainNameResolver(DomainNameResolver* realResolver, EventLoop* eventLoop); - ~CachingDomainNameResolver(); + class SWIFTEN_API CachingDomainNameResolver : public DomainNameResolver { + public: + CachingDomainNameResolver(DomainNameResolver* realResolver, EventLoop* eventLoop); + ~CachingDomainNameResolver(); - virtual DomainNameServiceQuery::ref createServiceQuery(const std::string& name); - virtual DomainNameAddressQuery::ref createAddressQuery(const std::string& name); + virtual DomainNameServiceQuery::ref createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain); + virtual DomainNameAddressQuery::ref createAddressQuery(const std::string& name); - private: - DomainNameResolver* realResolver; - }; + private: + DomainNameResolver* realResolver; + }; } diff --git a/Swiften/Network/ChainedConnector.cpp b/Swiften/Network/ChainedConnector.cpp index 8c7c04b..a9210ba 100644 --- a/Swiften/Network/ChainedConnector.cpp +++ b/Swiften/Network/ChainedConnector.cpp @@ -1,87 +1,95 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/ChainedConnector.h> -#include <boost/bind.hpp> #include <typeinfo> +#include <boost/bind.hpp> + #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Network/Connector.h> #include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/Connector.h> using namespace Swift; ChainedConnector::ChainedConnector( - const std::string& hostname, - int port, - bool doServiceLookups, - DomainNameResolver* resolver, - const std::vector<ConnectionFactory*>& connectionFactories, - TimerFactory* timerFactory) : - hostname(hostname), - port(port), - doServiceLookups(doServiceLookups), - resolver(resolver), - connectionFactories(connectionFactories), - timerFactory(timerFactory), - timeoutMilliseconds(0) { + const std::string& hostname, + unsigned short port, + const boost::optional<std::string>& serviceLookupPrefix, + DomainNameResolver* resolver, + const std::vector<ConnectionFactory*>& connectionFactories, + TimerFactory* timerFactory) : + hostname(hostname), + port(port), + serviceLookupPrefix(serviceLookupPrefix), + resolver(resolver), + connectionFactories(connectionFactories), + timerFactory(timerFactory), + timeoutMilliseconds(0) { +} + +ChainedConnector::~ChainedConnector() { + if (currentConnector) { + currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); + currentConnector->stop(); + currentConnector.reset(); + } } void ChainedConnector::setTimeoutMilliseconds(int milliseconds) { - timeoutMilliseconds = milliseconds; + timeoutMilliseconds = milliseconds; } void ChainedConnector::start() { - SWIFT_LOG(debug) << "Starting queued connector for " << hostname << std::endl; + SWIFT_LOG(debug) << "Starting queued connector for " << hostname; - connectionFactoryQueue = std::deque<ConnectionFactory*>(connectionFactories.begin(), connectionFactories.end()); - tryNextConnectionFactory(); + connectionFactoryQueue = std::deque<ConnectionFactory*>(connectionFactories.begin(), connectionFactories.end()); + tryNextConnectionFactory(); } void ChainedConnector::stop() { - if (currentConnector) { - currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); - currentConnector->stop(); - currentConnector.reset(); - } - finish(boost::shared_ptr<Connection>(), boost::shared_ptr<Error>()); + if (currentConnector) { + currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); + currentConnector->stop(); + currentConnector.reset(); + } + finish(std::shared_ptr<Connection>(), std::shared_ptr<Error>()); } void ChainedConnector::tryNextConnectionFactory() { - assert(!currentConnector); - if (connectionFactoryQueue.empty()) { - SWIFT_LOG(debug) << "No more connection factories" << std::endl; - finish(boost::shared_ptr<Connection>(), lastError); - } - else { - ConnectionFactory* connectionFactory = connectionFactoryQueue.front(); - SWIFT_LOG(debug) << "Trying next connection factory: " << typeid(*connectionFactory).name() << std::endl; - connectionFactoryQueue.pop_front(); - currentConnector = Connector::create(hostname, port, doServiceLookups, resolver, connectionFactory, timerFactory); - currentConnector->setTimeoutMilliseconds(timeoutMilliseconds); - currentConnector->onConnectFinished.connect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); - currentConnector->start(); - } + assert(!currentConnector); + if (connectionFactoryQueue.empty()) { + SWIFT_LOG(debug) << "No more connection factories"; + finish(std::shared_ptr<Connection>(), lastError); + } + else { + ConnectionFactory* connectionFactory = connectionFactoryQueue.front(); + SWIFT_LOG(debug) << "Trying next connection factory: " << typeid(*connectionFactory).name(); + connectionFactoryQueue.pop_front(); + currentConnector = Connector::create(hostname, port, serviceLookupPrefix, resolver, connectionFactory, timerFactory); + currentConnector->setTimeoutMilliseconds(timeoutMilliseconds); + currentConnector->onConnectFinished.connect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); + currentConnector->start(); + } } -void ChainedConnector::handleConnectorFinished(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error> error) { - SWIFT_LOG(debug) << "Connector finished" << std::endl; - currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); - lastError = error; - currentConnector.reset(); - if (connection) { - finish(connection, error); - } - else { - tryNextConnectionFactory(); - } +void ChainedConnector::handleConnectorFinished(std::shared_ptr<Connection> connection, std::shared_ptr<Error> error) { + SWIFT_LOG(debug) << "Connector finished"; + currentConnector->onConnectFinished.disconnect(boost::bind(&ChainedConnector::handleConnectorFinished, this, _1, _2)); + lastError = error; + currentConnector.reset(); + if (connection) { + finish(connection, error); + } + else { + tryNextConnectionFactory(); + } } -void ChainedConnector::finish(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error> error) { - onConnectFinished(connection, error); +void ChainedConnector::finish(std::shared_ptr<Connection> connection, std::shared_ptr<Error> error) { + onConnectFinished(connection, error); } diff --git a/Swiften/Network/ChainedConnector.h b/Swiften/Network/ChainedConnector.h index 03462bc..9620293 100644 --- a/Swiften/Network/ChainedConnector.h +++ b/Swiften/Network/ChainedConnector.h @@ -1,52 +1,55 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <deque> +#include <memory> #include <string> #include <vector> -#include <deque> -#include <boost/shared_ptr.hpp> + +#include <boost/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Base/Error.h> namespace Swift { - class Connection; - class Connector; - class ConnectionFactory; - class TimerFactory; - class DomainNameResolver; - - class SWIFTEN_API ChainedConnector { - public: - ChainedConnector(const std::string& hostname, int port, bool doServiceLookups, DomainNameResolver*, const std::vector<ConnectionFactory*>&, TimerFactory*); - - void setTimeoutMilliseconds(int milliseconds); - void start(); - void stop(); - - boost::signal<void (boost::shared_ptr<Connection>, boost::shared_ptr<Error>)> onConnectFinished; - - private: - void finish(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error>); - void tryNextConnectionFactory(); - void handleConnectorFinished(boost::shared_ptr<Connection>, boost::shared_ptr<Error>); - - private: - std::string hostname; - int port; - bool doServiceLookups; - DomainNameResolver* resolver; - std::vector<ConnectionFactory*> connectionFactories; - TimerFactory* timerFactory; - int timeoutMilliseconds; - std::deque<ConnectionFactory*> connectionFactoryQueue; - boost::shared_ptr<Connector> currentConnector; - boost::shared_ptr<Error> lastError; - }; + class Connection; + class Connector; + class ConnectionFactory; + class TimerFactory; + class DomainNameResolver; + + class SWIFTEN_API ChainedConnector { + public: + ChainedConnector(const std::string& hostname, unsigned short port, const boost::optional<std::string>& serviceLookupPrefix, DomainNameResolver*, const std::vector<ConnectionFactory*>&, TimerFactory*); + ~ChainedConnector(); + + void setTimeoutMilliseconds(int milliseconds); + void start(); + void stop(); + + boost::signals2::signal<void (std::shared_ptr<Connection>, std::shared_ptr<Error>)> onConnectFinished; + + private: + void finish(std::shared_ptr<Connection> connection, std::shared_ptr<Error>); + void tryNextConnectionFactory(); + void handleConnectorFinished(std::shared_ptr<Connection>, std::shared_ptr<Error>); + + private: + std::string hostname; + unsigned short port; + boost::optional<std::string> serviceLookupPrefix; + DomainNameResolver* resolver; + std::vector<ConnectionFactory*> connectionFactories; + TimerFactory* timerFactory; + int timeoutMilliseconds; + std::deque<ConnectionFactory*> connectionFactoryQueue; + std::shared_ptr<Connector> currentConnector; + std::shared_ptr<Error> lastError; + }; } diff --git a/Swiften/Network/Connection.cpp b/Swiften/Network/Connection.cpp index 9bb29e1..adf3c6c 100644 --- a/Swiften/Network/Connection.cpp +++ b/Swiften/Network/Connection.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/Connection.h> diff --git a/Swiften/Network/Connection.h b/Swiften/Network/Connection.h index 97c287d..85f33a8 100644 --- a/Swiften/Network/Connection.h +++ b/Swiften/Network/Connection.h @@ -1,43 +1,45 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> +#include <memory> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class HostAddressPort; - - class SWIFTEN_API Connection { - public: - typedef boost::shared_ptr<Connection> ref; - - enum Error { - ReadError, - WriteError - }; - - Connection(); - virtual ~Connection(); - - virtual void listen() = 0; - virtual void connect(const HostAddressPort& address) = 0; - virtual void disconnect() = 0; - virtual void write(const SafeByteArray& data) = 0; - - virtual HostAddressPort getLocalAddress() const = 0; - - public: - boost::signal<void (bool /* error */)> onConnectFinished; - boost::signal<void (const boost::optional<Error>&)> onDisconnected; - boost::signal<void (boost::shared_ptr<SafeByteArray>)> onDataRead; - boost::signal<void ()> onDataWritten; - }; + class HostAddressPort; + + class SWIFTEN_API Connection { + public: + typedef std::shared_ptr<Connection> ref; + + enum Error { + ReadError, + WriteError + }; + + Connection(); + virtual ~Connection(); + + virtual void listen() = 0; + virtual void connect(const HostAddressPort& address) = 0; + virtual void disconnect() = 0; + virtual void write(const SafeByteArray& data) = 0; + + virtual HostAddressPort getLocalAddress() const = 0; + virtual HostAddressPort getRemoteAddress() const = 0; + + public: + boost::signals2::signal<void (bool /* error */)> onConnectFinished; + boost::signals2::signal<void (const boost::optional<Error>&)> onDisconnected; + boost::signals2::signal<void (std::shared_ptr<SafeByteArray>)> onDataRead; + boost::signals2::signal<void ()> onDataWritten; + }; } diff --git a/Swiften/Network/ConnectionFactory.cpp b/Swiften/Network/ConnectionFactory.cpp index 2e38b21..372e029 100644 --- a/Swiften/Network/ConnectionFactory.cpp +++ b/Swiften/Network/ConnectionFactory.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/ConnectionFactory.h> diff --git a/Swiften/Network/ConnectionFactory.h b/Swiften/Network/ConnectionFactory.h index c8be2fc..e749fa3 100644 --- a/Swiften/Network/ConnectionFactory.h +++ b/Swiften/Network/ConnectionFactory.h @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> namespace Swift { - class Connection; + class Connection; - class SWIFTEN_API ConnectionFactory { - public: - virtual ~ConnectionFactory(); + class SWIFTEN_API ConnectionFactory { + public: + virtual ~ConnectionFactory(); - virtual boost::shared_ptr<Connection> createConnection() = 0; - }; + virtual std::shared_ptr<Connection> createConnection() = 0; + }; } diff --git a/Swiften/Network/ConnectionServer.cpp b/Swiften/Network/ConnectionServer.cpp index 78312e7..c2ac241 100644 --- a/Swiften/Network/ConnectionServer.cpp +++ b/Swiften/Network/ConnectionServer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/ConnectionServer.h> diff --git a/Swiften/Network/ConnectionServer.h b/Swiften/Network/ConnectionServer.h index 2e09348..769ab9f 100644 --- a/Swiften/Network/ConnectionServer.h +++ b/Swiften/Network/ConnectionServer.h @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <boost/optional/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/HostAddressPort.h> -#include <boost/optional/optional_fwd.hpp> namespace Swift { - class SWIFTEN_API ConnectionServer { - public: - enum Error { - Conflict, - UnknownError - }; + class SWIFTEN_API ConnectionServer { + public: + enum Error { + Conflict, + UnknownError + }; - virtual ~ConnectionServer(); + virtual ~ConnectionServer(); - virtual HostAddressPort getAddressPort() const = 0; + virtual HostAddressPort getAddressPort() const = 0; - virtual boost::optional<Error> tryStart() = 0; // FIXME: This should become the new start + virtual boost::optional<Error> tryStart() = 0; // FIXME: This should become the new start - virtual void start() = 0; + virtual void start() = 0; - virtual void stop() = 0; + virtual void stop() = 0; - boost::signal<void (boost::shared_ptr<Connection>)> onNewConnection; - }; + boost::signals2::signal<void (std::shared_ptr<Connection>)> onNewConnection; + }; } diff --git a/Swiften/Network/ConnectionServerFactory.h b/Swiften/Network/ConnectionServerFactory.h index df5f912..2ebccc1 100644 --- a/Swiften/Network/ConnectionServerFactory.h +++ b/Swiften/Network/ConnectionServerFactory.h @@ -4,20 +4,28 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <Swiften/Base/API.h> namespace Swift { - class ConnectionServer; - class HostAddress; + class ConnectionServer; + class HostAddress; - class ConnectionServerFactory { - public: - virtual ~ConnectionServerFactory(); + class SWIFTEN_API ConnectionServerFactory { + public: + virtual ~ConnectionServerFactory(); - virtual boost::shared_ptr<ConnectionServer> createConnectionServer(int port) = 0; + virtual std::shared_ptr<ConnectionServer> createConnectionServer(unsigned short port) = 0; - virtual boost::shared_ptr<ConnectionServer> createConnectionServer(const Swift::HostAddress& hostAddress, int port) = 0; - }; + virtual std::shared_ptr<ConnectionServer> createConnectionServer(const Swift::HostAddress& hostAddress, unsigned short port) = 0; + }; } diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp index a0155cf..e27b95d 100644 --- a/Swiften/Network/Connector.cpp +++ b/Swiften/Network/Connector.cpp @@ -1,186 +1,203 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/Connector.h> #include <boost/bind.hpp> -#include <iostream> +#include <Swiften/Base/Log.h> #include <Swiften/Network/ConnectionFactory.h> -#include <Swiften/Network/DomainNameResolver.h> #include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/Network/DomainNameResolver.h> +#include <Swiften/Network/HostAddress.h> #include <Swiften/Network/TimerFactory.h> -#include <Swiften/Base/Log.h> namespace Swift { -Connector::Connector(const std::string& hostname, int port, bool doServiceLookups, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) : hostname(hostname), port(port), doServiceLookups(doServiceLookups), resolver(resolver), connectionFactory(connectionFactory), timerFactory(timerFactory), timeoutMilliseconds(0), queriedAllServices(true), foundSomeDNS(false) { +Connector::Connector(const std::string& hostname, unsigned short port, const boost::optional<std::string>& serviceLookupPrefix, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) : hostname(hostname), port(port), serviceLookupPrefix(serviceLookupPrefix), resolver(resolver), connectionFactory(connectionFactory), timerFactory(timerFactory), timeoutMilliseconds(0), queriedAllServices(true), foundSomeDNS(false) { } void Connector::setTimeoutMilliseconds(int milliseconds) { - timeoutMilliseconds = milliseconds; + timeoutMilliseconds = milliseconds; } void Connector::start() { - SWIFT_LOG(debug) << "Starting connector for " << hostname << std::endl; - //std::cout << "Connector::start()" << std::endl; - assert(!currentConnection); - assert(!serviceQuery); - assert(!timer); - queriedAllServices = false; - if (doServiceLookups) { - serviceQuery = resolver->createServiceQuery("_xmpp-client._tcp." + hostname); - serviceQuery->onResult.connect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1)); - if (timeoutMilliseconds > 0) { - timer = timerFactory->createTimer(timeoutMilliseconds); - timer->onTick.connect(boost::bind(&Connector::handleTimeout, shared_from_this())); - } - serviceQuery->run(); - } - else { - queryAddress(hostname); - } + SWIFT_LOG(debug) << "Starting connector for " << hostname; + assert(!currentConnection); + assert(!serviceQuery); + assert(!timer); + auto hostAddress = HostAddress::fromString(hostname); + if (timeoutMilliseconds > 0) { + timer = timerFactory->createTimer(timeoutMilliseconds); + timer->onTick.connect(boost::bind(&Connector::handleTimeout, shared_from_this())); + } + if (serviceLookupPrefix) { + queriedAllServices = false; + serviceQuery = resolver->createServiceQuery(*serviceLookupPrefix, hostname); + serviceQuery->onResult.connect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1)); + serviceQuery->run(); + } + else if (hostAddress) { + // hostname is already a valid address; skip name lookup. + foundSomeDNS = true; + addressQueryResults.push_back(hostAddress.get()); + tryNextAddress(); + } else { + queryAddress(hostname); + } } void Connector::stop() { - finish(boost::shared_ptr<Connection>()); + if (currentConnection) { + currentConnection->onConnectFinished.disconnect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); + currentConnection->disconnect(); + } + finish(std::shared_ptr<Connection>()); } void Connector::queryAddress(const std::string& hostname) { - assert(!addressQuery); - addressQuery = resolver->createAddressQuery(hostname); - addressQuery->onResult.connect(boost::bind(&Connector::handleAddressQueryResult, shared_from_this(), _1, _2)); - addressQuery->run(); + assert(!addressQuery); + addressQuery = resolver->createAddressQuery(hostname); + addressQuery->onResult.connect(boost::bind(&Connector::handleAddressQueryResult, shared_from_this(), _1, _2)); + addressQuery->run(); } void Connector::handleServiceQueryResult(const std::vector<DomainNameServiceQuery::Result>& result) { - SWIFT_LOG(debug) << result.size() << " SRV result(s)" << std::endl; - serviceQueryResults = std::deque<DomainNameServiceQuery::Result>(result.begin(), result.end()); - serviceQuery.reset(); - if (!serviceQueryResults.empty()) { - foundSomeDNS = true; - } - tryNextServiceOrFallback(); + SWIFT_LOG(debug) << result.size() << " SRV result(s)"; + serviceQueryResults = std::deque<DomainNameServiceQuery::Result>(result.begin(), result.end()); + serviceQuery.reset(); + if (!serviceQueryResults.empty()) { + foundSomeDNS = true; + } + tryNextServiceOrFallback(); } void Connector::tryNextServiceOrFallback() { - if (queriedAllServices) { - SWIFT_LOG(debug) << "Queried all services" << std::endl; - finish(boost::shared_ptr<Connection>()); - } - else if (serviceQueryResults.empty()) { - SWIFT_LOG(debug) << "Falling back on A resolution" << std::endl; - // Fall back on simple address resolving - queriedAllServices = true; - queryAddress(hostname); - } - else { - SWIFT_LOG(debug) << "Querying next address" << std::endl; - queryAddress(serviceQueryResults.front().hostname); - } + if (queriedAllServices) { + SWIFT_LOG(debug) << "Queried all services"; + finish(std::shared_ptr<Connection>()); + } + else if (serviceQueryResults.empty()) { + SWIFT_LOG(debug) << "Falling back on A resolution"; + // Fall back on simple address resolving + queriedAllServices = true; + queryAddress(hostname); + } + else { + SWIFT_LOG(debug) << "Querying next address"; + queryAddress(serviceQueryResults.front().hostname); + } } void Connector::handleAddressQueryResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error) { - SWIFT_LOG(debug) << addresses.size() << " addresses" << std::endl; - addressQuery.reset(); - if (error || addresses.empty()) { - if (!serviceQueryResults.empty()) { - serviceQueryResults.pop_front(); - } - tryNextServiceOrFallback(); - } - else { - foundSomeDNS = true; - addressQueryResults = std::deque<HostAddress>(addresses.begin(), addresses.end()); - tryNextAddress(); - } + SWIFT_LOG(debug) << addresses.size() << " addresses"; + addressQuery.reset(); + if (error || addresses.empty()) { + if (!serviceQueryResults.empty()) { + serviceQueryResults.pop_front(); + } + tryNextServiceOrFallback(); + } + else { + foundSomeDNS = true; + addressQueryResults = std::deque<HostAddress>(addresses.begin(), addresses.end()); + tryNextAddress(); + } } void Connector::tryNextAddress() { - if (addressQueryResults.empty()) { - SWIFT_LOG(debug) << "Done trying addresses. Moving on." << std::endl; - // Done trying all addresses. Move on to the next host. - if (!serviceQueryResults.empty()) { - serviceQueryResults.pop_front(); - } - tryNextServiceOrFallback(); - } - else { - SWIFT_LOG(debug) << "Trying next address" << std::endl; - HostAddress address = addressQueryResults.front(); - addressQueryResults.pop_front(); - - int connectPort = (port == -1 ? 5222 : port); - if (!serviceQueryResults.empty()) { - connectPort = serviceQueryResults.front().port; - } - - tryConnect(HostAddressPort(address, connectPort)); - } + if (addressQueryResults.empty()) { + SWIFT_LOG(debug) << "Done trying addresses. Moving on."; + // Done trying all addresses. Move on to the next host. + if (!serviceQueryResults.empty()) { + serviceQueryResults.pop_front(); + } + tryNextServiceOrFallback(); + } + else { + SWIFT_LOG(debug) << "Trying next address"; + HostAddress address = addressQueryResults.front(); + addressQueryResults.pop_front(); + + unsigned short connectPort = (port == 0 ? 5222 : port); + if (!serviceQueryResults.empty()) { + connectPort = serviceQueryResults.front().port; + } + + tryConnect(HostAddressPort(address, connectPort)); + } } void Connector::tryConnect(const HostAddressPort& target) { - assert(!currentConnection); - SWIFT_LOG(debug) << "Trying to connect to " << target.getAddress().toString() << ":" << target.getPort() << std::endl; - currentConnection = connectionFactory->createConnection(); - currentConnection->onConnectFinished.connect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); - currentConnection->connect(target); - if (timer) { - timer->start(); - } + assert(!currentConnection); + SWIFT_LOG(debug) << "Trying to connect to " << target.getAddress().toString() << ":" << target.getPort(); + currentConnection = connectionFactory->createConnection(); + currentConnection->onConnectFinished.connect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); + currentConnection->connect(target); + if (timer) { + timer->start(); + } } void Connector::handleConnectionConnectFinished(bool error) { - SWIFT_LOG(debug) << "ConnectFinished: " << (error ? "error" : "success") << std::endl; - if (timer) { - timer->stop(); - timer.reset(); - } - currentConnection->onConnectFinished.disconnect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); - if (error) { - currentConnection.reset(); - if (!addressQueryResults.empty()) { - tryNextAddress(); - } - else { - if (!serviceQueryResults.empty()) { - serviceQueryResults.pop_front(); - } - tryNextServiceOrFallback(); - } - } - else { - finish(currentConnection); - } + SWIFT_LOG(debug) << "ConnectFinished: " << (error ? "error" : "success"); + if (timer) { + timer->stop(); + timer.reset(); + } + if (!currentConnection) { + // We've hit a race condition where multiple finisheds were on the eventloop queue at once. + // This is particularly likely on macOS where the hourly momentary wakeup while asleep + // can cause both a timeout and an onConnectFinished to be queued sequentially (SWIFT-232). + // Let the first one process as normal, but ignore the second. + return; + } + currentConnection->onConnectFinished.disconnect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); + if (error) { + currentConnection.reset(); + if (!addressQueryResults.empty()) { + tryNextAddress(); + } + else { + if (!serviceQueryResults.empty()) { + serviceQueryResults.pop_front(); + } + tryNextServiceOrFallback(); + } + } + else { + finish(currentConnection); + } } -void Connector::finish(boost::shared_ptr<Connection> connection) { - if (timer) { - timer->stop(); - timer->onTick.disconnect(boost::bind(&Connector::handleTimeout, shared_from_this())); - timer.reset(); - } - if (serviceQuery) { - serviceQuery->onResult.disconnect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1)); - serviceQuery.reset(); - } - if (addressQuery) { - addressQuery->onResult.disconnect(boost::bind(&Connector::handleAddressQueryResult, shared_from_this(), _1, _2)); - addressQuery.reset(); - } - if (currentConnection) { - currentConnection->onConnectFinished.disconnect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); - currentConnection.reset(); - } - onConnectFinished(connection, (connection || foundSomeDNS) ? boost::shared_ptr<Error>() : boost::make_shared<DomainNameResolveError>()); +void Connector::finish(std::shared_ptr<Connection> connection) { + if (timer) { + timer->stop(); + timer->onTick.disconnect(boost::bind(&Connector::handleTimeout, shared_from_this())); + timer.reset(); + } + if (serviceQuery) { + serviceQuery->onResult.disconnect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1)); + serviceQuery.reset(); + } + if (addressQuery) { + addressQuery->onResult.disconnect(boost::bind(&Connector::handleAddressQueryResult, shared_from_this(), _1, _2)); + addressQuery.reset(); + } + if (currentConnection) { + currentConnection->onConnectFinished.disconnect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1)); + currentConnection.reset(); + } + onConnectFinished(connection, (connection || foundSomeDNS) ? std::shared_ptr<Error>() : std::make_shared<DomainNameResolveError>()); } void Connector::handleTimeout() { - SWIFT_LOG(debug) << "Timeout" << std::endl; - handleConnectionConnectFinished(true); + SWIFT_LOG(debug) << "Timeout"; + SWIFT_LOG_ASSERT(currentConnection, error) << "Connection not valid but triggered a timeout"; + handleConnectionConnectFinished(true); } } diff --git a/Swiften/Network/Connector.h b/Swiften/Network/Connector.h index 49ac271..c76a4af 100644 --- a/Swiften/Network/Connector.h +++ b/Swiften/Network/Connector.h @@ -1,74 +1,81 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <deque> -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + +#include <boost/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Network/DomainNameServiceQuery.h> #include <Swiften/Network/Connection.h> -#include <Swiften/Network/Timer.h> -#include <Swiften/Network/HostAddressPort.h> -#include <string> #include <Swiften/Network/DomainNameResolveError.h> +#include <Swiften/Network/DomainNameServiceQuery.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Network/Timer.h> namespace Swift { - class DomainNameAddressQuery; - class DomainNameResolver; - class ConnectionFactory; - class TimerFactory; + class DomainNameAddressQuery; + class DomainNameResolver; + class ConnectionFactory; + class TimerFactory; - class SWIFTEN_API Connector : public boost::bsignals::trackable, public boost::enable_shared_from_this<Connector> { - public: - typedef boost::shared_ptr<Connector> ref; + class SWIFTEN_API Connector : public boost::signals2::trackable, public std::enable_shared_from_this<Connector> { + public: + typedef std::shared_ptr<Connector> ref; - static Connector::ref create(const std::string& hostname, int port, bool doServiceLookups, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) { - return ref(new Connector(hostname, port, doServiceLookups, resolver, connectionFactory, timerFactory)); - } + static Connector::ref create(const std::string& hostname, unsigned short port, const boost::optional<std::string>& serviceLookupPrefix, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) { + return ref(new Connector(hostname, port, serviceLookupPrefix, resolver, connectionFactory, timerFactory)); + } - void setTimeoutMilliseconds(int milliseconds); - void start(); - void stop(); + void setTimeoutMilliseconds(int milliseconds); + /** + * Start the connection attempt. + * Note that after calling this method, the caller is responsible for calling #stop() + * if it wants to cancel it. Not doing so can leak references. + */ + void start(); + void stop(); - boost::signal<void (boost::shared_ptr<Connection>, boost::shared_ptr<Error>)> onConnectFinished; + boost::signals2::signal<void (std::shared_ptr<Connection>, std::shared_ptr<Error>)> onConnectFinished; - private: - Connector(const std::string& hostname, int port, bool doServiceLookups, DomainNameResolver*, ConnectionFactory*, TimerFactory*); + private: + Connector(const std::string& hostname, unsigned short port, const boost::optional<std::string>& serviceLookupPrefix, DomainNameResolver*, ConnectionFactory*, TimerFactory*); - void handleServiceQueryResult(const std::vector<DomainNameServiceQuery::Result>& result); - void handleAddressQueryResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error); - void queryAddress(const std::string& hostname); + void handleServiceQueryResult(const std::vector<DomainNameServiceQuery::Result>& result); + void handleAddressQueryResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error); + void queryAddress(const std::string& hostname); - void tryNextServiceOrFallback(); - void tryNextAddress(); - void tryConnect(const HostAddressPort& target); + void tryNextServiceOrFallback(); + void tryNextAddress(); + void tryConnect(const HostAddressPort& target); - void handleConnectionConnectFinished(bool error); - void finish(boost::shared_ptr<Connection>); - void handleTimeout(); + void handleConnectionConnectFinished(bool error); + void finish(std::shared_ptr<Connection>); + void handleTimeout(); - private: - std::string hostname; - int port; - bool doServiceLookups; - DomainNameResolver* resolver; - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; - int timeoutMilliseconds; - boost::shared_ptr<Timer> timer; - boost::shared_ptr<DomainNameServiceQuery> serviceQuery; - std::deque<DomainNameServiceQuery::Result> serviceQueryResults; - boost::shared_ptr<DomainNameAddressQuery> addressQuery; - std::deque<HostAddress> addressQueryResults; - bool queriedAllServices; - boost::shared_ptr<Connection> currentConnection; - bool foundSomeDNS; - }; + private: + std::string hostname; + unsigned short port; + boost::optional<std::string> serviceLookupPrefix; + DomainNameResolver* resolver; + ConnectionFactory* connectionFactory; + TimerFactory* timerFactory; + int timeoutMilliseconds; + std::shared_ptr<Timer> timer; + std::shared_ptr<DomainNameServiceQuery> serviceQuery; + std::deque<DomainNameServiceQuery::Result> serviceQueryResults; + std::shared_ptr<DomainNameAddressQuery> addressQuery; + std::deque<HostAddress> addressQueryResults; + bool queriedAllServices; + std::shared_ptr<Connection> currentConnection; + bool foundSomeDNS; + }; } diff --git a/Swiften/Network/DomainNameAddressQuery.cpp b/Swiften/Network/DomainNameAddressQuery.cpp index 856f301..33d9e99 100644 --- a/Swiften/Network/DomainNameAddressQuery.cpp +++ b/Swiften/Network/DomainNameAddressQuery.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/DomainNameAddressQuery.h> diff --git a/Swiften/Network/DomainNameAddressQuery.h b/Swiften/Network/DomainNameAddressQuery.h index c8ed981..7f89546 100644 --- a/Swiften/Network/DomainNameAddressQuery.h +++ b/Swiften/Network/DomainNameAddressQuery.h @@ -1,27 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> +#include <memory> + #include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> #include <Swiften/Network/DomainNameResolveError.h> #include <Swiften/Network/HostAddress.h> namespace Swift { - class DomainNameAddressQuery { - public: - typedef boost::shared_ptr<DomainNameAddressQuery> ref; + class DomainNameAddressQuery { + public: + typedef std::shared_ptr<DomainNameAddressQuery> ref; - virtual ~DomainNameAddressQuery(); + virtual ~DomainNameAddressQuery(); - virtual void run() = 0; + virtual void run() = 0; - boost::signal<void (const std::vector<HostAddress>&, boost::optional<DomainNameResolveError>)> onResult; - }; + boost::signals2::signal<void (const std::vector<HostAddress>&, boost::optional<DomainNameResolveError>)> onResult; + }; } diff --git a/Swiften/Network/DomainNameResolveError.h b/Swiften/Network/DomainNameResolveError.h index aa4441d..7a5eed1 100644 --- a/Swiften/Network/DomainNameResolveError.h +++ b/Swiften/Network/DomainNameResolveError.h @@ -1,16 +1,19 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Base/Error.h> namespace Swift { - class DomainNameResolveError : public Error { - public: - DomainNameResolveError() {} - }; + class SWIFTEN_API DomainNameResolveError : public Error { + public: + DomainNameResolveError() {} + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(DomainNameResolveError) + SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(DomainNameResolveError) + }; } diff --git a/Swiften/Network/DomainNameResolver.cpp b/Swiften/Network/DomainNameResolver.cpp index 56a9d72..95c08db 100644 --- a/Swiften/Network/DomainNameResolver.cpp +++ b/Swiften/Network/DomainNameResolver.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/DomainNameResolver.h> diff --git a/Swiften/Network/DomainNameResolver.h b/Swiften/Network/DomainNameResolver.h index 491586a..5fe30d5 100644 --- a/Swiften/Network/DomainNameResolver.h +++ b/Swiften/Network/DomainNameResolver.h @@ -1,26 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> #include <Swiften/Base/API.h> namespace Swift { - class DomainNameServiceQuery; - class DomainNameAddressQuery; - + class DomainNameServiceQuery; + class DomainNameAddressQuery; - class SWIFTEN_API DomainNameResolver { - public: - virtual ~DomainNameResolver(); - virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& name) = 0; - virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name) = 0; - }; + class SWIFTEN_API DomainNameResolver { + public: + virtual ~DomainNameResolver(); + + virtual std::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) = 0; + virtual std::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name) = 0; + }; } diff --git a/Swiften/Network/DomainNameServiceQuery.cpp b/Swiften/Network/DomainNameServiceQuery.cpp index 6ce1d97..5784dd7 100644 --- a/Swiften/Network/DomainNameServiceQuery.cpp +++ b/Swiften/Network/DomainNameServiceQuery.cpp @@ -1,31 +1,28 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/DomainNameServiceQuery.h> -#include <numeric> #include <cassert> #include <functional> #include <iterator> +#include <numeric> -#include <Swiften/Base/RandomGenerator.h> #include <boost/numeric/conversion/cast.hpp> -#include <boost/lambda/lambda.hpp> -#include <boost/lambda/bind.hpp> -#include <boost/typeof/typeof.hpp> + +#include <Swiften/Base/RandomGenerator.h> using namespace Swift; -namespace lambda = boost::lambda; namespace { - struct ResultPriorityComparator { - bool operator()(const DomainNameServiceQuery::Result& a, const DomainNameServiceQuery::Result& b) const { - return a.priority < b.priority; - } - }; + struct ResultPriorityComparator { + bool operator()(const DomainNameServiceQuery::Result& a, const DomainNameServiceQuery::Result& b) const { + return a.priority < b.priority; + } + }; } namespace Swift { @@ -34,31 +31,37 @@ DomainNameServiceQuery::~DomainNameServiceQuery() { } void DomainNameServiceQuery::sortResults(std::vector<DomainNameServiceQuery::Result>& queries, RandomGenerator& generator) { - ResultPriorityComparator comparator; - std::sort(queries.begin(), queries.end(), comparator); + ResultPriorityComparator comparator; + std::stable_sort(queries.begin(), queries.end(), comparator); - std::vector<DomainNameServiceQuery::Result>::iterator i = queries.begin(); - while (i != queries.end()) { - std::vector<DomainNameServiceQuery::Result>::iterator next = std::upper_bound(i, queries.end(), *i, comparator); - if (std::distance(i, next) > 1) { - std::vector<int> weights; - std::transform(i, next, std::back_inserter(weights), - /* easy hack to account for '0' weights getting at least some weight */ - lambda::bind(&Result::weight, lambda::_1) + 1); - for (int j = 0; j < boost::numeric_cast<int>(weights.size() - 1); ++j) { - std::vector<int> cumulativeWeights; - std::partial_sum( - weights.begin() + j, - weights.end(), - std::back_inserter(cumulativeWeights)); - int randomNumber = generator.generateRandomInteger(cumulativeWeights.back()); - BOOST_AUTO(selectedIndex, std::lower_bound(cumulativeWeights.begin(), cumulativeWeights.end(), randomNumber) - cumulativeWeights.begin()); - std::swap(i[j], i[j + selectedIndex]); - std::swap(weights.begin()[j], weights.begin()[j + selectedIndex]); - } - } - i = next; - } + std::vector<DomainNameServiceQuery::Result>::iterator i = queries.begin(); + while (i != queries.end()) { + std::vector<DomainNameServiceQuery::Result>::iterator next = std::upper_bound(i, queries.end(), *i, comparator); + if (std::distance(i, next) > 1) { + std::vector<int> weights; + std::transform(i, next, std::back_inserter(weights), [](const DomainNameServiceQuery::Result& result) { + /* easy hack to account for '0' weights getting at least some weight */ + return result.weight + 1; + }); + try { + for (int j = 0; j < boost::numeric_cast<int>(weights.size()) - 1; ++j) { + std::vector<int> cumulativeWeights; + std::partial_sum( + weights.begin() + j, + weights.end(), + std::back_inserter(cumulativeWeights)); + int randomNumber = generator.generateRandomInteger(cumulativeWeights.back()); + auto selectedIndex = std::lower_bound(cumulativeWeights.begin(), cumulativeWeights.end(), randomNumber) - cumulativeWeights.begin(); + std::swap(i[j], i[j + selectedIndex]); + std::swap(weights.begin()[j], weights.begin()[j + selectedIndex]); + } + } + catch (const boost::numeric::bad_numeric_cast&) { + // In the unlikely event of weights.size() being too large, use the list as-is. + } + } + i = next; + } } diff --git a/Swiften/Network/DomainNameServiceQuery.h b/Swiften/Network/DomainNameServiceQuery.h index fdf5b5d..1631b99 100644 --- a/Swiften/Network/DomainNameServiceQuery.h +++ b/Swiften/Network/DomainNameServiceQuery.h @@ -1,40 +1,41 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/optional.hpp> +#include <memory> +#include <string> #include <vector> -#include <boost/shared_ptr.hpp> -#include <string> +#include <boost/optional.hpp> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> #include <Swiften/Network/DomainNameResolveError.h> namespace Swift { - class RandomGenerator; + class RandomGenerator; - class SWIFTEN_API DomainNameServiceQuery { - public: - typedef boost::shared_ptr<DomainNameServiceQuery> ref; + class SWIFTEN_API DomainNameServiceQuery { + public: + typedef std::shared_ptr<DomainNameServiceQuery> ref; - struct Result { - Result(const std::string& hostname = "", int port = -1, int priority = -1, int weight = -1) : hostname(hostname), port(port), priority(priority), weight(weight) {} - std::string hostname; - int port; - int priority; - int weight; - }; + struct Result { + Result(const std::string& hostname = "", unsigned short port = 0, int priority = -1, int weight = -1) : hostname(hostname), port(port), priority(priority), weight(weight) {} + std::string hostname; + unsigned short port; + int priority; + int weight; + }; - virtual ~DomainNameServiceQuery(); + virtual ~DomainNameServiceQuery(); - virtual void run() = 0; - static void sortResults(std::vector<DomainNameServiceQuery::Result>& queries, RandomGenerator& generator); + virtual void run() = 0; + static void sortResults(std::vector<DomainNameServiceQuery::Result>& queries, RandomGenerator& generator); - boost::signal<void (const std::vector<Result>&)> onResult; - }; + boost::signals2::signal<void (const std::vector<Result>&)> onResult; + }; } diff --git a/Swiften/Network/DummyConnection.cpp b/Swiften/Network/DummyConnection.cpp index 09bd06d..3024b21 100644 --- a/Swiften/Network/DummyConnection.cpp +++ b/Swiften/Network/DummyConnection.cpp @@ -1,14 +1,15 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/DummyConnection.h> -#include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <cassert> +#include <memory> + +#include <boost/bind.hpp> namespace Swift { @@ -16,15 +17,15 @@ DummyConnection::DummyConnection(EventLoop* eventLoop) : eventLoop(eventLoop) { } void DummyConnection::receive(const SafeByteArray& data) { - eventLoop->postEvent(boost::bind(boost::ref(onDataRead), boost::make_shared<SafeByteArray>(data)), shared_from_this()); + eventLoop->postEvent(boost::bind(boost::ref(onDataRead), std::make_shared<SafeByteArray>(data)), shared_from_this()); } void DummyConnection::listen() { - assert(false); + assert(false); } void DummyConnection::connect(const HostAddressPort&) { - assert(false); + assert(false); } diff --git a/Swiften/Network/DummyConnection.h b/Swiften/Network/DummyConnection.h index 36bf897..e58edf6 100644 --- a/Swiften/Network/DummyConnection.h +++ b/Swiften/Network/DummyConnection.h @@ -1,45 +1,50 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/enable_shared_from_this.hpp> +#include <memory> #include <Swiften/Base/API.h> -#include <Swiften/Network/Connection.h> -#include <Swiften/Network/HostAddressPort.h> #include <Swiften/EventLoop/EventLoop.h> #include <Swiften/EventLoop/EventOwner.h> +#include <Swiften/Network/Connection.h> +#include <Swiften/Network/HostAddressPort.h> namespace Swift { - class SWIFTEN_API DummyConnection : public Connection, public EventOwner, public boost::enable_shared_from_this<DummyConnection> { - public: - DummyConnection(EventLoop* eventLoop); + class SWIFTEN_API DummyConnection : public Connection, public EventOwner, public std::enable_shared_from_this<DummyConnection> { + public: + DummyConnection(EventLoop* eventLoop); + + void listen(); + void connect(const HostAddressPort&); - void listen(); - void connect(const HostAddressPort&); + void disconnect() { + //assert(false); + } - void disconnect() { - //assert(false); - } + void write(const SafeByteArray& data) { + eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); + onDataSent(data); + } - void write(const SafeByteArray& data) { - eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); - onDataSent(data); - } + void receive(const SafeByteArray& data); - void receive(const SafeByteArray& data); + HostAddressPort getLocalAddress() const { + return localAddress; + } - HostAddressPort getLocalAddress() const { - return localAddress; - } + HostAddressPort getRemoteAddress() const { + return remoteAddress; + } - boost::signal<void (const SafeByteArray&)> onDataSent; + boost::signals2::signal<void (const SafeByteArray&)> onDataSent; - EventLoop* eventLoop; - HostAddressPort localAddress; - }; + EventLoop* eventLoop; + HostAddressPort localAddress; + HostAddressPort remoteAddress; + }; } diff --git a/Swiften/Network/DummyConnectionFactory.h b/Swiften/Network/DummyConnectionFactory.h index e8a294e..d723283 100644 --- a/Swiften/Network/DummyConnectionFactory.h +++ b/Swiften/Network/DummyConnectionFactory.h @@ -4,9 +4,15 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Network/ConnectionFactory.h> #include <Swiften/Network/DummyConnection.h> @@ -17,13 +23,13 @@ class EventLoop; class DummyConnectionFactory : public ConnectionFactory { public: - DummyConnectionFactory(EventLoop *eventLoop) : eventLoop(eventLoop) {} - virtual ~DummyConnectionFactory() {} - virtual boost::shared_ptr<Connection> createConnection() { - return boost::make_shared<DummyConnection>(eventLoop); - } + DummyConnectionFactory(EventLoop *eventLoop) : eventLoop(eventLoop) {} + virtual ~DummyConnectionFactory() {} + virtual std::shared_ptr<Connection> createConnection() { + return std::make_shared<DummyConnection>(eventLoop); + } private: - EventLoop* eventLoop; + EventLoop* eventLoop; }; } diff --git a/Swiften/Network/DummyConnectionServer.h b/Swiften/Network/DummyConnectionServer.h new file mode 100644 index 0000000..a4fd07f --- /dev/null +++ b/Swiften/Network/DummyConnectionServer.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/EventLoop/EventOwner.h> +#include <Swiften/Network/ConnectionServer.h> +#include <Swiften/Network/HostAddressPort.h> + +namespace Swift { + class SWIFTEN_API DummyConnectionServer : public ConnectionServer, public EventOwner, public std::enable_shared_from_this<DummyConnectionServer> { + public: + DummyConnectionServer(EventLoop* /*eventLoop*/, unsigned short port) : localAddressPort(HostAddress(), port) {} + DummyConnectionServer(EventLoop* /*eventLoop*/, const Swift::HostAddress& hostAddress, unsigned short port) : localAddressPort(hostAddress, port) {} + virtual ~DummyConnectionServer() {} + + virtual HostAddressPort getAddressPort() const { + return localAddressPort; + } + + virtual boost::optional<Error> tryStart() { + return boost::optional<Error>(); + } + + virtual void start() { + + } + + virtual void stop() { + + } + + private: + HostAddressPort localAddressPort; + }; +} diff --git a/Swiften/Network/DummyConnectionServerFactory.h b/Swiften/Network/DummyConnectionServerFactory.h new file mode 100644 index 0000000..4b25118 --- /dev/null +++ b/Swiften/Network/DummyConnectionServerFactory.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Network/ConnectionServerFactory.h> +#include <Swiften/Network/DummyConnectionServer.h> + +namespace Swift { + +class EventLoop; + +class DummyConnectionServerFactory : public ConnectionServerFactory { +public: + DummyConnectionServerFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {} + virtual ~DummyConnectionServerFactory() {} + + virtual std::shared_ptr<ConnectionServer> createConnectionServer(unsigned short port) { + return std::make_shared<DummyConnectionServer>(eventLoop, port); + } + + virtual std::shared_ptr<ConnectionServer> createConnectionServer(const Swift::HostAddress& hostAddress, unsigned short port) { + return std::make_shared<DummyConnectionServer>(eventLoop, hostAddress, port); + } + +private: + EventLoop* eventLoop; +}; + +} diff --git a/Swiften/Network/DummyTimerFactory.cpp b/Swiften/Network/DummyTimerFactory.cpp index 16428b7..0bad7be 100644 --- a/Swiften/Network/DummyTimerFactory.cpp +++ b/Swiften/Network/DummyTimerFactory.cpp @@ -1,60 +1,59 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/DummyTimerFactory.h> #include <algorithm> -#include <Swiften/Base/foreach.h> #include <Swiften/Network/Timer.h> namespace Swift { class DummyTimerFactory::DummyTimer : public Timer { - public: - DummyTimer(int timeout, DummyTimerFactory* factory) : timeout(timeout), factory(factory), isRunning(false), startTime(~0) { - } - - virtual void start() { - isRunning = true; - startTime = factory->currentTime; - } - - virtual void stop() { - isRunning = false; - } - - int getAlarmTime() const { - return startTime + timeout; - } - - int timeout; - DummyTimerFactory* factory; - bool isRunning; - int startTime; + public: + DummyTimer(int timeout, DummyTimerFactory* factory) : timeout(timeout), factory(factory), isRunning(false), startTime(~0) { + } + + virtual void start() { + isRunning = true; + startTime = factory->currentTime; + } + + virtual void stop() { + isRunning = false; + } + + int getAlarmTime() const { + return startTime + timeout; + } + + int timeout; + DummyTimerFactory* factory; + bool isRunning; + int startTime; }; DummyTimerFactory::DummyTimerFactory() : currentTime(0) { } -boost::shared_ptr<Timer> DummyTimerFactory::createTimer(int milliseconds) { - boost::shared_ptr<DummyTimer> timer(new DummyTimer(milliseconds, this)); - timers.push_back(timer); - return timer; +std::shared_ptr<Timer> DummyTimerFactory::createTimer(int milliseconds) { + std::shared_ptr<DummyTimer> timer(new DummyTimer(milliseconds, this)); + timers.push_back(timer); + return timer; } void DummyTimerFactory::setTime(int time) { - assert(time > currentTime); - foreach(boost::shared_ptr<DummyTimer> timer, timers) { - if (timer->getAlarmTime() > currentTime && timer->getAlarmTime() <= time && timer->isRunning) { - timer->onTick(); - } - } - currentTime = time; + assert(time > currentTime); + for (auto&& timer : timers) { + if (timer->getAlarmTime() > currentTime && timer->getAlarmTime() <= time && timer->isRunning) { + timer->onTick(); + } + } + currentTime = time; } } diff --git a/Swiften/Network/DummyTimerFactory.h b/Swiften/Network/DummyTimerFactory.h index 1e9413b..5ccbf93 100644 --- a/Swiften/Network/DummyTimerFactory.h +++ b/Swiften/Network/DummyTimerFactory.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -12,18 +12,18 @@ #include <Swiften/Network/TimerFactory.h> namespace Swift { - class SWIFTEN_API DummyTimerFactory : public TimerFactory { - public: - class DummyTimer; + class SWIFTEN_API DummyTimerFactory : public TimerFactory { + public: + class DummyTimer; - DummyTimerFactory(); + DummyTimerFactory(); - virtual boost::shared_ptr<Timer> createTimer(int milliseconds); - void setTime(int time); + virtual std::shared_ptr<Timer> createTimer(int milliseconds); + void setTime(int time); - private: - friend class DummyTimer; - int currentTime; - std::list<boost::shared_ptr<DummyTimer> > timers; - }; + private: + friend class DummyTimer; + int currentTime; + std::list<std::shared_ptr<DummyTimer> > timers; + }; } diff --git a/Swiften/Network/EnvironmentProxyProvider.cpp b/Swiften/Network/EnvironmentProxyProvider.cpp index 7701da1..6fbf373 100644 --- a/Swiften/Network/EnvironmentProxyProvider.cpp +++ b/Swiften/Network/EnvironmentProxyProvider.cpp @@ -4,45 +4,59 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Network/EnvironmentProxyProvider.h> + #include <stdio.h> #include <stdlib.h> + #include <iostream> +#include <boost/numeric/conversion/cast.hpp> + #include <Swiften/Base/Log.h> -#include <Swiften/Network/EnvironmentProxyProvider.h> namespace Swift { EnvironmentProxyProvider::EnvironmentProxyProvider() { - socksProxy = getFromEnv("all_proxy", "socks"); - httpProxy = getFromEnv("http_proxy", "http"); - SWIFT_LOG(debug) << "Environment: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString() << std::endl; + socksProxy = getFromEnv("all_proxy", "socks"); + httpProxy = getFromEnv("http_proxy", "http"); + SWIFT_LOG(debug) << "Environment: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString(); } HostAddressPort EnvironmentProxyProvider::getHTTPConnectProxy() const { - return httpProxy; + return httpProxy; } HostAddressPort EnvironmentProxyProvider::getSOCKS5Proxy() const { - return socksProxy; + return socksProxy; } HostAddressPort EnvironmentProxyProvider::getFromEnv(const char* envVarName, std::string proxyProtocol) { - char* envVar = NULL; - std::string address; - int port = 0; - - envVar = getenv(envVarName); - - proxyProtocol += "://"; - address = envVar != NULL ? envVar : "0.0.0.0"; - if(envVar != NULL && address.compare(0, proxyProtocol.length(), proxyProtocol) == 0) { - address = address.substr(proxyProtocol.length(), address.length()); - port = atoi(address.substr(address.find(':') + 1, address.length()).c_str()); - address = address.substr(0, address.find(':')); - } - - return HostAddressPort(HostAddress(address), port); + char* envVar = nullptr; + std::string address; + unsigned short port = 0; + + envVar = getenv(envVarName); + + proxyProtocol += "://"; + address = envVar != nullptr ? envVar : "0.0.0.0"; + if(envVar != nullptr && address.compare(0, proxyProtocol.length(), proxyProtocol) == 0) { + address = address.substr(proxyProtocol.length(), address.length()); + try { + port = boost::numeric_cast<unsigned short>(atoi(address.substr(address.find(':') + 1, address.length()).c_str())); + } + catch (boost::numeric::bad_numeric_cast&) { + } + address = address.substr(0, address.find(':')); + } + + return HostAddressPort(HostAddress::fromString(address).get_value_or(HostAddress()), port); } } diff --git a/Swiften/Network/EnvironmentProxyProvider.h b/Swiften/Network/EnvironmentProxyProvider.h index 224d301..59463ff 100644 --- a/Swiften/Network/EnvironmentProxyProvider.h +++ b/Swiften/Network/EnvironmentProxyProvider.h @@ -4,21 +4,28 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Network/ProxyProvider.h> namespace Swift { - class EnvironmentProxyProvider : public ProxyProvider { - public: - EnvironmentProxyProvider(); - virtual HostAddressPort getHTTPConnectProxy() const; - virtual HostAddressPort getSOCKS5Proxy() const; - private: - HostAddressPort getFromEnv(const char* envVarName, std::string proxyProtocol); - HostAddressPort socksProxy; - HostAddressPort httpProxy; - }; + class SWIFTEN_API EnvironmentProxyProvider : public ProxyProvider { + public: + EnvironmentProxyProvider(); + virtual HostAddressPort getHTTPConnectProxy() const; + virtual HostAddressPort getSOCKS5Proxy() const; + private: + HostAddressPort getFromEnv(const char* envVarName, std::string proxyProtocol); + HostAddressPort socksProxy; + HostAddressPort httpProxy; + }; } diff --git a/Swiften/Network/FakeConnection.cpp b/Swiften/Network/FakeConnection.cpp index be5555c..82b792a 100644 --- a/Swiften/Network/FakeConnection.cpp +++ b/Swiften/Network/FakeConnection.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/FakeConnection.h> @@ -17,48 +17,48 @@ FakeConnection::~FakeConnection() { } void FakeConnection::listen() { - assert(false); + assert(false); } void FakeConnection::setError(const Error& e) { - error = boost::optional<Error>(e); - state = DisconnectedWithError; - if (connectedTo) { - eventLoop->postEvent( - boost::bind(boost::ref(onDisconnected), error), - shared_from_this()); - } + error = boost::optional<Error>(e); + state = DisconnectedWithError; + if (connectedTo) { + eventLoop->postEvent( + boost::bind(boost::ref(onDisconnected), error), + shared_from_this()); + } } void FakeConnection::connect(const HostAddressPort& address) { - if (delayConnect) { - state = Connecting; - } - else { - if (!error) { - connectedTo = address; - state = Connected; - } - else { - state = DisconnectedWithError; - } - eventLoop->postEvent( - boost::bind(boost::ref(onConnectFinished), error), - shared_from_this()); - } + if (delayConnect) { + state = Connecting; + } + else { + if (!error) { + connectedTo = address; + state = Connected; + } + else { + state = DisconnectedWithError; + } + eventLoop->postEvent( + boost::bind(boost::ref(onConnectFinished), error ? true : false), + shared_from_this()); + } } void FakeConnection::disconnect() { - if (!error) { - state = Disconnected; - } - else { - state = DisconnectedWithError; - } - connectedTo.reset(); - eventLoop->postEvent( - boost::bind(boost::ref(onDisconnected), error), - shared_from_this()); + if (!error) { + state = Disconnected; + } + else { + state = DisconnectedWithError; + } + connectedTo.reset(); + eventLoop->postEvent( + boost::bind(boost::ref(onDisconnected), error), + shared_from_this()); } } diff --git a/Swiften/Network/FakeConnection.h b/Swiften/Network/FakeConnection.h index eca45da..08c1d75 100644 --- a/Swiften/Network/FakeConnection.h +++ b/Swiften/Network/FakeConnection.h @@ -1,60 +1,64 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/optional.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <memory> #include <vector> +#include <boost/optional.hpp> + #include <Swiften/Base/API.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/EventLoop/EventOwner.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/HostAddressPort.h> -#include <Swiften/EventLoop/EventOwner.h> -#include <Swiften/EventLoop/EventLoop.h> namespace Swift { - class SWIFTEN_API FakeConnection : - public Connection, - public EventOwner, - public boost::enable_shared_from_this<FakeConnection> { - public: - enum State { - Initial, - Connecting, - Connected, - Disconnected, - DisconnectedWithError - }; - - FakeConnection(EventLoop* eventLoop); - ~FakeConnection(); - - virtual void listen(); - virtual HostAddressPort getLocalAddress() const { - return HostAddressPort(); - } - - void setError(const Error& e); - virtual void connect(const HostAddressPort& address); - virtual void disconnect(); - - virtual void write(const SafeByteArray& data) { - dataWritten.push_back(data); - } - - void setDelayConnect() { - delayConnect = true; - } - - EventLoop* eventLoop; - boost::optional<HostAddressPort> connectedTo; - std::vector<SafeByteArray> dataWritten; - boost::optional<Error> error; - State state; - bool delayConnect; - }; + class SWIFTEN_API FakeConnection : + public Connection, + public EventOwner, + public std::enable_shared_from_this<FakeConnection> { + public: + enum State { + Initial, + Connecting, + Connected, + Disconnected, + DisconnectedWithError + }; + + FakeConnection(EventLoop* eventLoop); + virtual ~FakeConnection(); + + virtual void listen(); + virtual HostAddressPort getLocalAddress() const { + return HostAddressPort(); + } + virtual HostAddressPort getRemoteAddress() const { + return HostAddressPort(); + } + + void setError(const Error& e); + virtual void connect(const HostAddressPort& address); + virtual void disconnect(); + + virtual void write(const SafeByteArray& data) { + dataWritten.push_back(data); + } + + void setDelayConnect() { + delayConnect = true; + } + + EventLoop* eventLoop; + boost::optional<HostAddressPort> connectedTo; + std::vector<SafeByteArray> dataWritten; + boost::optional<Error> error; + State state; + bool delayConnect; + }; } diff --git a/Swiften/Network/GConfProxyProvider.cpp b/Swiften/Network/GConfProxyProvider.cpp index 8d97c68..a2f8adc 100644 --- a/Swiften/Network/GConfProxyProvider.cpp +++ b/Swiften/Network/GConfProxyProvider.cpp @@ -4,55 +4,73 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include <stdio.h> -#include <stdlib.h> +/* + * Copyright (c) 2016-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Network/GConfProxyProvider.h> + +#include <cstdio> +#include <cstdlib> + #include <iostream> +extern "C" { #include <gconf/gconf-client.h> +} + +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Network/GConfProxyProvider.h> namespace Swift { GConfProxyProvider::GConfProxyProvider() { - // Ensure static GLib initialization methods are called - static bool glibInitialized = false; - if (!glibInitialized) { - g_type_init(); - glibInitialized = true; - } - - socksProxy = getFromGConf("/system/proxy/socks_host", "/system/proxy/socks_port"); - httpProxy = getFromGConf("/system/http_proxy/host", "/system/http_proxy/port"); - SWIFT_LOG(debug) << "GConf: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString() << std::endl; +#if !GLIB_CHECK_VERSION(2,35,0) + // Ensure static GLib initialization methods are called + static bool glibInitialized = false; + if (!glibInitialized) { + g_type_init(); + glibInitialized = true; + } +#endif + + socksProxy = getFromGConf("/system/proxy/socks_host", "/system/proxy/socks_port"); + httpProxy = getFromGConf("/system/http_proxy/host", "/system/http_proxy/port"); + SWIFT_LOG(debug) << "GConf: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString(); } HostAddressPort GConfProxyProvider::getHTTPConnectProxy() const { - return httpProxy; + return httpProxy; } HostAddressPort GConfProxyProvider::getSOCKS5Proxy() const { - return socksProxy; + return socksProxy; } HostAddressPort GConfProxyProvider::getFromGConf(const char* gcHost, const char* gcPort) { - std::string address; - int port = 0; - gchar* str; + std::string address; + unsigned short port = 0; + gchar* str; - GConfClient* client = gconf_client_get_default(); + GConfClient* client = gconf_client_get_default(); - str = gconf_client_get_string(client, gcHost, NULL); - port = static_cast<int> (gconf_client_get_int(client, gcPort, NULL)); + str = gconf_client_get_string(client, gcHost, NULL); + try { + port = boost::numeric_cast<unsigned short>(gconf_client_get_int(client, gcPort, NULL)); + } + catch (const boost::numeric::bad_numeric_cast&) { + } - if(str) { - address = static_cast<char*> (str); - g_free(str); - } + if(str) { + address = static_cast<char*> (str); + g_free(str); + } - g_object_unref(client); - return HostAddressPort(HostAddress(address), port); + g_object_unref(client); + return HostAddressPort(HostAddress::fromString(address).get_value_or(HostAddress()), port); } } diff --git a/Swiften/Network/GConfProxyProvider.h b/Swiften/Network/GConfProxyProvider.h index 31f38a9..826a67b 100644 --- a/Swiften/Network/GConfProxyProvider.h +++ b/Swiften/Network/GConfProxyProvider.h @@ -9,16 +9,16 @@ #include <Swiften/Network/ProxyProvider.h> namespace Swift { - class GConfProxyProvider : public ProxyProvider { - public: - GConfProxyProvider(); - virtual HostAddressPort getHTTPConnectProxy() const; - virtual HostAddressPort getSOCKS5Proxy() const; - private: - HostAddressPort getFromGConf(const char* gcHost, const char* gcPort); - HostAddressPort socksProxy; - HostAddressPort httpProxy; - }; + class GConfProxyProvider : public ProxyProvider { + public: + GConfProxyProvider(); + virtual HostAddressPort getHTTPConnectProxy() const; + virtual HostAddressPort getSOCKS5Proxy() const; + private: + HostAddressPort getFromGConf(const char* gcHost, const char* gcPort); + HostAddressPort socksProxy; + HostAddressPort httpProxy; + }; } diff --git a/Swiften/Network/HTTPConnectProxiedConnection.cpp b/Swiften/Network/HTTPConnectProxiedConnection.cpp index a88ded1..e63b8e2 100644 --- a/Swiften/Network/HTTPConnectProxiedConnection.cpp +++ b/Swiften/Network/HTTPConnectProxiedConnection.cpp @@ -5,80 +5,158 @@ */ /* - * Copyright (c) 2011-2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/HTTPConnectProxiedConnection.h> #include <iostream> +#include <utility> + +#include <boost/algorithm/string.hpp> #include <boost/bind.hpp> #include <boost/lexical_cast.hpp> #include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Log.h> #include <Swiften/Base/String.h> -#include <Swiften/Base/ByteArray.h> -#include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/HTTPTrafficFilter.h> +#include <Swiften/Network/HostAddressPort.h> #include <Swiften/StringCodecs/Base64.h> using namespace Swift; HTTPConnectProxiedConnection::HTTPConnectProxiedConnection( - DomainNameResolver* resolver, - ConnectionFactory* connectionFactory, - TimerFactory* timerFactory, - const std::string& proxyHost, - int proxyPort, - const SafeString& authID, - const SafeString& authPassword) : - ProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort), - authID_(authID), - authPassword_(authPassword) { + DomainNameResolver* resolver, + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + const std::string& proxyHost, + unsigned short proxyPort, + const SafeString& authID, + const SafeString& authPassword) : + ProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort), + authID_(authID), + authPassword_(authPassword) { +} + +HTTPConnectProxiedConnection::~HTTPConnectProxiedConnection() { + } +void HTTPConnectProxiedConnection::setHTTPTrafficFilter(std::shared_ptr<HTTPTrafficFilter> trafficFilter) { + trafficFilter_ = trafficFilter; +} void HTTPConnectProxiedConnection::initializeProxy() { - std::stringstream connect; - connect << "CONNECT " << getServer().getAddress().toString() << ":" << getServer().getPort() << " HTTP/1.1\r\n"; - SafeByteArray data = createSafeByteArray(connect.str()); - if (!authID_.empty() && !authPassword_.empty()) { - append(data, createSafeByteArray("Proxy-Authorization: Basic ")); - SafeByteArray credentials = authID_; - append(credentials, createSafeByteArray(":")); - append(credentials, authPassword_); - append(data, Base64::encode(credentials)); - append(data, createSafeByteArray("\r\n")); - } - append(data, createSafeByteArray("\r\n")); - SWIFT_LOG(debug) << "HTTP Proxy send headers: " << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl; - write(data); + httpResponseBuffer_.clear(); + + std::stringstream connect; + connect << "CONNECT " << getServer().getAddress().toString() << ":" << getServer().getPort() << " HTTP/1.1\r\n"; + SafeByteArray data = createSafeByteArray(connect.str()); + if (!authID_.empty() && !authPassword_.empty()) { + append(data, createSafeByteArray("Proxy-Authorization: Basic ")); + SafeByteArray credentials = authID_; + append(credentials, createSafeByteArray(":")); + append(credentials, authPassword_); + append(data, Base64::encode(credentials)); + append(data, createSafeByteArray("\r\n")); + } + else if (!nextHTTPRequestHeaders_.empty()) { + for (const auto& headerField : nextHTTPRequestHeaders_) { + append(data, createSafeByteArray(headerField.first)); + append(data, createSafeByteArray(": ")); + append(data, createSafeByteArray(headerField.second)); + append(data, createSafeByteArray("\r\n")); + } + + nextHTTPRequestHeaders_.clear(); + } + append(data, createSafeByteArray("\r\n")); + SWIFT_LOG(debug) << "HTTP Proxy send headers: " << byteArrayToString(ByteArray(data.begin(), data.end())); + write(data); } -void HTTPConnectProxiedConnection::handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data) { - SWIFT_LOG(debug) << byteArrayToString(ByteArray(data->begin(), data->end())) << std::endl; - std::vector<std::string> tmp = String::split(byteArrayToString(ByteArray(data->begin(), data->end())), ' '); - if (tmp.size() > 1) { - try { - int status = boost::lexical_cast<int>(tmp[1]); - SWIFT_LOG(debug) << "Proxy Status: " << status << std::endl; - if (status / 100 == 2) { // all 2XX states are OK - setProxyInitializeFinished(true); - } - else { - SWIFT_LOG(debug) << "HTTP Proxy returned an error: " << byteArrayToString(ByteArray(data->begin(), data->end())) << std::endl; - setProxyInitializeFinished(false); - } - } - catch (boost::bad_lexical_cast&) { - SWIFT_LOG(warning) << "Unexpected response: " << tmp[1] << std::endl; - setProxyInitializeFinished(false); - } - } - else { - setProxyInitializeFinished(false); - } +void HTTPConnectProxiedConnection::parseHTTPHeader(const std::string& data, std::string& statusLine, std::vector<std::pair<std::string, std::string> >& headerFields) { + std::istringstream dataStream(data); + + // parse status line + std::getline(dataStream, statusLine); + + // parse fields + std::string headerLine; + std::string::size_type splitIndex; + while (std::getline(dataStream, headerLine) && headerLine != "\r") { + splitIndex = headerLine.find(':', 0); + if (splitIndex != std::string::npos) { + headerFields.push_back(std::pair<std::string, std::string>(headerLine.substr(0, splitIndex), headerLine.substr(splitIndex + 1))); + } + } +} + +void HTTPConnectProxiedConnection::sendHTTPRequest(const std::string& statusLine, const std::vector<std::pair<std::string, std::string> >& headerFields) { + std::stringstream request; + + request << statusLine << "\r\n"; + for (const auto& field : headerFields) { + request << field.first << ":" << field.second << "\r\n"; + } + request << "\r\n"; + write(createSafeByteArray(request.str())); +} + +void HTTPConnectProxiedConnection::handleProxyInitializeData(std::shared_ptr<SafeByteArray> data) { + std::string dataString = byteArrayToString(ByteArray(data->begin(), data->end())); + SWIFT_LOG(debug) << data; + httpResponseBuffer_.append(dataString); + + std::string statusLine; + std::vector<std::pair<std::string, std::string> > headerFields; + + std::string::size_type headerEnd = httpResponseBuffer_.find("\r\n\r\n", 0); + if (headerEnd == std::string::npos) { + if ((httpResponseBuffer_.size() > 4) && (httpResponseBuffer_.substr(0, 4) != "HTTP")) { + setProxyInitializeFinished(false); + } + return; + } + + parseHTTPHeader(httpResponseBuffer_.substr(0, headerEnd), statusLine, headerFields); + + if (trafficFilter_) { + std::vector<std::pair<std::string, std::string> > newHeaderFields = trafficFilter_->filterHTTPResponseHeader(statusLine, headerFields); + if (!newHeaderFields.empty()) { + std::stringstream statusLine; + reconnect(); + nextHTTPRequestHeaders_ = newHeaderFields; + return; + } + } + + std::vector<std::string> tmp = String::split(statusLine, ' '); + if (tmp.size() > 1) { + try { + int status = boost::lexical_cast<int>(tmp[1]); + SWIFT_LOG(debug) << "Proxy Status: " << status; + if (status / 100 == 2) { // all 2XX states are OK + setProxyInitializeFinished(true); + } + else { + SWIFT_LOG(debug) << "HTTP Proxy returned an error: " << httpResponseBuffer_; + setProxyInitializeFinished(false); + } + } + catch (boost::bad_lexical_cast&) { + SWIFT_LOG(warning) << "Unexpected response: " << tmp[1]; + setProxyInitializeFinished(false); + } + } + else { + setProxyInitializeFinished(false); + } + httpResponseBuffer_.clear(); } diff --git a/Swiften/Network/HTTPConnectProxiedConnection.h b/Swiften/Network/HTTPConnectProxiedConnection.h index c209dc1..a83d47c 100644 --- a/Swiften/Network/HTTPConnectProxiedConnection.h +++ b/Swiften/Network/HTTPConnectProxiedConnection.h @@ -5,39 +5,51 @@ */ /* - * Copyright (c) 2011-2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <Swiften/Base/API.h> #include <Swiften/Network/ProxiedConnection.h> namespace Swift { - class DomainNameResolver; - class ConnectionFactory; - class EventLoop; - class TimerFactory; + class ConnectionFactory; + class DomainNameResolver; + class HTTPTrafficFilter; + class TimerFactory; + + class SWIFTEN_API HTTPConnectProxiedConnection : public ProxiedConnection { + public: + typedef std::shared_ptr<HTTPConnectProxiedConnection> ref; + + virtual ~HTTPConnectProxiedConnection(); + + static ref create(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort, const SafeString& authID, const SafeString& authPassword) { + return ref(new HTTPConnectProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort, authID, authPassword)); + } - class SWIFTEN_API HTTPConnectProxiedConnection : public ProxiedConnection { - public: - typedef boost::shared_ptr<HTTPConnectProxiedConnection> ref; + void setHTTPTrafficFilter(std::shared_ptr<HTTPTrafficFilter> trafficFilter); - static ref create(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword) { - return ref(new HTTPConnectProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort, authID, authPassword)); - } + private: + HTTPConnectProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort, const SafeString& authID, const SafeString& authPassword); - private: - HTTPConnectProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword); + virtual void initializeProxy(); + virtual void handleProxyInitializeData(std::shared_ptr<SafeByteArray> data); - virtual void initializeProxy(); - virtual void handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data); + void sendHTTPRequest(const std::string& statusLine, const std::vector<std::pair<std::string, std::string> >& headerFields); + void parseHTTPHeader(const std::string& data, std::string& statusLine, std::vector<std::pair<std::string, std::string> >& headerFields); - private: - SafeByteArray authID_; - SafeByteArray authPassword_; - }; + private: + SafeByteArray authID_; + SafeByteArray authPassword_; + std::shared_ptr<HTTPTrafficFilter> trafficFilter_; + std::string httpResponseBuffer_; + std::vector<std::pair<std::string, std::string> > nextHTTPRequestHeaders_; + }; } diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp index cf4cef5..54b998a 100644 --- a/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp +++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ /* @@ -16,15 +16,17 @@ namespace Swift { -HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), proxyHost_(proxyHost), proxyPort_(proxyPort), authID_(""), authPassword_("") { +HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort, std::shared_ptr<HTTPTrafficFilter> httpTrafficFilter) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), proxyHost_(proxyHost), proxyPort_(proxyPort), authID_(""), authPassword_(""), httpTrafficFilter_(httpTrafficFilter) { } -HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), proxyHost_(proxyHost), proxyPort_(proxyPort), authID_(authID), authPassword_(authPassword) { +HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort, const SafeString& authID, const SafeString& authPassword, std::shared_ptr<HTTPTrafficFilter> httpTrafficFilter) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), proxyHost_(proxyHost), proxyPort_(proxyPort), authID_(authID), authPassword_(authPassword), httpTrafficFilter_(httpTrafficFilter) { } -boost::shared_ptr<Connection> HTTPConnectProxiedConnectionFactory::createConnection() { - return HTTPConnectProxiedConnection::create(resolver_, connectionFactory_, timerFactory_, proxyHost_, proxyPort_, authID_, authPassword_); +std::shared_ptr<Connection> HTTPConnectProxiedConnectionFactory::createConnection() { + HTTPConnectProxiedConnection::ref proxyConnection = HTTPConnectProxiedConnection::create(resolver_, connectionFactory_, timerFactory_, proxyHost_, proxyPort_, authID_, authPassword_); + proxyConnection->setHTTPTrafficFilter(httpTrafficFilter_); + return proxyConnection; } } diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.h b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h index 3efcecd..7a5f527 100644 --- a/Swiften/Network/HTTPConnectProxiedConnectionFactory.h +++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ /* @@ -12,28 +12,31 @@ #pragma once +#include <Swiften/Base/API.h> +#include <Swiften/Base/SafeString.h> #include <Swiften/Network/ConnectionFactory.h> #include <Swiften/Network/HostAddressPort.h> -#include <Swiften/Base/SafeString.h> namespace Swift { - class DomainNameResolver; - class TimerFactory; - class EventLoop; - class HTTPConnectProxiedConnectionFactory : public ConnectionFactory { - public: - HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort); - HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort, const SafeString& authID, const SafeString& authPassword); + class DomainNameResolver; + class HTTPTrafficFilter; + class TimerFactory; + + class SWIFTEN_API HTTPConnectProxiedConnectionFactory : public ConnectionFactory { + public: + HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort, std::shared_ptr<HTTPTrafficFilter> httpTrafficFilter = std::shared_ptr<HTTPTrafficFilter>()); + HTTPConnectProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort, const SafeString& authID, const SafeString& authPassword, std::shared_ptr<HTTPTrafficFilter> httpTrafficFilter = std::shared_ptr<HTTPTrafficFilter>()); - virtual boost::shared_ptr<Connection> createConnection(); + virtual std::shared_ptr<Connection> createConnection(); - private: - DomainNameResolver* resolver_; - ConnectionFactory* connectionFactory_; - TimerFactory* timerFactory_; - std::string proxyHost_; - int proxyPort_; - SafeString authID_; - SafeString authPassword_; - }; + private: + DomainNameResolver* resolver_; + ConnectionFactory* connectionFactory_; + TimerFactory* timerFactory_; + std::string proxyHost_; + unsigned short proxyPort_; + SafeString authID_; + SafeString authPassword_; + std::shared_ptr<HTTPTrafficFilter> httpTrafficFilter_; + }; } diff --git a/Swiften/Network/HTTPTrafficFilter.cpp b/Swiften/Network/HTTPTrafficFilter.cpp new file mode 100644 index 0000000..d40fbdf --- /dev/null +++ b/Swiften/Network/HTTPTrafficFilter.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Network/HTTPTrafficFilter.h> + +namespace Swift { + +HTTPTrafficFilter::~HTTPTrafficFilter() { + +} + +} diff --git a/Swiften/Network/HTTPTrafficFilter.h b/Swiften/Network/HTTPTrafficFilter.h new file mode 100644 index 0000000..5c29bd6 --- /dev/null +++ b/Swiften/Network/HTTPTrafficFilter.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> +#include <utility> +#include <vector> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> + +namespace Swift { + +class SWIFTEN_API HTTPTrafficFilter { + public: + virtual ~HTTPTrafficFilter(); + /** + * @brief This method is called by the HTTPConnectPRoxiedConnection on every incoming HTTP response. + * It can be used to insert additional HTTP requests into the HTTP CONNECT proxy initalization process. + * @return A vector of HTTP header fields to use in a new request. If an empty vector is returned, + * no new request will be send and the normal proxy logic continues. + */ + virtual std::vector<std::pair<std::string, std::string> > filterHTTPResponseHeader(const std::string& statusLine, const std::vector<std::pair<std::string, std::string> >& /* responseHeader */) = 0; +}; + +} diff --git a/Swiften/Network/HostAddress.cpp b/Swiften/Network/HostAddress.cpp index ff5c1c4..e82f433 100644 --- a/Swiften/Network/HostAddress.cpp +++ b/Swiften/Network/HostAddress.cpp @@ -1,20 +1,17 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/HostAddress.h> -#include <boost/numeric/conversion/cast.hpp> -#include <boost/lexical_cast.hpp> #include <cassert> -#include <stdexcept> -#include <boost/array.hpp> - -#include <Swiften/Base/foreach.h> +#include <cstring> #include <string> +#include <Swiften/Base/Log.h> + static boost::asio::ip::address localhost4 = boost::asio::ip::address(boost::asio::ip::address_v4::loopback()); static boost::asio::ip::address localhost6 = boost::asio::ip::address(boost::asio::ip::address_v6::loopback()); @@ -23,49 +20,55 @@ namespace Swift { HostAddress::HostAddress() { } -HostAddress::HostAddress(const std::string& address) { - try { - address_ = boost::asio::ip::address::from_string(address); - } - catch (const std::exception&) { - } -} - HostAddress::HostAddress(const unsigned char* address, size_t length) { - assert(length == 4 || length == 16); - if (length == 4) { - boost::asio::ip::address_v4::bytes_type data; - for (size_t i = 0; i < length; ++i) { - data[i] = address[i]; - } - address_ = boost::asio::ip::address(boost::asio::ip::address_v4(data)); - } - else { - boost::asio::ip::address_v6::bytes_type data; - for (size_t i = 0; i < length; ++i) { - data[i] = address[i]; - } - address_ = boost::asio::ip::address(boost::asio::ip::address_v6(data)); - } + assert(length == 4 || length == 16); + if (length == 4) { + boost::asio::ip::address_v4::bytes_type data; + std::memcpy(data.data(), address, length); + address_ = boost::asio::ip::address(boost::asio::ip::address_v4(data)); + } + else { + boost::asio::ip::address_v6::bytes_type data; + std::memcpy(data.data(), address, length); + address_ = boost::asio::ip::address(boost::asio::ip::address_v6(data)); + } } HostAddress::HostAddress(const boost::asio::ip::address& address) : address_(address) { } std::string HostAddress::toString() const { - return address_.to_string(); + std::string addressString; + boost::system::error_code errorCode; + + addressString = address_.to_string(errorCode); + if (errorCode) { + SWIFT_LOG(debug) << "error: " << errorCode.message(); + } + + return addressString; } bool HostAddress::isValid() const { - return !(address_.is_v4() && address_.to_v4().to_ulong() == 0); + return !(address_.is_v4() && address_.to_v4().to_ulong() == 0); } boost::asio::ip::address HostAddress::getRawAddress() const { - return address_; + return address_; } bool HostAddress::isLocalhost() const { - return address_ == localhost4 || address_ == localhost6; + return address_ == localhost4 || address_ == localhost6; +} + +boost::optional<HostAddress> HostAddress::fromString(const std::string& addressString) { + boost::optional<HostAddress> hostAddress; + boost::system::error_code errorCode; + boost::asio::ip::address address = boost::asio::ip::address::from_string(addressString, errorCode); + if (!errorCode) { + hostAddress = HostAddress(address); + } + return hostAddress; } } diff --git a/Swiften/Network/HostAddress.h b/Swiften/Network/HostAddress.h index c62239b..7a22cf4 100644 --- a/Swiften/Network/HostAddress.h +++ b/Swiften/Network/HostAddress.h @@ -1,34 +1,42 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ + #pragma once #include <string> + #include <boost/asio/ip/address.hpp> +#include <boost/optional.hpp> #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API HostAddress { - public: - HostAddress(); - HostAddress(const std::string&); - HostAddress(const unsigned char* address, size_t length); - HostAddress(const boost::asio::ip::address& address); - - std::string toString() const; - boost::asio::ip::address getRawAddress() const; - - bool operator==(const HostAddress& o) const { - return address_ == o.address_; - } - - bool isValid() const; - bool isLocalhost() const; - - private: - boost::asio::ip::address address_; - }; + class SWIFTEN_API HostAddress { + public: + HostAddress(); + HostAddress(const unsigned char* address, size_t length); + HostAddress(const boost::asio::ip::address& address); + + std::string toString() const; + boost::asio::ip::address getRawAddress() const; + + bool operator==(const HostAddress& o) const { + return address_ == o.address_; + } + + bool operator<(const HostAddress& o) const { + return address_ < o.address_; + } + + bool isValid() const; + bool isLocalhost() const; + + static boost::optional<HostAddress> fromString(const std::string& addressString); + + private: + boost::asio::ip::address address_; + }; } diff --git a/Swiften/Network/HostAddressPort.cpp b/Swiften/Network/HostAddressPort.cpp index e2e6012..248be2d 100644 --- a/Swiften/Network/HostAddressPort.cpp +++ b/Swiften/Network/HostAddressPort.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/HostAddressPort.h> @@ -10,14 +10,19 @@ using namespace Swift; -HostAddressPort::HostAddressPort(const HostAddress& address, int port) : address_(address), port_(port) { +HostAddressPort::HostAddressPort(const HostAddress& address, unsigned short port) : address_(address), port_(port) { } HostAddressPort::HostAddressPort(const boost::asio::ip::tcp::endpoint& endpoint) { - address_ = HostAddress(endpoint.address()); - port_ = endpoint.port(); + address_ = HostAddress(endpoint.address()); + port_ = endpoint.port(); } std::string HostAddressPort::toString() const { - return getAddress().toString() + ":" + boost::lexical_cast<std::string>(getPort()); + std::string portAsString; + try { + portAsString = std::to_string(getPort()); + } catch (boost::bad_lexical_cast&) { + } + return getAddress().toString() + ":" + portAsString; } diff --git a/Swiften/Network/HostAddressPort.h b/Swiften/Network/HostAddressPort.h index 68f3a1c..759af01 100644 --- a/Swiften/Network/HostAddressPort.h +++ b/Swiften/Network/HostAddressPort.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -12,31 +12,38 @@ #include <Swiften/Network/HostAddress.h> namespace Swift { - class SWIFTEN_API HostAddressPort { - public: - HostAddressPort(const HostAddress& address = HostAddress(), int port = -1); - HostAddressPort(const boost::asio::ip::tcp::endpoint& endpoint); - - const HostAddress& getAddress() const { - return address_; - } - - int getPort() const { - return port_; - } - - bool operator==(const HostAddressPort& o) const { - return address_ == o.address_ && port_ == o.port_; - } - - bool isValid() const { - return address_.isValid() && port_ > 0; - } - - std::string toString() const; - - private: - HostAddress address_; - int port_; - }; + class SWIFTEN_API HostAddressPort { + public: + HostAddressPort(const HostAddress& address = HostAddress(), unsigned short port = 0); + HostAddressPort(const boost::asio::ip::tcp::endpoint& endpoint); + + const HostAddress& getAddress() const { + return address_; + } + + unsigned short getPort() const { + return port_; + } + + bool operator==(const HostAddressPort& o) const { + return address_ == o.address_ && port_ == o.port_; + } + + bool operator<(const HostAddressPort& o) const { + if (address_ < o.address_) { + return true; + } + return address_ == o.address_ && port_ < o.port_; + } + + bool isValid() const { + return address_.isValid() && port_ > 0; + } + + std::string toString() const; + + private: + HostAddress address_; + unsigned short port_; + }; } diff --git a/Swiften/Network/HostNameOrAddress.cpp b/Swiften/Network/HostNameOrAddress.cpp index bc2737d..5c5e5e0 100644 --- a/Swiften/Network/HostNameOrAddress.cpp +++ b/Swiften/Network/HostNameOrAddress.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/HostNameOrAddress.h> @@ -9,21 +9,21 @@ using namespace Swift; namespace { - struct ToStringVisitor : public boost::static_visitor<std::string> { - std::string operator()(const HostAddress& address) const { - return address.toString(); - } - - std::string operator()(const std::string & str) const { - return str; - } - }; + struct ToStringVisitor : public boost::static_visitor<std::string> { + std::string operator()(const HostAddress& address) const { + return address.toString(); + } + + std::string operator()(const std::string & str) const { + return str; + } + }; } namespace Swift { std::string toString(const HostNameOrAddress& address) { - return boost::apply_visitor(ToStringVisitor(), address); + return boost::apply_visitor(ToStringVisitor(), address); } } diff --git a/Swiften/Network/HostNameOrAddress.h b/Swiften/Network/HostNameOrAddress.h index f804d15..81c0995 100644 --- a/Swiften/Network/HostNameOrAddress.h +++ b/Swiften/Network/HostNameOrAddress.h @@ -1,16 +1,18 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> -#include <Swiften/Network/HostAddress.h> + #include <boost/variant.hpp> +#include <Swiften/Network/HostAddress.h> + namespace Swift { - typedef boost::variant<std::string, HostAddress> HostNameOrAddress; + typedef boost::variant<std::string, HostAddress> HostNameOrAddress; - std::string toString(const HostNameOrAddress& address); + std::string toString(const HostNameOrAddress& address); } diff --git a/Swiften/Network/MacOSXProxyProvider.cpp b/Swiften/Network/MacOSXProxyProvider.cpp index 3456c73..d3b10dd 100644 --- a/Swiften/Network/MacOSXProxyProvider.cpp +++ b/Swiften/Network/MacOSXProxyProvider.cpp @@ -5,9 +5,9 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/Platform.h> @@ -16,9 +16,10 @@ #include <stdio.h> #include <stdlib.h> #include <iostream> -#include <boost/numeric/conversion/cast.hpp> #include <utility> +#include <boost/numeric/conversion/cast.hpp> + #ifndef SWIFTEN_PLATFORM_IPHONE #include <SystemConfiguration/SystemConfiguration.h> #endif @@ -29,49 +30,51 @@ using namespace Swift; #ifndef SWIFTEN_PLATFORM_IPHONE static HostAddressPort getFromDictionary(CFDictionaryRef dict, CFStringRef enabledKey, CFStringRef hostKey, CFStringRef portKey) { - CFNumberRef numberValue = NULL; - HostAddressPort ret = HostAddressPort(HostAddress(), 0); - - if(CFDictionaryGetValueIfPresent(dict, reinterpret_cast<const void*> (enabledKey), reinterpret_cast<const void**> (&numberValue)) == true) { - const int i = 0; - CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i); - CFComparisonResult result = CFNumberCompare(numberValue, zero, NULL); - CFRelease(zero); - - if(result != kCFCompareEqualTo) { - int port = 0; - std::string host = ""; - - try { - CFNumberRef numberValue = reinterpret_cast<CFNumberRef> (CFDictionaryGetValue(dict, portKey)); - if(numberValue != NULL) { - CFNumberGetValue(numberValue, kCFNumberIntType, &port); - } - - CFStringRef stringValue = reinterpret_cast<CFStringRef> (CFDictionaryGetValue(dict, hostKey)); - if(stringValue != NULL) { - std::vector<char> buffer; - // length must be +1 for the ending zero; and the Docu of CFStringGetCString tells it like - // if the string is toby the length must be at least 5. - CFIndex length = CFStringGetLength(stringValue) + 1; - buffer.resize(boost::numeric_cast<size_t>(length)); - if(CFStringGetCString(stringValue, &buffer[0], length, kCFStringEncodingMacRoman)) { - for(std::vector<char>::iterator iter = buffer.begin(); iter != buffer.end(); ++iter) { - host += *iter; - } - } - } - } - catch(...) { - std::cerr << "Exception caught ... " << std::endl; - } - - if(host != "" && port != 0) { - ret = HostAddressPort(HostAddress(host), port); - } - } - } - return ret; + CFNumberRef numberValue = nullptr; + HostAddressPort ret = HostAddressPort(HostAddress(), 0); + + if(CFDictionaryGetValueIfPresent(dict, reinterpret_cast<const void*> (enabledKey), reinterpret_cast<const void**> (&numberValue)) == true) { + const int i = 0; + CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i); + CFComparisonResult result = CFNumberCompare(numberValue, zero, nullptr); + CFRelease(zero); + + if(result != kCFCompareEqualTo) { + unsigned short port = 0; + std::string host = ""; + + try { + CFNumberRef numberValue = reinterpret_cast<CFNumberRef> (CFDictionaryGetValue(dict, portKey)); + if(numberValue != nullptr) { + int intPort = 0; + CFNumberGetValue(numberValue, kCFNumberIntType, &intPort); + port = boost::numeric_cast<unsigned short>(intPort); + } + + CFStringRef stringValue = reinterpret_cast<CFStringRef> (CFDictionaryGetValue(dict, hostKey)); + if(stringValue != nullptr) { + std::vector<char> buffer; + // length must be +1 for the ending zero; and the Docu of CFStringGetCString tells it like + // if the string is toby the length must be at least 5. + CFIndex length = CFStringGetLength(stringValue) + 1; + buffer.resize(boost::numeric_cast<size_t>(length)); + if(CFStringGetCString(stringValue, &buffer[0], length, kCFStringEncodingMacRoman)) { + for(char& iter : buffer) { + host += iter; + } + } + } + } + catch(...) { + std::cerr << "Exception caught ... " << std::endl; + } + + if(host != "" && port != 0) { + ret = HostAddressPort(HostAddress::fromString(host).get(), port); + } + } + } + return ret; } #endif namespace Swift { @@ -80,27 +83,27 @@ MacOSXProxyProvider::MacOSXProxyProvider() { } HostAddressPort MacOSXProxyProvider::getHTTPConnectProxy() const { - HostAddressPort result; + HostAddressPort result; #ifndef SWIFTEN_PLATFORM_IPHONE - CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL); - if(proxies != NULL) { - result = getFromDictionary(proxies, kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort); - CFRelease(proxies); - } + CFDictionaryRef proxies = SCDynamicStoreCopyProxies(nullptr); + if(proxies != nullptr) { + result = getFromDictionary(proxies, kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort); + CFRelease(proxies); + } #endif - return result; + return result; } HostAddressPort MacOSXProxyProvider::getSOCKS5Proxy() const { - HostAddressPort result; + HostAddressPort result; #ifndef SWIFTEN_PLATFORM_IPHONE - CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL); - if(proxies != NULL) { - result = getFromDictionary(proxies, kSCPropNetProxiesSOCKSEnable, kSCPropNetProxiesSOCKSProxy, kSCPropNetProxiesSOCKSPort); - CFRelease(proxies); - } + CFDictionaryRef proxies = SCDynamicStoreCopyProxies(nullptr); + if(proxies != nullptr) { + result = getFromDictionary(proxies, kSCPropNetProxiesSOCKSEnable, kSCPropNetProxiesSOCKSProxy, kSCPropNetProxiesSOCKSPort); + CFRelease(proxies); + } #endif - return result; + return result; } } diff --git a/Swiften/Network/MacOSXProxyProvider.h b/Swiften/Network/MacOSXProxyProvider.h index 6666d30..56ffd9f 100644 --- a/Swiften/Network/MacOSXProxyProvider.h +++ b/Swiften/Network/MacOSXProxyProvider.h @@ -4,15 +4,23 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Network/ProxyProvider.h> + #include <CoreFoundation/CoreFoundation.h> +#include <Swiften/Network/ProxyProvider.h> + namespace Swift { - class MacOSXProxyProvider : public ProxyProvider { - public: - MacOSXProxyProvider(); - virtual HostAddressPort getHTTPConnectProxy() const; - virtual HostAddressPort getSOCKS5Proxy() const; - }; + class MacOSXProxyProvider : public ProxyProvider { + public: + MacOSXProxyProvider(); + virtual HostAddressPort getHTTPConnectProxy() const; + virtual HostAddressPort getSOCKS5Proxy() const; + }; } diff --git a/Swiften/Network/MiniUPnPInterface.cpp b/Swiften/Network/MiniUPnPInterface.cpp index bfa989f..8425c77 100644 --- a/Swiften/Network/MiniUPnPInterface.cpp +++ b/Swiften/Network/MiniUPnPInterface.cpp @@ -4,107 +4,117 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Network/MiniUPnPInterface.h> +#include <memory> + #include <miniupnpc.h> #include <upnpcommands.h> #include <upnperrors.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/lexical_cast.hpp> #include <Swiften/Base/Log.h> namespace Swift { struct MiniUPnPInterface::Private { - bool isValid; - std::string localAddress; - UPNPDev* deviceList; - UPNPUrls urls; - IGDdatas data; + bool isValid; + std::string localAddress; + UPNPDev* deviceList; + UPNPUrls urls; + IGDdatas data; }; -MiniUPnPInterface::MiniUPnPInterface() : p(boost::make_shared<Private>()) { - p->isValid = false; - int error = 0; - p->deviceList = upnpDiscover(1500 /* timeout in ms */, 0, 0, 0, 0 /* do IPv6? */, &error); - if (!p->deviceList) { - return; - } - - char lanAddress[64]; - if (!UPNP_GetValidIGD(p->deviceList, &p->urls, &p->data, lanAddress, sizeof(lanAddress))) { - return; - } - p->localAddress = std::string(lanAddress); - p->isValid = true; +MiniUPnPInterface::MiniUPnPInterface() : p(new Private()) { + p->isValid = false; + int error = 0; +#if MINIUPNPC_API_VERSION > 13 + p->deviceList = upnpDiscover(1500 /* timeout in ms */, nullptr, nullptr, 0, 0 /* do IPv6? */, 2 /* default TTL */, &error); +#else + p->deviceList = upnpDiscover(1500 /* timeout in ms */, nullptr, nullptr, 0, 0 /* do IPv6? */, &error); +#endif + if (!p->deviceList) { + return; + } + + char lanAddress[64]; + if (!UPNP_GetValidIGD(p->deviceList, &p->urls, &p->data, lanAddress, sizeof(lanAddress))) { + return; + } + p->localAddress = std::string(lanAddress); + p->isValid = true; } MiniUPnPInterface::~MiniUPnPInterface() { - if (p->isValid) { - FreeUPNPUrls(&p->urls); - } - freeUPNPDevlist(p->deviceList); + if (p->isValid) { + FreeUPNPUrls(&p->urls); + } + freeUPNPDevlist(p->deviceList); } boost::optional<HostAddress> MiniUPnPInterface::getPublicIP() { - if (!p->isValid) { - return boost::optional<HostAddress>(); - } - char externalIPAddress[40]; - int ret = UPNP_GetExternalIPAddress(p->urls.controlURL, p->data.first.servicetype, externalIPAddress); - if (ret != UPNPCOMMAND_SUCCESS) { - return boost::optional<HostAddress>(); - } - else { - return HostAddress(std::string(externalIPAddress)); - } + if (!p->isValid) { + return boost::optional<HostAddress>(); + } + char externalIPAddress[40]; + int ret = UPNP_GetExternalIPAddress(p->urls.controlURL, p->data.first.servicetype, externalIPAddress); + if (ret != UPNPCOMMAND_SUCCESS) { + return boost::optional<HostAddress>(); + } + else { + return HostAddress::fromString(std::string(externalIPAddress)); + } } -boost::optional<NATPortMapping> MiniUPnPInterface::addPortForward(int actualLocalPort, int actualPublicPort) { - if (!p->isValid) { - return boost::optional<NATPortMapping>(); - } - - NATPortMapping mapping(actualLocalPort, actualPublicPort, NATPortMapping::TCP); - - std::string publicPort = boost::lexical_cast<std::string>(mapping.getPublicPort()); - std::string localPort = boost::lexical_cast<std::string>(mapping.getLocalPort()); - std::string leaseSeconds = boost::lexical_cast<std::string>(mapping.getLeaseInSeconds()); - - int ret = UPNP_AddPortMapping( - p->urls.controlURL, - p->data.first.servicetype, - publicPort.c_str(), - localPort.c_str(), - p->localAddress.c_str(), - 0, - mapping.getProtocol() == NATPortMapping::TCP ? "TCP" : "UDP", - 0, - leaseSeconds.c_str()); - if (ret == UPNPCOMMAND_SUCCESS) { - return mapping; - } - else { - return boost::optional<NATPortMapping>(); - } +boost::optional<NATPortMapping> MiniUPnPInterface::addPortForward(unsigned short actualLocalPort, unsigned short actualPublicPort) { + if (!p->isValid) { + return boost::optional<NATPortMapping>(); + } + + NATPortMapping mapping(actualLocalPort, actualPublicPort, NATPortMapping::TCP); + + std::string publicPort = std::to_string(mapping.getPublicPort()); + std::string localPort = std::to_string(mapping.getLocalPort()); + std::string leaseSeconds = std::to_string(mapping.getLeaseInSeconds()); + + int ret = UPNP_AddPortMapping( + p->urls.controlURL, + p->data.first.servicetype, + publicPort.c_str(), + localPort.c_str(), + p->localAddress.c_str(), + "Swift", + mapping.getProtocol() == NATPortMapping::TCP ? "TCP" : "UDP", + nullptr, + leaseSeconds.c_str()); + if (ret == UPNPCOMMAND_SUCCESS) { + return mapping; + } + else { + return boost::optional<NATPortMapping>(); + } } bool MiniUPnPInterface::removePortForward(const NATPortMapping& mapping) { - if (!p->isValid) { - return false; - } + if (!p->isValid) { + return false; + } - std::string publicPort = boost::lexical_cast<std::string>(mapping.getPublicPort()); - std::string localPort = boost::lexical_cast<std::string>(mapping.getLocalPort()); - std::string leaseSeconds = boost::lexical_cast<std::string>(mapping.getLeaseInSeconds()); + std::string publicPort = std::to_string(mapping.getPublicPort()); + std::string localPort = std::to_string(mapping.getLocalPort()); + std::string leaseSeconds = std::to_string(mapping.getLeaseInSeconds()); - int ret = UPNP_DeletePortMapping(p->urls.controlURL, p->data.first.servicetype, publicPort.c_str(), mapping.getProtocol() == NATPortMapping::TCP ? "TCP" : "UDP", 0); - return ret == UPNPCOMMAND_SUCCESS; + int ret = UPNP_DeletePortMapping(p->urls.controlURL, p->data.first.servicetype, publicPort.c_str(), mapping.getProtocol() == NATPortMapping::TCP ? "TCP" : "UDP", nullptr); + return ret == UPNPCOMMAND_SUCCESS; } bool MiniUPnPInterface::isAvailable() { - return p->isValid; + return p->isValid; } } diff --git a/Swiften/Network/MiniUPnPInterface.h b/Swiften/Network/MiniUPnPInterface.h index 61d12ca..8c68268 100644 --- a/Swiften/Network/MiniUPnPInterface.h +++ b/Swiften/Network/MiniUPnPInterface.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2018 Isode Limited. * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ #pragma once -#include <boost/optional.hpp> +#include <memory> + #include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> +#include <boost/optional.hpp> #include <Swiften/Network/NATPortMapping.h> #include <Swiften/Network/NATTraversalInterface.h> namespace Swift { - class MiniUPnPInterface : public NATTraversalInterface, boost::noncopyable { - public: - MiniUPnPInterface(); - ~MiniUPnPInterface(); + class MiniUPnPInterface : public NATTraversalInterface, boost::noncopyable { + public: + MiniUPnPInterface(); + virtual ~MiniUPnPInterface(); - virtual bool isAvailable(); + virtual bool isAvailable(); - boost::optional<HostAddress> getPublicIP(); - boost::optional<NATPortMapping> addPortForward(int localPort, int publicPort); - bool removePortForward(const NATPortMapping&); + boost::optional<HostAddress> getPublicIP(); + boost::optional<NATPortMapping> addPortForward(unsigned short localPort, unsigned short publicPort); + bool removePortForward(const NATPortMapping&); - private: - struct Private; - boost::shared_ptr<Private> p; - }; + private: + struct Private; + const std::unique_ptr<Private> p; + }; } diff --git a/Swiften/Network/NATPMPInterface.cpp b/Swiften/Network/NATPMPInterface.cpp index c7a41ff..e20fecd 100644 --- a/Swiften/Network/NATPMPInterface.cpp +++ b/Swiften/Network/NATPMPInterface.cpp @@ -4,10 +4,15 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Network/NATPMPInterface.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/numeric/conversion/cast.hpp> +#include <memory> #include <Swiften/Base/Log.h> @@ -20,107 +25,117 @@ namespace Swift { struct NATPMPInterface::Private { - natpmp_t natpmp; + natpmp_t natpmp; }; -NATPMPInterface::NATPMPInterface() : p(boost::make_shared<Private>()) { - initnatpmp(&p->natpmp, 0, 0); +NATPMPInterface::NATPMPInterface() : p(new Private()) { + initnatpmp(&p->natpmp, 0, 0); } NATPMPInterface::~NATPMPInterface() { - closenatpmp(&p->natpmp); + closenatpmp(&p->natpmp); } bool NATPMPInterface::isAvailable() { - return getPublicIP(); + return getPublicIP() ? true : false; } boost::optional<HostAddress> NATPMPInterface::getPublicIP() { - if (sendpublicaddressrequest(&p->natpmp) < 0) { - SWIFT_LOG(debug) << "Failed to send NAT-PMP public address request!" << std::endl; - return boost::optional<HostAddress>(); - } - - int r = 0; - natpmpresp_t response; - do { - fd_set fds; - struct timeval timeout; - FD_ZERO(&fds); - FD_SET(p->natpmp.s, &fds); - getnatpmprequesttimeout(&p->natpmp, &timeout); - select(FD_SETSIZE, &fds, NULL, NULL, &timeout); - r = readnatpmpresponseorretry(&p->natpmp, &response); - } while (r == NATPMP_TRYAGAIN); - - if (r == 0) { - return boost::optional<HostAddress>(HostAddress(reinterpret_cast<const unsigned char*>(&(response.pnu.publicaddress.addr)), 4)); - } - else { - SWIFT_LOG(debug) << "Inavlid NAT-PMP response." << std::endl; - return boost::optional<HostAddress>(); - } + if (sendpublicaddressrequest(&p->natpmp) < 0) { + SWIFT_LOG(debug) << "Failed to send NAT-PMP public address request!"; + return boost::optional<HostAddress>(); + } + + int r = 0; + natpmpresp_t response; + do { + fd_set fds; + struct timeval timeout; + FD_ZERO(&fds); + FD_SET(p->natpmp.s, &fds); + getnatpmprequesttimeout(&p->natpmp, &timeout); + + // Limit NAT-PMP timeout to ten seconds. + timeout.tv_sec = 10; + timeout.tv_usec = 0; + + select(FD_SETSIZE, &fds, nullptr, nullptr, &timeout); + r = readnatpmpresponseorretry(&p->natpmp, &response); + } while (false /*r == NATPMP_TRYAGAIN*/); + + if (r == 0) { + return boost::optional<HostAddress>(HostAddress(reinterpret_cast<const unsigned char*>(&(response.pnu.publicaddress.addr)), 4)); + } + else { + SWIFT_LOG(debug) << "Inavlid NAT-PMP response."; + return boost::optional<HostAddress>(); + } } -boost::optional<NATPortMapping> NATPMPInterface::addPortForward(int localPort, int publicPort) { - NATPortMapping mapping(localPort, publicPort, NATPortMapping::TCP); - if (sendnewportmappingrequest( - &p->natpmp, - mapping.getProtocol() == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, - boost::numeric_cast<uint16_t>(mapping.getLocalPort()), - boost::numeric_cast<uint16_t>(mapping.getPublicPort()), - boost::numeric_cast<uint32_t>(mapping.getLeaseInSeconds())) < 0) { - SWIFT_LOG(debug) << "Failed to send NAT-PMP port forwarding request!" << std::endl; - return boost::optional<NATPortMapping>(); - } - - int r = 0; - natpmpresp_t response; - do { - fd_set fds; - struct timeval timeout; - FD_ZERO(&fds); - FD_SET(p->natpmp.s, &fds); - getnatpmprequesttimeout(&p->natpmp, &timeout); - select(FD_SETSIZE, &fds, NULL, NULL, &timeout); - r = readnatpmpresponseorretry(&p->natpmp, &response); - } while(r == NATPMP_TRYAGAIN); - - if (r == 0) { - NATPortMapping result(response.pnu.newportmapping.privateport, response.pnu.newportmapping.mappedpublicport, NATPortMapping::TCP, boost::numeric_cast<int>(response.pnu.newportmapping.lifetime)); - return result; - } - else { - SWIFT_LOG(debug) << "Invalid NAT-PMP response." << std::endl; - return boost::optional<NATPortMapping>(); - } +boost::optional<NATPortMapping> NATPMPInterface::addPortForward(unsigned short localPort, unsigned short publicPort) { + NATPortMapping mapping(localPort, publicPort, NATPortMapping::TCP); + if (sendnewportmappingrequest( + &p->natpmp, + mapping.getProtocol() == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, + mapping.getLocalPort(), + mapping.getPublicPort(), + mapping.getLeaseInSeconds()) < 0) { + SWIFT_LOG(debug) << "Failed to send NAT-PMP port forwarding request!"; + return boost::optional<NATPortMapping>(); + } + + int r = 0; + natpmpresp_t response; + do { + fd_set fds; + struct timeval timeout; + FD_ZERO(&fds); + FD_SET(p->natpmp.s, &fds); + getnatpmprequesttimeout(&p->natpmp, &timeout); + + // Limit NAT-PMP timeout to ten seconds. + timeout.tv_sec = 10; + timeout.tv_usec = 0; + + select(FD_SETSIZE, &fds, nullptr, nullptr, &timeout); + r = readnatpmpresponseorretry(&p->natpmp, &response); + } while(false /*r == NATPMP_TRYAGAIN*/); + + if (r == 0) { + NATPortMapping result(response.pnu.newportmapping.privateport, response.pnu.newportmapping.mappedpublicport, NATPortMapping::TCP, response.pnu.newportmapping.lifetime); + return result; + } + else { + SWIFT_LOG(debug) << "Invalid NAT-PMP response."; + return boost::optional<NATPortMapping>(); + } } bool NATPMPInterface::removePortForward(const NATPortMapping& mapping) { - if (sendnewportmappingrequest(&p->natpmp, mapping.getProtocol() == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, 0, 0, boost::numeric_cast<uint32_t>(mapping.getLocalPort())) < 0) { - SWIFT_LOG(debug) << "Failed to send NAT-PMP remove forwarding request!" << std::endl; - return false; - } - - int r = 0; - natpmpresp_t response; - do { - fd_set fds; - struct timeval timeout; - FD_ZERO(&fds); - FD_SET(p->natpmp.s, &fds); - getnatpmprequesttimeout(&p->natpmp, &timeout); - select(FD_SETSIZE, &fds, NULL, NULL, &timeout); - r = readnatpmpresponseorretry(&p->natpmp, &response); - } while(r == NATPMP_TRYAGAIN); - - if (r == 0) { - return true; - } - else { - SWIFT_LOG(debug) << "Invalid NAT-PMP response." << std::endl; - return false; - } + if (sendnewportmappingrequest(&p->natpmp, mapping.getProtocol() == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, mapping.getLocalPort(), 0, 0) < 0) { + SWIFT_LOG(debug) << "Failed to send NAT-PMP remove forwarding request!"; + return false; + } + + int r = 0; + natpmpresp_t response; + do { + fd_set fds; + struct timeval timeout; + FD_ZERO(&fds); + FD_SET(p->natpmp.s, &fds); + getnatpmprequesttimeout(&p->natpmp, &timeout); + select(FD_SETSIZE, &fds, nullptr, nullptr, &timeout); + r = readnatpmpresponseorretry(&p->natpmp, &response); + } while(r == NATPMP_TRYAGAIN); + + if (r == 0) { + return true; + } + else { + SWIFT_LOG(debug) << "Invalid NAT-PMP response."; + return false; + } } diff --git a/Swiften/Network/NATPMPInterface.h b/Swiften/Network/NATPMPInterface.h index e079a59..58d62b6 100644 --- a/Swiften/Network/NATPMPInterface.h +++ b/Swiften/Network/NATPMPInterface.h @@ -1,31 +1,33 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2018 Isode Limited. * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ #pragma once -#include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/noncopyable.hpp> +#include <boost/optional.hpp> + #include <Swiften/Network/NATPortMapping.h> #include <Swiften/Network/NATTraversalInterface.h> namespace Swift { - class NATPMPInterface : public NATTraversalInterface, boost::noncopyable { - public: - NATPMPInterface(); - ~NATPMPInterface(); + class NATPMPInterface : public NATTraversalInterface, boost::noncopyable { + public: + NATPMPInterface(); + virtual ~NATPMPInterface(); - virtual bool isAvailable(); + virtual bool isAvailable(); - virtual boost::optional<HostAddress> getPublicIP(); - virtual boost::optional<NATPortMapping> addPortForward(int localPort, int publicPort); - virtual bool removePortForward(const NATPortMapping&); + virtual boost::optional<HostAddress> getPublicIP(); + virtual boost::optional<NATPortMapping> addPortForward(unsigned short localPort, unsigned short publicPort); + virtual bool removePortForward(const NATPortMapping&); - private: - struct Private; - boost::shared_ptr<Private> p; - }; + private: + struct Private; + const std::unique_ptr<Private> p; + }; } diff --git a/Swiften/Network/NATPortMapping.h b/Swiften/Network/NATPortMapping.h index 0f6bd95..bf0fb1c 100644 --- a/Swiften/Network/NATPortMapping.h +++ b/Swiften/Network/NATPortMapping.h @@ -4,43 +4,50 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Network/HostAddress.h> namespace Swift { - class NATPortMapping { - public: - enum Protocol { - TCP, - UDP - }; - - NATPortMapping(int localPort, int publicPort, Protocol protocol = TCP, int leaseInSeconds = 60 * 60 * 24) : - publicPort(publicPort), localPort(localPort), protocol(protocol), leaseInSeconds(leaseInSeconds) { - - } - - int getPublicPort() const { - return publicPort; - } - - int getLocalPort() const { - return localPort; - } - - Protocol getProtocol() const { - return protocol; - } - - int getLeaseInSeconds() const { - return leaseInSeconds; - } - - private: - int publicPort; - int localPort; - Protocol protocol; - int leaseInSeconds; - }; + class SWIFTEN_API NATPortMapping { + public: + enum Protocol { + TCP, + UDP + }; + + NATPortMapping(unsigned short localPort, unsigned short publicPort, Protocol protocol = TCP, uint32_t leaseInSeconds = 60 * 60 * 24) : + publicPort(publicPort), localPort(localPort), protocol(protocol), leaseInSeconds(leaseInSeconds) { + + } + + unsigned short getPublicPort() const { + return publicPort; + } + + unsigned short getLocalPort() const { + return localPort; + } + + Protocol getProtocol() const { + return protocol; + } + + uint32_t getLeaseInSeconds() const { + return leaseInSeconds; + } + + private: + unsigned short publicPort; + unsigned short localPort; + Protocol protocol; + uint32_t leaseInSeconds; + }; } diff --git a/Swiften/Network/NATTraversalForwardPortRequest.h b/Swiften/Network/NATTraversalForwardPortRequest.h index 48f85ea..0f9c62c 100644 --- a/Swiften/Network/NATTraversalForwardPortRequest.h +++ b/Swiften/Network/NATTraversalForwardPortRequest.h @@ -4,21 +4,27 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> #include <Swiften/Network/NATPortMapping.h> namespace Swift { - class SWIFTEN_API NATTraversalForwardPortRequest { - public: - virtual ~NATTraversalForwardPortRequest(); + class SWIFTEN_API NATTraversalForwardPortRequest { + public: + virtual ~NATTraversalForwardPortRequest(); - virtual void start() = 0; - virtual void stop() = 0; + virtual void start() = 0; + virtual void stop() = 0; - boost::signal<void (boost::optional<NATPortMapping>)> onResult; - }; + boost::signals2::signal<void (boost::optional<NATPortMapping>)> onResult; + }; } diff --git a/Swiften/Network/NATTraversalGetPublicIPRequest.h b/Swiften/Network/NATTraversalGetPublicIPRequest.h index 1270db3..8b34e0f 100644 --- a/Swiften/Network/NATTraversalGetPublicIPRequest.h +++ b/Swiften/Network/NATTraversalGetPublicIPRequest.h @@ -4,19 +4,27 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Network/HostAddress.h> namespace Swift { - class NATTraversalGetPublicIPRequest { - public: - virtual ~NATTraversalGetPublicIPRequest(); + class SWIFTEN_API NATTraversalGetPublicIPRequest { + public: + virtual ~NATTraversalGetPublicIPRequest(); - virtual void start() = 0; - virtual void stop() = 0; + virtual void start() = 0; + virtual void stop() = 0; - boost::signal<void (boost::optional<HostAddress>)> onResult; - }; + boost::signals2::signal<void (boost::optional<HostAddress>)> onResult; + }; } diff --git a/Swiften/Network/NATTraversalInterface.cpp b/Swiften/Network/NATTraversalInterface.cpp index f8a0cc2..18ee843 100644 --- a/Swiften/Network/NATTraversalInterface.cpp +++ b/Swiften/Network/NATTraversalInterface.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2016 Isode Limited. * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ @@ -8,7 +8,6 @@ #include <Swiften/Base/Log.h> - namespace Swift { NATTraversalInterface::~NATTraversalInterface() { diff --git a/Swiften/Network/NATTraversalInterface.h b/Swiften/Network/NATTraversalInterface.h index c84deba..1655eb6 100644 --- a/Swiften/Network/NATTraversalInterface.h +++ b/Swiften/Network/NATTraversalInterface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2018 Isode Limited. * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ @@ -8,17 +8,18 @@ #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Network/NATPortMapping.h> namespace Swift { - class NATTraversalInterface { - public: - virtual ~NATTraversalInterface(); + class SWIFTEN_API NATTraversalInterface { + public: + virtual ~NATTraversalInterface(); - virtual bool isAvailable() = 0; + virtual bool isAvailable() = 0; - virtual boost::optional<HostAddress> getPublicIP() = 0; - virtual boost::optional<NATPortMapping> addPortForward(int localPort, int publicPort) = 0; - virtual bool removePortForward(const NATPortMapping&) = 0; - }; + virtual boost::optional<HostAddress> getPublicIP() = 0; + virtual boost::optional<NATPortMapping> addPortForward(unsigned short localPort, unsigned short publicPort) = 0; + virtual bool removePortForward(const NATPortMapping&) = 0; + }; } diff --git a/Swiften/Network/NATTraversalRemovePortForwardingRequest.h b/Swiften/Network/NATTraversalRemovePortForwardingRequest.h index 210cbcb..83235f9 100644 --- a/Swiften/Network/NATTraversalRemovePortForwardingRequest.h +++ b/Swiften/Network/NATTraversalRemovePortForwardingRequest.h @@ -4,32 +4,40 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Network/HostAddress.h> namespace Swift { - class NATTraversalRemovePortForwardingRequest { - public: - struct PortMapping { - enum Protocol { - TCP, - UDP - }; - - unsigned int publicPort; - unsigned int localPort; - Protocol protocol; - unsigned long leaseInSeconds; - }; - - public: - virtual ~NATTraversalRemovePortForwardingRequest(); - - virtual void start() = 0; - virtual void stop() = 0; - - boost::signal<void (boost::optional<bool> /* failure */)> onResult; - }; + class SWIFTEN_API NATTraversalRemovePortForwardingRequest { + public: + struct PortMapping { + enum Protocol { + TCP, + UDP + }; + + unsigned short publicPort; + unsigned short localPort; + Protocol protocol; + unsigned long leaseInSeconds; + }; + + public: + virtual ~NATTraversalRemovePortForwardingRequest(); + + virtual void start() = 0; + virtual void stop() = 0; + + boost::signals2::signal<void (boost::optional<bool> /* failure */)> onResult; + }; } diff --git a/Swiften/Network/NATTraverser.cpp b/Swiften/Network/NATTraverser.cpp index 8c628ee..824ae73 100644 --- a/Swiften/Network/NATTraverser.cpp +++ b/Swiften/Network/NATTraverser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/NATTraverser.h> diff --git a/Swiften/Network/NATTraverser.h b/Swiften/Network/NATTraverser.h index e48ce26..7f03c03 100644 --- a/Swiften/Network/NATTraverser.h +++ b/Swiften/Network/NATTraverser.h @@ -1,24 +1,26 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <Swiften/Base/API.h> namespace Swift { - class NATTraversalGetPublicIPRequest; - class NATTraversalForwardPortRequest; - class NATTraversalRemovePortForwardingRequest; + class NATTraversalGetPublicIPRequest; + class NATTraversalForwardPortRequest; + class NATTraversalRemovePortForwardingRequest; - class NATTraverser { - public: - virtual ~NATTraverser(); + class SWIFTEN_API NATTraverser { + public: + virtual ~NATTraverser(); - virtual boost::shared_ptr<NATTraversalGetPublicIPRequest> createGetPublicIPRequest() = 0; - virtual boost::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(int localPort, int publicPort) = 0; - virtual boost::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(int localPort, int publicPort) = 0; - }; + virtual std::shared_ptr<NATTraversalGetPublicIPRequest> createGetPublicIPRequest() = 0; + virtual std::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(unsigned short localPort, unsigned short publicPort) = 0; + virtual std::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(unsigned short localPort, unsigned short publicPort) = 0; + }; } diff --git a/Swiften/Network/NetworkEnvironment.cpp b/Swiften/Network/NetworkEnvironment.cpp index 52ceb01..87883c1 100644 --- a/Swiften/Network/NetworkEnvironment.cpp +++ b/Swiften/Network/NetworkEnvironment.cpp @@ -1,14 +1,13 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/NetworkEnvironment.h> -#include <Swiften/Network/NetworkInterface.h> #include <Swiften/Network/HostAddress.h> -#include <Swiften/Base/foreach.h> +#include <Swiften/Network/NetworkInterface.h> namespace Swift { @@ -16,17 +15,17 @@ NetworkEnvironment::~NetworkEnvironment() { } HostAddress NetworkEnvironment::getLocalAddress() const { - std::vector<NetworkInterface> networkInterfaces = getNetworkInterfaces(); - foreach (const NetworkInterface& iface, networkInterfaces) { - if (!iface.isLoopback()) { - foreach (const HostAddress& address, iface.getAddresses()) { - if (address.getRawAddress().is_v4()) { - return address; - } - } - } - } - return HostAddress(); + std::vector<NetworkInterface> networkInterfaces = getNetworkInterfaces(); + for (const auto& iface : networkInterfaces) { + if (!iface.isLoopback()) { + for (const auto& address : iface.getAddresses()) { + if (address.getRawAddress().is_v4()) { + return address; + } + } + } + } + return HostAddress(); } } diff --git a/Swiften/Network/NetworkEnvironment.h b/Swiften/Network/NetworkEnvironment.h index 36a2bde..0f68c29 100644 --- a/Swiften/Network/NetworkEnvironment.h +++ b/Swiften/Network/NetworkEnvironment.h @@ -4,21 +4,28 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <vector> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Network/NetworkInterface.h> namespace Swift { - class SWIFTEN_API NetworkEnvironment { - public: - virtual ~NetworkEnvironment(); + class SWIFTEN_API NetworkEnvironment { + public: + virtual ~NetworkEnvironment(); - virtual std::vector<NetworkInterface> getNetworkInterfaces() const = 0; + virtual std::vector<NetworkInterface> getNetworkInterfaces() const = 0; - HostAddress getLocalAddress() const; - }; + HostAddress getLocalAddress() const; + }; } diff --git a/Swiften/Network/NetworkFactories.cpp b/Swiften/Network/NetworkFactories.cpp index 7046fd3..0380c90 100644 --- a/Swiften/Network/NetworkFactories.cpp +++ b/Swiften/Network/NetworkFactories.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/NetworkFactories.h> diff --git a/Swiften/Network/NetworkFactories.h b/Swiften/Network/NetworkFactories.h index dd8e216..f31c448 100644 --- a/Swiften/Network/NetworkFactories.h +++ b/Swiften/Network/NetworkFactories.h @@ -1,44 +1,45 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> + namespace Swift { - class TimerFactory; - class ConnectionFactory; - class DomainNameResolver; - class ConnectionServerFactory; - class NATTraverser; - class XMLParserFactory; - class TLSContextFactory; - class CertificateFactory; - class ProxyProvider; - class EventLoop; - class IDNConverter; - class NetworkEnvironment; - class CryptoProvider; + class ConnectionFactory; + class ConnectionServerFactory; + class CryptoProvider; + class DomainNameResolver; + class EventLoop; + class IDNConverter; + class NATTraverser; + class NetworkEnvironment; + class ProxyProvider; + class TLSContextFactory; + class TimerFactory; + class XMLParserFactory; - /** - * An interface collecting network factories. - */ - class NetworkFactories { - public: - virtual ~NetworkFactories(); + /** + * An interface collecting network factories. + */ + class SWIFTEN_API NetworkFactories { + public: + virtual ~NetworkFactories(); - virtual TimerFactory* getTimerFactory() const = 0; - virtual ConnectionFactory* getConnectionFactory() const = 0; - virtual DomainNameResolver* getDomainNameResolver() const = 0; - virtual ConnectionServerFactory* getConnectionServerFactory() const = 0; - virtual NATTraverser* getNATTraverser() const = 0; - virtual NetworkEnvironment* getNetworkEnvironment() const = 0; - virtual XMLParserFactory* getXMLParserFactory() const = 0; - virtual TLSContextFactory* getTLSContextFactory() const = 0; - virtual ProxyProvider* getProxyProvider() const = 0; - virtual EventLoop* getEventLoop() const = 0; - virtual IDNConverter* getIDNConverter() const = 0; - virtual CryptoProvider* getCryptoProvider() const = 0; - }; + virtual TimerFactory* getTimerFactory() const = 0; + virtual ConnectionFactory* getConnectionFactory() const = 0; + virtual DomainNameResolver* getDomainNameResolver() const = 0; + virtual ConnectionServerFactory* getConnectionServerFactory() const = 0; + virtual NATTraverser* getNATTraverser() const = 0; + virtual NetworkEnvironment* getNetworkEnvironment() const = 0; + virtual XMLParserFactory* getXMLParserFactory() const = 0; + virtual TLSContextFactory* getTLSContextFactory() const = 0; + virtual ProxyProvider* getProxyProvider() const = 0; + virtual EventLoop* getEventLoop() const = 0; + virtual IDNConverter* getIDNConverter() const = 0; + virtual CryptoProvider* getCryptoProvider() const = 0; + }; } diff --git a/Swiften/Network/NetworkInterface.h b/Swiften/Network/NetworkInterface.h index 1d302cb..91aefc4 100644 --- a/Swiften/Network/NetworkInterface.h +++ b/Swiften/Network/NetworkInterface.h @@ -4,37 +4,44 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <vector> +#include <Swiften/Base/API.h> #include <Swiften/Network/HostAddress.h> namespace Swift { - class NetworkInterface { - public: - NetworkInterface(const std::string& name, bool loopback) : name(name), loopback(loopback) { - } - - void addAddress(const HostAddress& address) { - addresses.push_back(address); - } - - const std::vector<HostAddress>& getAddresses() const { - return addresses; - } - - const std::string& getName() const { - return name; - } - - bool isLoopback() const { - return loopback; - } - - private: - std::string name; - bool loopback; - std::vector<HostAddress> addresses; - }; + class SWIFTEN_API NetworkInterface { + public: + NetworkInterface(const std::string& name, bool loopback) : name(name), loopback(loopback) { + } + + void addAddress(const HostAddress& address) { + addresses.push_back(address); + } + + const std::vector<HostAddress>& getAddresses() const { + return addresses; + } + + const std::string& getName() const { + return name; + } + + bool isLoopback() const { + return loopback; + } + + private: + std::string name; + bool loopback; + std::vector<HostAddress> addresses; + }; } diff --git a/Swiften/Network/NullNATTraversalInterface.h b/Swiften/Network/NullNATTraversalInterface.h index 72a4a08..eabc197 100644 --- a/Swiften/Network/NullNATTraversalInterface.h +++ b/Swiften/Network/NullNATTraversalInterface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011 Isode Limited. * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ @@ -11,22 +11,22 @@ #include <Swiften/Network/NATTraversalInterface.h> namespace Swift { - class NullNATTraversalInterface : public NATTraversalInterface { - public: - virtual bool isAvailable() { - return true; - } + class NullNATTraversalInterface : public NATTraversalInterface { + public: + virtual bool isAvailable() { + return true; + } - virtual boost::optional<HostAddress> getPublicIP() { - return boost::optional<HostAddress>(); - } + virtual boost::optional<HostAddress> getPublicIP() { + return boost::optional<HostAddress>(); + } - virtual boost::optional<NATPortMapping> addPortForward(int, int) { - return boost::optional<NATPortMapping>(); - } + virtual boost::optional<NATPortMapping> addPortForward(unsigned short, unsigned short) { + return boost::optional<NATPortMapping>(); + } - virtual bool removePortForward(const NATPortMapping&) { - return false; - } - }; + virtual bool removePortForward(const NATPortMapping&) { + return false; + } + }; } diff --git a/Swiften/Network/NullNATTraverser.cpp b/Swiften/Network/NullNATTraverser.cpp index 43fcd08..0b9464e 100644 --- a/Swiften/Network/NullNATTraverser.cpp +++ b/Swiften/Network/NullNATTraverser.cpp @@ -1,82 +1,83 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/NullNATTraverser.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/bind.hpp> -#include <Swiften/Network/NATTraversalGetPublicIPRequest.h> +#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/Network/NATTraversalForwardPortRequest.h> +#include <Swiften/Network/NATTraversalGetPublicIPRequest.h> #include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h> -#include <Swiften/EventLoop/EventLoop.h> namespace Swift { class NullNATTraversalGetPublicIPRequest : public NATTraversalGetPublicIPRequest { - public: - NullNATTraversalGetPublicIPRequest(EventLoop* eventLoop) : eventLoop(eventLoop) { - } + public: + NullNATTraversalGetPublicIPRequest(EventLoop* eventLoop) : eventLoop(eventLoop) { + } - virtual void start() { - eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<HostAddress>())); - } + virtual void start() { + eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<HostAddress>())); + } - virtual void stop() { - } + virtual void stop() { + } - private: - EventLoop* eventLoop; + private: + EventLoop* eventLoop; }; class NullNATTraversalForwardPortRequest : public NATTraversalForwardPortRequest { - public: - NullNATTraversalForwardPortRequest(EventLoop* eventLoop) : eventLoop(eventLoop) { - } + public: + NullNATTraversalForwardPortRequest(EventLoop* eventLoop) : eventLoop(eventLoop) { + } - virtual void start() { - eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<NATPortMapping>())); - } + virtual void start() { + eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<NATPortMapping>())); + } - virtual void stop() { - } + virtual void stop() { + } - private: - EventLoop* eventLoop; + private: + EventLoop* eventLoop; }; class NullNATTraversalRemovePortForwardingRequest : public NATTraversalRemovePortForwardingRequest { - public: - NullNATTraversalRemovePortForwardingRequest(EventLoop* eventLoop) : eventLoop(eventLoop) { - } + public: + NullNATTraversalRemovePortForwardingRequest(EventLoop* eventLoop) : eventLoop(eventLoop) { + } - virtual void start() { - eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<bool>(true))); - } + virtual void start() { + eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<bool>(true))); + } - virtual void stop() { - } + virtual void stop() { + } - private: - EventLoop* eventLoop; + private: + EventLoop* eventLoop; }; NullNATTraverser::NullNATTraverser(EventLoop* eventLoop) : eventLoop(eventLoop) { } -boost::shared_ptr<NATTraversalGetPublicIPRequest> NullNATTraverser::createGetPublicIPRequest() { - return boost::make_shared<NullNATTraversalGetPublicIPRequest>(eventLoop); +std::shared_ptr<NATTraversalGetPublicIPRequest> NullNATTraverser::createGetPublicIPRequest() { + return std::make_shared<NullNATTraversalGetPublicIPRequest>(eventLoop); } -boost::shared_ptr<NATTraversalForwardPortRequest> NullNATTraverser::createForwardPortRequest(int, int) { - return boost::make_shared<NullNATTraversalForwardPortRequest>(eventLoop); +std::shared_ptr<NATTraversalForwardPortRequest> NullNATTraverser::createForwardPortRequest(unsigned short, unsigned short) { + return std::make_shared<NullNATTraversalForwardPortRequest>(eventLoop); } -boost::shared_ptr<NATTraversalRemovePortForwardingRequest> NullNATTraverser::createRemovePortForwardingRequest(int, int) { - return boost::make_shared<NullNATTraversalRemovePortForwardingRequest>(eventLoop); +std::shared_ptr<NATTraversalRemovePortForwardingRequest> NullNATTraverser::createRemovePortForwardingRequest(unsigned short, unsigned short) { + return std::make_shared<NullNATTraversalRemovePortForwardingRequest>(eventLoop); } } diff --git a/Swiften/Network/NullNATTraverser.h b/Swiften/Network/NullNATTraverser.h index 5775a9b..2f975bf 100644 --- a/Swiften/Network/NullNATTraverser.h +++ b/Swiften/Network/NullNATTraverser.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,17 +9,17 @@ #include <Swiften/Network/NATTraverser.h> namespace Swift { - class EventLoop; + class EventLoop; - class NullNATTraverser : public NATTraverser { - public: - NullNATTraverser(EventLoop* eventLoop); + class NullNATTraverser : public NATTraverser { + public: + NullNATTraverser(EventLoop* eventLoop); - boost::shared_ptr<NATTraversalGetPublicIPRequest> createGetPublicIPRequest(); - boost::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(int localPort, int publicPort); - boost::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(int localPort, int publicPort); + std::shared_ptr<NATTraversalGetPublicIPRequest> createGetPublicIPRequest(); + std::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(unsigned short localPort, unsigned short publicPort); + std::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(unsigned short localPort, unsigned short publicPort); - private: - EventLoop* eventLoop; - }; + private: + EventLoop* eventLoop; + }; } diff --git a/Swiften/Network/NullProxyProvider.cpp b/Swiften/Network/NullProxyProvider.cpp index 3b9d94d..32a1b9d 100644 --- a/Swiften/Network/NullProxyProvider.cpp +++ b/Swiften/Network/NullProxyProvider.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011 Isode Limited. * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ @@ -12,9 +12,9 @@ NullProxyProvider::NullProxyProvider() { } HostAddressPort NullProxyProvider::getHTTPConnectProxy() const { - return HostAddressPort(); + return HostAddressPort(); } HostAddressPort NullProxyProvider::getSOCKS5Proxy() const { - return HostAddressPort(); + return HostAddressPort(); } diff --git a/Swiften/Network/NullProxyProvider.h b/Swiften/Network/NullProxyProvider.h index 544bea2..ae7aaab 100644 --- a/Swiften/Network/NullProxyProvider.h +++ b/Swiften/Network/NullProxyProvider.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011 Isode Limited. * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ @@ -9,11 +9,11 @@ #include <Swiften/Network/ProxyProvider.h> namespace Swift { - class NullProxyProvider : public ProxyProvider { - public: - NullProxyProvider(); + class NullProxyProvider : public ProxyProvider { + public: + NullProxyProvider(); - virtual HostAddressPort getHTTPConnectProxy() const; - virtual HostAddressPort getSOCKS5Proxy() const; - }; + virtual HostAddressPort getHTTPConnectProxy() const; + virtual HostAddressPort getSOCKS5Proxy() const; + }; } diff --git a/Swiften/Network/PlatformDomainNameAddressQuery.cpp b/Swiften/Network/PlatformDomainNameAddressQuery.cpp index ec7e663..2d72146 100644 --- a/Swiften/Network/PlatformDomainNameAddressQuery.cpp +++ b/Swiften/Network/PlatformDomainNameAddressQuery.cpp @@ -1,58 +1,70 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/PlatformDomainNameAddressQuery.h> #include <boost/asio/ip/tcp.hpp> -#include <Swiften/Network/PlatformDomainNameResolver.h> #include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/Network/PlatformDomainNameResolver.h> namespace Swift { -PlatformDomainNameAddressQuery::PlatformDomainNameAddressQuery(const std::string& host, EventLoop* eventLoop, PlatformDomainNameResolver* resolver) : PlatformDomainNameQuery(resolver), hostname(host), eventLoop(eventLoop) { +PlatformDomainNameAddressQuery::PlatformDomainNameAddressQuery(const boost::optional<std::string>& host, EventLoop* eventLoop, PlatformDomainNameResolver* resolver) : PlatformDomainNameQuery(resolver), hostnameValid(false), eventLoop(eventLoop) { + if (!!host) { + hostname = *host; + hostnameValid = true; + } +} + +PlatformDomainNameAddressQuery::~PlatformDomainNameAddressQuery() { + } void PlatformDomainNameAddressQuery::run() { - getResolver()->addQueryToQueue(shared_from_this()); + getResolver()->addQueryToQueue(shared_from_this()); } void PlatformDomainNameAddressQuery::runBlocking() { - //std::cout << "PlatformDomainNameResolver::doRun()" << std::endl; - boost::asio::ip::tcp::resolver resolver(ioService); - boost::asio::ip::tcp::resolver::query query(hostname, "5222"); - try { - //std::cout << "PlatformDomainNameResolver::doRun(): Resolving" << std::endl; - boost::asio::ip::tcp::resolver::iterator endpointIterator = resolver.resolve(query); - //std::cout << "PlatformDomainNameResolver::doRun(): Resolved" << std::endl; - if (endpointIterator == boost::asio::ip::tcp::resolver::iterator()) { - //std::cout << "PlatformDomainNameResolver::doRun(): Error 1" << std::endl; - emitError(); - } - else { - std::vector<HostAddress> results; - for ( ; endpointIterator != boost::asio::ip::tcp::resolver::iterator(); ++endpointIterator) { - boost::asio::ip::address address = (*endpointIterator).endpoint().address(); - results.push_back(address.is_v4() ? HostAddress(&address.to_v4().to_bytes()[0], 4) : HostAddress(&address.to_v6().to_bytes()[0], 16)); - } - - //std::cout << "PlatformDomainNameResolver::doRun(): Success" << std::endl; - eventLoop->postEvent( - boost::bind(boost::ref(onResult), results, boost::optional<DomainNameResolveError>()), - shared_from_this()); - } - } - catch (...) { - //std::cout << "PlatformDomainNameResolver::doRun(): Error 2" << std::endl; - emitError(); - } + if (!hostnameValid) { + emitError(); + return; + } + //std::cout << "PlatformDomainNameResolver::doRun()" << std::endl; + boost::asio::ip::tcp::resolver resolver(ioService); + boost::asio::ip::tcp::resolver::query query(hostname, "5222", boost::asio::ip::resolver_query_base::passive); + try { + //std::cout << "PlatformDomainNameResolver::doRun(): Resolving" << std::endl; + boost::asio::ip::tcp::resolver::iterator endpointIterator = resolver.resolve(query); + //std::cout << "PlatformDomainNameResolver::doRun(): Resolved" << std::endl; + if (endpointIterator == boost::asio::ip::tcp::resolver::iterator()) { + //std::cout << "PlatformDomainNameResolver::doRun(): Error 1" << std::endl; + emitError(); + } + else { + std::vector<HostAddress> results; + for ( ; endpointIterator != boost::asio::ip::tcp::resolver::iterator(); ++endpointIterator) { + boost::asio::ip::address address = (*endpointIterator).endpoint().address(); + results.push_back(address.is_v4() ? HostAddress(&address.to_v4().to_bytes()[0], 4) : HostAddress(&address.to_v6().to_bytes()[0], 16)); + } + + //std::cout << "PlatformDomainNameResolver::doRun(): Success" << std::endl; + eventLoop->postEvent( + boost::bind(boost::ref(onResult), results, boost::optional<DomainNameResolveError>()), + shared_from_this()); + } + } + catch (...) { + //std::cout << "PlatformDomainNameResolver::doRun(): Error 2" << std::endl; + emitError(); + } } void PlatformDomainNameAddressQuery::emitError() { - eventLoop->postEvent(boost::bind(boost::ref(onResult), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), shared_from_this()); + eventLoop->postEvent(boost::bind(boost::ref(onResult), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), shared_from_this()); } } diff --git a/Swiften/Network/PlatformDomainNameAddressQuery.h b/Swiften/Network/PlatformDomainNameAddressQuery.h index e1dc05f..6cb3e0a 100644 --- a/Swiften/Network/PlatformDomainNameAddressQuery.h +++ b/Swiften/Network/PlatformDomainNameAddressQuery.h @@ -1,38 +1,41 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> +#include <string> + #include <boost/asio/io_service.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <Swiften/EventLoop/EventOwner.h> #include <Swiften/Network/DomainNameAddressQuery.h> #include <Swiften/Network/PlatformDomainNameQuery.h> -#include <Swiften/EventLoop/EventOwner.h> -#include <string> namespace Swift { - class PlatformDomainNameResolver; - class EventLoop; - - class PlatformDomainNameAddressQuery : public DomainNameAddressQuery, public PlatformDomainNameQuery, public boost::enable_shared_from_this<PlatformDomainNameAddressQuery>, public EventOwner { - public: - PlatformDomainNameAddressQuery(const std::string& host, EventLoop* eventLoop, PlatformDomainNameResolver*); - - void run(); - - private: - void runBlocking(); - void emitError(); - - private: - boost::asio::io_service ioService; - std::string hostname; - EventLoop* eventLoop; - }; + class PlatformDomainNameResolver; + class EventLoop; + + class PlatformDomainNameAddressQuery : public DomainNameAddressQuery, public PlatformDomainNameQuery, public std::enable_shared_from_this<PlatformDomainNameAddressQuery>, public EventOwner { + public: + PlatformDomainNameAddressQuery(const boost::optional<std::string>& host, EventLoop* eventLoop, PlatformDomainNameResolver*); + virtual ~PlatformDomainNameAddressQuery(); + + void run(); + + private: + void runBlocking(); + void emitError(); + + private: + boost::asio::io_service ioService; + std::string hostname; + bool hostnameValid; + EventLoop* eventLoop; + }; } diff --git a/Swiften/Network/PlatformDomainNameQuery.h b/Swiften/Network/PlatformDomainNameQuery.h index bbfb1d1..a279f20 100644 --- a/Swiften/Network/PlatformDomainNameQuery.h +++ b/Swiften/Network/PlatformDomainNameQuery.h @@ -1,31 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> namespace Swift { - class PlatformDomainNameResolver; + class PlatformDomainNameResolver; - class PlatformDomainNameQuery { - public: - typedef boost::shared_ptr<PlatformDomainNameQuery> ref; + class PlatformDomainNameQuery { + public: + typedef std::shared_ptr<PlatformDomainNameQuery> ref; - PlatformDomainNameQuery(PlatformDomainNameResolver* resolver) : resolver(resolver) {} - virtual ~PlatformDomainNameQuery() {} + PlatformDomainNameQuery(PlatformDomainNameResolver* resolver) : resolver(resolver) {} + virtual ~PlatformDomainNameQuery() {} - virtual void runBlocking() = 0; + virtual void runBlocking() = 0; - protected: - PlatformDomainNameResolver* getResolver() { - return resolver; - } + protected: + PlatformDomainNameResolver* getResolver() { + return resolver; + } - private: - PlatformDomainNameResolver* resolver; - }; + private: + PlatformDomainNameResolver* resolver; + }; } diff --git a/Swiften/Network/PlatformDomainNameResolver.cpp b/Swiften/Network/PlatformDomainNameResolver.cpp index 677f1d5..40e385d 100644 --- a/Swiften/Network/PlatformDomainNameResolver.cpp +++ b/Swiften/Network/PlatformDomainNameResolver.cpp @@ -1,76 +1,80 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/PlatformDomainNameResolver.h> -// Putting this early on, because some system types conflict with thread -#include <Swiften/Network/PlatformDomainNameServiceQuery.h> - +#include <algorithm> +#include <mutex> #include <string> +#include <thread> #include <vector> + #include <boost/bind.hpp> -#include <boost/thread.hpp> -#include <algorithm> -#include <string> +#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/IDN/IDNConverter.h> +#include <Swiften/Network/DomainNameAddressQuery.h> #include <Swiften/Network/HostAddress.h> -#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/Network/HostAddressPort.h> -#include <Swiften/Network/DomainNameAddressQuery.h> #include <Swiften/Network/PlatformDomainNameAddressQuery.h> +#include <Swiften/Network/PlatformDomainNameServiceQuery.h> using namespace Swift; namespace Swift { PlatformDomainNameResolver::PlatformDomainNameResolver(IDNConverter* idnConverter, EventLoop* eventLoop) : idnConverter(idnConverter), eventLoop(eventLoop), stopRequested(false) { - thread = new boost::thread(boost::bind(&PlatformDomainNameResolver::run, this)); + thread = new std::thread(boost::bind(&PlatformDomainNameResolver::run, this)); } PlatformDomainNameResolver::~PlatformDomainNameResolver() { - stopRequested = true; - addQueryToQueue(boost::shared_ptr<PlatformDomainNameQuery>()); - thread->join(); - delete thread; + stopRequested = true; + addQueryToQueue(std::shared_ptr<PlatformDomainNameQuery>()); + thread->join(); + delete thread; } -boost::shared_ptr<DomainNameServiceQuery> PlatformDomainNameResolver::createServiceQuery(const std::string& name) { - return boost::shared_ptr<DomainNameServiceQuery>(new PlatformDomainNameServiceQuery(idnConverter->getIDNAEncoded(name), eventLoop, this)); +std::shared_ptr<DomainNameServiceQuery> PlatformDomainNameResolver::createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) { + boost::optional<std::string> encodedDomain = idnConverter->getIDNAEncoded(domain); + std::string result; + if (encodedDomain) { + result = serviceLookupPrefix + *encodedDomain; + } + return std::make_shared<PlatformDomainNameServiceQuery>(result, eventLoop, this); } -boost::shared_ptr<DomainNameAddressQuery> PlatformDomainNameResolver::createAddressQuery(const std::string& name) { - return boost::shared_ptr<DomainNameAddressQuery>(new PlatformDomainNameAddressQuery(idnConverter->getIDNAEncoded(name), eventLoop, this)); +std::shared_ptr<DomainNameAddressQuery> PlatformDomainNameResolver::createAddressQuery(const std::string& name) { + return std::make_shared<PlatformDomainNameAddressQuery>(idnConverter->getIDNAEncoded(name), eventLoop, this); } void PlatformDomainNameResolver::run() { - while (!stopRequested) { - PlatformDomainNameQuery::ref query; - { - boost::unique_lock<boost::mutex> lock(queueMutex); - while (queue.empty()) { - queueNonEmpty.wait(lock); - } - query = queue.front(); - queue.pop_front(); - } - // Check whether we don't have a non-null query (used to stop the - // resolver) - if (query) { - query->runBlocking(); - } - } + while (!stopRequested) { + PlatformDomainNameQuery::ref query; + { + std::unique_lock<std::mutex> lock(queueMutex); + while (queue.empty()) { + queueNonEmpty.wait(lock); + } + query = queue.front(); + queue.pop_front(); + } + // Check whether we don't have a non-null query (used to stop the + // resolver) + if (query) { + query->runBlocking(); + } + } } void PlatformDomainNameResolver::addQueryToQueue(PlatformDomainNameQuery::ref query) { - { - boost::lock_guard<boost::mutex> lock(queueMutex); - queue.push_back(query); - } - queueNonEmpty.notify_one(); + { + std::lock_guard<std::mutex> lock(queueMutex); + queue.push_back(query); + } + queueNonEmpty.notify_one(); } } diff --git a/Swiften/Network/PlatformDomainNameResolver.h b/Swiften/Network/PlatformDomainNameResolver.h index 25d87cf..4ddb999 100644 --- a/Swiften/Network/PlatformDomainNameResolver.h +++ b/Swiften/Network/PlatformDomainNameResolver.h @@ -1,47 +1,48 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <condition_variable> #include <deque> -#include <boost/thread/thread.hpp> -#include <boost/thread/mutex.hpp> -#include <boost/thread/condition_variable.hpp> +#include <mutex> +#include <thread> #include <Swiften/Base/API.h> +#include <Swiften/Base/Atomic.h> +#include <Swiften/Network/DomainNameAddressQuery.h> #include <Swiften/Network/DomainNameResolver.h> -#include <Swiften/Network/PlatformDomainNameQuery.h> #include <Swiften/Network/DomainNameServiceQuery.h> -#include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/Network/PlatformDomainNameQuery.h> namespace Swift { - class IDNConverter; - class EventLoop; - - class SWIFTEN_API PlatformDomainNameResolver : public DomainNameResolver { - public: - PlatformDomainNameResolver(IDNConverter* idnConverter, EventLoop* eventLoop); - ~PlatformDomainNameResolver(); - - virtual DomainNameServiceQuery::ref createServiceQuery(const std::string& name); - virtual DomainNameAddressQuery::ref createAddressQuery(const std::string& name); - - private: - void run(); - void addQueryToQueue(PlatformDomainNameQuery::ref); - - private: - friend class PlatformDomainNameServiceQuery; - friend class PlatformDomainNameAddressQuery; - IDNConverter* idnConverter; - EventLoop* eventLoop; - bool stopRequested; - boost::thread* thread; - std::deque<PlatformDomainNameQuery::ref> queue; - boost::mutex queueMutex; - boost::condition_variable queueNonEmpty; - }; + class IDNConverter; + class EventLoop; + + class SWIFTEN_API PlatformDomainNameResolver : public DomainNameResolver { + public: + PlatformDomainNameResolver(IDNConverter* idnConverter, EventLoop* eventLoop); + virtual ~PlatformDomainNameResolver(); + + virtual DomainNameServiceQuery::ref createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain); + virtual DomainNameAddressQuery::ref createAddressQuery(const std::string& name); + + private: + void run(); + void addQueryToQueue(PlatformDomainNameQuery::ref); + + private: + friend class PlatformDomainNameServiceQuery; + friend class PlatformDomainNameAddressQuery; + IDNConverter* idnConverter; + EventLoop* eventLoop; + Atomic<bool> stopRequested; + std::thread* thread; + std::deque<PlatformDomainNameQuery::ref> queue; + std::mutex queueMutex; + std::condition_variable queueNonEmpty; + }; } diff --git a/Swiften/Network/PlatformDomainNameServiceQuery.cpp b/Swiften/Network/PlatformDomainNameServiceQuery.cpp index 5788d2f..2ff14e1 100644 --- a/Swiften/Network/PlatformDomainNameServiceQuery.cpp +++ b/Swiften/Network/PlatformDomainNameServiceQuery.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <boost/asio.hpp> @@ -29,145 +29,164 @@ #include <Swiften/Base/ByteArray.h> #include <Swiften/EventLoop/EventLoop.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Base/BoostRandomGenerator.h> #include <Swiften/Base/Log.h> +#include <Swiften/Base/StdRandomGenerator.h> #include <Swiften/Network/PlatformDomainNameResolver.h> using namespace Swift; namespace Swift { -PlatformDomainNameServiceQuery::PlatformDomainNameServiceQuery(const std::string& service, EventLoop* eventLoop, PlatformDomainNameResolver* resolver) : PlatformDomainNameQuery(resolver), eventLoop(eventLoop), service(service) { +PlatformDomainNameServiceQuery::PlatformDomainNameServiceQuery(const boost::optional<std::string>& serviceName, EventLoop* eventLoop, PlatformDomainNameResolver* resolver) : PlatformDomainNameQuery(resolver), eventLoop(eventLoop), serviceValid(false) { + if (!!serviceName) { + service = *serviceName; + serviceValid = true; + } +} + +PlatformDomainNameServiceQuery::~PlatformDomainNameServiceQuery() { + } void PlatformDomainNameServiceQuery::run() { - getResolver()->addQueryToQueue(shared_from_this()); + getResolver()->addQueryToQueue(shared_from_this()); } void PlatformDomainNameServiceQuery::runBlocking() { - SWIFT_LOG(debug) << "Querying " << service << std::endl; + if (!serviceValid) { + emitError(); + return; + } + + SWIFT_LOG(debug) << "Querying " << service; - std::vector<DomainNameServiceQuery::Result> records; + std::vector<DomainNameServiceQuery::Result> records; #if defined(SWIFTEN_PLATFORM_WINDOWS) - DNS_RECORD* responses; - // FIXME: This conversion doesn't work if unicode is deffed above - if (DnsQuery(service.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &responses, NULL) != ERROR_SUCCESS) { - emitError(); - return; - } - - DNS_RECORD* currentEntry = responses; - while (currentEntry) { - if (currentEntry->wType == DNS_TYPE_SRV) { - DomainNameServiceQuery::Result record; - record.priority = currentEntry->Data.SRV.wPriority; - record.weight = currentEntry->Data.SRV.wWeight; - record.port = currentEntry->Data.SRV.wPort; - - // The pNameTarget is actually a PCWSTR, so I would have expected this - // conversion to not work at all, but it does. - // Actually, it doesn't. Fix this and remove explicit cast - // Remove unicode undef above as well - record.hostname = std::string((const char*) currentEntry->Data.SRV.pNameTarget); - records.push_back(record); - } - currentEntry = currentEntry->pNext; - } - DnsRecordListFree(responses, DnsFreeRecordList); + DNS_RECORD* responses; + // FIXME: This conversion doesn't work if unicode is deffed above + if (DnsQuery(service.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &responses, NULL) != ERROR_SUCCESS) { + emitError(); + return; + } + + DNS_RECORD* currentEntry = responses; + while (currentEntry) { + if (currentEntry->wType == DNS_TYPE_SRV) { + DomainNameServiceQuery::Result record; + record.priority = currentEntry->Data.SRV.wPriority; + record.weight = currentEntry->Data.SRV.wWeight; + record.port = currentEntry->Data.SRV.wPort; + + // The pNameTarget is actually a PCWSTR, so I would have expected this + // conversion to not work at all, but it does. + // Actually, it doesn't. Fix this and remove explicit cast + // Remove unicode undef above as well + record.hostname = std::string((const char*) currentEntry->Data.SRV.pNameTarget); + records.push_back(record); + } + currentEntry = currentEntry->pNext; + } + DnsRecordListFree(responses, DnsFreeRecordList); #else - // Make sure we reinitialize the domain list every time - res_init(); - - ByteArray response; - response.resize(NS_PACKETSZ); - int responseLength = res_query(const_cast<char*>(service.c_str()), ns_c_in, ns_t_srv, reinterpret_cast<u_char*>(vecptr(response)), response.size()); - if (responseLength == -1) { - SWIFT_LOG(debug) << "Error" << std::endl; - emitError(); - return; - } - - // Parse header - HEADER* header = reinterpret_cast<HEADER*>(vecptr(response)); - unsigned char* messageStart = vecptr(response); - unsigned char* messageEnd = messageStart + responseLength; - unsigned char* currentEntry = messageStart + NS_HFIXEDSZ; - - // Skip over the queries - int queriesCount = ntohs(header->qdcount); - while (queriesCount > 0) { - int entryLength = dn_skipname(currentEntry, messageEnd); - if (entryLength < 0) { - emitError(); - return; - } - currentEntry += entryLength + NS_QFIXEDSZ; - queriesCount--; - } - - // Process the SRV answers - int answersCount = ntohs(header->ancount); - while (answersCount > 0) { - DomainNameServiceQuery::Result record; - - int entryLength = dn_skipname(currentEntry, messageEnd); - currentEntry += entryLength; - currentEntry += NS_RRFIXEDSZ; - - // Priority - if (currentEntry + 2 >= messageEnd) { - emitError(); - return; - } - record.priority = boost::numeric_cast<int>(ns_get16(currentEntry)); - currentEntry += 2; - - // Weight - if (currentEntry + 2 >= messageEnd) { - emitError(); - return; - } - record.weight = boost::numeric_cast<int>(ns_get16(currentEntry)); - currentEntry += 2; - - // Port - if (currentEntry + 2 >= messageEnd) { - emitError(); - return; - } - record.port = boost::numeric_cast<int>(ns_get16(currentEntry)); - currentEntry += 2; - - // Hostname - if (currentEntry >= messageEnd) { - emitError(); - return; - } - ByteArray entry; - entry.resize(NS_MAXDNAME); - entryLength = dn_expand(messageStart, messageEnd, currentEntry, reinterpret_cast<char*>(vecptr(entry)), entry.size()); - if (entryLength < 0) { - emitError(); - return; - } - record.hostname = std::string(reinterpret_cast<const char*>(vecptr(entry))); - records.push_back(record); - currentEntry += entryLength; - answersCount--; - } + // Make sure we reinitialize the domain list every time + res_init(); + + ByteArray response; + response.resize(NS_PACKETSZ); + int responseLength = res_query(const_cast<char*>(service.c_str()), ns_c_in, ns_t_srv, reinterpret_cast<u_char*>(vecptr(response)), response.size()); + if (responseLength == -1) { + SWIFT_LOG(debug) << "Error"; + emitError(); + return; + } + + // Parse header + HEADER* header = reinterpret_cast<HEADER*>(vecptr(response)); + unsigned char* messageStart = vecptr(response); + unsigned char* messageEnd = messageStart + responseLength; + unsigned char* currentEntry = messageStart + NS_HFIXEDSZ; + + // Skip over the queries + int queriesCount = ntohs(header->qdcount); + while (queriesCount > 0) { + int entryLength = dn_skipname(currentEntry, messageEnd); + if (entryLength < 0) { + emitError(); + return; + } + currentEntry += entryLength + NS_QFIXEDSZ; + queriesCount--; + } + + // Process the SRV answers + int answersCount = ntohs(header->ancount); + while (answersCount > 0) { + DomainNameServiceQuery::Result record; + + int entryLength = dn_skipname(currentEntry, messageEnd); + currentEntry += entryLength; + currentEntry += NS_RRFIXEDSZ; + + try { + // Priority + if (currentEntry + 2 >= messageEnd) { + emitError(); + return; + } + record.priority = boost::numeric_cast<int>(ns_get16(currentEntry)); + currentEntry += 2; + + // Weight + if (currentEntry + 2 >= messageEnd) { + emitError(); + return; + } + record.weight = boost::numeric_cast<int>(ns_get16(currentEntry)); + currentEntry += 2; + + // Port + if (currentEntry + 2 >= messageEnd) { + emitError(); + return; + } + record.port = boost::numeric_cast<unsigned short>(ns_get16(currentEntry)); + currentEntry += 2; + + // Hostname + if (currentEntry >= messageEnd) { + emitError(); + return; + } + } + catch (const boost::numeric::bad_numeric_cast&) { + emitError(); + return; + } + + ByteArray entry; + entry.resize(NS_MAXDNAME); + entryLength = dn_expand(messageStart, messageEnd, currentEntry, reinterpret_cast<char*>(vecptr(entry)), entry.size()); + if (entryLength < 0) { + emitError(); + return; + } + record.hostname = std::string(reinterpret_cast<const char*>(vecptr(entry))); + records.push_back(record); + currentEntry += entryLength; + answersCount--; + } #endif - BoostRandomGenerator generator; - DomainNameServiceQuery::sortResults(records, generator); - //std::cout << "Sending out " << records.size() << " SRV results " << std::endl; - eventLoop->postEvent(boost::bind(boost::ref(onResult), records), shared_from_this()); + StdRandomGenerator generator; + DomainNameServiceQuery::sortResults(records, generator); + //std::cout << "Sending out " << records.size() << " SRV results " << std::endl; + eventLoop->postEvent(boost::bind(boost::ref(onResult), records), shared_from_this()); } void PlatformDomainNameServiceQuery::emitError() { - eventLoop->postEvent(boost::bind(boost::ref(onResult), std::vector<DomainNameServiceQuery::Result>()), shared_from_this()); + eventLoop->postEvent(boost::bind(boost::ref(onResult), std::vector<DomainNameServiceQuery::Result>()), shared_from_this()); } } diff --git a/Swiften/Network/PlatformDomainNameServiceQuery.h b/Swiften/Network/PlatformDomainNameServiceQuery.h index 310e639..0d690f3 100644 --- a/Swiften/Network/PlatformDomainNameServiceQuery.h +++ b/Swiften/Network/PlatformDomainNameServiceQuery.h @@ -1,33 +1,35 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/enable_shared_from_this.hpp> +#include <memory> +#include <string> -#include <Swiften/Network/DomainNameServiceQuery.h> #include <Swiften/EventLoop/EventOwner.h> -#include <string> +#include <Swiften/Network/DomainNameServiceQuery.h> #include <Swiften/Network/PlatformDomainNameQuery.h> namespace Swift { - class EventLoop; + class EventLoop; - class PlatformDomainNameServiceQuery : public DomainNameServiceQuery, public PlatformDomainNameQuery, public boost::enable_shared_from_this<PlatformDomainNameServiceQuery>, public EventOwner { - public: - PlatformDomainNameServiceQuery(const std::string& service, EventLoop* eventLoop, PlatformDomainNameResolver* resolver); + class PlatformDomainNameServiceQuery : public DomainNameServiceQuery, public PlatformDomainNameQuery, public std::enable_shared_from_this<PlatformDomainNameServiceQuery>, public EventOwner { + public: + PlatformDomainNameServiceQuery(const boost::optional<std::string>& serviceName, EventLoop* eventLoop, PlatformDomainNameResolver* resolver); + virtual ~PlatformDomainNameServiceQuery(); - virtual void run(); + virtual void run(); - private: - void runBlocking(); - void emitError(); + private: + void runBlocking(); + void emitError(); - private: - EventLoop* eventLoop; - std::string service; - }; + private: + EventLoop* eventLoop; + std::string service; + bool serviceValid; + }; } diff --git a/Swiften/Network/PlatformNATTraversalWorker.cpp b/Swiften/Network/PlatformNATTraversalWorker.cpp index 133b006..5431379 100644 --- a/Swiften/Network/PlatformNATTraversalWorker.cpp +++ b/Swiften/Network/PlatformNATTraversalWorker.cpp @@ -4,13 +4,21 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "PlatformNATTraversalWorker.h" +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Network/PlatformNATTraversalWorker.h> + +#include <memory> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/enable_shared_from_this.hpp> #include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/Log.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/EventLoop/EventOwner.h> #include <Swiften/Network/NATTraversalGetPublicIPRequest.h> #include <Swiften/Network/NATTraversalForwardPortRequest.h> #include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h> @@ -23,179 +31,194 @@ namespace Swift { -class PlatformNATTraversalRequest : public boost::enable_shared_from_this<PlatformNATTraversalRequest> { - public: - typedef boost::shared_ptr<PlatformNATTraversalRequest> ref; +class PlatformNATTraversalRequest : public std::enable_shared_from_this<PlatformNATTraversalRequest>, public EventOwner { + public: + typedef std::shared_ptr<PlatformNATTraversalRequest> ref; - public: - PlatformNATTraversalRequest(PlatformNATTraversalWorker* worker) : worker(worker) { - } + public: + PlatformNATTraversalRequest(PlatformNATTraversalWorker* worker) : worker(worker) { + } - virtual ~PlatformNATTraversalRequest() { - } + virtual ~PlatformNATTraversalRequest() { + } - virtual void doRun() { - worker->addRequestToQueue(shared_from_this()); - } + virtual void doRun() { + worker->addRequestToQueue(shared_from_this()); + } - NATTraversalInterface* getNATTraversalInterface() const { - return worker->getNATTraversalInterface(); - } + NATTraversalInterface* getNATTraversalInterface() const { + return worker->getNATTraversalInterface(); + } + EventLoop* getEventLoop() const { + return worker->getEventLoop(); + } - virtual void runBlocking() = 0; - private: - PlatformNATTraversalWorker* worker; + virtual void runBlocking() = 0; + + private: + PlatformNATTraversalWorker* worker; }; class PlatformNATTraversalGetPublicIPRequest : public NATTraversalGetPublicIPRequest, public PlatformNATTraversalRequest { - public: - PlatformNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) { - } + public: + PlatformNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) { + } + + virtual ~PlatformNATTraversalGetPublicIPRequest() { + } - virtual void start() { - doRun(); - } + virtual void start() { + doRun(); + } - virtual void stop() { - // TODO - } + virtual void stop() { + onResult.disconnect_all_slots(); + } - virtual void runBlocking() { - onResult(getNATTraversalInterface()->getPublicIP()); - } + virtual void runBlocking() { + getEventLoop()->postEvent(boost::bind(boost::ref(onResult), getNATTraversalInterface()->getPublicIP()), shared_from_this()); + } }; class PlatformNATTraversalForwardPortRequest : public NATTraversalForwardPortRequest, public PlatformNATTraversalRequest { - public: - PlatformNATTraversalForwardPortRequest(PlatformNATTraversalWorker* worker, unsigned int localIP, unsigned int publicIP) : PlatformNATTraversalRequest(worker), localIP(localIP), publicIP(publicIP) { - } + public: + PlatformNATTraversalForwardPortRequest(PlatformNATTraversalWorker* worker, unsigned short localPort, unsigned short publicPort) : PlatformNATTraversalRequest(worker), localPort(localPort), publicPort(publicPort) { + } - virtual void start() { - doRun(); - } + virtual ~PlatformNATTraversalForwardPortRequest() { + } - virtual void stop() { - // TODO - } + virtual void start() { + doRun(); + } - virtual void runBlocking() { - onResult(getNATTraversalInterface()->addPortForward(boost::numeric_cast<int>(localIP), boost::numeric_cast<int>(publicIP))); - } + virtual void stop() { + onResult.disconnect_all_slots(); + } - private: - unsigned int localIP; - unsigned int publicIP; + virtual void runBlocking() { + getEventLoop()->postEvent(boost::bind(boost::ref(onResult), getNATTraversalInterface()->addPortForward(localPort, publicPort)), shared_from_this()); + } + + private: + unsigned short localPort; + unsigned short publicPort; }; class PlatformNATTraversalRemovePortForwardingRequest : public NATTraversalRemovePortForwardingRequest, public PlatformNATTraversalRequest { - public: - PlatformNATTraversalRemovePortForwardingRequest(PlatformNATTraversalWorker* worker, const NATPortMapping& mapping) : PlatformNATTraversalRequest(worker), mapping(mapping) { - } + public: + PlatformNATTraversalRemovePortForwardingRequest(PlatformNATTraversalWorker* worker, const NATPortMapping& mapping) : PlatformNATTraversalRequest(worker), mapping(mapping) { + } + + virtual ~PlatformNATTraversalRemovePortForwardingRequest() { + } - virtual void start() { - doRun(); - } + virtual void start() { + doRun(); + } - virtual void stop() { - // TODO - } + virtual void stop() { + onResult.disconnect_all_slots(); + } - virtual void runBlocking() { - onResult(getNATTraversalInterface()->removePortForward(mapping)); - } + virtual void runBlocking() { + getEventLoop()->postEvent(boost::bind(boost::ref(onResult), getNATTraversalInterface()->removePortForward(mapping)), shared_from_this()); + } - private: - NATPortMapping mapping; + private: + NATPortMapping mapping; }; -PlatformNATTraversalWorker::PlatformNATTraversalWorker(EventLoop* eventLoop) : eventLoop(eventLoop), stopRequested(false), natPMPSupported(boost::logic::indeterminate), natPMPInterface(NULL), miniUPnPSupported(boost::logic::indeterminate), miniUPnPInterface(NULL) { - nullNATTraversalInterface = new NullNATTraversalInterface(); - // FIXME: This should be done from start(), and the current start() should be an internal method - thread = new boost::thread(boost::bind(&PlatformNATTraversalWorker::start, this)); +PlatformNATTraversalWorker::PlatformNATTraversalWorker(EventLoop* eventLoop) : eventLoop(eventLoop), stopRequested(false), natPMPSupported(boost::logic::indeterminate), natPMPInterface(nullptr), miniUPnPSupported(boost::logic::indeterminate), miniUPnPInterface(nullptr) { + nullNATTraversalInterface = new NullNATTraversalInterface(); + // FIXME: This should be done from start(), and the current start() should be an internal method + thread = new std::thread(boost::bind(&PlatformNATTraversalWorker::start, this)); } PlatformNATTraversalWorker::~PlatformNATTraversalWorker() { - stopRequested = true; - addRequestToQueue(boost::shared_ptr<PlatformNATTraversalRequest>()); - thread->join(); - delete thread; + stopRequested = true; + addRequestToQueue(std::shared_ptr<PlatformNATTraversalRequest>()); + thread->join(); + delete thread; #ifdef HAVE_LIBNATPMP - delete natPMPInterface; + delete natPMPInterface; #endif #ifdef HAVE_LIBMINIUPNPC - delete miniUPnPInterface; + delete miniUPnPInterface; #endif - delete nullNATTraversalInterface; + delete nullNATTraversalInterface; } NATTraversalInterface* PlatformNATTraversalWorker::getNATTraversalInterface() const { #ifdef HAVE_LIBMINIUPNPC - if (boost::logic::indeterminate(miniUPnPSupported)) { - miniUPnPInterface = new MiniUPnPInterface(); - miniUPnPSupported = miniUPnPInterface->isAvailable(); - } - if (miniUPnPSupported) { - return miniUPnPInterface; - } + if (boost::logic::indeterminate(miniUPnPSupported)) { + miniUPnPInterface = new MiniUPnPInterface(); + miniUPnPSupported = miniUPnPInterface->isAvailable(); + } + SWIFT_LOG(debug) << "UPnP NAT traversal supported: " << static_cast<bool>(miniUPnPSupported); + if (miniUPnPSupported) { + return miniUPnPInterface; + } #endif #ifdef HAVE_LIBNATPMP - if (boost::logic::indeterminate(natPMPSupported)) { - natPMPInterface = new NATPMPInterface(); - natPMPSupported = natPMPInterface->isAvailable(); - } - if (natPMPSupported) { - return natPMPInterface; - } + if (boost::logic::indeterminate(natPMPSupported)) { + natPMPInterface = new NATPMPInterface(); + natPMPSupported = natPMPInterface->isAvailable(); + } + SWIFT_LOG(debug) << "NAT-PMP NAT traversal supported: " << static_cast<bool>(natPMPSupported); + if (natPMPSupported) { + return natPMPInterface; + } #endif - return nullNATTraversalInterface; + return nullNATTraversalInterface; } -boost::shared_ptr<NATTraversalGetPublicIPRequest> PlatformNATTraversalWorker::createGetPublicIPRequest() { - return boost::make_shared<PlatformNATTraversalGetPublicIPRequest>(this); +std::shared_ptr<NATTraversalGetPublicIPRequest> PlatformNATTraversalWorker::createGetPublicIPRequest() { + return std::make_shared<PlatformNATTraversalGetPublicIPRequest>(this); } -boost::shared_ptr<NATTraversalForwardPortRequest> PlatformNATTraversalWorker::createForwardPortRequest(int localPort, int publicPort) { - return boost::make_shared<PlatformNATTraversalForwardPortRequest>(this, localPort, publicPort); +std::shared_ptr<NATTraversalForwardPortRequest> PlatformNATTraversalWorker::createForwardPortRequest(unsigned short localPort, unsigned short publicPort) { + return std::make_shared<PlatformNATTraversalForwardPortRequest>(this, localPort, publicPort); } -boost::shared_ptr<NATTraversalRemovePortForwardingRequest> PlatformNATTraversalWorker::createRemovePortForwardingRequest(int localPort, int publicPort) { - NATPortMapping mapping(localPort, publicPort, NATPortMapping::TCP); // FIXME - return boost::make_shared<PlatformNATTraversalRemovePortForwardingRequest>(this, mapping); +std::shared_ptr<NATTraversalRemovePortForwardingRequest> PlatformNATTraversalWorker::createRemovePortForwardingRequest(unsigned short localPort, unsigned short publicPort) { + NATPortMapping mapping(localPort, publicPort, NATPortMapping::TCP); // FIXME + return std::make_shared<PlatformNATTraversalRemovePortForwardingRequest>(this, mapping); } void PlatformNATTraversalWorker::start() { - while (!stopRequested) { - PlatformNATTraversalRequest::ref request; - { - boost::unique_lock<boost::mutex> lock(queueMutex); - while (queue.empty()) { - queueNonEmpty.wait(lock); - } - request = queue.front(); - queue.pop_front(); - } - // Check whether we don't have a non-null request (used to stop the - // worker) - if (request) { - request->runBlocking(); - } - } + while (!stopRequested) { + PlatformNATTraversalRequest::ref request; + { + std::unique_lock<std::mutex> lock(queueMutex); + while (queue.empty()) { + queueNonEmpty.wait(lock); + } + request = queue.front(); + queue.pop_front(); + } + // Check whether we don't have a non-null request (used to stop the + // worker) + if (request) { + request->runBlocking(); + } + } } void PlatformNATTraversalWorker::stop() { - // TODO + // TODO } void PlatformNATTraversalWorker::addRequestToQueue(PlatformNATTraversalRequest::ref request) { - { - boost::lock_guard<boost::mutex> lock(queueMutex); - queue.push_back(request); - } - queueNonEmpty.notify_one(); + { + std::lock_guard<std::mutex> lock(queueMutex); + queue.push_back(request); + } + queueNonEmpty.notify_one(); } } diff --git a/Swiften/Network/PlatformNATTraversalWorker.h b/Swiften/Network/PlatformNATTraversalWorker.h index 6148705..368798e 100644 --- a/Swiften/Network/PlatformNATTraversalWorker.h +++ b/Swiften/Network/PlatformNATTraversalWorker.h @@ -4,60 +4,71 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <condition_variable> #include <deque> -#include <boost/optional.hpp> -#include <boost/thread/thread.hpp> -#include <boost/thread/mutex.hpp> -#include <boost/thread/condition_variable.hpp> +#include <mutex> +#include <thread> + #include <boost/logic/tribool.hpp> +#include <boost/optional.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Network/NATTraverser.h> +#include <Swiften/Base/Atomic.h> #include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Network/NATTraverser.h> #include <Swiften/Network/NullNATTraversalInterface.h> namespace Swift { - class EventLoop; - class NATTraversalGetPublicIPRequest; - class NATTraversalForwardPortRequest; - class NATTraversalRemovePortForwardingRequest; - class PlatformNATTraversalRequest; - class NATPMPInterface; - class MiniUPnPInterface; - class NATTraversalInterface; - class NATPortMapping; - - class SWIFTEN_API PlatformNATTraversalWorker : public NATTraverser { - friend class PlatformNATTraversalRequest; - - public: - PlatformNATTraversalWorker(EventLoop* eventLoop); - ~PlatformNATTraversalWorker(); - - boost::shared_ptr<NATTraversalGetPublicIPRequest> createGetPublicIPRequest(); - boost::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(int localPort, int publicPort); - boost::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(int localPort, int publicPort); - - private: - NATTraversalInterface* getNATTraversalInterface() const; - void addRequestToQueue(boost::shared_ptr<PlatformNATTraversalRequest>); - void start(); - void stop(); - - private: - EventLoop* eventLoop; - bool stopRequested; - boost::thread* thread; - std::deque<boost::shared_ptr<PlatformNATTraversalRequest> > queue; - boost::mutex queueMutex; - boost::condition_variable queueNonEmpty; - - NullNATTraversalInterface* nullNATTraversalInterface; - mutable boost::logic::tribool natPMPSupported; - mutable NATPMPInterface* natPMPInterface; - mutable boost::logic::tribool miniUPnPSupported; - mutable MiniUPnPInterface* miniUPnPInterface; - }; + class EventLoop; + class NATTraversalGetPublicIPRequest; + class NATTraversalForwardPortRequest; + class NATTraversalRemovePortForwardingRequest; + class PlatformNATTraversalRequest; + class NATPMPInterface; + class MiniUPnPInterface; + class NATTraversalInterface; + + class SWIFTEN_API PlatformNATTraversalWorker : public NATTraverser { + friend class PlatformNATTraversalRequest; + + public: + PlatformNATTraversalWorker(EventLoop* eventLoop); + virtual ~PlatformNATTraversalWorker(); + + std::shared_ptr<NATTraversalGetPublicIPRequest> createGetPublicIPRequest(); + std::shared_ptr<NATTraversalForwardPortRequest> createForwardPortRequest(unsigned short localPort, unsigned short publicPort); + std::shared_ptr<NATTraversalRemovePortForwardingRequest> createRemovePortForwardingRequest(unsigned short localPort, unsigned short publicPort); + + private: + NATTraversalInterface* getNATTraversalInterface() const; + void addRequestToQueue(std::shared_ptr<PlatformNATTraversalRequest>); + void start(); + void stop(); + + EventLoop* getEventLoop() const { + return eventLoop; + } + + private: + EventLoop* eventLoop; + Atomic<bool> stopRequested; + std::thread* thread; + std::deque<std::shared_ptr<PlatformNATTraversalRequest> > queue; + std::mutex queueMutex; + std::condition_variable queueNonEmpty; + + NullNATTraversalInterface* nullNATTraversalInterface; + mutable boost::logic::tribool natPMPSupported; + mutable NATPMPInterface* natPMPInterface; + mutable boost::logic::tribool miniUPnPSupported; + mutable MiniUPnPInterface* miniUPnPInterface; + }; } diff --git a/Swiften/Network/PlatformNetworkEnvironment.h b/Swiften/Network/PlatformNetworkEnvironment.h index c6b945e..ff29491 100644 --- a/Swiften/Network/PlatformNetworkEnvironment.h +++ b/Swiften/Network/PlatformNetworkEnvironment.h @@ -11,16 +11,22 @@ #if defined(SWIFTEN_PLATFORM_MACOSX) #include <Swiften/Network/UnixNetworkEnvironment.h> namespace Swift { - typedef UnixNetworkEnvironment PlatformNetworkEnvironment; + typedef UnixNetworkEnvironment PlatformNetworkEnvironment; } #elif defined(SWIFTEN_PLATFORM_WIN32) #include <Swiften/Network/WindowsNetworkEnvironment.h> namespace Swift { - typedef WindowsNetworkEnvironment PlatformNetworkEnvironment; + typedef WindowsNetworkEnvironment PlatformNetworkEnvironment; } +#elif defined(SWIFTEN_PLATFORM_SOLARIS) +#include <Swiften/Network/SolarisNetworkEnvironment.h> +namespace Swift { + typedef SolarisNetworkEnvironment PlatformNetworkEnvironment; +} + #else #include <Swiften/Network/UnixNetworkEnvironment.h> namespace Swift { - typedef UnixNetworkEnvironment PlatformNetworkEnvironment; + typedef UnixNetworkEnvironment PlatformNetworkEnvironment; } #endif diff --git a/Swiften/Network/PlatformProxyProvider.h b/Swiften/Network/PlatformProxyProvider.h index 1a0a1c6..c63e718 100644 --- a/Swiften/Network/PlatformProxyProvider.h +++ b/Swiften/Network/PlatformProxyProvider.h @@ -11,16 +11,16 @@ #if defined(SWIFTEN_PLATFORM_MACOSX) #include <Swiften/Network/MacOSXProxyProvider.h> namespace Swift { - typedef MacOSXProxyProvider PlatformProxyProvider; + typedef MacOSXProxyProvider PlatformProxyProvider; } #elif defined(SWIFTEN_PLATFORM_WIN32) #include <Swiften/Network/WindowsProxyProvider.h> namespace Swift { - typedef WindowsProxyProvider PlatformProxyProvider; + typedef WindowsProxyProvider PlatformProxyProvider; } #else #include <Swiften/Network/UnixProxyProvider.h> namespace Swift { - typedef UnixProxyProvider PlatformProxyProvider; + typedef UnixProxyProvider PlatformProxyProvider; } #endif diff --git a/Swiften/Network/ProxiedConnection.cpp b/Swiften/Network/ProxiedConnection.cpp index 8bf12d3..0c5cda6 100644 --- a/Swiften/Network/ProxiedConnection.cpp +++ b/Swiften/Network/ProxiedConnection.cpp @@ -1,112 +1,127 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ - #include <Swiften/Network/ProxiedConnection.h> -#include <iostream> #include <boost/bind.hpp> #include <Swiften/Base/ByteArray.h> -#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Base/Log.h> #include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/HostAddressPort.h> using namespace Swift; ProxiedConnection::ProxiedConnection( - DomainNameResolver* resolver, - ConnectionFactory* connectionFactory, - TimerFactory* timerFactory, - const std::string& proxyHost, - int proxyPort) : - resolver_(resolver), - connectionFactory_(connectionFactory), - timerFactory_(timerFactory), - proxyHost_(proxyHost), - proxyPort_(proxyPort), - server_(HostAddressPort(HostAddress("0.0.0.0"), 0)) { - connected_ = false; + DomainNameResolver* resolver, + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + const std::string& proxyHost, + unsigned short proxyPort) : + resolver_(resolver), + connectionFactory_(connectionFactory), + timerFactory_(timerFactory), + proxyHost_(proxyHost), + proxyPort_(proxyPort), + server_(HostAddressPort(HostAddress::fromString("0.0.0.0").get(), 0)) { + connected_ = false; } ProxiedConnection::~ProxiedConnection() { - cancelConnector(); - if (connection_) { - connection_->onDataRead.disconnect(boost::bind(&ProxiedConnection::handleDataRead, shared_from_this(), _1)); - connection_->onDisconnected.disconnect(boost::bind(&ProxiedConnection::handleDisconnected, shared_from_this(), _1)); - } - if (connected_) { - std::cerr << "Warning: Connection was still established." << std::endl; - } + cancelConnector(); + if (connection_) { + connection_->onDataRead.disconnect(boost::bind(&ProxiedConnection::handleDataRead, shared_from_this(), _1)); + connection_->onDisconnected.disconnect(boost::bind(&ProxiedConnection::handleDisconnected, shared_from_this(), _1)); + } + if (connected_) { + SWIFT_LOG(warning) << "Connection was still established."; + } } void ProxiedConnection::cancelConnector() { - if (connector_) { - connector_->onConnectFinished.disconnect(boost::bind(&ProxiedConnection::handleConnectFinished, shared_from_this(), _1)); - connector_->stop(); - connector_.reset(); - } + if (connector_) { + connector_->onConnectFinished.disconnect(boost::bind(&ProxiedConnection::handleConnectFinished, shared_from_this(), _1)); + connector_->stop(); + connector_.reset(); + } } void ProxiedConnection::connect(const HostAddressPort& server) { - server_ = server; + server_ = server; - connector_ = Connector::create(proxyHost_, proxyPort_, false, resolver_, connectionFactory_, timerFactory_); - connector_->onConnectFinished.connect(boost::bind(&ProxiedConnection::handleConnectFinished, shared_from_this(), _1)); - connector_->start(); + connector_ = Connector::create(proxyHost_, proxyPort_, boost::optional<std::string>(), resolver_, connectionFactory_, timerFactory_); + connector_->onConnectFinished.connect(boost::bind(&ProxiedConnection::handleConnectFinished, shared_from_this(), _1)); + connector_->start(); } void ProxiedConnection::listen() { - assert(false); - connection_->listen(); + assert(false); + connection_->listen(); } void ProxiedConnection::disconnect() { - connected_ = false; - connection_->disconnect(); + cancelConnector(); + connected_ = false; + if (connection_) { + connection_->disconnect(); + } } void ProxiedConnection::handleDisconnected(const boost::optional<Error>& error) { - onDisconnected(error); + onDisconnected(error); } void ProxiedConnection::write(const SafeByteArray& data) { - connection_->write(data); + connection_->write(data); } void ProxiedConnection::handleConnectFinished(Connection::ref connection) { - cancelConnector(); - if (connection) { - connection_ = connection; - connection_->onDataRead.connect(boost::bind(&ProxiedConnection::handleDataRead, shared_from_this(), _1)); - connection_->onDisconnected.connect(boost::bind(&ProxiedConnection::handleDisconnected, shared_from_this(), _1)); - - initializeProxy(); - } - else { - onConnectFinished(true); - } + cancelConnector(); + if (connection) { + connection_ = connection; + connection_->onDataRead.connect(boost::bind(&ProxiedConnection::handleDataRead, shared_from_this(), _1)); + connection_->onDisconnected.connect(boost::bind(&ProxiedConnection::handleDisconnected, shared_from_this(), _1)); + + initializeProxy(); + } + else { + onConnectFinished(true); + } } -void ProxiedConnection::handleDataRead(boost::shared_ptr<SafeByteArray> data) { - if (!connected_) { - handleProxyInitializeData(data); - } - else { - onDataRead(data); - } +void ProxiedConnection::handleDataRead(std::shared_ptr<SafeByteArray> data) { + if (!connected_) { + handleProxyInitializeData(data); + } + else { + onDataRead(data); + } } HostAddressPort ProxiedConnection::getLocalAddress() const { - return connection_->getLocalAddress(); + return connection_->getLocalAddress(); +} + +HostAddressPort ProxiedConnection::getRemoteAddress() const { + return connection_->getRemoteAddress(); } void ProxiedConnection::setProxyInitializeFinished(bool success) { - connected_ = success; - if (!success) { - disconnect(); - } - onConnectFinished(!success); + connected_ = success; + if (!success) { + disconnect(); + } + onConnectFinished(!success); +} + +void ProxiedConnection::reconnect() { + if (connected_) { + connection_->onDataRead.disconnect(boost::bind(&ProxiedConnection::handleDataRead, shared_from_this(), _1)); + connection_->onDisconnected.disconnect(boost::bind(&ProxiedConnection::handleDisconnected, shared_from_this(), _1)); + connection_->disconnect(); + } + connect(server_); } diff --git a/Swiften/Network/ProxiedConnection.h b/Swiften/Network/ProxiedConnection.h index aa8df38..f79845a 100644 --- a/Swiften/Network/ProxiedConnection.h +++ b/Swiften/Network/ProxiedConnection.h @@ -1,67 +1,64 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/enable_shared_from_this.hpp> +#include <memory> +#include <Swiften/Base/API.h> +#include <Swiften/Base/SafeString.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/Connector.h> #include <Swiften/Network/HostAddressPort.h> -#include <Swiften/Base/SafeString.h> - -namespace boost { - class thread; - namespace system { - class error_code; - } -} namespace Swift { - class ConnectionFactory; + class ConnectionFactory; + + class SWIFTEN_API ProxiedConnection : public Connection, public std::enable_shared_from_this<ProxiedConnection> { + public: + ProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort); + virtual ~ProxiedConnection(); - class ProxiedConnection : public Connection, public boost::enable_shared_from_this<ProxiedConnection> { - public: - ProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort); - ~ProxiedConnection(); + virtual void listen(); + virtual void connect(const HostAddressPort& address); + virtual void disconnect(); + virtual void write(const SafeByteArray& data); - virtual void listen(); - virtual void connect(const HostAddressPort& address); - virtual void disconnect(); - virtual void write(const SafeByteArray& data); + virtual HostAddressPort getLocalAddress() const; + virtual HostAddressPort getRemoteAddress() const; - virtual HostAddressPort getLocalAddress() const; + private: + void handleConnectFinished(Connection::ref connection); + void handleDataRead(std::shared_ptr<SafeByteArray> data); + void handleDisconnected(const boost::optional<Error>& error); + void cancelConnector(); - private: - void handleConnectFinished(Connection::ref connection); - void handleDataRead(boost::shared_ptr<SafeByteArray> data); - void handleDisconnected(const boost::optional<Error>& error); - void cancelConnector(); + protected: + void setProxyInitializeFinished(bool success); - protected: - void setProxyInitializeFinished(bool success); + virtual void initializeProxy() = 0; + virtual void handleProxyInitializeData(std::shared_ptr<SafeByteArray> data) = 0; - virtual void initializeProxy() = 0; - virtual void handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data) = 0; + const HostAddressPort& getServer() const { + return server_; + } - const HostAddressPort& getServer() const { - return server_; - } + void reconnect(); - private: - bool connected_; - DomainNameResolver* resolver_; - ConnectionFactory* connectionFactory_; - TimerFactory* timerFactory_; - std::string proxyHost_; - int proxyPort_; - HostAddressPort server_; - Connector::ref connector_; - boost::shared_ptr<Connection> connection_; - }; + private: + bool connected_; + DomainNameResolver* resolver_; + ConnectionFactory* connectionFactory_; + TimerFactory* timerFactory_; + std::string proxyHost_; + unsigned short proxyPort_; + HostAddressPort server_; + Connector::ref connector_; + std::shared_ptr<Connection> connection_; + }; } diff --git a/Swiften/Network/ProxyProvider.cpp b/Swiften/Network/ProxyProvider.cpp index fe235b1..dd07d3a 100644 --- a/Swiften/Network/ProxyProvider.cpp +++ b/Swiften/Network/ProxyProvider.cpp @@ -4,7 +4,13 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "ProxyProvider.h" +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Network/ProxyProvider.h> namespace Swift { diff --git a/Swiften/Network/ProxyProvider.h b/Swiften/Network/ProxyProvider.h index 9a1ccee..bf737c0 100644 --- a/Swiften/Network/ProxyProvider.h +++ b/Swiften/Network/ProxyProvider.h @@ -4,19 +4,27 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once + #include <map> -#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Base/API.h> #include <Swiften/Base/String.h> +#include <Swiften/Network/HostAddressPort.h> namespace Swift { - class ProxyProvider { - public: - ProxyProvider(); - virtual ~ProxyProvider(); - virtual HostAddressPort getHTTPConnectProxy() const = 0; - virtual HostAddressPort getSOCKS5Proxy() const = 0; - }; + class SWIFTEN_API ProxyProvider { + public: + ProxyProvider(); + virtual ~ProxyProvider(); + virtual HostAddressPort getHTTPConnectProxy() const = 0; + virtual HostAddressPort getSOCKS5Proxy() const = 0; + }; } diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript index ea0fb62..9c2a134 100644 --- a/Swiften/Network/SConscript +++ b/Swiften/Network/SConscript @@ -3,104 +3,109 @@ Import("swiften_env") myenv = swiften_env.Clone() if myenv.get("unbound", False) : - myenv.MergeFlags(myenv.get("UNBOUND_FLAGS", {})) - myenv.MergeFlags(myenv.get("LDNS_FLAGS", {})) + myenv.MergeFlags(myenv.get("UNBOUND_FLAGS", {})) + myenv.MergeFlags(myenv.get("LDNS_FLAGS", {})) sourceList = [ - "ProxiedConnection.cpp", - "HTTPConnectProxiedConnection.cpp", - "HTTPConnectProxiedConnectionFactory.cpp", - "SOCKS5ProxiedConnection.cpp", - "SOCKS5ProxiedConnectionFactory.cpp", - "BoostConnection.cpp", - "BoostConnectionFactory.cpp", - "BoostConnectionServer.cpp", - "BoostConnectionServerFactory.cpp", - "BoostIOServiceThread.cpp", - "BOSHConnection.cpp", - "BOSHConnectionPool.cpp", - "CachingDomainNameResolver.cpp", - "ConnectionFactory.cpp", - "ConnectionServer.cpp", - "ConnectionServerFactory.cpp", - "DummyConnection.cpp", - "FakeConnection.cpp", - "ChainedConnector.cpp", - "Connector.cpp", - "Connection.cpp", - "TimerFactory.cpp", - "DummyTimerFactory.cpp", - "BoostTimerFactory.cpp", - "DomainNameResolver.cpp", - "DomainNameAddressQuery.cpp", - "DomainNameServiceQuery.cpp", - "StaticDomainNameResolver.cpp", - "HostAddress.cpp", - "HostAddressPort.cpp", - "HostNameOrAddress.cpp", - "NetworkFactories.cpp", - "BoostNetworkFactories.cpp", - "NetworkEnvironment.cpp", - "Timer.cpp", - "TLSConnection.cpp", - "TLSConnectionFactory.cpp", - "BoostTimer.cpp", - "ProxyProvider.cpp", - "NullProxyProvider.cpp", - "NATTraverser.cpp", - "NullNATTraverser.cpp", - "NATTraversalGetPublicIPRequest.cpp", - "NATTraversalForwardPortRequest.cpp", - "NATTraversalRemovePortForwardingRequest.cpp", - "NATTraversalInterface.cpp", - ] + "ProxiedConnection.cpp", + "HTTPConnectProxiedConnection.cpp", + "HTTPConnectProxiedConnectionFactory.cpp", + "SOCKS5ProxiedConnection.cpp", + "SOCKS5ProxiedConnectionFactory.cpp", + "BoostConnection.cpp", + "BoostConnectionFactory.cpp", + "BoostConnectionServer.cpp", + "BoostConnectionServerFactory.cpp", + "BoostIOServiceThread.cpp", + "BOSHConnection.cpp", + "BOSHConnectionPool.cpp", + "CachingDomainNameResolver.cpp", + "ConnectionFactory.cpp", + "ConnectionServer.cpp", + "ConnectionServerFactory.cpp", + "DummyConnection.cpp", + "FakeConnection.cpp", + "ChainedConnector.cpp", + "Connector.cpp", + "Connection.cpp", + "TimerFactory.cpp", + "DummyTimerFactory.cpp", + "BoostTimerFactory.cpp", + "DomainNameResolver.cpp", + "DomainNameAddressQuery.cpp", + "DomainNameServiceQuery.cpp", + "StaticDomainNameResolver.cpp", + "HostAddress.cpp", + "HostAddressPort.cpp", + "HostNameOrAddress.cpp", + "NetworkFactories.cpp", + "BoostNetworkFactories.cpp", + "NetworkEnvironment.cpp", + "Timer.cpp", + "TLSConnection.cpp", + "TLSConnectionFactory.cpp", + "BoostTimer.cpp", + "ProxyProvider.cpp", + "NullProxyProvider.cpp", + "NATTraverser.cpp", + "NullNATTraverser.cpp", + "NATTraversalGetPublicIPRequest.cpp", + "NATTraversalForwardPortRequest.cpp", + "NATTraversalRemovePortForwardingRequest.cpp", + "NATTraversalInterface.cpp", + "HTTPTrafficFilter.cpp", + ] if myenv.get("unbound", False) : - myenv.Append(CPPDEFINES = "USE_UNBOUND") - sourceList.append("UnboundDomainNameResolver.cpp") + myenv.Append(CPPDEFINES = "USE_UNBOUND") + sourceList.append("UnboundDomainNameResolver.cpp") else : - sourceList.append("PlatformDomainNameResolver.cpp") - sourceList.append("PlatformDomainNameServiceQuery.cpp") - sourceList.append("PlatformDomainNameAddressQuery.cpp") + sourceList.append("PlatformDomainNameResolver.cpp") + sourceList.append("PlatformDomainNameServiceQuery.cpp") + sourceList.append("PlatformDomainNameAddressQuery.cpp") if myenv["PLATFORM"] == "darwin" and myenv["target"] != "android": - myenv.Append(FRAMEWORKS = ["CoreServices", "SystemConfiguration"]) - sourceList += [ "MacOSXProxyProvider.cpp" ] - sourceList += [ "UnixNetworkEnvironment.cpp" ] + myenv.Append(FRAMEWORKS = ["CoreServices", "SystemConfiguration"]) + sourceList += [ "MacOSXProxyProvider.cpp" ] + sourceList += [ "UnixNetworkEnvironment.cpp" ] elif myenv["PLATFORM"] == "win32" : - sourceList += [ "WindowsProxyProvider.cpp" ] - sourceList += [ "WindowsNetworkEnvironment.cpp" ] + sourceList += [ "WindowsProxyProvider.cpp" ] + sourceList += [ "WindowsNetworkEnvironment.cpp" ] +elif myenv["PLATFORM"] == "sunos" : + sourceList += [ "UnixProxyProvider.cpp" ] + sourceList += [ "SolarisNetworkEnvironment.cpp" ] + sourceList += [ "EnvironmentProxyProvider.cpp" ] else : - sourceList += [ "UnixNetworkEnvironment.cpp" ] - sourceList += [ "UnixProxyProvider.cpp" ] - sourceList += [ "EnvironmentProxyProvider.cpp" ] - if myenv.get("HAVE_GCONF", 0) : - myenv.Append(CPPDEFINES = "HAVE_GCONF") - myenv.MergeFlags(myenv["GCONF_FLAGS"]) - sourceList += [ "GConfProxyProvider.cpp" ] + sourceList += [ "UnixNetworkEnvironment.cpp" ] + sourceList += [ "UnixProxyProvider.cpp" ] + sourceList += [ "EnvironmentProxyProvider.cpp" ] + if myenv.get("HAVE_GCONF", 0) : + myenv.Append(CPPDEFINES = "HAVE_GCONF") + myenv.MergeFlags(myenv["GCONF_FLAGS"]) + sourceList += [ "GConfProxyProvider.cpp" ] objects = myenv.SwiftenObject(sourceList) -if myenv["experimental"] : - # LibNATPMP classes - if myenv.get("HAVE_LIBNATPMP", False) : - natpmp_env = myenv.Clone() - natpmp_env.Append(CPPDEFINES = natpmp_env["LIBNATPMP_FLAGS"].get("INTERNAL_CPPDEFINES", [])) - myenv.Append(CPPDEFINES = ["HAVE_LIBNATPMP"]) - objects += natpmp_env.SwiftenObject([ - "NATPMPInterface.cpp", - ]) +if myenv["experimental_ft"] : + # LibNATPMP classes + if myenv.get("HAVE_LIBNATPMP", False) : + natpmp_env = myenv.Clone() + natpmp_env.Append(CPPDEFINES = natpmp_env["LIBNATPMP_FLAGS"].get("INTERNAL_CPPDEFINES", [])) + myenv.Append(CPPDEFINES = ["HAVE_LIBNATPMP"]) + objects += natpmp_env.SwiftenObject([ + "NATPMPInterface.cpp", + ]) - # LibMINIUPnP classes - if myenv.get("HAVE_LIBMINIUPNPC", False) : - upnp_env = myenv.Clone() - upnp_env.Append(CPPDEFINES = upnp_env["LIBMINIUPNPC_FLAGS"].get("INTERNAL_CPPDEFINES", [])) - myenv.Append(CPPDEFINES = ["HAVE_LIBMINIUPNPC"]) - objects += upnp_env.SwiftenObject([ - "MiniUPnPInterface.cpp", - ]) - objects += myenv.SwiftenObject([ - "PlatformNATTraversalWorker.cpp", - ]) + # LibMINIUPnP classes + if myenv.get("HAVE_LIBMINIUPNPC", False) : + upnp_env = myenv.Clone() + upnp_env.Append(CPPDEFINES = upnp_env["LIBMINIUPNPC_FLAGS"].get("INTERNAL_CPPDEFINES", [])) + myenv.Append(CPPDEFINES = ["HAVE_LIBMINIUPNPC"]) + objects += upnp_env.SwiftenObject([ + "MiniUPnPInterface.cpp", + ]) + objects += myenv.SwiftenObject([ + "PlatformNATTraversalWorker.cpp", + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Network/SOCKS5ProxiedConnection.cpp b/Swiften/Network/SOCKS5ProxiedConnection.cpp index a9243d6..c76b6e6 100644 --- a/Swiften/Network/SOCKS5ProxiedConnection.cpp +++ b/Swiften/Network/SOCKS5ProxiedConnection.cpp @@ -4,112 +4,117 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Network/SOCKS5ProxiedConnection.h> -#include <iostream> #include <boost/bind.hpp> -#include <boost/thread.hpp> -#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Log.h> #include <Swiften/Base/String.h> -#include <Swiften/Base/ByteArray.h> +#include <Swiften/Network/ConnectionFactory.h> #include <Swiften/Network/HostAddressPort.h> using namespace Swift; SOCKS5ProxiedConnection::SOCKS5ProxiedConnection( - DomainNameResolver* resolver, - ConnectionFactory* connectionFactory, - TimerFactory* timerFactory, - const std::string& proxyHost, - int proxyPort) : - ProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort) { - } + DomainNameResolver* resolver, + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + const std::string& proxyHost, + unsigned short proxyPort) : + ProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort), + proxyState_(Initial) { + } void SOCKS5ProxiedConnection::initializeProxy() { - proxyState_ = ProxyAuthenticating; - SafeByteArray socksConnect; - socksConnect.push_back(0x05); // VER = SOCKS5 = 0x05 - socksConnect.push_back(0x01); // Number of authentication methods after this byte. - socksConnect.push_back(0x00); // 0x00 == no authentication - // buffer.push_back(0x01); // 0x01 == GSSAPI - // buffer.push_back(0x02); // 0x02 == Username/Password - // rest see RFC 1928 (http://tools.ietf.org/html/rfc1928) - write(socksConnect); + proxyState_ = ProxyAuthenticating; + SafeByteArray socksConnect; + socksConnect.push_back(0x05); // VER = SOCKS5 = 0x05 + socksConnect.push_back(0x01); // Number of authentication methods after this byte. + socksConnect.push_back(0x00); // 0x00 == no authentication + // buffer.push_back(0x01); // 0x01 == GSSAPI + // buffer.push_back(0x02); // 0x02 == Username/Password + // rest see RFC 1928 (http://tools.ietf.org/html/rfc1928) + write(socksConnect); } -void SOCKS5ProxiedConnection::handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data) { - SafeByteArray socksConnect; - boost::asio::ip::address rawAddress = getServer().getAddress().getRawAddress(); - assert(rawAddress.is_v4() || rawAddress.is_v6()); +void SOCKS5ProxiedConnection::handleProxyInitializeData(std::shared_ptr<SafeByteArray> data) { + SafeByteArray socksConnect; + boost::asio::ip::address rawAddress = getServer().getAddress().getRawAddress(); + assert(rawAddress.is_v4() || rawAddress.is_v6()); + + if (proxyState_ == ProxyAuthenticating) { + SWIFT_LOG(debug) << "ProxyAuthenticating response received, reply with the connect BYTEs"; + unsigned char choosenMethod = static_cast<unsigned char> ((*data)[1]); + if ((*data)[0] == 0x05 && choosenMethod != 0xFF) { + switch(choosenMethod) { // use the correct Method + case 0x00: + try { + proxyState_ = ProxyConnecting; + socksConnect.push_back(0x05); // VER = SOCKS5 = 0x05 + socksConnect.push_back(0x01); // Construct a TCP connection. (CMD) + socksConnect.push_back(0x00); // reserved. + socksConnect.push_back(rawAddress.is_v4() ? 0x01 : 0x04); // IPv4 == 0x01, Hostname == 0x02, IPv6 == 0x04. (ATYP) + size_t size = rawAddress.is_v4() ? rawAddress.to_v4().to_bytes().size() : rawAddress.to_v6().to_bytes().size(); + for (size_t s = 0; s < size; s++) { + unsigned char uc; + if(rawAddress.is_v4()) { + uc = rawAddress.to_v4().to_bytes()[s]; // the address. + } + else { + uc = rawAddress.to_v6().to_bytes()[s]; // the address. + } + socksConnect.push_back(uc); - if (proxyState_ == ProxyAuthenticating) { - SWIFT_LOG(debug) << "ProxyAuthenticating response received, reply with the connect BYTEs" << std::endl; - unsigned char choosenMethod = static_cast<unsigned char> ((*data)[1]); - if ((*data)[0] == 0x05 && choosenMethod != 0xFF) { - switch(choosenMethod) { // use the correct Method - case 0x00: - try { - proxyState_ = ProxyConnecting; - socksConnect.push_back(0x05); // VER = SOCKS5 = 0x05 - socksConnect.push_back(0x01); // Construct a TCP connection. (CMD) - socksConnect.push_back(0x00); // reserved. - socksConnect.push_back(rawAddress.is_v4() ? 0x01 : 0x04); // IPv4 == 0x01, Hostname == 0x02, IPv6 == 0x04. (ATYP) - size_t size = rawAddress.is_v4() ? rawAddress.to_v4().to_bytes().size() : rawAddress.to_v6().to_bytes().size(); - for (size_t s = 0; s < size; s++) { - unsigned char uc; - if(rawAddress.is_v4()) { - uc = rawAddress.to_v4().to_bytes()[s]; // the address. - } - else { - uc = rawAddress.to_v6().to_bytes()[s]; // the address. - } - socksConnect.push_back(uc); - - } - socksConnect.push_back(static_cast<unsigned char> ((getServer().getPort() >> 8) & 0xFF)); // highbyte of the port. - socksConnect.push_back(static_cast<unsigned char> (getServer().getPort() & 0xFF)); // lowbyte of the port. - write(socksConnect); - return; - } - catch(...) { - std::cerr << "exception caught" << std::endl; - } - write(socksConnect); - break; - default: - setProxyInitializeFinished(true); - break; - } - return; - } - setProxyInitializeFinished(false); - } - else if (proxyState_ == ProxyConnecting) { - SWIFT_LOG(debug) << "Connect response received, check if successfully." << std::endl; - SWIFT_LOG(debug) << "Errorbyte: 0x" << std::hex << static_cast<int> ((*data)[1]) << std::dec << std::endl; - /* + } + socksConnect.push_back(static_cast<unsigned char> ((getServer().getPort() >> 8) & 0xFF)); // highbyte of the port. + socksConnect.push_back(static_cast<unsigned char> (getServer().getPort() & 0xFF)); // lowbyte of the port. + write(socksConnect); + return; + } + catch(...) { + SWIFT_LOG(error) << "exception caught"; + } + write(socksConnect); + break; + default: + setProxyInitializeFinished(true); + break; + } + return; + } + setProxyInitializeFinished(false); + } + else if (proxyState_ == ProxyConnecting) { + SWIFT_LOG(debug) << "Connect response received, check if successfully."; + SWIFT_LOG(debug) << "Errorbyte: 0x" << std::hex << static_cast<int> ((*data)[1]) << std::dec; + /* - data.at(1) can be one of the following: - 0x00 succeeded - 0x01 general SOCKS server failure - 0x02 connection not allowed by ruleset - 0x03 Network unreachable - 0x04 Host unreachable - 0x05 Connection refused - 0x06 TTL expired - 0x07 Command not supported (CMD) - 0x08 Address type not supported (ATYP) - 0x09 bis 0xFF unassigned - */ - if ((*data)[0] == 0x05 && (*data)[1] == 0x0) { - SWIFT_LOG(debug) << "Successfully connected the server via the proxy." << std::endl; - setProxyInitializeFinished(true); - } - else { - std::cerr << "SOCKS Proxy returned an error: " << std::hex << (*data)[1] << std::endl; - setProxyInitializeFinished(false); - } - } + data.at(1) can be one of the following: + 0x00 succeeded + 0x01 general SOCKS server failure + 0x02 connection not allowed by ruleset + 0x03 Network unreachable + 0x04 Host unreachable + 0x05 Connection refused + 0x06 TTL expired + 0x07 Command not supported (CMD) + 0x08 Address type not supported (ATYP) + 0x09 bis 0xFF unassigned + */ + if ((*data)[0] == 0x05 && (*data)[1] == 0x0) { + SWIFT_LOG(debug) << "Successfully connected the server via the proxy."; + setProxyInitializeFinished(true); + } + else { + SWIFT_LOG(error) << "SOCKS Proxy returned an error: " << std::hex << (*data)[1]; + setProxyInitializeFinished(false); + } + } } diff --git a/Swiften/Network/SOCKS5ProxiedConnection.h b/Swiften/Network/SOCKS5ProxiedConnection.h index 7906879..515c5b7 100644 --- a/Swiften/Network/SOCKS5ProxiedConnection.h +++ b/Swiften/Network/SOCKS5ProxiedConnection.h @@ -4,33 +4,41 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Network/ProxiedConnection.h> namespace Swift { - class ConnectionFactory; - class DomainNameResolver; - class TimerFactory; - - class SOCKS5ProxiedConnection : public ProxiedConnection { - public: - typedef boost::shared_ptr<SOCKS5ProxiedConnection> ref; - - static ref create(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort) { - return ref(new SOCKS5ProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort)); - } - - private: - SOCKS5ProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort); - - virtual void initializeProxy(); - virtual void handleProxyInitializeData(boost::shared_ptr<SafeByteArray> data); - - private: - enum { - ProxyAuthenticating = 0, - ProxyConnecting - } proxyState_; - }; + class ConnectionFactory; + class DomainNameResolver; + class TimerFactory; + + class SWIFTEN_API SOCKS5ProxiedConnection : public ProxiedConnection { + public: + typedef std::shared_ptr<SOCKS5ProxiedConnection> ref; + + static ref create(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort) { + return ref(new SOCKS5ProxiedConnection(resolver, connectionFactory, timerFactory, proxyHost, proxyPort)); + } + + private: + SOCKS5ProxiedConnection(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort); + + virtual void initializeProxy(); + virtual void handleProxyInitializeData(std::shared_ptr<SafeByteArray> data); + + private: + enum { + Initial = 0, + ProxyAuthenticating, + ProxyConnecting + } proxyState_; + }; } diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp index af99034..abd7718 100644 --- a/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp +++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp @@ -4,17 +4,23 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Network/SOCKS5ProxiedConnectionFactory.h> #include <Swiften/Network/SOCKS5ProxiedConnection.h> namespace Swift { -SOCKS5ProxiedConnectionFactory::SOCKS5ProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), proxyHost_(proxyHost), proxyPort_(proxyPort) { +SOCKS5ProxiedConnectionFactory::SOCKS5ProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort) : resolver_(resolver), connectionFactory_(connectionFactory), timerFactory_(timerFactory), proxyHost_(proxyHost), proxyPort_(proxyPort) { } -boost::shared_ptr<Connection> SOCKS5ProxiedConnectionFactory::createConnection() { - return SOCKS5ProxiedConnection::create(resolver_, connectionFactory_, timerFactory_, proxyHost_, proxyPort_); +std::shared_ptr<Connection> SOCKS5ProxiedConnectionFactory::createConnection() { + return SOCKS5ProxiedConnection::create(resolver_, connectionFactory_, timerFactory_, proxyHost_, proxyPort_); } } diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.h b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h index 4c5c585..47ae9a3 100644 --- a/Swiften/Network/SOCKS5ProxiedConnectionFactory.h +++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h @@ -4,27 +4,34 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Network/ConnectionFactory.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/HostNameOrAddress.h> namespace Swift { - class DomainNameResolver; - class TimerFactory; + class DomainNameResolver; + class TimerFactory; - class SOCKS5ProxiedConnectionFactory : public ConnectionFactory { - public: - SOCKS5ProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, int proxyPort); + class SWIFTEN_API SOCKS5ProxiedConnectionFactory : public ConnectionFactory { + public: + SOCKS5ProxiedConnectionFactory(DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory, const std::string& proxyHost, unsigned short proxyPort); - virtual boost::shared_ptr<Connection> createConnection(); + virtual std::shared_ptr<Connection> createConnection(); - private: - DomainNameResolver* resolver_; - ConnectionFactory* connectionFactory_; - TimerFactory* timerFactory_; - std::string proxyHost_; - int proxyPort_; - }; + private: + DomainNameResolver* resolver_; + ConnectionFactory* connectionFactory_; + TimerFactory* timerFactory_; + std::string proxyHost_; + unsigned short proxyPort_; + }; } diff --git a/Swiften/Network/SolarisNetworkEnvironment.cpp b/Swiften/Network/SolarisNetworkEnvironment.cpp new file mode 100644 index 0000000..db8c740 --- /dev/null +++ b/Swiften/Network/SolarisNetworkEnvironment.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Network/SolarisNetworkEnvironment.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <map> +#include <string> +#include <vector> + +#include <boost/optional.hpp> +#include <boost/signals2.hpp> + +#include <net/if.h> +#include <sys/socket.h> +#include <sys/sockio.h> +#include <sys/types.h> +#include <unistd.h> + +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/NetworkInterface.h> + +/* + * Copyright (c) 2006 WIDE Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#undef ifa_broadaddr +#undef ifa_dstaddr +struct ifaddrs { + struct ifaddrs *ifa_next; /* Pointer to next struct */ + char *ifa_name; /* Interface name */ + uint64_t ifa_flags; /* Interface flags */ + struct sockaddr *ifa_addr; /* Interface address */ + struct sockaddr *ifa_netmask; /* Interface netmask */ + struct sockaddr *ifa_dstaddr; /* P2P interface destination */ +}; +#define ifa_broadaddr ifa_dstaddr + +static int +get_lifreq(int fd, struct lifreq **ifr_ret) +{ + struct lifnum lifn; + struct lifconf lifc; + struct lifreq *lifrp; + + lifn.lifn_family = AF_UNSPEC; + lifn.lifn_flags = 0; + if (ioctl(fd, SIOCGLIFNUM, &lifn) == -1) + lifn.lifn_count = 16; + else + lifn.lifn_count += 16; + + for (;;) { + lifc.lifc_len = lifn.lifn_count * sizeof (*lifrp); + lifrp = (struct lifreq *) malloc(lifc.lifc_len); + if (lifrp == NULL) + return (-1); + + lifc.lifc_family = AF_UNSPEC; + lifc.lifc_flags = 0; + lifc.lifc_buf = (char *)lifrp; + if (ioctl(fd, SIOCGLIFCONF, &lifc) == -1) { + free(lifrp); + if (errno == EINVAL) { + lifn.lifn_count <<= 1; + continue; + } + (void) close(fd); + return (-1); + } + if (lifc.lifc_len < (lifn.lifn_count - 1) * sizeof (*lifrp)) + break; + free(lifrp); + lifn.lifn_count <<= 1; + } + (void) close(fd); + + *ifr_ret = lifrp; + + return (lifc.lifc_len / sizeof (*lifrp)); +} + +static size_t +nbytes(const struct lifreq *lifrp, int nlif, size_t socklen) +{ + size_t len = 0; + size_t slen; + + while (nlif > 0) { + slen = strlen(lifrp->lifr_name) + 1; + len += sizeof (struct ifaddrs) + ((slen + 3) & ~3); + len += 3 * socklen; + lifrp++; + nlif--; + } + return (len); +} + +static struct sockaddr * +addrcpy(struct sockaddr_storage *addr, char **bufp) +{ + char *buf = *bufp; + size_t len; + + len = addr->ss_family == AF_INET ? sizeof (struct sockaddr_in) : + sizeof (struct sockaddr_in6); + (void) memcpy(buf, addr, len); + *bufp = buf + len; + return ((struct sockaddr *)buf); +} + +static int +populate(struct ifaddrs *ifa, int fd, struct lifreq *lifrp, int nlif, int af, + char **bufp) +{ + char *buf = *bufp; + size_t slen; + + while (nlif > 0) { + ifa->ifa_next = (nlif > 1) ? ifa + 1 : NULL; + (void) strcpy(ifa->ifa_name = buf, lifrp->lifr_name); + slen = strlen(lifrp->lifr_name) + 1; + buf += (slen + 3) & ~3; + if (ioctl(fd, SIOCGLIFFLAGS, lifrp) == -1) + ifa->ifa_flags = 0; + else + ifa->ifa_flags = lifrp->lifr_flags; + if (ioctl(fd, SIOCGLIFADDR, lifrp) == -1) + ifa->ifa_addr = NULL; + else + ifa->ifa_addr = addrcpy(&lifrp->lifr_addr, &buf); + if (ioctl(fd, SIOCGLIFNETMASK, lifrp) == -1) + ifa->ifa_netmask = NULL; + else + ifa->ifa_netmask = addrcpy(&lifrp->lifr_addr, &buf); + if (ifa->ifa_flags & IFF_POINTOPOINT) { + if (ioctl(fd, SIOCGLIFDSTADDR, lifrp) == -1) + ifa->ifa_dstaddr = NULL; + else + ifa->ifa_dstaddr = + addrcpy(&lifrp->lifr_dstaddr, &buf); + } else if (ifa->ifa_flags & IFF_BROADCAST) { + if (ioctl(fd, SIOCGLIFBRDADDR, lifrp) == -1) + ifa->ifa_broadaddr = NULL; + else + ifa->ifa_broadaddr = + addrcpy(&lifrp->lifr_broadaddr, &buf); + } else { + ifa->ifa_dstaddr = NULL; + } + + ifa++; + nlif--; + lifrp++; + } + *bufp = buf; + return (0); +} + +static int +getifaddrs(struct ifaddrs **ifap) +{ + int fd4, fd6; + int nif4, nif6 = 0; + struct lifreq *ifr4 = NULL; + struct lifreq *ifr6 = NULL; + struct ifaddrs *ifa = NULL; + char *buf; + + if ((fd4 = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + return (-1); + if ((fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) == -1 && + errno != EAFNOSUPPORT) { + (void) close(fd4); + return (-1); + } + + if ((nif4 = get_lifreq(fd4, &ifr4)) == -1 || + (fd6 != -1 && (nif6 = get_lifreq(fd6, &ifr6)) == -1)) + goto failure; + + if (nif4 == 0 && nif6 == 0) { + *ifap = NULL; + return (0); + } + + ifa = (struct ifaddrs *) malloc(nbytes(ifr4, nif4, sizeof (struct sockaddr_in)) + + nbytes(ifr6, nif6, sizeof (struct sockaddr_in6))); + if (ifa == NULL) + goto failure; + + buf = (char *)(ifa + nif4 + nif6); + + if (populate(ifa, fd4, ifr4, nif4, AF_INET, &buf) == -1) + goto failure; + if (nif4 > 0 && nif6 > 0) + ifa[nif4 - 1].ifa_next = ifa + nif4; + if (populate(ifa + nif4, fd6, ifr6, nif6, AF_INET6, &buf) == -1) + goto failure; + + return (0); + +failure: + free(ifa); + (void) close(fd4); + if (fd6 != -1) + (void) close(fd6); + free(ifr4); + free(ifr6); + return (-1); +} + +static void +freeifaddrs(struct ifaddrs *ifa) +{ + free(ifa); +} + +/* End WIDE Project code */ + +namespace Swift { + +std::vector<NetworkInterface> SolarisNetworkEnvironment::getNetworkInterfaces() const { + std::map<std::string, NetworkInterface> interfaces; + + ifaddrs* addrs = 0; + int ret = getifaddrs(&addrs); + if (ret != 0) { + return std::vector<NetworkInterface>(); + } + + for (ifaddrs* a = addrs; a != 0; a = a->ifa_next) { + std::string name(a->ifa_name); + boost::optional<HostAddress> address; + if (a->ifa_addr->sa_family == PF_INET) { + sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(a->ifa_addr); + address = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin_addr)), 4); + } + else if (a->ifa_addr->sa_family == PF_INET6) { + sockaddr_in6* sa = reinterpret_cast<sockaddr_in6*>(a->ifa_addr); + address = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin6_addr)), 16); + } + if (address) { + std::map<std::string, NetworkInterface>::iterator i = interfaces.insert(std::make_pair(name, NetworkInterface(name, a->ifa_flags & IFF_LOOPBACK))).first; + i->second.addAddress(*address); + } + } + + freeifaddrs(addrs); + + std::vector<NetworkInterface> result; + for (std::map<std::string,NetworkInterface>::const_iterator i = interfaces.begin(); i != interfaces.end(); ++i) { + result.push_back(i->second); + } + return result; +} + +} diff --git a/Swiften/Network/SolarisNetworkEnvironment.h b/Swiften/Network/SolarisNetworkEnvironment.h new file mode 100644 index 0000000..199fc6f --- /dev/null +++ b/Swiften/Network/SolarisNetworkEnvironment.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <vector> + +#include <boost/signals2.hpp> + +#include <Swiften/Network/NetworkEnvironment.h> +#include <Swiften/Network/NetworkInterface.h> + +namespace Swift { + + class SolarisNetworkEnvironment : public NetworkEnvironment { + public: + std::vector<NetworkInterface> getNetworkInterfaces() const; + }; + +} diff --git a/Swiften/Network/StaticDomainNameResolver.cpp b/Swiften/Network/StaticDomainNameResolver.cpp index ee18ee5..eca6687 100644 --- a/Swiften/Network/StaticDomainNameResolver.cpp +++ b/Swiften/Network/StaticDomainNameResolver.cpp @@ -1,80 +1,85 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/StaticDomainNameResolver.h> +#include <string> + #include <boost/bind.hpp> #include <boost/lexical_cast.hpp> -#include <Swiften/Network/DomainNameResolveError.h> #include <Swiften/EventLoop/EventOwner.h> -#include <string> +#include <Swiften/Network/DomainNameResolveError.h> using namespace Swift; namespace { - struct ServiceQuery : public DomainNameServiceQuery, public boost::enable_shared_from_this<ServiceQuery> { - ServiceQuery(const std::string& service, Swift::StaticDomainNameResolver* resolver, EventLoop* eventLoop, boost::shared_ptr<EventOwner> owner) : eventLoop(eventLoop), service(service), resolver(resolver), owner(owner) {} - - virtual void run() { - if (!resolver->getIsResponsive()) { - return; - } - std::vector<DomainNameServiceQuery::Result> results; - for(StaticDomainNameResolver::ServicesCollection::const_iterator i = resolver->getServices().begin(); i != resolver->getServices().end(); ++i) { - if (i->first == service) { - results.push_back(i->second); - } - } - eventLoop->postEvent(boost::bind(&ServiceQuery::emitOnResult, shared_from_this(), results), owner); - } - - void emitOnResult(std::vector<DomainNameServiceQuery::Result> results) { - onResult(results); - } - - EventLoop* eventLoop; - std::string service; - StaticDomainNameResolver* resolver; - boost::shared_ptr<EventOwner> owner; - }; - - struct AddressQuery : public DomainNameAddressQuery, public boost::enable_shared_from_this<AddressQuery> { - AddressQuery(const std::string& host, StaticDomainNameResolver* resolver, EventLoop* eventLoop, boost::shared_ptr<EventOwner> owner) : eventLoop(eventLoop), host(host), resolver(resolver), owner(owner) {} - - virtual void run() { - if (!resolver->getIsResponsive()) { - return; - } - StaticDomainNameResolver::AddressesMap::const_iterator i = resolver->getAddresses().find(host); - if (i != resolver->getAddresses().end()) { - eventLoop->postEvent( - boost::bind(&AddressQuery::emitOnResult, shared_from_this(), i->second, boost::optional<DomainNameResolveError>())); - } - else { - eventLoop->postEvent(boost::bind(&AddressQuery::emitOnResult, shared_from_this(), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), owner); - } - } - - void emitOnResult(std::vector<HostAddress> results, boost::optional<DomainNameResolveError> error) { - onResult(results, error); - } - - EventLoop* eventLoop; - std::string host; - StaticDomainNameResolver* resolver; - boost::shared_ptr<EventOwner> owner; - }; + struct ServiceQuery : public DomainNameServiceQuery, public std::enable_shared_from_this<ServiceQuery> { + ServiceQuery(const std::string& service, Swift::StaticDomainNameResolver* resolver, EventLoop* eventLoop, std::shared_ptr<EventOwner> owner) : eventLoop(eventLoop), service(service), resolver(resolver), owner(owner) {} + + virtual void run() { + if (!resolver->getIsResponsive()) { + return; + } + std::vector<DomainNameServiceQuery::Result> results; + for(const auto& i : resolver->getServices()) { + if (i.first == service) { + results.push_back(i.second); + } + } + eventLoop->postEvent(boost::bind(&ServiceQuery::emitOnResult, shared_from_this(), results), owner); + } + + void emitOnResult(std::vector<DomainNameServiceQuery::Result> results) { + onResult(results); + } + + EventLoop* eventLoop; + std::string service; + StaticDomainNameResolver* resolver; + std::shared_ptr<EventOwner> owner; + }; + + struct AddressQuery : public DomainNameAddressQuery, public std::enable_shared_from_this<AddressQuery> { + AddressQuery(const std::string& host, StaticDomainNameResolver* resolver, EventLoop* eventLoop, std::shared_ptr<EventOwner> owner) : eventLoop(eventLoop), host(host), resolver(resolver), owner(owner) {} + + virtual void run() { + if (!resolver->getIsResponsive()) { + return; + } + if (auto address = HostAddress::fromString(host)) { + // IP Literals should resolve to themselves + resolver->addAddress(host, *address); + } + StaticDomainNameResolver::AddressesMap::const_iterator i = resolver->getAddresses().find(host); + if (i != resolver->getAddresses().end()) { + eventLoop->postEvent( + boost::bind(&AddressQuery::emitOnResult, shared_from_this(), i->second, boost::optional<DomainNameResolveError>())); + } + else { + eventLoop->postEvent(boost::bind(&AddressQuery::emitOnResult, shared_from_this(), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), owner); + } + } + + void emitOnResult(std::vector<HostAddress> results, boost::optional<DomainNameResolveError> error) { + onResult(results, error); + } + + EventLoop* eventLoop; + std::string host; + StaticDomainNameResolver* resolver; + std::shared_ptr<EventOwner> owner; + }; } class StaticDomainNameResolverEventOwner : public EventOwner { - public: - ~StaticDomainNameResolverEventOwner() { + public: + ~StaticDomainNameResolverEventOwner() { - } + } }; @@ -84,36 +89,36 @@ StaticDomainNameResolver::StaticDomainNameResolver(EventLoop* eventLoop) : event } StaticDomainNameResolver::~StaticDomainNameResolver() { - eventLoop->removeEventsFromOwner(owner); + eventLoop->removeEventsFromOwner(owner); } void StaticDomainNameResolver::addAddress(const std::string& domain, const HostAddress& address) { - addresses[domain].push_back(address); + addresses[domain].push_back(address); } void StaticDomainNameResolver::addService(const std::string& service, const DomainNameServiceQuery::Result& result) { - services.push_back(std::make_pair(service, result)); + services.push_back(std::make_pair(service, result)); } void StaticDomainNameResolver::addXMPPClientService(const std::string& domain, const HostAddressPort& address) { - static int hostid = 0; - std::string hostname(std::string("host-") + boost::lexical_cast<std::string>(hostid)); - hostid++; + static int hostid = 0; + std::string hostname(std::string("host-") + std::to_string(hostid)); + hostid++; - addService("_xmpp-client._tcp." + domain, ServiceQuery::Result(hostname, address.getPort(), 0, 0)); - addAddress(hostname, address.getAddress()); + addService("_xmpp-client._tcp." + domain, ServiceQuery::Result(hostname, address.getPort(), 0, 0)); + addAddress(hostname, address.getAddress()); } -void StaticDomainNameResolver::addXMPPClientService(const std::string& domain, const std::string& hostname, int port) { - addService("_xmpp-client._tcp." + domain, ServiceQuery::Result(hostname, port, 0, 0)); +void StaticDomainNameResolver::addXMPPClientService(const std::string& domain, const std::string& hostname, unsigned short port) { + addService("_xmpp-client._tcp." + domain, ServiceQuery::Result(hostname, port, 0, 0)); } -boost::shared_ptr<DomainNameServiceQuery> StaticDomainNameResolver::createServiceQuery(const std::string& name) { - return boost::shared_ptr<DomainNameServiceQuery>(new ServiceQuery(name, this, eventLoop, owner)); +std::shared_ptr<DomainNameServiceQuery> StaticDomainNameResolver::createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) { + return std::make_shared<ServiceQuery>(serviceLookupPrefix + domain, this, eventLoop, owner); } -boost::shared_ptr<DomainNameAddressQuery> StaticDomainNameResolver::createAddressQuery(const std::string& name) { - return boost::shared_ptr<DomainNameAddressQuery>(new AddressQuery(name, this, eventLoop, owner)); +std::shared_ptr<DomainNameAddressQuery> StaticDomainNameResolver::createAddressQuery(const std::string& name) { + return std::make_shared<AddressQuery>(name, this, eventLoop, owner); } } diff --git a/Swiften/Network/StaticDomainNameResolver.h b/Swiften/Network/StaticDomainNameResolver.h index 386179b..2064046 100644 --- a/Swiften/Network/StaticDomainNameResolver.h +++ b/Swiften/Network/StaticDomainNameResolver.h @@ -1,60 +1,61 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <map> +#include <memory> +#include <vector> #include <Swiften/Base/API.h> -#include <Swiften/Network/HostAddress.h> -#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/Network/DomainNameAddressQuery.h> #include <Swiften/Network/DomainNameResolver.h> #include <Swiften/Network/DomainNameServiceQuery.h> -#include <Swiften/Network/DomainNameAddressQuery.h> -#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/HostAddressPort.h> namespace Swift { - class SWIFTEN_API StaticDomainNameResolver : public DomainNameResolver { - public: - typedef std::map<std::string, std::vector<HostAddress> > AddressesMap; - typedef std::vector< std::pair<std::string, DomainNameServiceQuery::Result> > ServicesCollection; - - public: - StaticDomainNameResolver(EventLoop* eventLoop); - ~StaticDomainNameResolver(); - - void addAddress(const std::string& domain, const HostAddress& address); - void addService(const std::string& service, const DomainNameServiceQuery::Result& result); - void addXMPPClientService(const std::string& domain, const HostAddressPort&); - void addXMPPClientService(const std::string& domain, const std::string& host, int port); - - const AddressesMap& getAddresses() const { - return addresses; - } - - const ServicesCollection& getServices() const { - return services; - } - - bool getIsResponsive() const { - return isResponsive; - } - - void setIsResponsive(bool b) { - isResponsive = b; - } - - virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& name); - virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name); - private: - EventLoop* eventLoop; - bool isResponsive; - AddressesMap addresses; - ServicesCollection services; - boost::shared_ptr<EventOwner> owner; - }; + class SWIFTEN_API StaticDomainNameResolver : public DomainNameResolver { + public: + typedef std::map<std::string, std::vector<HostAddress> > AddressesMap; + typedef std::vector< std::pair<std::string, DomainNameServiceQuery::Result> > ServicesCollection; + + public: + StaticDomainNameResolver(EventLoop* eventLoop); + virtual ~StaticDomainNameResolver(); + + void addAddress(const std::string& domain, const HostAddress& address); + void addService(const std::string& service, const DomainNameServiceQuery::Result& result); + void addXMPPClientService(const std::string& domain, const HostAddressPort&); + void addXMPPClientService(const std::string& domain, const std::string& host, unsigned short port); + + const AddressesMap& getAddresses() const { + return addresses; + } + + const ServicesCollection& getServices() const { + return services; + } + + bool getIsResponsive() const { + return isResponsive; + } + + void setIsResponsive(bool b) { + isResponsive = b; + } + + virtual std::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain); + virtual std::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name); + private: + EventLoop* eventLoop; + bool isResponsive; + AddressesMap addresses; + ServicesCollection services; + std::shared_ptr<EventOwner> owner; + }; } diff --git a/Swiften/Network/TLSConnection.cpp b/Swiften/Network/TLSConnection.cpp index 543ee1e..82bf114 100644 --- a/Swiften/Network/TLSConnection.cpp +++ b/Swiften/Network/TLSConnection.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/TLSConnection.h> @@ -14,78 +14,85 @@ namespace Swift { -TLSConnection::TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory) : connection(connection) { - context = tlsFactory->createTLSContext(); - context->onDataForNetwork.connect(boost::bind(&TLSConnection::handleTLSDataForNetwork, this, _1)); - context->onDataForApplication.connect(boost::bind(&TLSConnection::handleTLSDataForApplication, this, _1)); - context->onConnected.connect(boost::bind(&TLSConnection::handleTLSConnectFinished, this, false)); - context->onError.connect(boost::bind(&TLSConnection::handleTLSConnectFinished, this, true)); - - connection->onConnectFinished.connect(boost::bind(&TLSConnection::handleRawConnectFinished, this, _1)); - connection->onDataRead.connect(boost::bind(&TLSConnection::handleRawDataRead, this, _1)); - connection->onDataWritten.connect(boost::bind(&TLSConnection::handleRawDataWritten, this)); - connection->onDisconnected.connect(boost::bind(&TLSConnection::handleRawDisconnected, this, _1)); +TLSConnection::TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory, const TLSOptions& tlsOptions) : connection(connection) { + context = tlsFactory->createTLSContext(tlsOptions); + context->onDataForNetwork.connect(boost::bind(&TLSConnection::handleTLSDataForNetwork, this, _1)); + context->onDataForApplication.connect(boost::bind(&TLSConnection::handleTLSDataForApplication, this, _1)); + context->onConnected.connect(boost::bind(&TLSConnection::handleTLSConnectFinished, this, false)); + context->onError.connect(boost::bind(&TLSConnection::handleTLSConnectFinished, this, true)); + + connection->onConnectFinished.connect(boost::bind(&TLSConnection::handleRawConnectFinished, this, _1)); + connection->onDataRead.connect(boost::bind(&TLSConnection::handleRawDataRead, this, _1)); + connection->onDataWritten.connect(boost::bind(&TLSConnection::handleRawDataWritten, this)); + connection->onDisconnected.connect(boost::bind(&TLSConnection::handleRawDisconnected, this, _1)); } TLSConnection::~TLSConnection() { - connection->onConnectFinished.disconnect(boost::bind(&TLSConnection::handleRawConnectFinished, this, _1)); - connection->onDataRead.disconnect(boost::bind(&TLSConnection::handleRawDataRead, this, _1)); - connection->onDataWritten.disconnect(boost::bind(&TLSConnection::handleRawDataWritten, this)); - connection->onDisconnected.disconnect(boost::bind(&TLSConnection::handleRawDisconnected, this, _1)); - delete context; + connection->onConnectFinished.disconnect(boost::bind(&TLSConnection::handleRawConnectFinished, this, _1)); + connection->onDataRead.disconnect(boost::bind(&TLSConnection::handleRawDataRead, this, _1)); + connection->onDataWritten.disconnect(boost::bind(&TLSConnection::handleRawDataWritten, this)); + connection->onDisconnected.disconnect(boost::bind(&TLSConnection::handleRawDisconnected, this, _1)); } void TLSConnection::handleTLSConnectFinished(bool error) { - onConnectFinished(error); - if (error) { - disconnect(); - } + onConnectFinished(error); + if (error) { + disconnect(); + } } void TLSConnection::handleTLSDataForNetwork(const SafeByteArray& data) { - connection->write(data); + connection->write(data); } void TLSConnection::handleTLSDataForApplication(const SafeByteArray& data) { - onDataRead(boost::make_shared<SafeByteArray>(data)); + onDataRead(std::make_shared<SafeByteArray>(data)); } void TLSConnection::connect(const HostAddressPort& address) { - connection->connect(address); + connection->connect(address); } void TLSConnection::disconnect() { - connection->disconnect(); + connection->disconnect(); } void TLSConnection::write(const SafeByteArray& data) { - context->handleDataFromApplication(data); + context->handleDataFromApplication(data); } HostAddressPort TLSConnection::getLocalAddress() const { - return connection->getLocalAddress(); + return connection->getLocalAddress(); +} + +HostAddressPort TLSConnection::getRemoteAddress() const { + return connection->getRemoteAddress(); +} + +TLSContext* TLSConnection::getTLSContext() const { + return context.get(); } void TLSConnection::handleRawConnectFinished(bool error) { - connection->onConnectFinished.disconnect(boost::bind(&TLSConnection::handleRawConnectFinished, this, _1)); - if (error) { - onConnectFinished(true); - } - else { - context->connect(); - } + connection->onConnectFinished.disconnect(boost::bind(&TLSConnection::handleRawConnectFinished, this, _1)); + if (error) { + onConnectFinished(true); + } + else { + context->connect(); + } } void TLSConnection::handleRawDisconnected(const boost::optional<Error>& error) { - onDisconnected(error); + onDisconnected(error); } -void TLSConnection::handleRawDataRead(boost::shared_ptr<SafeByteArray> data) { - context->handleDataFromNetwork(*data); +void TLSConnection::handleRawDataRead(std::shared_ptr<SafeByteArray> data) { + context->handleDataFromNetwork(*data); } void TLSConnection::handleRawDataWritten() { - onDataWritten(); + onDataWritten(); } } diff --git a/Swiften/Network/TLSConnection.h b/Swiften/Network/TLSConnection.h index 60f73ea..1ab1ec6 100644 --- a/Swiften/Network/TLSConnection.h +++ b/Swiften/Network/TLSConnection.h @@ -1,46 +1,52 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <Swiften/Base/boost_bsignals.h> +#include <memory> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> #include <Swiften/Network/Connection.h> +#include <Swiften/TLS/TLSOptions.h> namespace Swift { - class HostAddressPort; - class TLSContextFactory; - class TLSContext; - - class TLSConnection : public Connection { - public: - - TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory); - virtual ~TLSConnection(); - - virtual void listen() {assert(false);} - virtual void connect(const HostAddressPort& address); - virtual void disconnect(); - virtual void write(const SafeByteArray& data); - - virtual HostAddressPort getLocalAddress() const; - - private: - void handleRawConnectFinished(bool error); - void handleRawDisconnected(const boost::optional<Error>& error); - void handleRawDataRead(boost::shared_ptr<SafeByteArray> data); - void handleRawDataWritten(); - void handleTLSConnectFinished(bool error); - void handleTLSDataForNetwork(const SafeByteArray& data); - void handleTLSDataForApplication(const SafeByteArray& data); - private: - TLSContext* context; - Connection::ref connection; - }; + class HostAddressPort; + class TLSContextFactory; + class TLSContext; + + class SWIFTEN_API TLSConnection : public Connection { + public: + + TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory, const TLSOptions&); + virtual ~TLSConnection(); + + virtual void listen() {assert(false);} + virtual void connect(const HostAddressPort& address); + virtual void disconnect(); + virtual void write(const SafeByteArray& data); + + virtual HostAddressPort getLocalAddress() const; + virtual HostAddressPort getRemoteAddress() const; + + TLSContext* getTLSContext() const; + + private: + void handleRawConnectFinished(bool error); + void handleRawDisconnected(const boost::optional<Error>& error); + void handleRawDataRead(std::shared_ptr<SafeByteArray> data); + void handleRawDataWritten(); + void handleTLSConnectFinished(bool error); + void handleTLSDataForNetwork(const SafeByteArray& data); + void handleTLSDataForApplication(const SafeByteArray& data); + + private: + std::unique_ptr<TLSContext> context; + Connection::ref connection; + }; } diff --git a/Swiften/Network/TLSConnectionFactory.cpp b/Swiften/Network/TLSConnectionFactory.cpp index 0c21650..b311c7d 100644 --- a/Swiften/Network/TLSConnectionFactory.cpp +++ b/Swiften/Network/TLSConnectionFactory.cpp @@ -1,18 +1,18 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/TLSConnectionFactory.h> -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Network/TLSConnection.h> namespace Swift { -TLSConnectionFactory::TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory) : contextFactory(contextFactory), connectionFactory(connectionFactory){ +TLSConnectionFactory::TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory, const TLSOptions& o) : contextFactory(contextFactory), connectionFactory(connectionFactory), options_(o) { } @@ -21,8 +21,8 @@ TLSConnectionFactory::~TLSConnectionFactory() { } -boost::shared_ptr<Connection> TLSConnectionFactory::createConnection() { - return boost::make_shared<TLSConnection>(connectionFactory->createConnection(), contextFactory); +std::shared_ptr<Connection> TLSConnectionFactory::createConnection() { + return std::make_shared<TLSConnection>(connectionFactory->createConnection(), contextFactory, options_); } } diff --git a/Swiften/Network/TLSConnectionFactory.h b/Swiften/Network/TLSConnectionFactory.h index 32757a1..148e345 100644 --- a/Swiften/Network/TLSConnectionFactory.h +++ b/Swiften/Network/TLSConnectionFactory.h @@ -1,27 +1,30 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Network/ConnectionFactory.h> #include <Swiften/TLS/TLSContextFactory.h> +#include <Swiften/TLS/TLSOptions.h> namespace Swift { - class Connection; + class Connection; - class TLSConnectionFactory : public ConnectionFactory { - public: - TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory); - virtual ~TLSConnectionFactory(); + class SWIFTEN_API TLSConnectionFactory : public ConnectionFactory { + public: + TLSConnectionFactory(TLSContextFactory* contextFactory, ConnectionFactory* connectionFactory, const TLSOptions&); + virtual ~TLSConnectionFactory(); - virtual boost::shared_ptr<Connection> createConnection(); - private: - TLSContextFactory* contextFactory; - ConnectionFactory* connectionFactory; - }; + virtual std::shared_ptr<Connection> createConnection(); + private: + TLSContextFactory* contextFactory; + ConnectionFactory* connectionFactory; + TLSOptions options_; + }; } diff --git a/Swiften/Network/Timer.cpp b/Swiften/Network/Timer.cpp index 3efbd3b..f1d16bb 100644 --- a/Swiften/Network/Timer.cpp +++ b/Swiften/Network/Timer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/Timer.h> diff --git a/Swiften/Network/Timer.h b/Swiften/Network/Timer.h index d08cf3c..977ed89 100644 --- a/Swiften/Network/Timer.h +++ b/Swiften/Network/Timer.h @@ -1,41 +1,42 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> namespace Swift { - /** - * A class for triggering an event after a given period. - */ - class SWIFTEN_API Timer { - public: - typedef boost::shared_ptr<Timer> ref; - - virtual ~Timer(); - - /** - * Starts the timer. - * - * After the given period, onTick() will be called. - */ - virtual void start() = 0; - - /** - * Cancels the timer. - * - * If the timer was started, onTick() will no longer be called. - */ - virtual void stop() = 0; - - /** - * Emitted when the timer expires. - */ - boost::signal<void ()> onTick; - }; + /** + * A class for triggering an event after a given period. + */ + class SWIFTEN_API Timer { + public: + typedef std::shared_ptr<Timer> ref; + + virtual ~Timer(); + + /** + * Starts the timer. + * + * After the given period, onTick() will be called. + */ + virtual void start() = 0; + + /** + * Cancels the timer. + * + * If the timer was started, onTick() will no longer be called. + */ + virtual void stop() = 0; + + /** + * Emitted when the timer expires. + */ + boost::signals2::signal<void ()> onTick; + }; } diff --git a/Swiften/Network/TimerFactory.cpp b/Swiften/Network/TimerFactory.cpp index 3fb807c..86b8b2b 100644 --- a/Swiften/Network/TimerFactory.cpp +++ b/Swiften/Network/TimerFactory.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Network/TimerFactory.h> diff --git a/Swiften/Network/TimerFactory.h b/Swiften/Network/TimerFactory.h index 62850bc..ebb1b6e 100644 --- a/Swiften/Network/TimerFactory.h +++ b/Swiften/Network/TimerFactory.h @@ -1,21 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Network/Timer.h> namespace Swift { - class SWIFTEN_API TimerFactory { - public: - virtual ~TimerFactory(); + class SWIFTEN_API TimerFactory { + public: + virtual ~TimerFactory(); - virtual Timer::ref createTimer(int milliseconds) = 0; - }; + virtual Timer::ref createTimer(int milliseconds) = 0; + }; } diff --git a/Swiften/Network/UnboundDomainNameResolver.cpp b/Swiften/Network/UnboundDomainNameResolver.cpp index d986385..21bc697 100755..100644 --- a/Swiften/Network/UnboundDomainNameResolver.cpp +++ b/Swiften/Network/UnboundDomainNameResolver.cpp @@ -4,238 +4,249 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "UnboundDomainNameResolver.h" +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +#include <Swiften/Network/UnboundDomainNameResolver.h> + +#include <memory> #include <vector> #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/enable_shared_from_this.hpp> + +#include <arpa/inet.h> +#include <ldns/ldns.h> +#include <unbound.h> +#include <unistd.h> #include <Swiften/Base/Log.h> #include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/IDN/IDNConverter.h> #include <Swiften/Network/DomainNameAddressQuery.h> #include <Swiften/Network/DomainNameResolveError.h> #include <Swiften/Network/DomainNameServiceQuery.h> #include <Swiften/Network/HostAddress.h> #include <Swiften/Network/TimerFactory.h> -#include <arpa/inet.h> -#include <unbound.h> -#include <ldns/ldns.h> -#include <unistd.h> - namespace Swift { class UnboundQuery { - public: - UnboundQuery(UnboundDomainNameResolver* resolver, ub_ctx* context) : resolver(resolver), ubContext(context) {} - virtual ~UnboundQuery() {} - virtual void handleResult(int err, ub_result* result) = 0; - protected: - UnboundDomainNameResolver* resolver; - ub_ctx* ubContext; + public: + UnboundQuery(UnboundDomainNameResolver* resolver, ub_ctx* context) : resolver(resolver), ubContext(context) {} + virtual ~UnboundQuery() {} + virtual void handleResult(int err, ub_result* result) = 0; + protected: + UnboundDomainNameResolver* resolver; + ub_ctx* ubContext; }; struct UnboundWrapperHelper { - UnboundWrapperHelper(UnboundDomainNameResolver* resolver, boost::shared_ptr<UnboundQuery> query) : resolver(resolver), query(query) {} - UnboundDomainNameResolver* resolver; - boost::shared_ptr<UnboundQuery> query; + UnboundWrapperHelper(UnboundDomainNameResolver* resolver, std::shared_ptr<UnboundQuery> query) : resolver(resolver), query(query) {} + UnboundDomainNameResolver* resolver; + std::shared_ptr<UnboundQuery> query; }; -class UnboundDomainNameServiceQuery : public DomainNameServiceQuery, public UnboundQuery, public boost::enable_shared_from_this<UnboundDomainNameServiceQuery> { - public: - UnboundDomainNameServiceQuery(UnboundDomainNameResolver* resolver, ub_ctx* context, std::string name) : UnboundQuery(resolver, context), name(name) { - } - - virtual ~UnboundDomainNameServiceQuery() { } - - virtual void run() { - int retval; - UnboundWrapperHelper* helper = new UnboundWrapperHelper(resolver, shared_from_this()); - - retval = ub_resolve_async(ubContext, const_cast<char*>(name.c_str()), LDNS_RR_TYPE_SRV, - 1 /* CLASS IN (internet) */, - helper, UnboundDomainNameResolver::unbound_callback_wrapper, NULL); - if(retval != 0) { - SWIFT_LOG(debug) << "resolve error: " << ub_strerror(retval) << std::endl; - delete helper; - } - } - - void handleResult(int err, struct ub_result* result) { - std::vector<DomainNameServiceQuery::Result> serviceRecords; - - if(err != 0) { - SWIFT_LOG(debug) << "resolve error: " << ub_strerror(err) << std::endl; - } else { - if(result->havedata) { - ldns_pkt* replyPacket = 0; - ldns_buffer* buffer = ldns_buffer_new(1024); - if (buffer && ldns_wire2pkt(&replyPacket, static_cast<const uint8_t*>(result->answer_packet), result->answer_len) == LDNS_STATUS_OK) { - ldns_rr_list* rrList = ldns_pkt_answer(replyPacket); - for (size_t n = 0; n < ldns_rr_list_rr_count(rrList); n++) { - ldns_rr* rr = ldns_rr_list_rr(rrList, n); - if ((ldns_rr_get_type(rr) != LDNS_RR_TYPE_SRV) || - (ldns_rr_get_class(rr) != LDNS_RR_CLASS_IN) || - (ldns_rr_rd_count(rr) != 4)) { - continue; - } - - DomainNameServiceQuery::Result serviceRecord; - serviceRecord.priority = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0)); - serviceRecord.weight = ldns_rdf2native_int16(ldns_rr_rdf(rr, 1)); - serviceRecord.port = ldns_rdf2native_int16(ldns_rr_rdf(rr, 2)); - - ldns_buffer_rewind(buffer); - if ((ldns_rdf2buffer_str_dname(buffer, ldns_rr_rdf(rr, 3)) != LDNS_STATUS_OK) || - (ldns_buffer_position(buffer) < 2) || - !ldns_buffer_reserve(buffer, 1)) { - // either name invalid, empty or buffer to small - continue; - } - char terminator = 0; - ldns_buffer_write(buffer, &terminator, sizeof(terminator)); - - serviceRecord.hostname = std::string(reinterpret_cast<char*>(ldns_buffer_at(buffer, 0))); - serviceRecords.push_back(serviceRecord); - SWIFT_LOG(debug) << "hostname " << serviceRecord.hostname << " added" << std::endl; - } - } - if (replyPacket) ldns_pkt_free(replyPacket); - if (buffer) ldns_buffer_free(buffer); - } - } - - ub_resolve_free(result); - onResult(serviceRecords); - } - - private: - std::string name; +class UnboundDomainNameServiceQuery : public DomainNameServiceQuery, public UnboundQuery, public std::enable_shared_from_this<UnboundDomainNameServiceQuery> { + public: + UnboundDomainNameServiceQuery(UnboundDomainNameResolver* resolver, ub_ctx* context, std::string name) : UnboundQuery(resolver, context), name(name) { + } + + virtual ~UnboundDomainNameServiceQuery() { } + + virtual void run() { + int retval; + UnboundWrapperHelper* helper = new UnboundWrapperHelper(resolver, shared_from_this()); + + retval = ub_resolve_async(ubContext, const_cast<char*>(name.c_str()), LDNS_RR_TYPE_SRV, + 1 /* CLASS IN (internet) */, + helper, UnboundDomainNameResolver::unbound_callback_wrapper, NULL); + if(retval != 0) { + SWIFT_LOG(debug) << "resolve error: " << ub_strerror(retval); + delete helper; + } + } + + void handleResult(int err, struct ub_result* result) { + std::vector<DomainNameServiceQuery::Result> serviceRecords; + + if(err != 0) { + SWIFT_LOG(debug) << "resolve error: " << ub_strerror(err); + } else { + if(result->havedata) { + ldns_pkt* replyPacket = 0; + ldns_buffer* buffer = ldns_buffer_new(1024); + if (buffer && ldns_wire2pkt(&replyPacket, static_cast<const uint8_t*>(result->answer_packet), result->answer_len) == LDNS_STATUS_OK) { + ldns_rr_list* rrList = ldns_pkt_answer(replyPacket); + for (size_t n = 0; n < ldns_rr_list_rr_count(rrList); n++) { + ldns_rr* rr = ldns_rr_list_rr(rrList, n); + if ((ldns_rr_get_type(rr) != LDNS_RR_TYPE_SRV) || + (ldns_rr_get_class(rr) != LDNS_RR_CLASS_IN) || + (ldns_rr_rd_count(rr) != 4)) { + continue; + } + + DomainNameServiceQuery::Result serviceRecord; + serviceRecord.priority = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0)); + serviceRecord.weight = ldns_rdf2native_int16(ldns_rr_rdf(rr, 1)); + serviceRecord.port = ldns_rdf2native_int16(ldns_rr_rdf(rr, 2)); + + ldns_buffer_rewind(buffer); + if ((ldns_rdf2buffer_str_dname(buffer, ldns_rr_rdf(rr, 3)) != LDNS_STATUS_OK) || + (ldns_buffer_position(buffer) < 2) || + !ldns_buffer_reserve(buffer, 1)) { + // either name invalid, empty or buffer to small + continue; + } + char terminator = 0; + ldns_buffer_write(buffer, &terminator, sizeof(terminator)); + + serviceRecord.hostname = std::string(reinterpret_cast<char*>(ldns_buffer_at(buffer, 0))); + serviceRecords.push_back(serviceRecord); + SWIFT_LOG(debug) << "hostname " << serviceRecord.hostname << " added"; + } + } + if (replyPacket) ldns_pkt_free(replyPacket); + if (buffer) ldns_buffer_free(buffer); + } + } + + ub_resolve_free(result); + onResult(serviceRecords); + } + + private: + std::string name; }; -class UnboundDomainNameAddressQuery : public DomainNameAddressQuery, public UnboundQuery, public boost::enable_shared_from_this<UnboundDomainNameAddressQuery> { - public: - UnboundDomainNameAddressQuery(UnboundDomainNameResolver* resolver, ub_ctx* context, std::string name) : UnboundQuery(resolver, context), name(name) { - } - - virtual ~UnboundDomainNameAddressQuery() { } - - virtual void run() { - int retval; - UnboundWrapperHelper* helper = new UnboundWrapperHelper(resolver, shared_from_this()); - - //FIXME: support AAAA queries in some way - retval = ub_resolve_async(ubContext, const_cast<char*>(name.c_str()), LDNS_RR_TYPE_A, - 1 /* CLASS IN (internet) */, - helper, UnboundDomainNameResolver::unbound_callback_wrapper, NULL); - if(retval != 0) { - SWIFT_LOG(debug) << "resolve error: " << ub_strerror(retval) << std::endl; - delete helper; - } - } - - void handleResult(int err, struct ub_result* result) { - std::vector<HostAddress> addresses; - boost::optional<DomainNameResolveError> error; - SWIFT_LOG(debug) << "Result for: " << name << std::endl; - - if(err != 0) { - SWIFT_LOG(debug) << "resolve error: " << ub_strerror(err) << std::endl; - error = DomainNameResolveError(); - } else { - if(result->havedata) { - for(int i=0; result->data[i]; i++) { - char address[100]; - const char* addressStr = 0; - if ((addressStr = inet_ntop(AF_INET, result->data[i], address, 100))) { - SWIFT_LOG(debug) << "IPv4 address: " << addressStr << std::endl; - addresses.push_back(HostAddress(std::string(addressStr))); - } else if ((addressStr = inet_ntop(AF_INET6, result->data[i], address, 100))) { - SWIFT_LOG(debug) << "IPv6 address: " << addressStr << std::endl; - addresses.push_back(HostAddress(std::string(addressStr))); - } else { - SWIFT_LOG(debug) << "inet_ntop() failed" << std::endl; - error = DomainNameResolveError(); - } - } - } else { - error = DomainNameResolveError(); - } - } - - ub_resolve_free(result); - onResult(addresses, error); - } - - private: - std::string name; +class UnboundDomainNameAddressQuery : public DomainNameAddressQuery, public UnboundQuery, public std::enable_shared_from_this<UnboundDomainNameAddressQuery> { + public: + UnboundDomainNameAddressQuery(UnboundDomainNameResolver* resolver, ub_ctx* context, std::string name) : UnboundQuery(resolver, context), name(name) { + } + + virtual ~UnboundDomainNameAddressQuery() { } + + virtual void run() { + int retval; + UnboundWrapperHelper* helper = new UnboundWrapperHelper(resolver, shared_from_this()); + + //FIXME: support AAAA queries in some way + retval = ub_resolve_async(ubContext, const_cast<char*>(name.c_str()), LDNS_RR_TYPE_A, + 1 /* CLASS IN (internet) */, + helper, UnboundDomainNameResolver::unbound_callback_wrapper, NULL); + if(retval != 0) { + SWIFT_LOG(debug) << "resolve error: " << ub_strerror(retval); + delete helper; + } + } + + void handleResult(int err, struct ub_result* result) { + std::vector<HostAddress> addresses; + boost::optional<DomainNameResolveError> error; + SWIFT_LOG(debug) << "Result for: " << name; + + if(err != 0) { + SWIFT_LOG(debug) << "resolve error: " << ub_strerror(err); + error = DomainNameResolveError(); + } else { + if(result->havedata) { + for(int i=0; result->data[i]; i++) { + char address[100]; + const char* addressStr = 0; + if ((addressStr = inet_ntop(AF_INET, result->data[i], address, 100))) { + SWIFT_LOG(debug) << "IPv4 address: " << addressStr; + addresses.push_back(HostAddress(std::string(addressStr))); + } else if ((addressStr = inet_ntop(AF_INET6, result->data[i], address, 100))) { + SWIFT_LOG(debug) << "IPv6 address: " << addressStr; + addresses.push_back(HostAddress(std::string(addressStr))); + } else { + SWIFT_LOG(debug) << "inet_ntop() failed"; + error = DomainNameResolveError(); + } + } + } else { + error = DomainNameResolveError(); + } + } + + ub_resolve_free(result); + onResult(addresses, error); + } + + private: + std::string name; }; -UnboundDomainNameResolver::UnboundDomainNameResolver(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : ioService(ioService), ubDescriptior(*ioService), eventLoop(eventLoop) { - ubContext = ub_ctx_create(); - if(!ubContext) { - SWIFT_LOG(debug) << "could not create unbound context" << std::endl; - } - eventOwner = boost::make_shared<EventOwner>(); +UnboundDomainNameResolver::UnboundDomainNameResolver(IDNConverter* idnConverter, std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : idnConverter(idnConverter), ioService(ioService), ubDescriptior(*ioService), eventLoop(eventLoop) { + ubContext = ub_ctx_create(); + if(!ubContext) { + SWIFT_LOG(debug) << "could not create unbound context"; + } + eventOwner = std::make_shared<EventOwner>(); - ub_ctx_async(ubContext, true); + ub_ctx_async(ubContext, true); - int ret; + int ret; - /* read /etc/resolv.conf for DNS proxy settings (from DHCP) */ - if( (ret=ub_ctx_resolvconf(ubContext, const_cast<char*>("/etc/resolv.conf"))) != 0) { - SWIFT_LOG(debug) << "error reading resolv.conf: " << ub_strerror(ret) << ". errno says: " << strerror(errno) << std::endl; - } - /* read /etc/hosts for locally supplied host addresses */ - if( (ret=ub_ctx_hosts(ubContext, const_cast<char*>("/etc/hosts"))) != 0) { - SWIFT_LOG(debug) << "error reading hosts: " << ub_strerror(ret) << ". errno says: " << strerror(errno) << std::endl; - } + /* read /etc/resolv.conf for DNS proxy settings (from DHCP) */ + if( (ret=ub_ctx_resolvconf(ubContext, const_cast<char*>("/etc/resolv.conf"))) != 0) { + SWIFT_LOG(error) << "error reading resolv.conf: " << ub_strerror(ret) << ". errno says: " << strerror(errno); + } + /* read /etc/hosts for locally supplied host addresses */ + if( (ret=ub_ctx_hosts(ubContext, const_cast<char*>("/etc/hosts"))) != 0) { + SWIFT_LOG(error) << "error reading hosts: " << ub_strerror(ret) << ". errno says: " << strerror(errno); + } - ubDescriptior.assign(ub_fd(ubContext)); + ubDescriptior.assign(ub_fd(ubContext)); - ubDescriptior.async_read_some(boost::asio::null_buffers(), boost::bind(&UnboundDomainNameResolver::handleUBSocketReadable, this, boost::asio::placeholders::error)); + ubDescriptior.async_read_some(boost::asio::null_buffers(), boost::bind(&UnboundDomainNameResolver::handleUBSocketReadable, this, boost::asio::placeholders::error)); } UnboundDomainNameResolver::~UnboundDomainNameResolver() { - eventLoop->removeEventsFromOwner(eventOwner); - if (ubContext) { - ub_ctx_delete(ubContext); - } + eventLoop->removeEventsFromOwner(eventOwner); + if (ubContext) { + ub_ctx_delete(ubContext); + } } -void UnboundDomainNameResolver::unbound_callback(boost::shared_ptr<UnboundQuery> query, int err, ub_result* result) { - query->handleResult(err, result); +void UnboundDomainNameResolver::unbound_callback(std::shared_ptr<UnboundQuery> query, int err, ub_result* result) { + query->handleResult(err, result); } void UnboundDomainNameResolver::unbound_callback_wrapper(void* data, int err, ub_result* result) { - UnboundWrapperHelper* helper = static_cast<UnboundWrapperHelper*>(data); - UnboundDomainNameResolver* resolver = helper->resolver; - resolver->unbound_callback(helper->query, err, result); - delete helper; + UnboundWrapperHelper* helper = static_cast<UnboundWrapperHelper*>(data); + UnboundDomainNameResolver* resolver = helper->resolver; + resolver->unbound_callback(helper->query, err, result); + delete helper; } void UnboundDomainNameResolver::handleUBSocketReadable(boost::system::error_code) { - eventLoop->postEvent(boost::bind(&UnboundDomainNameResolver::processData, this), eventOwner); - ubDescriptior.async_read_some(boost::asio::null_buffers(), boost::bind(&UnboundDomainNameResolver::handleUBSocketReadable, this, boost::asio::placeholders::error)); + eventLoop->postEvent(boost::bind(&UnboundDomainNameResolver::processData, this), eventOwner); + ubDescriptior.async_read_some(boost::asio::null_buffers(), boost::bind(&UnboundDomainNameResolver::handleUBSocketReadable, this, boost::asio::placeholders::error)); } void UnboundDomainNameResolver::processData() { - if (ub_poll(ubContext)) { - int ret = ub_process(ubContext); - if(ret != 0) { - SWIFT_LOG(debug) << "resolve error: " << ub_strerror(ret) << std::endl; - } - } + if (ub_poll(ubContext)) { + int ret = ub_process(ubContext); + if(ret != 0) { + SWIFT_LOG(debug) << "resolve error: " << ub_strerror(ret); + } + } } -boost::shared_ptr<DomainNameServiceQuery> UnboundDomainNameResolver::createServiceQuery(const std::string& name) { - return boost::make_shared<UnboundDomainNameServiceQuery>(this, ubContext, name); +std::shared_ptr<DomainNameServiceQuery> UnboundDomainNameResolver::createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) { + boost::optional<std::string> encodedDomain = idnConverter->getIDNAEncoded(domain); + std::string result; + if (encodedDomain) { + result = serviceLookupPrefix + *encodedDomain; + } + return std::make_shared<UnboundDomainNameServiceQuery>(this, ubContext, result); } -boost::shared_ptr<DomainNameAddressQuery> UnboundDomainNameResolver::createAddressQuery(const std::string& name) { - return boost::make_shared<UnboundDomainNameAddressQuery>(this, ubContext, name); +std::shared_ptr<DomainNameAddressQuery> UnboundDomainNameResolver::createAddressQuery(const std::string& name) { + return std::make_shared<UnboundDomainNameAddressQuery>(this, ubContext, idnConverter->getIDNAEncoded(name).get_value_or("")); } } diff --git a/Swiften/Network/UnboundDomainNameResolver.h b/Swiften/Network/UnboundDomainNameResolver.h index 0db8a66..988a415 100755..100644 --- a/Swiften/Network/UnboundDomainNameResolver.h +++ b/Swiften/Network/UnboundDomainNameResolver.h @@ -4,48 +4,55 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Network/DomainNameResolver.h> -#include <Swiften/Network/Timer.h> -#include <Swiften/EventLoop/EventOwner.h> +#include <memory> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> #include <boost/asio.hpp> +#include <Swiften/EventLoop/EventOwner.h> +#include <Swiften/Network/DomainNameResolver.h> +#include <Swiften/Network/Timer.h> + struct ub_ctx; struct ub_result; namespace Swift { - class EventLoop; - class TimerFactory; + class EventLoop; + class IDNConverter; - class UnboundDomainNameResolver; - class UnboundQuery; + class UnboundDomainNameResolver; + class UnboundQuery; - class UnboundDomainNameResolver : public DomainNameResolver, public EventOwner, public boost::enable_shared_from_this<UnboundDomainNameResolver> { - public: - UnboundDomainNameResolver(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); - virtual ~UnboundDomainNameResolver(); + class UnboundDomainNameResolver : public DomainNameResolver, public EventOwner, public std::enable_shared_from_this<UnboundDomainNameResolver> { + public: + UnboundDomainNameResolver(IDNConverter* idnConverter, std::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); + virtual ~UnboundDomainNameResolver(); - virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& name); - virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name); + virtual std::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain); + virtual std::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name); - static void unbound_callback_wrapper(void* data, int err, ub_result* result); + static void unbound_callback_wrapper(void* data, int err, ub_result* result); - private: - void unbound_callback(boost::shared_ptr<UnboundQuery> query, int err, ub_result* result); + private: + void unbound_callback(std::shared_ptr<UnboundQuery> query, int err, ub_result* result); - void handleUBSocketReadable(boost::system::error_code); - void processData(); + void handleUBSocketReadable(boost::system::error_code); + void processData(); - private: - boost::shared_ptr<EventOwner> eventOwner; - boost::shared_ptr<boost::asio::io_service> ioService; - boost::asio::posix::stream_descriptor ubDescriptior; - EventLoop* eventLoop; - ub_ctx* ubContext; - }; + private: + IDNConverter* idnConverter; + std::shared_ptr<EventOwner> eventOwner; + std::shared_ptr<boost::asio::io_service> ioService; + boost::asio::posix::stream_descriptor ubDescriptior; + EventLoop* eventLoop; + ub_ctx* ubContext; + }; } diff --git a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp index 8a63fcb..4aeaf24 100644 --- a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp +++ b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp @@ -1,469 +1,468 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + +#include <boost/bind.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> + #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/optional.hpp> -#include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/lexical_cast.hpp> - #include <Swiften/Base/Algorithm.h> -#include <Swiften/Network/Connection.h> -#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Network/BOSHConnection.h> #include <Swiften/Network/BOSHConnectionPool.h> +#include <Swiften/Network/Connection.h> +#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/DummyTimerFactory.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/StaticDomainNameResolver.h> -#include <Swiften/Network/DummyTimerFactory.h> -#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Parser/PlatformXMLParserFactory.h> - - +#include <Swiften/TLS/TLSOptions.h> using namespace Swift; -typedef boost::shared_ptr<BOSHConnectionPool> PoolRef; +typedef std::shared_ptr<BOSHConnectionPool> PoolRef; class BOSHConnectionPoolTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(BOSHConnectionPoolTest); - CPPUNIT_TEST(testConnectionCount_OneWrite); - CPPUNIT_TEST(testConnectionCount_TwoWrites); - CPPUNIT_TEST(testConnectionCount_ThreeWrites); - CPPUNIT_TEST(testConnectionCount_ThreeWrites_ManualConnect); - CPPUNIT_TEST(testConnectionCount_ThreeWritesTwoReads); - CPPUNIT_TEST(testSession); - CPPUNIT_TEST(testWrite_Empty); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - to = "wonderland.lit"; - path = "/http-bind"; - port = "5280"; - sid = "MyShinySID"; - initial = "<body wait='60' " - "inactivity='30' " - "polling='5' " - "requests='2' " - "hold='1' " - "maxpause='120' " - "sid='" + sid + "' " - "ver='1.6' " - "from='wonderland.lit' " - "xmlns='http://jabber.org/protocol/httpbind'/>"; - eventLoop = new DummyEventLoop(); - connectionFactory = new MockConnectionFactory(eventLoop); - boshURL = URL("http", to, 5280, path); - sessionTerminated = 0; - sessionStarted = 0; - initialRID = 2349876; - xmppDataRead.clear(); - boshDataRead.clear(); - boshDataWritten.clear(); - resolver = new StaticDomainNameResolver(eventLoop); - resolver->addAddress(to, HostAddress("127.0.0.1")); - timerFactory = new DummyTimerFactory(); - } - - void tearDown() { - eventLoop->processEvents(); - delete connectionFactory; - delete resolver; - delete timerFactory; - delete eventLoop; - } - - void testConnectionCount_OneWrite() { - PoolRef testling = createTestling(); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(0, sessionStarted); - readResponse(initial, connectionFactory->connections[0]); - CPPUNIT_ASSERT_EQUAL(1, sessionStarted); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - testling->write(createSafeByteArray("<blah/>")); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - CPPUNIT_ASSERT_EQUAL(1, sessionStarted); - } - - void testConnectionCount_TwoWrites() { - PoolRef testling = createTestling(); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - eventLoop->processEvents(); - readResponse(initial, connectionFactory->connections[0]); - eventLoop->processEvents(); - testling->write(createSafeByteArray("<blah/>")); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - testling->write(createSafeByteArray("<bleh/>")); - eventLoop->processEvents(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); - } - - void testConnectionCount_ThreeWrites() { - PoolRef testling = createTestling(); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - eventLoop->processEvents(); - readResponse(initial, connectionFactory->connections[0]); - testling->restartStream(); - readResponse("<body/>", connectionFactory->connections[0]); - testling->restartStream(); - readResponse("<body/>", connectionFactory->connections[0]); - testling->write(createSafeByteArray("<blah/>")); - testling->write(createSafeByteArray("<bleh/>")); - testling->write(createSafeByteArray("<bluh/>")); - eventLoop->processEvents(); - CPPUNIT_ASSERT(st(2) >= connectionFactory->connections.size()); - } - - void testConnectionCount_ThreeWrites_ManualConnect() { - connectionFactory->autoFinishConnect = false; - PoolRef testling = createTestling(); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - CPPUNIT_ASSERT_EQUAL(st(0), boshDataWritten.size()); /* Connection not connected yet, can't send data */ - - connectionFactory->connections[0]->onConnectFinished(false); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Connection finished, stream header sent */ - - readResponse(initial, connectionFactory->connections[0]); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Don't respond to initial data with a holding call */ - - testling->restartStream(); - eventLoop->processEvents(); - readResponse("<body/>", connectionFactory->connections[0]); - eventLoop->processEvents(); - testling->restartStream(); - eventLoop->processEvents(); - - - testling->write(createSafeByteArray("<blah/>")); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); - CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); /* New connection isn't up yet. */ - - connectionFactory->connections[1]->onConnectFinished(false); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* New connection ready. */ - - testling->write(createSafeByteArray("<bleh/>")); - eventLoop->processEvents(); - testling->write(createSafeByteArray("<bluh/>")); - CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* New data can't be sent, no free connections. */ - eventLoop->processEvents(); - CPPUNIT_ASSERT(st(2) >= connectionFactory->connections.size()); - } - - void testConnectionCount_ThreeWritesTwoReads() { - boost::shared_ptr<MockConnection> c0; - boost::shared_ptr<MockConnection> c1; - unsigned long long rid = initialRID; - - PoolRef testling = createTestling(); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - c0 = connectionFactory->connections[0]; - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* header*/ - - rid++; - readResponse(initial, c0); - CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - CPPUNIT_ASSERT(!c0->pending); - - rid++; - testling->restartStream(); - eventLoop->processEvents(); - readResponse("<body/>", connectionFactory->connections[0]); - - rid++; - testling->write(createSafeByteArray("<blah/>")); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); /* 0 was waiting for response, open and send on 1 */ - CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* data */ - c1 = connectionFactory->connections[1]; - std::string fullBody = "<body rid='" + boost::lexical_cast<std::string>(rid) + "' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'><blah/></body>"; /* check empty write */ - CPPUNIT_ASSERT_EQUAL(fullBody, lastBody()); - CPPUNIT_ASSERT(c0->pending); - CPPUNIT_ASSERT(c1->pending); - - - rid++; - readResponse("<body xmlns='http://jabber.org/protocol/httpbind'><message><splatploing/></message></body>", c0); /* Doesn't include necessary attributes - as the support is improved this'll start to fail */ - eventLoop->processEvents(); - CPPUNIT_ASSERT(!c0->pending); - CPPUNIT_ASSERT(c1->pending); - CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* don't send empty in [0], still have [1] waiting */ - CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); - - rid++; - readResponse("<body xmlns='http://jabber.org/protocol/httpbind'><message><splatploing><blittlebarg/></splatploing></message></body>", c1); - eventLoop->processEvents(); - CPPUNIT_ASSERT(!c1->pending); - CPPUNIT_ASSERT(c0->pending); - CPPUNIT_ASSERT_EQUAL(st(5), boshDataWritten.size()); /* empty to make room */ - CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); - - rid++; - testling->write(createSafeByteArray("<bleh/>")); - eventLoop->processEvents(); - CPPUNIT_ASSERT(c0->pending); - CPPUNIT_ASSERT(c1->pending); - CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); /* data */ - - rid++; - testling->write(createSafeByteArray("<bluh/>")); - CPPUNIT_ASSERT(c0->pending); - CPPUNIT_ASSERT(c1->pending); - CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); /* Don't send data, no room */ - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); - } - - void testSession() { - to = "prosody.doomsong.co.uk"; - resolver->addAddress("prosody.doomsong.co.uk", HostAddress("127.0.0.1")); - path = "/http-bind/"; - boshURL = URL("http", to, 5280, path); - - PoolRef testling = createTestling(); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* header*/ - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - - std::string response = "<body authid='743da605-4c2e-4de1-afac-ac040dd4a940' xmpp:version='1.0' xmlns:stream='http://etherx.jabber.org/streams' xmlns:xmpp='urn:xmpp:xbosh' inactivity='60' wait='60' polling='5' secure='true' hold='1' from='prosody.doomsong.co.uk' ver='1.6' sid='743da605-4c2e-4de1-afac-ac040dd4a940' requests='2' xmlns='http://jabber.org/protocol/httpbind'><stream:features><auth xmlns='http://jabber.org/features/iq-auth'/><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>SCRAM-SHA-1</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features></body>"; - readResponse(response, connectionFactory->connections[0]); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - - std::string send = "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"SCRAM-SHA-1\">biwsbj1hZG1pbixyPWZhOWE5ZDhiLWZmMDctNGE4Yy04N2E3LTg4YWRiNDQxZGUwYg==</auth>"; - testling->write(createSafeByteArray(send)); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size()); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - - response = "<body xmlns='http://jabber.org/protocol/httpbind' sid='743da605-4c2e-4de1-afac-ac040dd4a940' xmlns:stream = 'http://etherx.jabber.org/streams'><challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cj1mYTlhOWQ4Yi1mZjA3LTRhOGMtODdhNy04OGFkYjQ0MWRlMGJhZmZlMWNhMy1mMDJkLTQ5NzEtYjkyNS0yM2NlNWQ2MDQyMjYscz1OVGd5WkdWaFptTXRaVE15WXkwMFpXUmhMV0ZqTURRdFpqYzRNbUppWmpGa1pqWXgsaT00MDk2</challenge></body>"; - readResponse(response, connectionFactory->connections[0]); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size()); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - - send = "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">Yz1iaXdzLHI9ZmE5YTlkOGItZmYwNy00YThjLTg3YTctODhhZGI0NDFkZTBiYWZmZTFjYTMtZjAyZC00OTcxLWI5MjUtMjNjZTVkNjA0MjI2LHA9aU11NWt3dDN2VWplU2RqL01Jb3VIRldkZjBnPQ==</response>"; - testling->write(createSafeByteArray(send)); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - - response = "<body xmlns='http://jabber.org/protocol/httpbind' sid='743da605-4c2e-4de1-afac-ac040dd4a940' xmlns:stream = 'http://etherx.jabber.org/streams'><success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>dj1YNmNBY3BBOWxHNjNOOXF2bVQ5S0FacERrVm89</success></body>"; - readResponse(response, connectionFactory->connections[0]); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - - testling->restartStream(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - - response = "<body xmpp:version='1.0' xmlns:stream='http://etherx.jabber.org/streams' xmlns:xmpp='urn:xmpp:xbosh' inactivity='60' wait='60' polling='5' secure='true' hold='1' from='prosody.doomsong.co.uk' ver='1.6' sid='743da605-4c2e-4de1-afac-ac040dd4a940' requests='2' xmlns='http://jabber.org/protocol/httpbind'><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><required/></bind><session xmlns='urn:ietf:params:xml:ns:xmpp-session'><optional/></session><sm xmlns='urn:xmpp:sm:2'><optional/></sm></stream:features></body>"; - readResponse(response, connectionFactory->connections[0]); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(5), boshDataWritten.size()); /* Now we've authed (restarted) we should be keeping one query in flight so the server can reply to us at any time it wants. */ - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - - send = "<body rid='2821988967416214' sid='cf663f6b94279d4f' xmlns='http://jabber.org/protocol/httpbind'><iq id='session-bind' type='set'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>d5a9744036cd20a0</resource></bind></iq></body>"; - testling->write(createSafeByteArray(send)); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); - CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); /* and as it keeps one in flight, it's needed to open a second to send these data */ - - } - - void testWrite_Empty() { - boost::shared_ptr<MockConnection> c0; - - PoolRef testling = createTestling(); - CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); - c0 = connectionFactory->connections[0]; - - readResponse(initial, c0); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Shouldn't have sent anything extra */ - eventLoop->processEvents(); - testling->restartStream(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size()); - readResponse("<body></body>", c0); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); - std::string fullBody = "<body rid='" + boost::lexical_cast<std::string>(initialRID + 2) + "' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'></body>"; - std::string response = boshDataWritten[2]; - size_t bodyPosition = response.find("\r\n\r\n"); - CPPUNIT_ASSERT_EQUAL(fullBody, response.substr(bodyPosition+4)); - - - } - - private: - - PoolRef createTestling() { - BOSHConnectionPool* a = new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString("")); - PoolRef pool(a); - //FIXME: Remko - why does the above work, but the below fail? - //PoolRef pool = boost::make_shared<BOSHConnectionPool>(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(NULL), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString("")); - pool->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleXMPPDataRead, this, _1)); - pool->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataRead, this, _1)); - pool->onBOSHDataWritten.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataWritten, this, _1)); - pool->onSessionStarted.connect(boost::bind(&BOSHConnectionPoolTest::handleSessionStarted, this)); - pool->onSessionTerminated.connect(boost::bind(&BOSHConnectionPoolTest::handleSessionTerminated, this)); - eventLoop->processEvents(); - eventLoop->processEvents(); - return pool; - } - - std::string lastBody() { - std::string response = boshDataWritten[boshDataWritten.size() - 1]; - size_t bodyPosition = response.find("\r\n\r\n"); - return response.substr(bodyPosition+4); - } - - size_t st(int val) { - return static_cast<size_t>(val); - } - - void handleXMPPDataRead(const SafeByteArray& d) { - xmppDataRead.push_back(safeByteArrayToString(d)); - } - - void handleBOSHDataRead(const SafeByteArray& d) { - boshDataRead.push_back(safeByteArrayToString(d)); - } - - void handleBOSHDataWritten(const SafeByteArray& d) { - boshDataWritten.push_back(safeByteArrayToString(d)); - } - - - void handleSessionStarted() { - sessionStarted++; - } - - void handleSessionTerminated() { - sessionTerminated++; - } - - struct MockConnection : public Connection { - public: - MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop, bool autoFinishConnect) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false), pending(false), autoFinishConnect(autoFinishConnect) { - } - - void listen() { assert(false); } - - void connect(const HostAddressPort& address) { - hostAddressPort = address; - bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); - if (autoFinishConnect) { - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); - } - } - - HostAddressPort getLocalAddress() const { return HostAddressPort(); } - - void disconnect() { - disconnected = true; - onDisconnected(boost::optional<Connection::Error>()); - } - - void write(const SafeByteArray& d) { - append(dataWritten, d); - pending = true; - } - - EventLoop* eventLoop; - boost::optional<HostAddressPort> hostAddressPort; - std::vector<HostAddressPort> failingPorts; - ByteArray dataWritten; - bool disconnected; - bool pending; - bool autoFinishConnect; - }; - - struct MockConnectionFactory : public ConnectionFactory { - MockConnectionFactory(EventLoop* eventLoop, bool autoFinishConnect = true) : eventLoop(eventLoop), autoFinishConnect(autoFinishConnect) { - } - - boost::shared_ptr<Connection> createConnection() { - boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop, autoFinishConnect); - connections.push_back(connection); - return connection; - } - - EventLoop* eventLoop; - std::vector< boost::shared_ptr<MockConnection> > connections; - std::vector<HostAddressPort> failingPorts; - bool autoFinishConnect; - }; - - void readResponse(const std::string& response, boost::shared_ptr<MockConnection> connection) { - connection->pending = false; - boost::shared_ptr<SafeByteArray> data1 = boost::make_shared<SafeByteArray>(createSafeByteArray( - "HTTP/1.1 200 OK\r\n" - "Content-Type: text/xml; charset=utf-8\r\n" - "Access-Control-Allow-Origin: *\r\n" - "Access-Control-Allow-Headers: Content-Type\r\n" - "Content-Length: ")); - connection->onDataRead(data1); - boost::shared_ptr<SafeByteArray> data2 = boost::make_shared<SafeByteArray>(createSafeByteArray(boost::lexical_cast<std::string>(response.size()))); - connection->onDataRead(data2); - boost::shared_ptr<SafeByteArray> data3 = boost::make_shared<SafeByteArray>(createSafeByteArray("\r\n\r\n")); - connection->onDataRead(data3); - boost::shared_ptr<SafeByteArray> data4 = boost::make_shared<SafeByteArray>(createSafeByteArray(response)); - connection->onDataRead(data4); - } - - std::string fullRequestFor(const std::string& data) { - std::string body = data; - std::string result = "POST /" + path + " HTTP/1.1\r\n" - + "Host: " + to + ":" + port + "\r\n" - + "Content-Type: text/xml; charset=utf-8\r\n" - + "Content-Length: " + boost::lexical_cast<std::string>(body.size()) + "\r\n\r\n" - + body; - return result; - } - - private: - URL boshURL; - DummyEventLoop* eventLoop; - MockConnectionFactory* connectionFactory; - std::vector<std::string> xmppDataRead; - std::vector<std::string> boshDataRead; - std::vector<std::string> boshDataWritten; - PlatformXMLParserFactory parserFactory; - StaticDomainNameResolver* resolver; - TimerFactory* timerFactory; - std::string to; - std::string path; - std::string port; - std::string sid; - std::string initial; - unsigned long long initialRID; - int sessionStarted; - int sessionTerminated; + CPPUNIT_TEST_SUITE(BOSHConnectionPoolTest); + CPPUNIT_TEST(testConnectionCount_OneWrite); + CPPUNIT_TEST(testConnectionCount_TwoWrites); + CPPUNIT_TEST(testConnectionCount_ThreeWrites); + CPPUNIT_TEST(testConnectionCount_ThreeWrites_ManualConnect); + CPPUNIT_TEST(testConnectionCount_ThreeWritesTwoReads); + CPPUNIT_TEST(testSession); + CPPUNIT_TEST(testWrite_Empty); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + to = "wonderland.lit"; + path = "/http-bind"; + port = "5280"; + sid = "MyShinySID"; + initial = "<body wait='60' " + "inactivity='30' " + "polling='5' " + "requests='2' " + "hold='1' " + "maxpause='120' " + "sid='" + sid + "' " + "ver='1.6' " + "from='wonderland.lit' " + "xmlns='http://jabber.org/protocol/httpbind'/>"; + eventLoop = new DummyEventLoop(); + connectionFactory = new MockConnectionFactory(eventLoop); + boshURL = URL("http", to, 5280, path); + sessionTerminated = 0; + sessionStarted = 0; + initialRID = 2349876; + xmppDataRead.clear(); + boshDataRead.clear(); + boshDataWritten.clear(); + resolver = new StaticDomainNameResolver(eventLoop); + resolver->addAddress(to, HostAddress::fromString("127.0.0.1").get()); + timerFactory = new DummyTimerFactory(); + } + + void tearDown() { + eventLoop->processEvents(); + delete connectionFactory; + delete resolver; + delete timerFactory; + delete eventLoop; + } + + void testConnectionCount_OneWrite() { + PoolRef testling = createTestling(); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(0, sessionStarted); + readResponse(initial, connectionFactory->connections[0]); + CPPUNIT_ASSERT_EQUAL(1, sessionStarted); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + testling->write(createSafeByteArray("<blah/>")); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + CPPUNIT_ASSERT_EQUAL(1, sessionStarted); + } + + void testConnectionCount_TwoWrites() { + PoolRef testling = createTestling(); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + eventLoop->processEvents(); + readResponse(initial, connectionFactory->connections[0]); + eventLoop->processEvents(); + testling->write(createSafeByteArray("<blah/>")); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + testling->write(createSafeByteArray("<bleh/>")); + eventLoop->processEvents(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); + } + + void testConnectionCount_ThreeWrites() { + PoolRef testling = createTestling(); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + eventLoop->processEvents(); + readResponse(initial, connectionFactory->connections[0]); + testling->restartStream(); + readResponse("<body/>", connectionFactory->connections[0]); + testling->restartStream(); + readResponse("<body/>", connectionFactory->connections[0]); + testling->write(createSafeByteArray("<blah/>")); + testling->write(createSafeByteArray("<bleh/>")); + testling->write(createSafeByteArray("<bluh/>")); + eventLoop->processEvents(); + CPPUNIT_ASSERT(st(2) >= connectionFactory->connections.size()); + } + + void testConnectionCount_ThreeWrites_ManualConnect() { + connectionFactory->autoFinishConnect = false; + PoolRef testling = createTestling(); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + CPPUNIT_ASSERT_EQUAL(st(0), boshDataWritten.size()); /* Connection not connected yet, can't send data */ + + connectionFactory->connections[0]->onConnectFinished(false); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Connection finished, stream header sent */ + + readResponse(initial, connectionFactory->connections[0]); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Don't respond to initial data with a holding call */ + + testling->restartStream(); + eventLoop->processEvents(); + readResponse("<body/>", connectionFactory->connections[0]); + eventLoop->processEvents(); + testling->restartStream(); + eventLoop->processEvents(); + + + testling->write(createSafeByteArray("<blah/>")); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); + CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); /* New connection isn't up yet. */ + + connectionFactory->connections[1]->onConnectFinished(false); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* New connection ready. */ + + testling->write(createSafeByteArray("<bleh/>")); + eventLoop->processEvents(); + testling->write(createSafeByteArray("<bluh/>")); + CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* New data can't be sent, no free connections. */ + eventLoop->processEvents(); + CPPUNIT_ASSERT(st(2) >= connectionFactory->connections.size()); + } + + void testConnectionCount_ThreeWritesTwoReads() { + std::shared_ptr<MockConnection> c0; + std::shared_ptr<MockConnection> c1; + unsigned long long rid = initialRID; + + PoolRef testling = createTestling(); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + c0 = connectionFactory->connections[0]; + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* header*/ + + rid++; + readResponse(initial, c0); + CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + CPPUNIT_ASSERT(!c0->pending); + + rid++; + testling->restartStream(); + eventLoop->processEvents(); + readResponse("<body/>", connectionFactory->connections[0]); + + rid++; + testling->write(createSafeByteArray("<blah/>")); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); /* 0 was waiting for response, open and send on 1 */ + CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* data */ + c1 = connectionFactory->connections[1]; + std::string fullBody = "<body rid='" + std::to_string(rid) + "' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'><blah/></body>"; /* check empty write */ + CPPUNIT_ASSERT_EQUAL(fullBody, lastBody()); + CPPUNIT_ASSERT(c0->pending); + CPPUNIT_ASSERT(c1->pending); + + + rid++; + readResponse("<body xmlns='http://jabber.org/protocol/httpbind'><message><splatploing/></message></body>", c0); /* Doesn't include necessary attributes - as the support is improved this'll start to fail */ + eventLoop->processEvents(); + CPPUNIT_ASSERT(!c0->pending); + CPPUNIT_ASSERT(c1->pending); + CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); /* don't send empty in [0], still have [1] waiting */ + CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); + + rid++; + readResponse("<body xmlns='http://jabber.org/protocol/httpbind'><message><splatploing><blittlebarg/></splatploing></message></body>", c1); + eventLoop->processEvents(); + CPPUNIT_ASSERT(!c1->pending); + CPPUNIT_ASSERT(c0->pending); + CPPUNIT_ASSERT_EQUAL(st(5), boshDataWritten.size()); /* empty to make room */ + CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); + + rid++; + testling->write(createSafeByteArray("<bleh/>")); + eventLoop->processEvents(); + CPPUNIT_ASSERT(c0->pending); + CPPUNIT_ASSERT(c1->pending); + CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); /* data */ + + rid++; + testling->write(createSafeByteArray("<bluh/>")); + CPPUNIT_ASSERT(c0->pending); + CPPUNIT_ASSERT(c1->pending); + CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); /* Don't send data, no room */ + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); + } + + void testSession() { + to = "prosody.doomsong.co.uk"; + resolver->addAddress("prosody.doomsong.co.uk", HostAddress::fromString("127.0.0.1").get()); + path = "/http-bind/"; + boshURL = URL("http", to, 5280, path); + + PoolRef testling = createTestling(); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* header*/ + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + + std::string response = "<body authid='743da605-4c2e-4de1-afac-ac040dd4a940' xmpp:version='1.0' xmlns:stream='http://etherx.jabber.org/streams' xmlns:xmpp='urn:xmpp:xbosh' inactivity='60' wait='60' polling='5' secure='true' hold='1' from='prosody.doomsong.co.uk' ver='1.6' sid='743da605-4c2e-4de1-afac-ac040dd4a940' requests='2' xmlns='http://jabber.org/protocol/httpbind'><stream:features><auth xmlns='http://jabber.org/features/iq-auth'/><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>SCRAM-SHA-1</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features></body>"; + readResponse(response, connectionFactory->connections[0]); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + + std::string send = "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"SCRAM-SHA-1\">biwsbj1hZG1pbixyPWZhOWE5ZDhiLWZmMDctNGE4Yy04N2E3LTg4YWRiNDQxZGUwYg==</auth>"; + testling->write(createSafeByteArray(send)); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size()); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + + response = "<body xmlns='http://jabber.org/protocol/httpbind' sid='743da605-4c2e-4de1-afac-ac040dd4a940' xmlns:stream = 'http://etherx.jabber.org/streams'><challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cj1mYTlhOWQ4Yi1mZjA3LTRhOGMtODdhNy04OGFkYjQ0MWRlMGJhZmZlMWNhMy1mMDJkLTQ5NzEtYjkyNS0yM2NlNWQ2MDQyMjYscz1OVGd5WkdWaFptTXRaVE15WXkwMFpXUmhMV0ZqTURRdFpqYzRNbUppWmpGa1pqWXgsaT00MDk2</challenge></body>"; + readResponse(response, connectionFactory->connections[0]); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size()); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + + send = "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">Yz1iaXdzLHI9ZmE5YTlkOGItZmYwNy00YThjLTg3YTctODhhZGI0NDFkZTBiYWZmZTFjYTMtZjAyZC00OTcxLWI5MjUtMjNjZTVkNjA0MjI2LHA9aU11NWt3dDN2VWplU2RqL01Jb3VIRldkZjBnPQ==</response>"; + testling->write(createSafeByteArray(send)); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + + response = "<body xmlns='http://jabber.org/protocol/httpbind' sid='743da605-4c2e-4de1-afac-ac040dd4a940' xmlns:stream = 'http://etherx.jabber.org/streams'><success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>dj1YNmNBY3BBOWxHNjNOOXF2bVQ5S0FacERrVm89</success></body>"; + readResponse(response, connectionFactory->connections[0]); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + + testling->restartStream(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(4), boshDataWritten.size()); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + + response = "<body xmpp:version='1.0' xmlns:stream='http://etherx.jabber.org/streams' xmlns:xmpp='urn:xmpp:xbosh' inactivity='60' wait='60' polling='5' secure='true' hold='1' from='prosody.doomsong.co.uk' ver='1.6' sid='743da605-4c2e-4de1-afac-ac040dd4a940' requests='2' xmlns='http://jabber.org/protocol/httpbind'><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><required/></bind><session xmlns='urn:ietf:params:xml:ns:xmpp-session'><optional/></session><sm xmlns='urn:xmpp:sm:2'><optional/></sm></stream:features></body>"; + readResponse(response, connectionFactory->connections[0]); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(5), boshDataWritten.size()); /* Now we've authed (restarted) we should be keeping one query in flight so the server can reply to us at any time it wants. */ + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + + send = "<body rid='2821988967416214' sid='cf663f6b94279d4f' xmlns='http://jabber.org/protocol/httpbind'><iq id='session-bind' type='set'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>d5a9744036cd20a0</resource></bind></iq></body>"; + testling->write(createSafeByteArray(send)); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(6), boshDataWritten.size()); + CPPUNIT_ASSERT_EQUAL(st(2), connectionFactory->connections.size()); /* and as it keeps one in flight, it's needed to open a second to send these data */ + + } + + void testWrite_Empty() { + std::shared_ptr<MockConnection> c0; + + PoolRef testling = createTestling(); + CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); + c0 = connectionFactory->connections[0]; + + readResponse(initial, c0); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(1), boshDataWritten.size()); /* Shouldn't have sent anything extra */ + eventLoop->processEvents(); + testling->restartStream(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(2), boshDataWritten.size()); + readResponse("<body></body>", c0); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(st(3), boshDataWritten.size()); + std::string fullBody = "<body rid='" + std::to_string(initialRID + 2) + "' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'></body>"; + std::string response = boshDataWritten[2]; + size_t bodyPosition = response.find("\r\n\r\n"); + CPPUNIT_ASSERT_EQUAL(fullBody, response.substr(bodyPosition+4)); + + + } + + private: + + PoolRef createTestling() { + // make_shared is limited to 9 arguments; instead new is used here. + PoolRef pool = PoolRef(new BOSHConnectionPool(boshURL, resolver, connectionFactory, &parserFactory, static_cast<TLSContextFactory*>(nullptr), timerFactory, eventLoop, to, initialRID, URL(), SafeString(""), SafeString(""), TLSOptions())); + pool->open(); + pool->onXMPPDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleXMPPDataRead, this, _1)); + pool->onBOSHDataRead.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataRead, this, _1)); + pool->onBOSHDataWritten.connect(boost::bind(&BOSHConnectionPoolTest::handleBOSHDataWritten, this, _1)); + pool->onSessionStarted.connect(boost::bind(&BOSHConnectionPoolTest::handleSessionStarted, this)); + pool->onSessionTerminated.connect(boost::bind(&BOSHConnectionPoolTest::handleSessionTerminated, this)); + eventLoop->processEvents(); + eventLoop->processEvents(); + return pool; + } + + std::string lastBody() { + std::string response = boshDataWritten[boshDataWritten.size() - 1]; + size_t bodyPosition = response.find("\r\n\r\n"); + return response.substr(bodyPosition+4); + } + + size_t st(int val) { + return static_cast<size_t>(val); + } + + void handleXMPPDataRead(const SafeByteArray& d) { + xmppDataRead.push_back(safeByteArrayToString(d)); + } + + void handleBOSHDataRead(const SafeByteArray& d) { + boshDataRead.push_back(safeByteArrayToString(d)); + } + + void handleBOSHDataWritten(const SafeByteArray& d) { + boshDataWritten.push_back(safeByteArrayToString(d)); + } + + + void handleSessionStarted() { + sessionStarted++; + } + + void handleSessionTerminated() { + sessionTerminated++; + } + + struct MockConnection : public Connection { + public: + MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop, bool autoFinishConnect) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false), pending(false), autoFinishConnect(autoFinishConnect) { + } + + void listen() { assert(false); } + + void connect(const HostAddressPort& address) { + hostAddressPort = address; + bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); + if (autoFinishConnect) { + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); + } + } + + HostAddressPort getLocalAddress() const { return HostAddressPort(); } + HostAddressPort getRemoteAddress() const { return HostAddressPort(); } + + void disconnect() { + disconnected = true; + onDisconnected(boost::optional<Connection::Error>()); + } + + void write(const SafeByteArray& d) { + append(dataWritten, d); + pending = true; + } + + EventLoop* eventLoop; + boost::optional<HostAddressPort> hostAddressPort; + std::vector<HostAddressPort> failingPorts; + ByteArray dataWritten; + bool disconnected; + bool pending; + bool autoFinishConnect; + }; + + struct MockConnectionFactory : public ConnectionFactory { + MockConnectionFactory(EventLoop* eventLoop, bool autoFinishConnect = true) : eventLoop(eventLoop), autoFinishConnect(autoFinishConnect) { + } + + std::shared_ptr<Connection> createConnection() { + std::shared_ptr<MockConnection> connection = std::make_shared<MockConnection>(failingPorts, eventLoop, autoFinishConnect); + connections.push_back(connection); + return connection; + } + + EventLoop* eventLoop; + std::vector< std::shared_ptr<MockConnection> > connections; + std::vector<HostAddressPort> failingPorts; + bool autoFinishConnect; + }; + + void readResponse(const std::string& response, std::shared_ptr<MockConnection> connection) { + connection->pending = false; + std::shared_ptr<SafeByteArray> data1 = std::make_shared<SafeByteArray>(createSafeByteArray( + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/xml; charset=utf-8\r\n" + "Access-Control-Allow-Origin: *\r\n" + "Access-Control-Allow-Headers: Content-Type\r\n" + "Content-Length: ")); + connection->onDataRead(data1); + std::shared_ptr<SafeByteArray> data2 = std::make_shared<SafeByteArray>(createSafeByteArray(std::to_string(response.size()))); + connection->onDataRead(data2); + std::shared_ptr<SafeByteArray> data3 = std::make_shared<SafeByteArray>(createSafeByteArray("\r\n\r\n")); + connection->onDataRead(data3); + std::shared_ptr<SafeByteArray> data4 = std::make_shared<SafeByteArray>(createSafeByteArray(response)); + connection->onDataRead(data4); + } + + std::string fullRequestFor(const std::string& data) { + std::string body = data; + std::string result = "POST /" + path + " HTTP/1.1\r\n" + + "Host: " + to + ":" + port + "\r\n" + + "Content-Type: text/xml; charset=utf-8\r\n" + + "Content-Length: " + std::to_string(body.size()) + "\r\n\r\n" + + body; + return result; + } + + private: + URL boshURL; + DummyEventLoop* eventLoop; + MockConnectionFactory* connectionFactory; + std::vector<std::string> xmppDataRead; + std::vector<std::string> boshDataRead; + std::vector<std::string> boshDataWritten; + PlatformXMLParserFactory parserFactory; + StaticDomainNameResolver* resolver; + TimerFactory* timerFactory; + std::string to; + std::string path; + std::string port; + std::string sid; + std::string initial; + unsigned long long initialRID; + int sessionStarted; + int sessionTerminated; }; diff --git a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp index 7ef0249..17d8333 100644 --- a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp +++ b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp @@ -1,300 +1,346 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + +#include <boost/bind.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> + #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/optional.hpp> -#include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/lexical_cast.hpp> - #include <Swiften/Base/Algorithm.h> +#include <Swiften/EventLoop/DummyEventLoop.h> +#include <Swiften/Network/BOSHConnection.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/ConnectionFactory.h> -#include <Swiften/Network/BOSHConnection.h> +#include <Swiften/Network/DummyTimerFactory.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/StaticDomainNameResolver.h> -#include <Swiften/Network/DummyTimerFactory.h> -#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Parser/PlatformXMLParserFactory.h> +#include <Swiften/TLS/TLSOptions.h> using namespace Swift; class BOSHConnectionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(BOSHConnectionTest); - CPPUNIT_TEST(testHeader); - CPPUNIT_TEST(testReadiness_ok); - CPPUNIT_TEST(testReadiness_pending); - CPPUNIT_TEST(testReadiness_disconnect); - CPPUNIT_TEST(testReadiness_noSID); - CPPUNIT_TEST(testWrite_Receive); - CPPUNIT_TEST(testWrite_ReceiveTwice); - CPPUNIT_TEST(testRead_Fragment); - CPPUNIT_TEST(testHTTPRequest); - CPPUNIT_TEST(testHTTPRequest_Empty); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - eventLoop = new DummyEventLoop(); - connectionFactory = new MockConnectionFactory(eventLoop); - resolver = new StaticDomainNameResolver(eventLoop); - timerFactory = new DummyTimerFactory(); - connectFinished = false; - disconnected = false; - disconnectedError = false; - dataRead.clear(); - } - - void tearDown() { - eventLoop->processEvents(); - delete connectionFactory; - delete resolver; - delete timerFactory; - delete eventLoop; - } - - void testHeader() { - BOSHConnection::ref testling = createTestling(); - testling->connect(); - eventLoop->processEvents(); - testling->startStream("wonderland.lit", 1); - std::string initial("<body wait='60' " - "inactivity='30' " - "polling='5' " - "requests='2' " - "hold='1' " - "maxpause='120' " - "sid='MyShinySID' " - "ver='1.6' " - "from='wonderland.lit' " - "xmlns='http://jabber.org/protocol/httpbind'/>"); - readResponse(initial, connectionFactory->connections[0]); - CPPUNIT_ASSERT_EQUAL(std::string("MyShinySID"), sid); - CPPUNIT_ASSERT(testling->isReadyToSend()); - } - - void testReadiness_ok() { - BOSHConnection::ref testling = createTestling(); - testling->connect(); - eventLoop->processEvents(); - testling->setSID("blahhhhh"); - CPPUNIT_ASSERT(testling->isReadyToSend()); - } - - void testReadiness_pending() { - BOSHConnection::ref testling = createTestling(); - testling->connect(); - eventLoop->processEvents(); - testling->setSID("mySID"); - CPPUNIT_ASSERT(testling->isReadyToSend()); - testling->write(createSafeByteArray("<mypayload/>")); - CPPUNIT_ASSERT(!testling->isReadyToSend()); - readResponse("<body><blah/></body>", connectionFactory->connections[0]); - CPPUNIT_ASSERT(testling->isReadyToSend()); - } - - void testReadiness_disconnect() { - BOSHConnection::ref testling = createTestling(); - testling->connect(); - eventLoop->processEvents(); - testling->setSID("mySID"); - CPPUNIT_ASSERT(testling->isReadyToSend()); - connectionFactory->connections[0]->onDisconnected(false); - CPPUNIT_ASSERT(!testling->isReadyToSend()); - } - - - void testReadiness_noSID() { - BOSHConnection::ref testling = createTestling(); - testling->connect(); - eventLoop->processEvents(); - CPPUNIT_ASSERT(!testling->isReadyToSend()); - } - - void testWrite_Receive() { - BOSHConnection::ref testling = createTestling(); - testling->connect(); - eventLoop->processEvents(); - testling->setSID("mySID"); - testling->write(createSafeByteArray("<mypayload/>")); - readResponse("<body><blah/></body>", connectionFactory->connections[0]); - CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead)); - - } - - void testWrite_ReceiveTwice() { - BOSHConnection::ref testling = createTestling(); - testling->connect(); - eventLoop->processEvents(); - testling->setSID("mySID"); - testling->write(createSafeByteArray("<mypayload/>")); - readResponse("<body><blah/></body>", connectionFactory->connections[0]); - CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead)); - dataRead.clear(); - testling->write(createSafeByteArray("<mypayload2/>")); - readResponse("<body><bleh/></body>", connectionFactory->connections[0]); - CPPUNIT_ASSERT_EQUAL(std::string("<bleh/>"), byteArrayToString(dataRead)); - } - - void testRead_Fragment() { - BOSHConnection::ref testling = createTestling(); - testling->connect(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), connectionFactory->connections.size()); - boost::shared_ptr<MockConnection> connection = connectionFactory->connections[0]; - boost::shared_ptr<SafeByteArray> data1 = boost::make_shared<SafeByteArray>(createSafeByteArray( - "HTTP/1.1 200 OK\r\n" - "Content-Type: text/xml; charset=utf-8\r\n" - "Access-Control-Allow-Origin: *\r\n" - "Access-Control-Allow-Headers: Content-Type\r\n" - "Content-Length: 64\r\n")); - boost::shared_ptr<SafeByteArray> data2 = boost::make_shared<SafeByteArray>(createSafeByteArray( - "\r\n<body xmlns='http://jabber.org/protocol/httpbind'>" - "<bl")); - boost::shared_ptr<SafeByteArray> data3 = boost::make_shared<SafeByteArray>(createSafeByteArray( - "ah/>" - "</body>")); - connection->onDataRead(data1); - connection->onDataRead(data2); - CPPUNIT_ASSERT(dataRead.empty()); - connection->onDataRead(data3); - CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead)); - } - - void testHTTPRequest() { - std::string data = "<blah/>"; - std::string sid = "wigglebloom"; - std::string fullBody = "<body xmlns='http://jabber.org/protocol/httpbind' sid='" + sid + "' rid='20'>" + data + "</body>"; - std::pair<SafeByteArray, size_t> http = BOSHConnection::createHTTPRequest(createSafeByteArray(data), false, false, 20, sid, URL()); - CPPUNIT_ASSERT_EQUAL(fullBody.size(), http.second); - } - - void testHTTPRequest_Empty() { - std::string data = ""; - std::string sid = "wigglebloomsickle"; - std::string fullBody = "<body rid='42' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'>" + data + "</body>"; - std::pair<SafeByteArray, size_t> http = BOSHConnection::createHTTPRequest(createSafeByteArray(data), false, false, 42, sid, URL()); - CPPUNIT_ASSERT_EQUAL(fullBody.size(), http.second); - std::string response = safeByteArrayToString(http.first); - size_t bodyPosition = response.find("\r\n\r\n"); - CPPUNIT_ASSERT_EQUAL(fullBody, response.substr(bodyPosition+4)); - } - - private: - - BOSHConnection::ref createTestling() { - resolver->addAddress("wonderland.lit", HostAddress("127.0.0.1")); - Connector::ref connector = Connector::create("wonderland.lit", 5280, false, resolver, connectionFactory, timerFactory); - BOSHConnection::ref c = BOSHConnection::create(URL("http", "wonderland.lit", 5280, "/http-bind"), connector, &parserFactory); - c->onConnectFinished.connect(boost::bind(&BOSHConnectionTest::handleConnectFinished, this, _1)); - c->onDisconnected.connect(boost::bind(&BOSHConnectionTest::handleDisconnected, this, _1)); - c->onXMPPDataRead.connect(boost::bind(&BOSHConnectionTest::handleDataRead, this, _1)); - c->onSessionStarted.connect(boost::bind(&BOSHConnectionTest::handleSID, this, _1)); - c->setRID(42); - return c; - } - - void handleConnectFinished(bool error) { - connectFinished = true; - connectFinishedWithError = error; - } - - void handleDisconnected(bool e) { - disconnected = true; - disconnectedError = e; - } - - void handleDataRead(const SafeByteArray& d) { - append(dataRead, d); - } - - void handleSID(const std::string& s) { - sid = s; - } - - struct MockConnection : public Connection { - public: - MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false) { - } - - void listen() { assert(false); } - - void connect(const HostAddressPort& address) { - hostAddressPort = address; - bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); - } - - HostAddressPort getLocalAddress() const { return HostAddressPort(); } - - void disconnect() { - disconnected = true; - onDisconnected(boost::optional<Connection::Error>()); - } - - void write(const SafeByteArray& d) { - append(dataWritten, d); - } - - EventLoop* eventLoop; - boost::optional<HostAddressPort> hostAddressPort; - std::vector<HostAddressPort> failingPorts; - ByteArray dataWritten; - bool disconnected; - }; - - struct MockConnectionFactory : public ConnectionFactory { - MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) { - } - - boost::shared_ptr<Connection> createConnection() { - boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop); - connections.push_back(connection); - return connection; - } - - EventLoop* eventLoop; - std::vector< boost::shared_ptr<MockConnection> > connections; - std::vector<HostAddressPort> failingPorts; - }; - - void readResponse(const std::string& response, boost::shared_ptr<MockConnection> connection) { - boost::shared_ptr<SafeByteArray> data1 = boost::make_shared<SafeByteArray>(createSafeByteArray( - "HTTP/1.1 200 OK\r\n" - "Content-Type: text/xml; charset=utf-8\r\n" - "Access-Control-Allow-Origin: *\r\n" - "Access-Control-Allow-Headers: Content-Type\r\n" - "Content-Length: ")); - connection->onDataRead(data1); - boost::shared_ptr<SafeByteArray> data2 = boost::make_shared<SafeByteArray>(createSafeByteArray(boost::lexical_cast<std::string>(response.size()))); - connection->onDataRead(data2); - boost::shared_ptr<SafeByteArray> data3 = boost::make_shared<SafeByteArray>(createSafeByteArray("\r\n\r\n")); - connection->onDataRead(data3); - boost::shared_ptr<SafeByteArray> data4 = boost::make_shared<SafeByteArray>(createSafeByteArray(response)); - connection->onDataRead(data4); - } - - - private: - DummyEventLoop* eventLoop; - MockConnectionFactory* connectionFactory; - bool connectFinished; - bool connectFinishedWithError; - bool disconnected; - bool disconnectedError; - ByteArray dataRead; - PlatformXMLParserFactory parserFactory; - StaticDomainNameResolver* resolver; - TimerFactory* timerFactory; - std::string sid; + CPPUNIT_TEST_SUITE(BOSHConnectionTest); + CPPUNIT_TEST(testHeader); + CPPUNIT_TEST(testReadiness_ok); + CPPUNIT_TEST(testReadiness_pending); + CPPUNIT_TEST(testReadiness_disconnect); + CPPUNIT_TEST(testReadiness_noSID); + CPPUNIT_TEST(testWrite_Receive); + CPPUNIT_TEST(testWrite_ReceiveTwice); + CPPUNIT_TEST(testRead_Fragment); + CPPUNIT_TEST(testHTTPRequest); + CPPUNIT_TEST(testHTTPRequest_Empty); + CPPUNIT_TEST(testTerminate); + CPPUNIT_TEST(testTerminateWithAdditionalData); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + eventLoop = new DummyEventLoop(); + connectionFactory = new MockConnectionFactory(eventLoop); + resolver = new StaticDomainNameResolver(eventLoop); + timerFactory = new DummyTimerFactory(); + tlsContextFactory = nullptr; + connectFinished = false; + disconnected = false; + disconnectedError = false; + sessionTerminatedError.reset(); + dataRead.clear(); + } + + void tearDown() { + eventLoop->processEvents(); + delete connectionFactory; + delete resolver; + delete timerFactory; + delete eventLoop; + } + + void testHeader() { + BOSHConnection::ref testling = createTestling(); + testling->connect(); + eventLoop->processEvents(); + testling->startStream("wonderland.lit", 1); + std::string initial("<body wait='60' " + "inactivity='30' " + "polling='5' " + "requests='2' " + "hold='1' " + "maxpause='120' " + "sid='MyShinySID' " + "ver='1.6' " + "from='wonderland.lit' " + "xmlns='http://jabber.org/protocol/httpbind'/>"); + readResponse(initial, connectionFactory->connections[0]); + CPPUNIT_ASSERT_EQUAL(std::string("MyShinySID"), sid); + CPPUNIT_ASSERT(testling->isReadyToSend()); + } + + void testReadiness_ok() { + BOSHConnection::ref testling = createTestling(); + testling->connect(); + eventLoop->processEvents(); + testling->setSID("blahhhhh"); + CPPUNIT_ASSERT(testling->isReadyToSend()); + } + + void testReadiness_pending() { + BOSHConnection::ref testling = createTestling(); + testling->connect(); + eventLoop->processEvents(); + testling->setSID("mySID"); + CPPUNIT_ASSERT(testling->isReadyToSend()); + testling->write(createSafeByteArray("<mypayload/>")); + CPPUNIT_ASSERT(!testling->isReadyToSend()); + readResponse("<body><blah/></body>", connectionFactory->connections[0]); + CPPUNIT_ASSERT(testling->isReadyToSend()); + } + + void testReadiness_disconnect() { + BOSHConnection::ref testling = createTestling(); + testling->connect(); + eventLoop->processEvents(); + testling->setSID("mySID"); + CPPUNIT_ASSERT(testling->isReadyToSend()); + connectionFactory->connections[0]->onDisconnected(boost::optional<Connection::Error>()); + CPPUNIT_ASSERT(!testling->isReadyToSend()); + } + + + void testReadiness_noSID() { + BOSHConnection::ref testling = createTestling(); + testling->connect(); + eventLoop->processEvents(); + CPPUNIT_ASSERT(!testling->isReadyToSend()); + } + + void testWrite_Receive() { + BOSHConnection::ref testling = createTestling(); + testling->connect(); + eventLoop->processEvents(); + testling->setSID("mySID"); + testling->write(createSafeByteArray("<mypayload/>")); + readResponse("<body><blah/></body>", connectionFactory->connections[0]); + CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead)); + + } + + void testWrite_ReceiveTwice() { + BOSHConnection::ref testling = createTestling(); + testling->connect(); + eventLoop->processEvents(); + testling->setSID("mySID"); + testling->write(createSafeByteArray("<mypayload/>")); + readResponse("<body><blah/></body>", connectionFactory->connections[0]); + CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead)); + dataRead.clear(); + testling->write(createSafeByteArray("<mypayload2/>")); + readResponse("<body><bleh/></body>", connectionFactory->connections[0]); + CPPUNIT_ASSERT_EQUAL(std::string("<bleh/>"), byteArrayToString(dataRead)); + } + + void testRead_Fragment() { + BOSHConnection::ref testling = createTestling(); + testling->connect(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), connectionFactory->connections.size()); + std::shared_ptr<MockConnection> connection = connectionFactory->connections[0]; + std::shared_ptr<SafeByteArray> data1 = std::make_shared<SafeByteArray>(createSafeByteArray( + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/xml; charset=utf-8\r\n" + "Access-Control-Allow-Origin: *\r\n" + "Access-Control-Allow-Headers: Content-Type\r\n" + "Content-Length: 64\r\n")); + std::shared_ptr<SafeByteArray> data2 = std::make_shared<SafeByteArray>(createSafeByteArray( + "\r\n<body xmlns='http://jabber.org/protocol/httpbind'>" + "<bl")); + std::shared_ptr<SafeByteArray> data3 = std::make_shared<SafeByteArray>(createSafeByteArray( + "ah/>" + "</body>")); + connection->onDataRead(data1); + connection->onDataRead(data2); + CPPUNIT_ASSERT(dataRead.empty()); + connection->onDataRead(data3); + CPPUNIT_ASSERT_EQUAL(std::string("<blah/>"), byteArrayToString(dataRead)); + } + + void testHTTPRequest() { + std::string data = "<blah/>"; + std::string sid = "wigglebloom"; + std::string fullBody = "<body xmlns='http://jabber.org/protocol/httpbind' sid='" + sid + "' rid='20'>" + data + "</body>"; + std::pair<SafeByteArray, size_t> http = BOSHConnection::createHTTPRequest(createSafeByteArray(data), false, false, 20, sid, URL()); + CPPUNIT_ASSERT_EQUAL(fullBody.size(), http.second); + } + + void testHTTPRequest_Empty() { + std::string data = ""; + std::string sid = "wigglebloomsickle"; + std::string fullBody = "<body rid='42' sid='" + sid + "' xmlns='http://jabber.org/protocol/httpbind'>" + data + "</body>"; + std::pair<SafeByteArray, size_t> http = BOSHConnection::createHTTPRequest(createSafeByteArray(data), false, false, 42, sid, URL()); + CPPUNIT_ASSERT_EQUAL(fullBody.size(), http.second); + std::string response = safeByteArrayToString(http.first); + size_t bodyPosition = response.find("\r\n\r\n"); + CPPUNIT_ASSERT_EQUAL(fullBody, response.substr(bodyPosition+4)); + } + + void testTerminate() { + BOSHConnection::ref testling = createTestling(); + testling->connect(); + eventLoop->processEvents(); + testling->startStream("localhost", 1); + std::string initial("<body xmlns=\"http://jabber.org/protocol/httpbind\" " + "condition=\"bad-request\" " + "type=\"terminate\">" + "</body>"); + readResponse(initial, connectionFactory->connections[0]); + CPPUNIT_ASSERT(sessionTerminatedError); + CPPUNIT_ASSERT_EQUAL(BOSHError::BadRequest, sessionTerminatedError->getType()); + CPPUNIT_ASSERT_EQUAL(true, dataRead.empty()); + } + + // On a BOSH error no additional data may be emitted. + void testTerminateWithAdditionalData() { + BOSHConnection::ref testling = createTestling(); + testling->connect(); + eventLoop->processEvents(); + testling->startStream("localhost", 1); + std::string initial("<body xmlns=\"http://jabber.org/protocol/httpbind\" " + "condition=\"bad-request\" " + "type=\"terminate\">" + "<text>an error message</text>" + "</body>"); + readResponse(initial, connectionFactory->connections[0]); + CPPUNIT_ASSERT(sessionTerminatedError); + CPPUNIT_ASSERT_EQUAL(BOSHError::BadRequest, sessionTerminatedError->getType()); + CPPUNIT_ASSERT_EQUAL(true, dataRead.empty()); + } + + + private: + + BOSHConnection::ref createTestling() { + resolver->addAddress("wonderland.lit", HostAddress::fromString("127.0.0.1").get()); + Connector::ref connector = Connector::create("wonderland.lit", 5280, boost::optional<std::string>(), resolver, connectionFactory, timerFactory); + BOSHConnection::ref c = BOSHConnection::create(URL("http", "wonderland.lit", 5280, "/http-bind"), connector, &parserFactory, tlsContextFactory, TLSOptions()); + c->onConnectFinished.connect(boost::bind(&BOSHConnectionTest::handleConnectFinished, this, _1)); + c->onDisconnected.connect(boost::bind(&BOSHConnectionTest::handleDisconnected, this, _1)); + c->onXMPPDataRead.connect(boost::bind(&BOSHConnectionTest::handleDataRead, this, _1)); + c->onSessionStarted.connect(boost::bind(&BOSHConnectionTest::handleSID, this, _1)); + c->onSessionTerminated.connect(boost::bind(&BOSHConnectionTest::handleSessionTerminated, this, _1)); + c->setRID(42); + return c; + } + + void handleConnectFinished(bool error) { + connectFinished = true; + connectFinishedWithError = error; + } + + void handleDisconnected(bool e) { + disconnected = true; + disconnectedError = e; + } + + void handleDataRead(const SafeByteArray& d) { + append(dataRead, d); + } + + void handleSID(const std::string& s) { + sid = s; + } + + void handleSessionTerminated(BOSHError::ref error) { + sessionTerminatedError = error; + } + + struct MockConnection : public Connection { + public: + MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false) { + } + + void listen() { assert(false); } + + void connect(const HostAddressPort& address) { + hostAddressPort = address; + bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); + } + + HostAddressPort getLocalAddress() const { return HostAddressPort(); } + HostAddressPort getRemoteAddress() const { return HostAddressPort(); } + + void disconnect() { + disconnected = true; + onDisconnected(boost::optional<Connection::Error>()); + } + + void write(const SafeByteArray& d) { + append(dataWritten, d); + } + + EventLoop* eventLoop; + boost::optional<HostAddressPort> hostAddressPort; + std::vector<HostAddressPort> failingPorts; + ByteArray dataWritten; + bool disconnected; + }; + + struct MockConnectionFactory : public ConnectionFactory { + MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) { + } + + std::shared_ptr<Connection> createConnection() { + std::shared_ptr<MockConnection> connection = std::make_shared<MockConnection>(failingPorts, eventLoop); + connections.push_back(connection); + return connection; + } + + EventLoop* eventLoop; + std::vector< std::shared_ptr<MockConnection> > connections; + std::vector<HostAddressPort> failingPorts; + }; + + void readResponse(const std::string& response, std::shared_ptr<MockConnection> connection) { + std::shared_ptr<SafeByteArray> data1 = std::make_shared<SafeByteArray>(createSafeByteArray( + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/xml; charset=utf-8\r\n" + "Access-Control-Allow-Origin: *\r\n" + "Access-Control-Allow-Headers: Content-Type\r\n" + "Content-Length: ")); + connection->onDataRead(data1); + std::shared_ptr<SafeByteArray> data2 = std::make_shared<SafeByteArray>(createSafeByteArray(std::to_string(response.size()))); + connection->onDataRead(data2); + std::shared_ptr<SafeByteArray> data3 = std::make_shared<SafeByteArray>(createSafeByteArray("\r\n\r\n")); + connection->onDataRead(data3); + std::shared_ptr<SafeByteArray> data4 = std::make_shared<SafeByteArray>(createSafeByteArray(response)); + connection->onDataRead(data4); + } + + + private: + DummyEventLoop* eventLoop; + MockConnectionFactory* connectionFactory; + bool connectFinished; + bool connectFinishedWithError; + bool disconnected; + bool disconnectedError; + BOSHError::ref sessionTerminatedError; + ByteArray dataRead; + PlatformXMLParserFactory parserFactory; + StaticDomainNameResolver* resolver; + TimerFactory* timerFactory; + TLSContextFactory* tlsContextFactory; + std::string sid; }; diff --git a/Swiften/Network/UnitTest/ChainedConnectorTest.cpp b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp index 9abed57..2d78cd7 100644 --- a/Swiften/Network/UnitTest/ChainedConnectorTest.cpp +++ b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp @@ -1,186 +1,188 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <memory> #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Network/ChainedConnector.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/DomainNameResolveError.h> +#include <Swiften/Network/DummyTimerFactory.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/StaticDomainNameResolver.h> -#include <Swiften/Network/DummyTimerFactory.h> -#include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/Network/DomainNameResolveError.h> using namespace Swift; class ChainedConnectorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ChainedConnectorTest); - CPPUNIT_TEST(testConnect_FirstConnectorSucceeds); - CPPUNIT_TEST(testConnect_SecondConnectorSucceeds); - CPPUNIT_TEST(testConnect_NoConnectorSucceeds); - CPPUNIT_TEST(testConnect_NoDNS); - CPPUNIT_TEST(testStop); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - error.reset(); - host = HostAddressPort(HostAddress("1.1.1.1"), 1234); - eventLoop = new DummyEventLoop(); - resolver = new StaticDomainNameResolver(eventLoop); - resolver->addXMPPClientService("foo.com", host); - connectionFactory1 = new MockConnectionFactory(eventLoop, 1); - connectionFactory2 = new MockConnectionFactory(eventLoop, 2); - timerFactory = new DummyTimerFactory(); - } - - void tearDown() { - delete timerFactory; - delete connectionFactory2; - delete connectionFactory1; - delete resolver; - delete eventLoop; - } - - void testConnect_FirstConnectorSucceeds() { - boost::shared_ptr<ChainedConnector> testling(createConnector()); - connectionFactory1->connects = true; - connectionFactory2->connects = false; - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT_EQUAL(1, boost::dynamic_pointer_cast<MockConnection>(connections[0])->id); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_SecondConnectorSucceeds() { - boost::shared_ptr<ChainedConnector> testling(createConnector()); - connectionFactory1->connects = false; - connectionFactory2->connects = true; - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT_EQUAL(2, boost::dynamic_pointer_cast<MockConnection>(connections[0])->id); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_NoConnectorSucceeds() { - boost::shared_ptr<ChainedConnector> testling(createConnector()); - connectionFactory1->connects = false; - connectionFactory2->connects = false; - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_NoDNS() { - /* Reset resolver so there's no record */ - delete resolver; - resolver = new StaticDomainNameResolver(eventLoop); - boost::shared_ptr<ChainedConnector> testling(createConnector()); - connectionFactory1->connects = false; - connectionFactory2->connects = false; - - testling->start(); - //testling->stop(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testStop() { - boost::shared_ptr<ChainedConnector> testling(createConnector()); - connectionFactory1->connects = true; - connectionFactory2->connects = false; - - testling->start(); - testling->stop(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - } - - private: - boost::shared_ptr<ChainedConnector> createConnector() { - std::vector<ConnectionFactory*> factories; - factories.push_back(connectionFactory1); - factories.push_back(connectionFactory2); - boost::shared_ptr<ChainedConnector> connector = boost::make_shared<ChainedConnector>("foo.com", -1, true, resolver, factories, timerFactory); - connector->onConnectFinished.connect(boost::bind(&ChainedConnectorTest::handleConnectorFinished, this, _1, _2)); - return connector; - } - - void handleConnectorFinished(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error> resultError) { - error = resultError; - boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection)); - if (connection) { - assert(c); - } - connections.push_back(c); - } - - struct MockConnection : public Connection { - public: - MockConnection(bool connects, int id, EventLoop* eventLoop) : connects(connects), id(id), eventLoop(eventLoop) { - } - - void listen() { assert(false); } - void connect(const HostAddressPort&) { - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), !connects)); - } - - HostAddressPort getLocalAddress() const { return HostAddressPort(); } - void disconnect() { assert(false); } - void write(const SafeByteArray&) { assert(false); } - - bool connects; - int id; - EventLoop* eventLoop; - }; - - struct MockConnectionFactory : public ConnectionFactory { - MockConnectionFactory(EventLoop* eventLoop, int id) : eventLoop(eventLoop), connects(true), id(id) { - } - - boost::shared_ptr<Connection> createConnection() { - return boost::make_shared<MockConnection>(connects, id, eventLoop); - } - - EventLoop* eventLoop; - bool connects; - int id; - }; - - private: - HostAddressPort host; - DummyEventLoop* eventLoop; - StaticDomainNameResolver* resolver; - MockConnectionFactory* connectionFactory1; - MockConnectionFactory* connectionFactory2; - DummyTimerFactory* timerFactory; - std::vector< boost::shared_ptr<MockConnection> > connections; - boost::shared_ptr<Error> error; + CPPUNIT_TEST_SUITE(ChainedConnectorTest); + CPPUNIT_TEST(testConnect_FirstConnectorSucceeds); + CPPUNIT_TEST(testConnect_SecondConnectorSucceeds); + CPPUNIT_TEST(testConnect_NoConnectorSucceeds); + CPPUNIT_TEST(testConnect_NoDNS); + CPPUNIT_TEST(testStop); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + error.reset(); + host = HostAddressPort(HostAddress::fromString("1.1.1.1").get(), 1234); + eventLoop = new DummyEventLoop(); + resolver = new StaticDomainNameResolver(eventLoop); + resolver->addXMPPClientService("foo.com", host); + connectionFactory1 = new MockConnectionFactory(eventLoop, 1); + connectionFactory2 = new MockConnectionFactory(eventLoop, 2); + timerFactory = new DummyTimerFactory(); + } + + void tearDown() { + delete timerFactory; + delete connectionFactory2; + delete connectionFactory1; + delete resolver; + delete eventLoop; + } + + void testConnect_FirstConnectorSucceeds() { + std::shared_ptr<ChainedConnector> testling(createConnector()); + connectionFactory1->connects = true; + connectionFactory2->connects = false; + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT_EQUAL(1, std::dynamic_pointer_cast<MockConnection>(connections[0])->id); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_SecondConnectorSucceeds() { + std::shared_ptr<ChainedConnector> testling(createConnector()); + connectionFactory1->connects = false; + connectionFactory2->connects = true; + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT_EQUAL(2, std::dynamic_pointer_cast<MockConnection>(connections[0])->id); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_NoConnectorSucceeds() { + std::shared_ptr<ChainedConnector> testling(createConnector()); + connectionFactory1->connects = false; + connectionFactory2->connects = false; + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_NoDNS() { + /* Reset resolver so there's no record */ + delete resolver; + resolver = new StaticDomainNameResolver(eventLoop); + std::shared_ptr<ChainedConnector> testling(createConnector()); + connectionFactory1->connects = false; + connectionFactory2->connects = false; + + testling->start(); + //testling->stop(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + CPPUNIT_ASSERT(std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testStop() { + std::shared_ptr<ChainedConnector> testling(createConnector()); + connectionFactory1->connects = true; + connectionFactory2->connects = false; + + testling->start(); + testling->stop(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + private: + std::shared_ptr<ChainedConnector> createConnector() { + std::vector<ConnectionFactory*> factories; + factories.push_back(connectionFactory1); + factories.push_back(connectionFactory2); + std::shared_ptr<ChainedConnector> connector = std::make_shared<ChainedConnector>("foo.com", -1, boost::optional<std::string>("_xmpp-client._tcp."), resolver, factories, timerFactory); + connector->onConnectFinished.connect(boost::bind(&ChainedConnectorTest::handleConnectorFinished, this, _1, _2)); + return connector; + } + + void handleConnectorFinished(std::shared_ptr<Connection> connection, std::shared_ptr<Error> resultError) { + error = resultError; + std::shared_ptr<MockConnection> c(std::dynamic_pointer_cast<MockConnection>(connection)); + if (connection) { + assert(c); + } + connections.push_back(c); + } + + struct MockConnection : public Connection { + public: + MockConnection(bool connects, int id, EventLoop* eventLoop) : connects(connects), id(id), eventLoop(eventLoop) { + } + + void listen() { assert(false); } + void connect(const HostAddressPort&) { + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), !connects)); + } + + HostAddressPort getLocalAddress() const { return HostAddressPort(); } + HostAddressPort getRemoteAddress() const { return HostAddressPort(); } + void disconnect() { assert(false); } + void write(const SafeByteArray&) { assert(false); } + + bool connects; + int id; + EventLoop* eventLoop; + }; + + struct MockConnectionFactory : public ConnectionFactory { + MockConnectionFactory(EventLoop* eventLoop, int id) : eventLoop(eventLoop), connects(true), id(id) { + } + + std::shared_ptr<Connection> createConnection() { + return std::make_shared<MockConnection>(connects, id, eventLoop); + } + + EventLoop* eventLoop; + bool connects; + int id; + }; + + private: + HostAddressPort host; + DummyEventLoop* eventLoop; + StaticDomainNameResolver* resolver; + MockConnectionFactory* connectionFactory1; + MockConnectionFactory* connectionFactory2; + DummyTimerFactory* timerFactory; + std::vector< std::shared_ptr<MockConnection> > connections; + std::shared_ptr<Error> error; }; CPPUNIT_TEST_SUITE_REGISTRATION(ChainedConnectorTest); diff --git a/Swiften/Network/UnitTest/ConnectorTest.cpp b/Swiften/Network/UnitTest/ConnectorTest.cpp index fe18340..065911d 100644 --- a/Swiften/Network/UnitTest/ConnectorTest.cpp +++ b/Swiften/Network/UnitTest/ConnectorTest.cpp @@ -1,378 +1,398 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <boost/bind.hpp> +#include <boost/optional.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/optional.hpp> -#include <boost/bind.hpp> - -#include <Swiften/Network/Connector.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/Connector.h> +#include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/Network/DummyTimerFactory.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/StaticDomainNameResolver.h> -#include <Swiften/Network/DummyTimerFactory.h> -#include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/Network/DomainNameAddressQuery.h> using namespace Swift; class ConnectorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ConnectorTest); - CPPUNIT_TEST(testConnect); - CPPUNIT_TEST(testConnect_NoServiceLookups); - CPPUNIT_TEST(testConnect_NoServiceLookups_DefaultPort); - CPPUNIT_TEST(testConnect_FirstAddressHostFails); - CPPUNIT_TEST(testConnect_NoSRVHost); - CPPUNIT_TEST(testConnect_NoHosts); - CPPUNIT_TEST(testConnect_FirstSRVHostFails); - CPPUNIT_TEST(testConnect_AllSRVHostsFailWithoutFallbackHost); - CPPUNIT_TEST(testConnect_AllSRVHostsFailWithFallbackHost); - CPPUNIT_TEST(testConnect_SRVAndFallbackHostsFail); - //CPPUNIT_TEST(testConnect_TimeoutDuringResolve); - CPPUNIT_TEST(testConnect_TimeoutDuringConnectToOnlyCandidate); - CPPUNIT_TEST(testConnect_TimeoutDuringConnectToCandidateFallsBack); - CPPUNIT_TEST(testConnect_NoTimeout); - CPPUNIT_TEST(testStop_DuringSRVQuery); - CPPUNIT_TEST(testStop_Timeout); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - host1 = HostAddressPort(HostAddress("1.1.1.1"), 1234); - host2 = HostAddressPort(HostAddress("2.2.2.2"), 2345); - host3 = HostAddressPort(HostAddress("3.3.3.3"), 5222); - eventLoop = new DummyEventLoop(); - resolver = new StaticDomainNameResolver(eventLoop); - connectionFactory = new MockConnectionFactory(eventLoop); - timerFactory = new DummyTimerFactory(); - } - - void tearDown() { - delete timerFactory; - delete connectionFactory; - delete resolver; - delete eventLoop; - } - - void testConnect() { - Connector::ref testling(createConnector()); - resolver->addXMPPClientService("foo.com", host1); - resolver->addXMPPClientService("foo.com", host2); - resolver->addAddress("foo.com", host3.getAddress()); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(host1 == *(connections[0]->hostAddressPort)); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_NoServiceLookups() { - Connector::ref testling(createConnector(4321, false)); - resolver->addXMPPClientService("foo.com", host1); - resolver->addXMPPClientService("foo.com", host2); - resolver->addAddress("foo.com", host3.getAddress()); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(host3.getAddress() == (*(connections[0]->hostAddressPort)).getAddress()); - CPPUNIT_ASSERT(4321 == (*(connections[0]->hostAddressPort)).getPort()); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_NoServiceLookups_DefaultPort() { - Connector::ref testling(createConnector(-1, false)); - resolver->addXMPPClientService("foo.com", host1); - resolver->addXMPPClientService("foo.com", host2); - resolver->addAddress("foo.com", host3.getAddress()); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(host3.getAddress() == (*(connections[0]->hostAddressPort)).getAddress()); - CPPUNIT_ASSERT_EQUAL(5222, (*(connections[0]->hostAddressPort)).getPort()); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_NoSRVHost() { - Connector::ref testling(createConnector()); - resolver->addAddress("foo.com", host3.getAddress()); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(host3 == *(connections[0]->hostAddressPort)); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_FirstAddressHostFails() { - Connector::ref testling(createConnector()); - - HostAddress address1("1.1.1.1"); - HostAddress address2("2.2.2.2"); - resolver->addXMPPClientService("foo.com", "host-foo.com", 1234); - resolver->addAddress("host-foo.com", address1); - resolver->addAddress("host-foo.com", address2); - connectionFactory->failingPorts.push_back(HostAddressPort(address1, 1234)); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(HostAddressPort(address2, 1234) == *(connections[0]->hostAddressPort)); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_NoHosts() { - Connector::ref testling(createConnector()); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_FirstSRVHostFails() { - Connector::ref testling(createConnector()); - resolver->addXMPPClientService("foo.com", host1); - resolver->addXMPPClientService("foo.com", host2); - connectionFactory->failingPorts.push_back(host1); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(host2 == *(connections[0]->hostAddressPort)); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_AllSRVHostsFailWithoutFallbackHost() { - Connector::ref testling(createConnector()); - resolver->addXMPPClientService("foo.com", host1); - resolver->addXMPPClientService("foo.com", host2); - connectionFactory->failingPorts.push_back(host1); - connectionFactory->failingPorts.push_back(host2); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_AllSRVHostsFailWithFallbackHost() { - Connector::ref testling(createConnector()); - resolver->addXMPPClientService("foo.com", host1); - resolver->addXMPPClientService("foo.com", host2); - resolver->addAddress("foo.com", host3.getAddress()); - connectionFactory->failingPorts.push_back(host1); - connectionFactory->failingPorts.push_back(host2); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(host3 == *(connections[0]->hostAddressPort)); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_SRVAndFallbackHostsFail() { - Connector::ref testling(createConnector()); - resolver->addXMPPClientService("foo.com", host1); - resolver->addAddress("foo.com", host3.getAddress()); - connectionFactory->failingPorts.push_back(host1); - connectionFactory->failingPorts.push_back(host3); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - /*void testConnect_TimeoutDuringResolve() { - Connector::ref testling(createConnector()); - testling->setTimeoutMilliseconds(10); - resolver->setIsResponsive(false); - - testling->start(); - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - CPPUNIT_ASSERT(!connections[0]); - }*/ - - void testConnect_TimeoutDuringConnectToOnlyCandidate() { - Connector::ref testling(createConnector()); - testling->setTimeoutMilliseconds(10); - resolver->addXMPPClientService("foo.com", host1); - connectionFactory->isResponsive = false; - - testling->start(); - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testConnect_TimeoutDuringConnectToCandidateFallsBack() { - Connector::ref testling(createConnector()); - testling->setTimeoutMilliseconds(10); - - resolver->addXMPPClientService("foo.com", "host-foo.com", 1234); - HostAddress address1("1.1.1.1"); - resolver->addAddress("host-foo.com", address1); - HostAddress address2("2.2.2.2"); - resolver->addAddress("host-foo.com", address2); - - connectionFactory->isResponsive = false; - testling->start(); - eventLoop->processEvents(); - connectionFactory->isResponsive = true; - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(HostAddressPort(address2, 1234) == *(connections[0]->hostAddressPort)); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - - void testConnect_NoTimeout() { - Connector::ref testling(createConnector()); - testling->setTimeoutMilliseconds(10); - resolver->addXMPPClientService("foo.com", host1); - - testling->start(); - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testStop_DuringSRVQuery() { - Connector::ref testling(createConnector()); - resolver->addXMPPClientService("foo.com", host1); - - testling->start(); - testling->stop(); - - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<DomainNameResolveError>(error)); - } - - void testStop_Timeout() { - Connector::ref testling(createConnector()); - testling->setTimeoutMilliseconds(10); - resolver->addXMPPClientService("foo.com", host1); - - testling->start(); - testling->stop(); - - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - } - - - private: - Connector::ref createConnector(int port = -1, bool doServiceLookups = true) { - Connector::ref connector = Connector::create("foo.com", port, doServiceLookups, resolver, connectionFactory, timerFactory); - connector->onConnectFinished.connect(boost::bind(&ConnectorTest::handleConnectorFinished, this, _1, _2)); - return connector; - } - - void handleConnectorFinished(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error> resultError) { - boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection)); - if (connection) { - assert(c); - } - connections.push_back(c); - error = resultError; - } - - struct MockConnection : public Connection { - public: - MockConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive) {} - - void listen() { assert(false); } - void connect(const HostAddressPort& address) { - hostAddressPort = address; - if (isResponsive) { - bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); - } - } - - HostAddressPort getLocalAddress() const { return HostAddressPort(); } - void disconnect() { assert(false); } - void write(const SafeByteArray&) { assert(false); } - - EventLoop* eventLoop; - boost::optional<HostAddressPort> hostAddressPort; - std::vector<HostAddressPort> failingPorts; - bool isResponsive; - }; - - struct MockConnectionFactory : public ConnectionFactory { - MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop), isResponsive(true) { - } - - boost::shared_ptr<Connection> createConnection() { - return boost::shared_ptr<Connection>(new MockConnection(failingPorts, isResponsive, eventLoop)); - } - - EventLoop* eventLoop; - bool isResponsive; - std::vector<HostAddressPort> failingPorts; - }; - - private: - HostAddressPort host1; - HostAddressPort host2; - HostAddressPort host3; - DummyEventLoop* eventLoop; - StaticDomainNameResolver* resolver; - MockConnectionFactory* connectionFactory; - DummyTimerFactory* timerFactory; - std::vector< boost::shared_ptr<MockConnection> > connections; - boost::shared_ptr<Error> error; + CPPUNIT_TEST_SUITE(ConnectorTest); + CPPUNIT_TEST(testConnect); + CPPUNIT_TEST(testConnect_NoServiceLookups); + CPPUNIT_TEST(testConnect_NoServiceLookups_DefaultPort); + CPPUNIT_TEST(testConnect_OnlyLiteral); + CPPUNIT_TEST(testConnect_FirstAddressHostFails); + CPPUNIT_TEST(testConnect_NoSRVHost); + CPPUNIT_TEST(testConnect_NoHosts); + CPPUNIT_TEST(testConnect_FirstSRVHostFails); + CPPUNIT_TEST(testConnect_AllSRVHostsFailWithoutFallbackHost); + CPPUNIT_TEST(testConnect_AllSRVHostsFailWithFallbackHost); + CPPUNIT_TEST(testConnect_SRVAndFallbackHostsFail); + //CPPUNIT_TEST(testConnect_TimeoutDuringResolve); + CPPUNIT_TEST(testConnect_TimeoutDuringConnectToOnlyCandidate); + CPPUNIT_TEST(testConnect_TimeoutDuringConnectToCandidateFallsBack); + CPPUNIT_TEST(testConnect_NoTimeout); + CPPUNIT_TEST(testStop_DuringSRVQuery); + CPPUNIT_TEST(testStop_Timeout); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + host1 = HostAddressPort(HostAddress::fromString("1.1.1.1").get(), 1234); + host2 = HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345); + host3 = HostAddressPort(HostAddress::fromString("3.3.3.3").get(), 5222); + eventLoop = new DummyEventLoop(); + resolver = new StaticDomainNameResolver(eventLoop); + connectionFactory = new MockConnectionFactory(eventLoop); + timerFactory = new DummyTimerFactory(); + } + + void tearDown() { + delete timerFactory; + delete connectionFactory; + delete resolver; + delete eventLoop; + } + + void testConnect() { + Connector::ref testling(createConnector()); + resolver->addXMPPClientService("foo.com", host1); + resolver->addXMPPClientService("foo.com", host2); + resolver->addAddress("foo.com", host3.getAddress()); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(host1 == *(connections[0]->hostAddressPort)); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_NoServiceLookups() { + Connector::ref testling(createConnector(4321, boost::optional<std::string>())); + resolver->addXMPPClientService("foo.com", host1); + resolver->addXMPPClientService("foo.com", host2); + resolver->addAddress("foo.com", host3.getAddress()); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(host3.getAddress() == (*(connections[0]->hostAddressPort)).getAddress()); + CPPUNIT_ASSERT(4321 == (*(connections[0]->hostAddressPort)).getPort()); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_NoServiceLookups_DefaultPort() { + Connector::ref testling(createConnector(0, boost::optional<std::string>())); + resolver->addXMPPClientService("foo.com", host1); + resolver->addXMPPClientService("foo.com", host2); + resolver->addAddress("foo.com", host3.getAddress()); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(host3.getAddress() == (*(connections[0]->hostAddressPort)).getAddress()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(5222), (*(connections[0]->hostAddressPort)).getPort()); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_NoSRVHost() { + Connector::ref testling(createConnector()); + resolver->addAddress("foo.com", host3.getAddress()); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(host3 == *(connections[0]->hostAddressPort)); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_OnlyLiteral() { + auto testling = Connector::create("1.1.1.1", 1234, boost::none, resolver, connectionFactory, timerFactory); + testling->onConnectFinished.connect(boost::bind(&ConnectorTest::handleConnectorFinished, this, _1, _2)); + + auto address1 = HostAddress::fromString("1.1.1.1").get(); + connectionFactory->failingPorts.push_back(HostAddressPort(address1, 1234)); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connectionFactory->createdConnections.size())); + } + + void testConnect_FirstAddressHostFails() { + Connector::ref testling(createConnector()); + + auto address1 = HostAddress::fromString("1.1.1.1").get(); + auto address2 = HostAddress::fromString("2.2.2.2").get(); + resolver->addXMPPClientService("foo.com", "host-foo.com", 1234); + resolver->addAddress("host-foo.com", address1); + resolver->addAddress("host-foo.com", address2); + connectionFactory->failingPorts.push_back(HostAddressPort(address1, 1234)); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(HostAddressPort(address2, 1234) == *(connections[0]->hostAddressPort)); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_NoHosts() { + Connector::ref testling(createConnector()); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + CPPUNIT_ASSERT(std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_FirstSRVHostFails() { + Connector::ref testling(createConnector()); + resolver->addXMPPClientService("foo.com", host1); + resolver->addXMPPClientService("foo.com", host2); + connectionFactory->failingPorts.push_back(host1); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(host2 == *(connections[0]->hostAddressPort)); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_AllSRVHostsFailWithoutFallbackHost() { + Connector::ref testling(createConnector()); + resolver->addXMPPClientService("foo.com", host1); + resolver->addXMPPClientService("foo.com", host2); + connectionFactory->failingPorts.push_back(host1); + connectionFactory->failingPorts.push_back(host2); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_AllSRVHostsFailWithFallbackHost() { + Connector::ref testling(createConnector()); + resolver->addXMPPClientService("foo.com", host1); + resolver->addXMPPClientService("foo.com", host2); + resolver->addAddress("foo.com", host3.getAddress()); + connectionFactory->failingPorts.push_back(host1); + connectionFactory->failingPorts.push_back(host2); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(host3 == *(connections[0]->hostAddressPort)); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_SRVAndFallbackHostsFail() { + Connector::ref testling(createConnector()); + resolver->addXMPPClientService("foo.com", host1); + resolver->addAddress("foo.com", host3.getAddress()); + connectionFactory->failingPorts.push_back(host1); + connectionFactory->failingPorts.push_back(host3); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + /*void testConnect_TimeoutDuringResolve() { + Connector::ref testling(createConnector()); + testling->setTimeoutMilliseconds(10); + resolver->setIsResponsive(false); + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(std::dynamic_pointer_cast<DomainNameResolveError>(error)); + CPPUNIT_ASSERT(!connections[0]); + }*/ + + void testConnect_TimeoutDuringConnectToOnlyCandidate() { + Connector::ref testling(createConnector()); + testling->setTimeoutMilliseconds(10); + resolver->addXMPPClientService("foo.com", host1); + connectionFactory->isResponsive = false; + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testConnect_TimeoutDuringConnectToCandidateFallsBack() { + Connector::ref testling(createConnector()); + testling->setTimeoutMilliseconds(10); + + auto address2 = HostAddress::fromString("2.2.2.2").get(); + + resolver->addXMPPClientService("foo.com", "host-foo.com", 1234); + resolver->addAddress("host-foo.com", HostAddress::fromString("1.1.1.1").get()); + resolver->addAddress("host-foo.com", address2); + + connectionFactory->isResponsive = false; + testling->start(); + eventLoop->processEvents(); + connectionFactory->isResponsive = true; + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(HostAddressPort(address2, 1234) == *(connections[0]->hostAddressPort)); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + + void testConnect_NoTimeout() { + Connector::ref testling(createConnector()); + testling->setTimeoutMilliseconds(10); + resolver->addXMPPClientService("foo.com", host1); + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testStop_DuringSRVQuery() { + Connector::ref testling(createConnector()); + resolver->addXMPPClientService("foo.com", host1); + + testling->start(); + testling->stop(); + + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + CPPUNIT_ASSERT(std::dynamic_pointer_cast<DomainNameResolveError>(error)); + } + + void testStop_Timeout() { + Connector::ref testling(createConnector()); + testling->setTimeoutMilliseconds(10); + resolver->addXMPPClientService("foo.com", host1); + + testling->start(); + testling->stop(); + + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + + private: + Connector::ref createConnector(unsigned short port = 0, boost::optional<std::string> serviceLookupPrefix = boost::optional<std::string>("_xmpp-client._tcp.")) { + Connector::ref connector = Connector::create("foo.com", port, serviceLookupPrefix, resolver, connectionFactory, timerFactory); + connector->onConnectFinished.connect(boost::bind(&ConnectorTest::handleConnectorFinished, this, _1, _2)); + return connector; + } + + void handleConnectorFinished(std::shared_ptr<Connection> connection, std::shared_ptr<Error> resultError) { + std::shared_ptr<MockConnection> c(std::dynamic_pointer_cast<MockConnection>(connection)); + if (connection) { + assert(c); + } + connections.push_back(c); + error = resultError; + } + + struct MockConnection : public Connection { + public: + MockConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive) {} + + void listen() { assert(false); } + void connect(const HostAddressPort& address) { + hostAddressPort = address; + if (isResponsive) { + bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); + } + } + + HostAddressPort getLocalAddress() const { return HostAddressPort(); } + HostAddressPort getRemoteAddress() const { return HostAddressPort(); } + void disconnect() { assert(false); } + void write(const SafeByteArray&) { assert(false); } + + EventLoop* eventLoop; + boost::optional<HostAddressPort> hostAddressPort; + std::vector<HostAddressPort> failingPorts; + bool isResponsive; + }; + + struct MockConnectionFactory : public ConnectionFactory { + MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop), isResponsive(true) { + } + + std::shared_ptr<Connection> createConnection() { + auto connection = std::make_shared<MockConnection>(failingPorts, isResponsive, eventLoop); + createdConnections.push_back(connection); + return connection; + } + + EventLoop* eventLoop; + bool isResponsive; + std::vector<HostAddressPort> failingPorts; + std::vector<std::shared_ptr<MockConnection>> createdConnections; + }; + + private: + HostAddressPort host1; + HostAddressPort host2; + HostAddressPort host3; + DummyEventLoop* eventLoop; + StaticDomainNameResolver* resolver; + MockConnectionFactory* connectionFactory; + DummyTimerFactory* timerFactory; + std::vector< std::shared_ptr<MockConnection> > connections; + std::shared_ptr<Error> error; }; diff --git a/Swiften/Network/UnitTest/DomainNameServiceQueryTest.cpp b/Swiften/Network/UnitTest/DomainNameServiceQueryTest.cpp index 53b9413..7042b27 100644 --- a/Swiften/Network/UnitTest/DomainNameServiceQueryTest.cpp +++ b/Swiften/Network/UnitTest/DomainNameServiceQueryTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <QA/Checker/IO.h> @@ -9,73 +9,73 @@ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Network/DomainNameServiceQuery.h> #include <Swiften/Base/RandomGenerator.h> +#include <Swiften/Network/DomainNameServiceQuery.h> using namespace Swift; namespace { - struct RandomGenerator1 : public RandomGenerator { - virtual int generateRandomInteger(int) { - return 0; - } - }; + struct RandomGenerator1 : public RandomGenerator { + virtual int generateRandomInteger(int) { + return 0; + } + }; - struct RandomGenerator2 : public RandomGenerator { - virtual int generateRandomInteger(int i) { - return i; - } - }; + struct RandomGenerator2 : public RandomGenerator { + virtual int generateRandomInteger(int i) { + return i; + } + }; } class DomainNameServiceQueryTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DomainNameServiceQueryTest); - CPPUNIT_TEST(testSortResults_Random1); - CPPUNIT_TEST(testSortResults_Random2); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(DomainNameServiceQueryTest); + CPPUNIT_TEST(testSortResults_Random1); + CPPUNIT_TEST(testSortResults_Random2); + CPPUNIT_TEST_SUITE_END(); - public: - void testSortResults_Random1() { - std::vector<DomainNameServiceQuery::Result> results; - results.push_back(DomainNameServiceQuery::Result("server1.com", 5222, 5, 1)); - results.push_back(DomainNameServiceQuery::Result("server2.com", 5222, 3, 10)); - results.push_back(DomainNameServiceQuery::Result("server3.com", 5222, 6, 1)); - results.push_back(DomainNameServiceQuery::Result("server4.com", 5222, 3, 20)); - results.push_back(DomainNameServiceQuery::Result("server5.com", 5222, 2, 1)); - results.push_back(DomainNameServiceQuery::Result("server6.com", 5222, 3, 10)); + public: + void testSortResults_Random1() { + std::vector<DomainNameServiceQuery::Result> results; + results.push_back(DomainNameServiceQuery::Result("server1.com", 5222, 5, 1)); + results.push_back(DomainNameServiceQuery::Result("server2.com", 5222, 3, 10)); + results.push_back(DomainNameServiceQuery::Result("server3.com", 5222, 6, 1)); + results.push_back(DomainNameServiceQuery::Result("server4.com", 5222, 3, 20)); + results.push_back(DomainNameServiceQuery::Result("server5.com", 5222, 2, 1)); + results.push_back(DomainNameServiceQuery::Result("server6.com", 5222, 3, 10)); - RandomGenerator1 generator; - DomainNameServiceQuery::sortResults(results, generator); + RandomGenerator1 generator; + DomainNameServiceQuery::sortResults(results, generator); - CPPUNIT_ASSERT_EQUAL(std::string("server5.com"), results[0].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server2.com"), results[1].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server4.com"), results[2].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server6.com"), results[3].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server1.com"), results[4].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server3.com"), results[5].hostname); - } + CPPUNIT_ASSERT_EQUAL(std::string("server5.com"), results[0].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server2.com"), results[1].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server4.com"), results[2].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server6.com"), results[3].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server1.com"), results[4].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server3.com"), results[5].hostname); + } - void testSortResults_Random2() { - std::vector<DomainNameServiceQuery::Result> results; - results.push_back(DomainNameServiceQuery::Result("server1.com", 5222, 5, 1)); - results.push_back(DomainNameServiceQuery::Result("server2.com", 5222, 3, 10)); - results.push_back(DomainNameServiceQuery::Result("server3.com", 5222, 6, 1)); - results.push_back(DomainNameServiceQuery::Result("server4.com", 5222, 3, 20)); - results.push_back(DomainNameServiceQuery::Result("server5.com", 5222, 2, 1)); - results.push_back(DomainNameServiceQuery::Result("server6.com", 5222, 3, 10)); - results.push_back(DomainNameServiceQuery::Result("server7.com", 5222, 3, 40)); + void testSortResults_Random2() { + std::vector<DomainNameServiceQuery::Result> results; + results.push_back(DomainNameServiceQuery::Result("server1.com", 5222, 5, 1)); + results.push_back(DomainNameServiceQuery::Result("server2.com", 5222, 3, 10)); + results.push_back(DomainNameServiceQuery::Result("server3.com", 5222, 6, 1)); + results.push_back(DomainNameServiceQuery::Result("server4.com", 5222, 3, 20)); + results.push_back(DomainNameServiceQuery::Result("server5.com", 5222, 2, 1)); + results.push_back(DomainNameServiceQuery::Result("server6.com", 5222, 3, 10)); + results.push_back(DomainNameServiceQuery::Result("server7.com", 5222, 3, 40)); - RandomGenerator2 generator; - DomainNameServiceQuery::sortResults(results, generator); + RandomGenerator2 generator; + DomainNameServiceQuery::sortResults(results, generator); - CPPUNIT_ASSERT_EQUAL(std::string("server5.com"), results[0].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server7.com"), results[1].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server2.com"), results[2].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server4.com"), results[3].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server6.com"), results[4].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server1.com"), results[5].hostname); - CPPUNIT_ASSERT_EQUAL(std::string("server3.com"), results[6].hostname); - } + CPPUNIT_ASSERT_EQUAL(std::string("server5.com"), results[0].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server7.com"), results[1].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server2.com"), results[2].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server4.com"), results[3].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server6.com"), results[4].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server1.com"), results[5].hostname); + CPPUNIT_ASSERT_EQUAL(std::string("server3.com"), results[6].hostname); + } }; diff --git a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp index 134748f..e9268b0 100644 --- a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp +++ b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp @@ -1,257 +1,437 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ + +#include <memory> + +#include <boost/algorithm/string.hpp> +#include <boost/bind.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> + #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/optional.hpp> -#include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/shared_ptr.hpp> - #include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/Log.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Network/Connection.h> #include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/DummyTimerFactory.h> #include <Swiften/Network/HTTPConnectProxiedConnection.h> +#include <Swiften/Network/HTTPTrafficFilter.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/StaticDomainNameResolver.h> -#include <Swiften/Network/DummyTimerFactory.h> -#include <Swiften/EventLoop/DummyEventLoop.h> using namespace Swift; +namespace { + class ExampleHTTPTrafficFilter : public HTTPTrafficFilter { + public: + ExampleHTTPTrafficFilter() {} + virtual ~ExampleHTTPTrafficFilter() {} + + virtual std::vector<std::pair<std::string, std::string> > filterHTTPResponseHeader(const std::string& /* statusLine */, const std::vector<std::pair<std::string, std::string> >& response) { + filterResponses.push_back(response); + SWIFT_LOG(debug); + return filterResponseReturn; + } + + std::vector<std::vector<std::pair<std::string, std::string> > > filterResponses; + + std::vector<std::pair<std::string, std::string> > filterResponseReturn; + }; + + class ProxyAuthenticationHTTPTrafficFilter : public HTTPTrafficFilter { + static std::string to_lower(const std::string& str) { + std::string lower = str; + boost::algorithm::to_lower(lower); + return lower; + } + + public: + ProxyAuthenticationHTTPTrafficFilter() {} + virtual ~ProxyAuthenticationHTTPTrafficFilter() {} + + virtual std::vector<std::pair<std::string, std::string> > filterHTTPResponseHeader(const std::string& statusLine, const std::vector<std::pair<std::string, std::string> >& response) { + std::vector<std::pair<std::string, std::string> > filterResponseReturn; + std::vector<std::string> statusLineFields; + boost::split(statusLineFields, statusLine, boost::is_any_of(" "), boost::token_compress_on); + + int statusCode = boost::lexical_cast<int>(statusLineFields[1]); + if (statusCode == 407) { + for (const auto& field : response) { + if (to_lower(field.first) == to_lower("Proxy-Authenticate")) { + if (field.second.size() >= 6 && field.second.substr(0, 6) == " NTLM ") { + filterResponseReturn.push_back(std::pair<std::string, std::string>("Proxy-Authorization", "NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABIAEgBIAAAABgAGAFoAAAASABIVNTUAADAAYAAAABAAEACiAAAANYKI4gUBKAoAAAAPTABBAEIAUwBNAE8ASwBFADMAXwBxAGEATABBAEIAUwBNAE8ASwBFADMA0NKq8HYYhj8AAAAAAAAAAAAAAAAAAAAAOIiih3mR+AkyM4r99sy1mdFonCu2ILODro1WTTrJ4b4JcXEzUBA2Ig==")); + return filterResponseReturn; + } + else if (field.second.size() >= 5 && field.second.substr(0, 5) == " NTLM") { + filterResponseReturn.push_back(std::pair<std::string, std::string>("Proxy-Authorization", "NTLM TlRMTVNTUAABAAAAt7II4gkACQAxAAAACQAJACgAAAVNTUAADAAFASgKAAAAD0xBQlNNT0tFM1dPUktHUk9VUA==")); + return filterResponseReturn; + } + } + } + + return filterResponseReturn; + } + else { + return std::vector<std::pair<std::string, std::string> >(); + } + } + }; +} + class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(HTTPConnectProxiedConnectionTest); - CPPUNIT_TEST(testConnect_CreatesConnectionToProxy); - CPPUNIT_TEST(testConnect_SendsConnectRequest); - CPPUNIT_TEST(testConnect_ReceiveConnectResponse); - CPPUNIT_TEST(testConnect_ReceiveMalformedConnectResponse); - CPPUNIT_TEST(testConnect_ReceiveErrorConnectResponse); - CPPUNIT_TEST(testConnect_ReceiveDataAfterConnect); - CPPUNIT_TEST(testWrite_AfterConnect); - CPPUNIT_TEST(testDisconnect_AfterConnectRequest); - CPPUNIT_TEST(testDisconnect_AfterConnect); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - proxyHost = "doo.bah"; - proxyPort = 1234; - proxyHostAddress = HostAddressPort(HostAddress("1.1.1.1"), proxyPort); - host = HostAddressPort(HostAddress("2.2.2.2"), 2345); - eventLoop = new DummyEventLoop(); - resolver = new StaticDomainNameResolver(eventLoop); - resolver->addAddress(proxyHost, proxyHostAddress.getAddress()); - timerFactory = new DummyTimerFactory(); - connectionFactory = new MockConnectionFactory(eventLoop); - connectFinished = false; - disconnected = false; - } - - void tearDown() { - delete timerFactory; - delete connectionFactory; - delete resolver; - delete eventLoop; - } - - void connect(HTTPConnectProxiedConnection::ref connection, const HostAddressPort& to) { - connection->connect(to); - eventLoop->processEvents(); - eventLoop->processEvents(); - eventLoop->processEvents(); - } - - void testConnect_CreatesConnectionToProxy() { - HTTPConnectProxiedConnection::ref testling(createTestling()); - - connect(testling, host); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connectionFactory->connections.size())); - CPPUNIT_ASSERT(connectionFactory->connections[0]->hostAddressPort); - CPPUNIT_ASSERT(proxyHostAddress == *connectionFactory->connections[0]->hostAddressPort); - CPPUNIT_ASSERT(!connectFinished); - } - - void testConnect_SendsConnectRequest() { - HTTPConnectProxiedConnection::ref testling(createTestling()); - - connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345)); - - CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n\r\n"), connectionFactory->connections[0]->dataWritten); - } - - void testConnect_ReceiveConnectResponse() { - HTTPConnectProxiedConnection::ref testling(createTestling()); - connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345)); - - connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n")); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(connectFinished); - CPPUNIT_ASSERT(!connectFinishedWithError); - CPPUNIT_ASSERT(dataRead.empty()); - } - - void testConnect_ReceiveMalformedConnectResponse() { - HTTPConnectProxiedConnection::ref testling(createTestling()); - connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345)); - - connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("FLOOP")); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(connectFinished); - CPPUNIT_ASSERT(connectFinishedWithError); - CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); - } - - void testConnect_ReceiveErrorConnectResponse() { - HTTPConnectProxiedConnection::ref testling(createTestling()); - connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345)); - - connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 401 Unauthorized\r\n\r\n")); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(connectFinished); - CPPUNIT_ASSERT(connectFinishedWithError); - CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); - } - - void testConnect_ReceiveDataAfterConnect() { - HTTPConnectProxiedConnection::ref testling(createTestling()); - connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345)); - connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n")); - eventLoop->processEvents(); - - connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("abcdef")); - - CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), dataRead); - } - - void testWrite_AfterConnect() { - HTTPConnectProxiedConnection::ref testling(createTestling()); - connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345)); - connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n")); - eventLoop->processEvents(); - connectionFactory->connections[0]->dataWritten.clear(); - - testling->write(createSafeByteArray("abcdef")); - - CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), connectionFactory->connections[0]->dataWritten); - } - - void testDisconnect_AfterConnectRequest() { - HTTPConnectProxiedConnection::ref testling(createTestling()); - connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345)); - - testling->disconnect(); - - CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); - CPPUNIT_ASSERT(disconnected); - CPPUNIT_ASSERT(!disconnectedError); - } - - void testDisconnect_AfterConnect() { - HTTPConnectProxiedConnection::ref testling(createTestling()); - connect(testling, HostAddressPort(HostAddress("2.2.2.2"), 2345)); - connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n")); - eventLoop->processEvents(); - - testling->disconnect(); - - CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); - CPPUNIT_ASSERT(disconnected); - CPPUNIT_ASSERT(!disconnectedError); - } - - private: - HTTPConnectProxiedConnection::ref createTestling() { - boost::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(resolver, connectionFactory, timerFactory, proxyHost, proxyPort, "", ""); - c->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleConnectFinished, this, _1)); - c->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDisconnected, this, _1)); - c->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDataRead, this, _1)); - return c; - } - - void handleConnectFinished(bool error) { - connectFinished = true; - connectFinishedWithError = error; - } - - void handleDisconnected(const boost::optional<Connection::Error>& e) { - disconnected = true; - disconnectedError = e; - } - - void handleDataRead(boost::shared_ptr<SafeByteArray> d) { - append(dataRead, *d); - } - - struct MockConnection : public Connection { - public: - MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false) { - } - - void listen() { assert(false); } - - void connect(const HostAddressPort& address) { - hostAddressPort = address; - bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); - } - - HostAddressPort getLocalAddress() const { return HostAddressPort(); } - - void disconnect() { - disconnected = true; - onDisconnected(boost::optional<Connection::Error>()); - } - - void write(const SafeByteArray& d) { - append(dataWritten, d); - } - - EventLoop* eventLoop; - boost::optional<HostAddressPort> hostAddressPort; - std::vector<HostAddressPort> failingPorts; - ByteArray dataWritten; - bool disconnected; - }; - - struct MockConnectionFactory : public ConnectionFactory { - MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) { - } - - boost::shared_ptr<Connection> createConnection() { - boost::shared_ptr<MockConnection> connection = boost::make_shared<MockConnection>(failingPorts, eventLoop); - connections.push_back(connection); - return connection; - } - - EventLoop* eventLoop; - std::vector< boost::shared_ptr<MockConnection> > connections; - std::vector<HostAddressPort> failingPorts; - }; - - private: - std::string proxyHost; - HostAddressPort proxyHostAddress; - int proxyPort; - HostAddressPort host; - DummyEventLoop* eventLoop; - StaticDomainNameResolver* resolver; - MockConnectionFactory* connectionFactory; - TimerFactory* timerFactory; - std::vector< boost::shared_ptr<MockConnection> > connections; - bool connectFinished; - bool connectFinishedWithError; - bool disconnected; - boost::optional<Connection::Error> disconnectedError; - ByteArray dataRead; + CPPUNIT_TEST_SUITE(HTTPConnectProxiedConnectionTest); + CPPUNIT_TEST(testConnect_CreatesConnectionToProxy); + CPPUNIT_TEST(testConnect_SendsConnectRequest); + CPPUNIT_TEST(testConnect_ReceiveConnectResponse); + CPPUNIT_TEST(testConnect_ReceiveConnectChunkedResponse); + CPPUNIT_TEST(testConnect_ReceiveMalformedConnectResponse); + CPPUNIT_TEST(testConnect_ReceiveErrorConnectResponse); + CPPUNIT_TEST(testConnect_ReceiveDataAfterConnect); + CPPUNIT_TEST(testWrite_AfterConnect); + CPPUNIT_TEST(testDisconnect_AfterConnectRequest); + CPPUNIT_TEST(testDisconnect_AfterConnect); + CPPUNIT_TEST(testTrafficFilter); + CPPUNIT_TEST(testTrafficFilterNoConnectionReuse); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + proxyHost = "doo.bah"; + proxyPort = 1234; + proxyHostAddress = HostAddressPort(HostAddress::fromString("1.1.1.1").get(), proxyPort); + host = HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345); + eventLoop = new DummyEventLoop(); + resolver = new StaticDomainNameResolver(eventLoop); + resolver->addAddress(proxyHost, proxyHostAddress.getAddress()); + timerFactory = new DummyTimerFactory(); + connectionFactory = new MockConnectionFactory(eventLoop); + connectFinished = false; + connectFinishedWithError = false; + disconnected = false; + } + + void tearDown() { + delete timerFactory; + delete connectionFactory; + delete resolver; + delete eventLoop; + } + + void connect(HTTPConnectProxiedConnection::ref connection, const HostAddressPort& to) { + connection->connect(to); + eventLoop->processEvents(); + eventLoop->processEvents(); + eventLoop->processEvents(); + } + + void testConnect_CreatesConnectionToProxy() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + + connect(testling, host); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connectionFactory->connections.size())); + CPPUNIT_ASSERT(connectionFactory->connections[0]->hostAddressPort); + CPPUNIT_ASSERT(proxyHostAddress == *connectionFactory->connections[0]->hostAddressPort); + CPPUNIT_ASSERT(!connectFinished); + } + + void testConnect_SendsConnectRequest() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + + CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n\r\n"), connectionFactory->connections[0]->dataWritten); + } + + void testConnect_ReceiveConnectResponse() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n")); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(connectFinished); + CPPUNIT_ASSERT(!connectFinishedWithError); + CPPUNIT_ASSERT(dataRead.empty()); + } + + void testConnect_ReceiveConnectChunkedResponse() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 ")); + eventLoop->processEvents(); + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("200 Connection established\r\n\r\n")); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(connectFinished); + CPPUNIT_ASSERT(!connectFinishedWithError); + CPPUNIT_ASSERT(dataRead.empty()); + } + + + void testConnect_ReceiveMalformedConnectResponse() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("FLOOP")); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(connectFinished); + CPPUNIT_ASSERT(connectFinishedWithError); + CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); + } + + void testConnect_ReceiveErrorConnectResponse() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 401 Unauthorized\r\n\r\n")); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(connectFinished); + CPPUNIT_ASSERT(connectFinishedWithError); + CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); + } + + void testConnect_ReceiveDataAfterConnect() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n")); + eventLoop->processEvents(); + + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("abcdef")); + + CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), dataRead); + } + + void testWrite_AfterConnect() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n")); + eventLoop->processEvents(); + connectionFactory->connections[0]->dataWritten.clear(); + + testling->write(createSafeByteArray("abcdef")); + + CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), connectionFactory->connections[0]->dataWritten); + } + + void testDisconnect_AfterConnectRequest() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + + testling->disconnect(); + + CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); + CPPUNIT_ASSERT(disconnected); + CPPUNIT_ASSERT(!disconnectedError); + } + + void testDisconnect_AfterConnect() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef("HTTP/1.0 200 Connection established\r\n\r\n")); + eventLoop->processEvents(); + + testling->disconnect(); + + CPPUNIT_ASSERT(connectionFactory->connections[0]->disconnected); + CPPUNIT_ASSERT(disconnected); + CPPUNIT_ASSERT(!disconnectedError); + } + + void testTrafficFilter() { + HTTPConnectProxiedConnection::ref testling(createTestling()); + + std::shared_ptr<ExampleHTTPTrafficFilter> httpTrafficFilter = std::make_shared<ExampleHTTPTrafficFilter>(); + + testling->setHTTPTrafficFilter(httpTrafficFilter); + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + + // set a default response so the server response is answered by the traffic filter + httpTrafficFilter->filterResponseReturn.clear(); + httpTrafficFilter->filterResponseReturn.push_back(std::pair<std::string, std::string>("Authorization", "Negotiate a87421000492aa874209af8bc028")); + + connectionFactory->connections[0]->dataWritten.clear(); + + // test chunked response + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef( + "HTTP/1.0 401 Unauthorized\r\n")); + eventLoop->processEvents(); + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef( + "WWW-Authenticate: Negotiate\r\n" + "\r\n")); + eventLoop->processEvents(); + + + // verify that the traffic filter got called and answered with its response + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), httpTrafficFilter->filterResponses.size()); + CPPUNIT_ASSERT_EQUAL(std::string("WWW-Authenticate"), httpTrafficFilter->filterResponses[0][0].first); + + // remove the default response from the traffic filter + httpTrafficFilter->filterResponseReturn.clear(); + eventLoop->processEvents(); + + // verify that the traffic filter answer is send over the wire + CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\nAuthorization: Negotiate a87421000492aa874209af8bc028\r\n\r\n"), connectionFactory->connections[1]->dataWritten); + + // verify that after without the default response, the traffic filter is skipped, authentication proceeds and traffic goes right through + connectionFactory->connections[1]->dataWritten.clear(); + testling->write(createSafeByteArray("abcdef")); + CPPUNIT_ASSERT_EQUAL(createByteArray("abcdef"), connectionFactory->connections[1]->dataWritten); + } + + void testTrafficFilterNoConnectionReuse() { + HTTPConnectProxiedConnection::ref testling = createTestling(); + + std::shared_ptr<ProxyAuthenticationHTTPTrafficFilter> httpTrafficFilter = std::make_shared<ProxyAuthenticationHTTPTrafficFilter>(); + testling->setHTTPTrafficFilter(httpTrafficFilter); + + connect(testling, HostAddressPort(HostAddress::fromString("2.2.2.2").get(), 2345)); + + // First HTTP CONNECT request assumes the proxy will work. + CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n" + "\r\n"), connectionFactory->connections[0]->dataWritten); + + // First reply presents initiator with authentication options. + connectionFactory->connections[0]->onDataRead(createSafeByteArrayRef( + "HTTP/1.0 407 ProxyAuthentication Required\r\n" + "proxy-Authenticate: Negotiate\r\n" + "Proxy-Authenticate: Kerberos\r\n" + "proxy-Authenticate: NTLM\r\n" + "\r\n")); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(false, connectFinished); + CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError); + + // The HTTP proxy responds with code 407, so the traffic filter should inject the authentication response on a new connection. + CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n" + "Proxy-Authorization: NTLM TlRMTVNTUAABAAAAt7II4gkACQAxAAAACQAJACgAAAVNTUAADAAFASgKAAAAD0xBQlNNT0tFM1dPUktHUk9VUA==\r\n" + "\r\n"), connectionFactory->connections[1]->dataWritten); + + // The proxy responds with another authentication step. + connectionFactory->connections[1]->onDataRead(createSafeByteArrayRef( + "HTTP/1.0 407 ProxyAuthentication Required\r\n" + "Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAEAAQADgAAAA1goriluCDYHcYI/sAAAAAAAAAAFQAVABIAAAABQLODgAAAA9TAFAASQBSAEkAVAAxAEIAAgAQAFMAUABJAFIASQBUADEAQgABABAAUwBQAEkAUgBJAFQAMQBCAAQAEABzAHAAaQByAGkAdAAxAGIAAwAQAHMAcABpAHIAaQB0ADEAYgAAAAAA\r\n" + "\r\n")); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(false, connectFinished); + CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError); + + // Last HTTP request that should succeed. Further traffic will go over the connection of this request. + CPPUNIT_ASSERT_EQUAL(createByteArray("CONNECT 2.2.2.2:2345 HTTP/1.1\r\n" + "Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABIAEgBIAAAABgAGAFoAAAASABIVNTUAADAAYAAAABAAEACiAAAANYKI4gUBKAoAAAAPTABBAEIAUwBNAE8ASwBFADMAXwBxAGEATABBAEIAUwBNAE8ASwBFADMA0NKq8HYYhj8AAAAAAAAAAAAAAAAAAAAAOIiih3mR+AkyM4r99sy1mdFonCu2ILODro1WTTrJ4b4JcXEzUBA2Ig==\r\n" + "\r\n"), connectionFactory->connections[2]->dataWritten); + + connectionFactory->connections[2]->onDataRead(createSafeByteArrayRef( + "HTTP/1.0 200 OK\r\n" + "\r\n")); + eventLoop->processEvents(); + + // The HTTP CONNECT proxy initialization finished without error. + CPPUNIT_ASSERT_EQUAL(true, connectFinished); + CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError); + + // Further traffic is written directly, without interception of the filter. + connectionFactory->connections[2]->dataWritten.clear(); + testling->write(createSafeByteArray("This is some basic data traffic.")); + CPPUNIT_ASSERT_EQUAL(createByteArray("This is some basic data traffic."), connectionFactory->connections[2]->dataWritten); + } + + private: + HTTPConnectProxiedConnection::ref createTestling() { + std::shared_ptr<HTTPConnectProxiedConnection> c = HTTPConnectProxiedConnection::create(resolver, connectionFactory, timerFactory, proxyHost, proxyPort, "", ""); + c->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleConnectFinished, this, _1)); + c->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDisconnected, this, _1)); + c->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnectionTest::handleDataRead, this, _1)); + return c; + } + + void handleConnectFinished(bool error) { + connectFinished = true; + connectFinishedWithError = error; + } + + void handleDisconnected(const boost::optional<Connection::Error>& e) { + disconnected = true; + disconnectedError = e; + } + + void handleDataRead(std::shared_ptr<SafeByteArray> d) { + append(dataRead, *d); + } + + struct MockConnection : public Connection { + public: + MockConnection(const std::vector<HostAddressPort>& failingPorts, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), disconnected(false) { + } + + void listen() { assert(false); } + + void connect(const HostAddressPort& address) { + hostAddressPort = address; + bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); + } + + HostAddressPort getLocalAddress() const { return HostAddressPort(); } + HostAddressPort getRemoteAddress() const { return HostAddressPort(); } + + void disconnect() { + disconnected = true; + onDisconnected(boost::optional<Connection::Error>()); + } + + void write(const SafeByteArray& d) { + append(dataWritten, d); + } + + EventLoop* eventLoop; + boost::optional<HostAddressPort> hostAddressPort; + std::vector<HostAddressPort> failingPorts; + ByteArray dataWritten; + bool disconnected; + }; + + struct MockConnectionFactory : public ConnectionFactory { + MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop) { + } + + std::shared_ptr<Connection> createConnection() { + std::shared_ptr<MockConnection> connection = std::make_shared<MockConnection>(failingPorts, eventLoop); + connections.push_back(connection); + SWIFT_LOG(debug) << "new connection created"; + return connection; + } + + EventLoop* eventLoop; + std::vector< std::shared_ptr<MockConnection> > connections; + std::vector<HostAddressPort> failingPorts; + }; + + private: + std::string proxyHost; + HostAddressPort proxyHostAddress; + unsigned short proxyPort; + HostAddressPort host; + DummyEventLoop* eventLoop; + StaticDomainNameResolver* resolver; + MockConnectionFactory* connectionFactory; + TimerFactory* timerFactory; + bool connectFinished; + bool connectFinishedWithError; + bool disconnected; + boost::optional<Connection::Error> disconnectedError; + ByteArray dataRead; }; CPPUNIT_TEST_SUITE_REGISTRATION(HTTPConnectProxiedConnectionTest); diff --git a/Swiften/Network/UnitTest/HostAddressTest.cpp b/Swiften/Network/UnitTest/HostAddressTest.cpp index b2511a8..bd345a7 100644 --- a/Swiften/Network/UnitTest/HostAddressTest.cpp +++ b/Swiften/Network/UnitTest/HostAddressTest.cpp @@ -1,66 +1,95 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <string> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Network/HostAddress.h> -#include <string> +#include <Swiften/Network/HostAddressPort.h> using namespace Swift; class HostAddressTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(HostAddressTest); - CPPUNIT_TEST(testConstructor); - CPPUNIT_TEST(testConstructor_Invalid); - CPPUNIT_TEST(testConstructor_InvalidString); - CPPUNIT_TEST(testToString); - CPPUNIT_TEST(testToString_IPv6); - CPPUNIT_TEST(testToString_Invalid); - CPPUNIT_TEST_SUITE_END(); - - public: - void testConstructor() { - HostAddress testling("192.168.1.254"); - - CPPUNIT_ASSERT_EQUAL(std::string("192.168.1.254"), testling.toString()); - CPPUNIT_ASSERT(testling.isValid()); - } - - void testConstructor_Invalid() { - HostAddress testling; - - CPPUNIT_ASSERT(!testling.isValid()); - } - - void testConstructor_InvalidString() { - HostAddress testling("invalid"); - - CPPUNIT_ASSERT(!testling.isValid()); - } - - void testToString() { - unsigned char address[4] = {10, 0, 1, 253}; - HostAddress testling(address, 4); - - CPPUNIT_ASSERT_EQUAL(std::string("10.0.1.253"), testling.toString()); - } - - void testToString_IPv6() { - unsigned char address[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17}; - HostAddress testling(address, 16); - - CPPUNIT_ASSERT_EQUAL(std::string("102:304:506:708:90a:b0c:d0e:f11"), testling.toString()); - } - - void testToString_Invalid() { - HostAddress testling; - - CPPUNIT_ASSERT_EQUAL(std::string("0.0.0.0"), testling.toString()); - } + CPPUNIT_TEST_SUITE(HostAddressTest); + CPPUNIT_TEST(testConstructor); + CPPUNIT_TEST(testConstructor_Invalid); + CPPUNIT_TEST(testConstructor_InvalidString); + CPPUNIT_TEST(testToString); + CPPUNIT_TEST(testToString_IPv6); + CPPUNIT_TEST(testToString_Invalid); + CPPUNIT_TEST(testComparison); + CPPUNIT_TEST_SUITE_END(); + + public: + void testConstructor() { + auto testling = HostAddress::fromString("192.168.1.254"); + + CPPUNIT_ASSERT_EQUAL(std::string("192.168.1.254"), testling->toString()); + CPPUNIT_ASSERT(testling->isValid()); + } + + void testConstructor_Invalid() { + HostAddress testling; + + CPPUNIT_ASSERT(!testling.isValid()); + } + + void testConstructor_InvalidString() { + auto testling = HostAddress::fromString("invalid"); + + CPPUNIT_ASSERT(!testling); + } + + void testToString() { + unsigned char address[4] = {10, 0, 1, 253}; + HostAddress testling(address, 4); + + CPPUNIT_ASSERT_EQUAL(std::string("10.0.1.253"), testling.toString()); + } + + void testToString_IPv6() { + unsigned char address[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17}; + HostAddress testling(address, 16); + + CPPUNIT_ASSERT_EQUAL(std::string("102:304:506:708:90a:b0c:d0e:f11"), testling.toString()); + } + + void testToString_Invalid() { + HostAddress testling; + + CPPUNIT_ASSERT_EQUAL(std::string("0.0.0.0"), testling.toString()); + } + + void testComparison() { + auto ha127_0_0_1 = *HostAddress::fromString("127.0.0.1"); + auto ha127_0_0_2 = *HostAddress::fromString("127.0.0.2"); + auto ha127_0_1_0 = *HostAddress::fromString("127.0.1.0"); + + CPPUNIT_ASSERT(ha127_0_0_1 < ha127_0_0_2); + CPPUNIT_ASSERT(ha127_0_0_2 < ha127_0_1_0); + CPPUNIT_ASSERT(!(ha127_0_0_1 < ha127_0_0_1)); + CPPUNIT_ASSERT(!(ha127_0_0_2 < ha127_0_0_1)); + CPPUNIT_ASSERT(!(ha127_0_0_2 == ha127_0_0_1)); + CPPUNIT_ASSERT(ha127_0_0_1 == ha127_0_0_1); + + auto hap_127_0_0_1__1 = HostAddressPort(ha127_0_0_1, 1); + auto hap_127_0_0_1__2 = HostAddressPort(ha127_0_0_1, 2); + auto hap_127_0_0_2__1 = HostAddressPort(ha127_0_0_2, 1); + auto hap_127_0_0_2__2 = HostAddressPort(ha127_0_0_2, 2); + + CPPUNIT_ASSERT(hap_127_0_0_1__1 < hap_127_0_0_1__2); + CPPUNIT_ASSERT(!(hap_127_0_0_1__1 < hap_127_0_0_1__1)); + CPPUNIT_ASSERT(!(hap_127_0_0_1__1 == hap_127_0_0_1__2)); + CPPUNIT_ASSERT(hap_127_0_0_1__1 == hap_127_0_0_1__1); + CPPUNIT_ASSERT(!(hap_127_0_0_1__2 == hap_127_0_0_1__1)); + CPPUNIT_ASSERT(hap_127_0_0_1__2 < hap_127_0_0_2__1); + CPPUNIT_ASSERT(hap_127_0_0_2__1 < hap_127_0_0_2__2); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(HostAddressTest); diff --git a/Swiften/Network/UnixNetworkEnvironment.cpp b/Swiften/Network/UnixNetworkEnvironment.cpp index e1fdc88..dc90589 100644 --- a/Swiften/Network/UnixNetworkEnvironment.cpp +++ b/Swiften/Network/UnixNetworkEnvironment.cpp @@ -4,60 +4,68 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Network/UnixNetworkEnvironment.h> +#include <map> #include <string> #include <vector> -#include <map> + #include <boost/optional.hpp> -#include <sys/types.h> -#include <sys/socket.h> +#include <boost/signals2.hpp> + #include <arpa/inet.h> #include <net/if.h> +#include <sys/socket.h> +#include <sys/types.h> #ifndef __ANDROID__ #include <ifaddrs.h> #endif -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Network/HostAddress.h> #include <Swiften/Network/NetworkInterface.h> namespace Swift { std::vector<NetworkInterface> UnixNetworkEnvironment::getNetworkInterfaces() const { - std::map<std::string, NetworkInterface> interfaces; + std::map<std::string, NetworkInterface> interfaces; #ifndef __ANDROID__ - ifaddrs* addrs = 0; - int ret = getifaddrs(&addrs); - if (ret != 0) { - return std::vector<NetworkInterface>(); - } - - for (ifaddrs* a = addrs; a != 0; a = a->ifa_next) { - std::string name(a->ifa_name); - boost::optional<HostAddress> address; - if (a->ifa_addr->sa_family == PF_INET) { - sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(a->ifa_addr); - address = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin_addr)), 4); - } - else if (a->ifa_addr->sa_family == PF_INET6) { - sockaddr_in6* sa = reinterpret_cast<sockaddr_in6*>(a->ifa_addr); - address = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin6_addr)), 16); - } - if (address && !address->isLocalhost()) { - std::map<std::string, NetworkInterface>::iterator i = interfaces.insert(std::make_pair(name, NetworkInterface(name, a->ifa_flags & IFF_LOOPBACK))).first; - i->second.addAddress(*address); - } - } - - freeifaddrs(addrs); + ifaddrs* addrs = nullptr; + int ret = getifaddrs(&addrs); + if (ret != 0) { + return std::vector<NetworkInterface>(); + } + + for (ifaddrs* a = addrs; a != nullptr; a = a->ifa_next) { + std::string name(a->ifa_name); + boost::optional<HostAddress> address; + if (a->ifa_addr->sa_family == PF_INET) { + sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(a->ifa_addr); + address = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin_addr)), 4); + } + else if (a->ifa_addr->sa_family == PF_INET6) { + sockaddr_in6* sa = reinterpret_cast<sockaddr_in6*>(a->ifa_addr); + address = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin6_addr)), 16); + } + if (address && !address->isLocalhost()) { + std::map<std::string, NetworkInterface>::iterator i = interfaces.insert(std::make_pair(name, NetworkInterface(name, a->ifa_flags & IFF_LOOPBACK))).first; + i->second.addAddress(*address); + } + } + + freeifaddrs(addrs); #endif - std::vector<NetworkInterface> result; - for (std::map<std::string,NetworkInterface>::const_iterator i = interfaces.begin(); i != interfaces.end(); ++i) { - result.push_back(i->second); - } - return result; + std::vector<NetworkInterface> result; + for (std::map<std::string,NetworkInterface>::const_iterator i = interfaces.begin(); i != interfaces.end(); ++i) { + result.push_back(i->second); + } + return result; } } diff --git a/Swiften/Network/UnixNetworkEnvironment.h b/Swiften/Network/UnixNetworkEnvironment.h index 8b51cae..89a01ab 100644 --- a/Swiften/Network/UnixNetworkEnvironment.h +++ b/Swiften/Network/UnixNetworkEnvironment.h @@ -4,11 +4,17 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <vector> -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> #include <Swiften/Network/NetworkEnvironment.h> #include <Swiften/Network/NetworkInterface.h> @@ -16,8 +22,8 @@ namespace Swift { class UnixNetworkEnvironment : public NetworkEnvironment { - public: - std::vector<NetworkInterface> getNetworkInterfaces() const; + public: + std::vector<NetworkInterface> getNetworkInterfaces() const; }; } diff --git a/Swiften/Network/UnixProxyProvider.cpp b/Swiften/Network/UnixProxyProvider.cpp index 4ca9311..854d501 100644 --- a/Swiften/Network/UnixProxyProvider.cpp +++ b/Swiften/Network/UnixProxyProvider.cpp @@ -4,12 +4,14 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include <stdio.h> -#include <stdlib.h> -#include <iostream> +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <Swiften/Base/foreach.h> #include <Swiften/Network/UnixProxyProvider.h> + #if defined(HAVE_GCONF) # include "Swiften/Network/GConfProxyProvider.h" #endif @@ -17,48 +19,50 @@ namespace Swift { UnixProxyProvider::UnixProxyProvider() : - gconfProxyProvider(0), - environmentProxyProvider() + gconfProxyProvider(nullptr), + environmentProxyProvider() { #if defined(HAVE_GCONF) - gconfProxyProvider = new GConfProxyProvider(); + gconfProxyProvider = new GConfProxyProvider(); #endif } UnixProxyProvider::~UnixProxyProvider() { #if defined(HAVE_GCONF) - delete gconfProxyProvider; + delete gconfProxyProvider; +#else + (void)gconfProxyProvider; #endif } HostAddressPort UnixProxyProvider::getSOCKS5Proxy() const { - HostAddressPort proxy; + HostAddressPort proxy; #if defined(HAVE_GCONF) - proxy = gconfProxyProvider->getSOCKS5Proxy(); - if(proxy.isValid()) { - return proxy; - } + proxy = gconfProxyProvider->getSOCKS5Proxy(); + if(proxy.isValid()) { + return proxy; + } #endif - proxy = environmentProxyProvider.getSOCKS5Proxy(); - if(proxy.isValid()) { - return proxy; - } - return HostAddressPort(HostAddress(), 0); + proxy = environmentProxyProvider.getSOCKS5Proxy(); + if(proxy.isValid()) { + return proxy; + } + return HostAddressPort(HostAddress(), 0); } HostAddressPort UnixProxyProvider::getHTTPConnectProxy() const { - HostAddressPort proxy; + HostAddressPort proxy; #if defined(HAVE_GCONF) - proxy = gconfProxyProvider->getHTTPConnectProxy(); - if(proxy.isValid()) { - return proxy; - } + proxy = gconfProxyProvider->getHTTPConnectProxy(); + if(proxy.isValid()) { + return proxy; + } #endif - proxy = environmentProxyProvider.getHTTPConnectProxy(); - if(proxy.isValid()) { - return proxy; - } - return HostAddressPort(HostAddress(), 0); + proxy = environmentProxyProvider.getHTTPConnectProxy(); + if(proxy.isValid()) { + return proxy; + } + return HostAddressPort(HostAddress(), 0); } diff --git a/Swiften/Network/UnixProxyProvider.h b/Swiften/Network/UnixProxyProvider.h index 37a4d05..1721480 100644 --- a/Swiften/Network/UnixProxyProvider.h +++ b/Swiften/Network/UnixProxyProvider.h @@ -4,23 +4,29 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/Network/EnvironmentProxyProvider.h> namespace Swift { - class GConfProxyProvider; + class GConfProxyProvider; - class UnixProxyProvider : public ProxyProvider { - public: - UnixProxyProvider(); - ~UnixProxyProvider(); + class UnixProxyProvider : public ProxyProvider { + public: + UnixProxyProvider(); + virtual ~UnixProxyProvider(); - virtual HostAddressPort getHTTPConnectProxy() const; - virtual HostAddressPort getSOCKS5Proxy() const; + virtual HostAddressPort getHTTPConnectProxy() const; + virtual HostAddressPort getSOCKS5Proxy() const; - private: - GConfProxyProvider* gconfProxyProvider; - EnvironmentProxyProvider environmentProxyProvider; - }; + private: + GConfProxyProvider* gconfProxyProvider; + EnvironmentProxyProvider environmentProxyProvider; + }; } diff --git a/Swiften/Network/WindowsNetworkEnvironment.cpp b/Swiften/Network/WindowsNetworkEnvironment.cpp index e2d1966..e90a5c6 100644 --- a/Swiften/Network/WindowsNetworkEnvironment.cpp +++ b/Swiften/Network/WindowsNetworkEnvironment.cpp @@ -4,63 +4,70 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Network/WindowsNetworkEnvironment.h> +#include <map> #include <string> #include <vector> -#include <map> + #include <boost/optional.hpp> -#include <Swiften/Network/HostAddress.h> -#include <Swiften/Network/NetworkInterface.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Base/ByteArray.h> -#include <winsock2.h> #include <iphlpapi.h> +#include <winsock2.h> + +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/NetworkInterface.h> namespace Swift { std::vector<NetworkInterface> WindowsNetworkEnvironment::getNetworkInterfaces() const { - std::vector<NetworkInterface> result; + std::vector<NetworkInterface> result; - ByteArray adapters; - ULONG bufferSize = 0; - ULONG ret; - ULONG flags = GAA_FLAG_INCLUDE_ALL_INTERFACES | GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; - while ((ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, reinterpret_cast<IP_ADAPTER_ADDRESSES*>(vecptr(adapters)), &bufferSize)) == ERROR_BUFFER_OVERFLOW) { - adapters.resize(bufferSize); - }; - if (ret != ERROR_SUCCESS) { - return result; - } + ByteArray adapters; + ULONG bufferSize = 0; + ULONG ret; + ULONG flags = GAA_FLAG_INCLUDE_ALL_INTERFACES | GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; + while ((ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, reinterpret_cast<IP_ADAPTER_ADDRESSES*>(vecptr(adapters)), &bufferSize)) == ERROR_BUFFER_OVERFLOW) { + adapters.resize(bufferSize); + }; + if (ret != ERROR_SUCCESS) { + return result; + } - std::map<std::string,NetworkInterface> interfaces; - for (IP_ADAPTER_ADDRESSES* adapter = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(vecptr(adapters)); adapter; adapter = adapter->Next) { - std::string name(adapter->AdapterName); - if (adapter->OperStatus != IfOperStatusUp) { - continue; - } - for (IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress; address; address = address->Next) { - boost::optional<HostAddress> hostAddress; - if (address->Address.lpSockaddr->sa_family == PF_INET) { - sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(address->Address.lpSockaddr); - hostAddress = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin_addr)), 4); - } - else if (address->Address.lpSockaddr->sa_family == PF_INET6) { - sockaddr_in6* sa = reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr); - hostAddress = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin6_addr)), 16); - } - if (hostAddress && !hostAddress->isLocalhost()) { - std::map<std::string, NetworkInterface>::iterator i = interfaces.insert(std::make_pair(name, NetworkInterface(name, false))).first; - i->second.addAddress(*hostAddress); - } - } - } + std::map<std::string,NetworkInterface> interfaces; + for (IP_ADAPTER_ADDRESSES* adapter = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(vecptr(adapters)); adapter; adapter = adapter->Next) { + std::string name(adapter->AdapterName); + if (adapter->OperStatus != IfOperStatusUp) { + continue; + } + for (IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress; address; address = address->Next) { + boost::optional<HostAddress> hostAddress; + if (address->Address.lpSockaddr->sa_family == PF_INET) { + sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(address->Address.lpSockaddr); + hostAddress = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin_addr)), 4); + } + else if (address->Address.lpSockaddr->sa_family == PF_INET6) { + sockaddr_in6* sa = reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr); + hostAddress = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin6_addr)), 16); + } + if (hostAddress && !hostAddress->isLocalhost()) { + std::map<std::string, NetworkInterface>::iterator i = interfaces.insert(std::make_pair(name, NetworkInterface(name, false))).first; + i->second.addAddress(*hostAddress); + } + } + } - for (std::map<std::string,NetworkInterface>::const_iterator i = interfaces.begin(); i != interfaces.end(); ++i) { - result.push_back(i->second); - } - return result; + for (const auto& interface : interfaces) { + result.push_back(interface.second); + } + return result; } } diff --git a/Swiften/Network/WindowsNetworkEnvironment.h b/Swiften/Network/WindowsNetworkEnvironment.h index 18996ed..81de826 100644 --- a/Swiften/Network/WindowsNetworkEnvironment.h +++ b/Swiften/Network/WindowsNetworkEnvironment.h @@ -4,17 +4,24 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <vector> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Network/NetworkEnvironment.h> namespace Swift { - class SWIFTEN_API WindowsNetworkEnvironment : public NetworkEnvironment { - public: - std::vector<NetworkInterface> getNetworkInterfaces() const; - }; + class SWIFTEN_API WindowsNetworkEnvironment : public NetworkEnvironment { + public: + std::vector<NetworkInterface> getNetworkInterfaces() const; + }; } diff --git a/Swiften/Network/WindowsProxyProvider.cpp b/Swiften/Network/WindowsProxyProvider.cpp index 3ae43e0..13fdb25 100644 --- a/Swiften/Network/WindowsProxyProvider.cpp +++ b/Swiften/Network/WindowsProxyProvider.cpp @@ -4,110 +4,122 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Network/WindowsProxyProvider.h> + +#include <math.h> #include <stdio.h> #include <stdlib.h> -#include <math.h> -#include <iostream> -#include <boost/lexical_cast.hpp> -#include <Swiften/Base/log.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Network/WindowsProxyProvider.h> -#include <Swiften/Base/ByteArray.h> +#include <boost/lexical_cast.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <windows.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Log.h> +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/HostAddressPort.h> + namespace Swift { WindowsProxyProvider::WindowsProxyProvider() : ProxyProvider() { - HKEY hKey = (HKEY)INVALID_HANDLE_VALUE; - long result; - - result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 0, KEY_READ, &hKey); - if (result == ERROR_SUCCESS && hKey != INVALID_HANDLE_VALUE && proxyEnabled(hKey)) { - DWORD dataType = REG_SZ; - DWORD dataSize = 0; - ByteArray dataBuffer; - - result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, NULL, &dataSize); - if(result != ERROR_SUCCESS) { - return; - } - dataBuffer.resize(dataSize); - result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, reinterpret_cast<BYTE*>(vecptr(dataBuffer)), &dataSize); - if(result == ERROR_SUCCESS) { - std::vector<std::string> proxies = String::split(byteArrayToString(dataBuffer), ';'); - std::pair<std::string, std::string> protocolAndProxy; - foreach(std::string proxy, proxies) { - if(proxy.find('=') != std::string::npos) { - protocolAndProxy = String::getSplittedAtFirst(proxy, '='); - SWIFT_LOG(debug) << "Found proxy: " << protocolAndProxy.first << " => " << protocolAndProxy.second << std::endl; - if(protocolAndProxy.first.compare("socks") == 0) { - socksProxy = getAsHostAddressPort(protocolAndProxy.second); - } - else if (protocolAndProxy.first.compare("http") == 0) { - httpProxy = getAsHostAddressPort(protocolAndProxy.second); - } - } - } - } - } + HKEY hKey = (HKEY)INVALID_HANDLE_VALUE; + long result; + + result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 0, KEY_READ, &hKey); + if (result == ERROR_SUCCESS && hKey != INVALID_HANDLE_VALUE && proxyEnabled(hKey)) { + DWORD dataType = REG_SZ; + DWORD dataSize = 0; + ByteArray dataBuffer; + + result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, NULL, &dataSize); + if(result != ERROR_SUCCESS) { + return; + } + dataBuffer.resize(dataSize); + result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, reinterpret_cast<BYTE*>(vecptr(dataBuffer)), &dataSize); + if(result == ERROR_SUCCESS) { + std::vector<std::string> proxies = String::split(byteArrayToString(dataBuffer), ';'); + std::pair<std::string, std::string> protocolAndProxy; + for(auto&& proxy : proxies) { + if(proxy.find('=') != std::string::npos) { + protocolAndProxy = String::getSplittedAtFirst(proxy, '='); + SWIFT_LOG(debug) << "Found proxy: " << protocolAndProxy.first << " => " << protocolAndProxy.second; + if(protocolAndProxy.first.compare("socks") == 0) { + socksProxy = getAsHostAddressPort(protocolAndProxy.second); + } + else if (protocolAndProxy.first.compare("http") == 0) { + httpProxy = getAsHostAddressPort(protocolAndProxy.second); + } + } + } + } + } } HostAddressPort WindowsProxyProvider::getHTTPConnectProxy() const { - return httpProxy; + return httpProxy; } HostAddressPort WindowsProxyProvider::getSOCKS5Proxy() const { - return socksProxy; + return socksProxy; } HostAddressPort WindowsProxyProvider::getAsHostAddressPort(std::string proxy) { - HostAddressPort ret(HostAddress(), 0); - - try { - std::pair<std::string, std::string> tmp; - int port = 0; - tmp = String::getSplittedAtFirst(proxy, ':'); - // .c_str() is needed as tmp.second can include a \0 char which will end in an exception of the lexical cast. - // with .c_str() the \0 will not be part of the string which is to be casted - port = boost::lexical_cast<int> (tmp.second.c_str()); - ret = HostAddressPort(HostAddress(tmp.first), port); - } - catch(...) { - std::cerr << "Exception occured while parsing windows proxy \"getHostAddressPort\"." << std::endl; - } - - return ret; + HostAddressPort ret(HostAddress(), 0); + + try { + std::pair<std::string, std::string> tmp; + unsigned short port = 0; + tmp = String::getSplittedAtFirst(proxy, ':'); + // .c_str() is needed as tmp.second can include a \0 char which will end in an exception of the lexical cast. + // with .c_str() the \0 will not be part of the string which is to be casted + port = boost::numeric_cast<unsigned short>(boost::lexical_cast<int> (tmp.second.c_str())); + ret = HostAddressPort(HostAddress::fromString(tmp.first).get(), port); + } + catch(...) { + SWIFT_LOG(error) << "Exception occured while parsing windows proxy \"getHostAddressPort\"."; + } + + return ret; } bool WindowsProxyProvider::proxyEnabled(HKEY hKey) const { - bool ret = false; - long result; - DWORD dataType = REG_DWORD; - DWORD dataSize = 0; - DWORD data = 0; - ByteArray dataBuffer; - - if(hKey == INVALID_HANDLE_VALUE) - return ret; - - result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, NULL, &dataSize); - if(result != ERROR_SUCCESS) - return ret; - - dataBuffer.resize(dataSize); - result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, reinterpret_cast<BYTE*>(vecptr(dataBuffer)), &dataSize); - if(result != ERROR_SUCCESS) - return ret; - - for(size_t t = 0; t < dataBuffer.size(); t++) { - data += static_cast<int> (dataBuffer[t]) * pow(256, static_cast<double>(t)); - } - return (data == 1); + bool ret = false; + long result; + DWORD dataType = REG_DWORD; + DWORD dataSize = 0; + DWORD data = 0; + ByteArray dataBuffer; + + if(hKey == INVALID_HANDLE_VALUE) { + return ret; + } + + result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, NULL, &dataSize); + if(result != ERROR_SUCCESS) { + return ret; + } + + dataBuffer.resize(dataSize); + result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, reinterpret_cast<BYTE*>(vecptr(dataBuffer)), &dataSize); + if(result != ERROR_SUCCESS) { + return ret; + } + + for(size_t t = 0; t < dataBuffer.size(); t++) { + data += static_cast<int> (dataBuffer[t]) * pow(256, static_cast<double>(t)); + } + return (data == 1); } } diff --git a/Swiften/Network/WindowsProxyProvider.h b/Swiften/Network/WindowsProxyProvider.h index 12aa18d..0ca897d 100644 --- a/Swiften/Network/WindowsProxyProvider.h +++ b/Swiften/Network/WindowsProxyProvider.h @@ -4,21 +4,28 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/Base/API.h> +#include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/ProxyProvider.h> namespace Swift { - class SWIFTEN_API WindowsProxyProvider : public ProxyProvider { - public: - WindowsProxyProvider(); - virtual HostAddressPort getHTTPConnectProxy() const; - virtual HostAddressPort getSOCKS5Proxy() const; - private: - HostAddressPort getAsHostAddressPort(std::string proxy); - bool proxyEnabled(HKEY hKey) const; - HostAddressPort socksProxy; - HostAddressPort httpProxy; - }; + class SWIFTEN_API WindowsProxyProvider : public ProxyProvider { + public: + WindowsProxyProvider(); + virtual HostAddressPort getHTTPConnectProxy() const; + virtual HostAddressPort getSOCKS5Proxy() const; + private: + HostAddressPort getAsHostAddressPort(std::string proxy); + bool proxyEnabled(HKEY hKey) const; + HostAddressPort socksProxy; + HostAddressPort httpProxy; + }; } diff --git a/Swiften/Parser/Attribute.h b/Swiften/Parser/Attribute.h index f1f9a83..07e63b4 100644 --- a/Swiften/Parser/Attribute.h +++ b/Swiften/Parser/Attribute.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,25 +9,33 @@ #include <string> namespace Swift { - class Attribute { - public: - Attribute(const std::string& name, const std::string& ns) : name(name), ns(ns) { - } - - const std::string& getName() const { - return name; - } - - const std::string& getNamespace() const { - return ns; - } - - bool operator==(const Attribute& o) const { - return o.name == name && o.ns == ns; - } - - private: - std::string name; - std::string ns; - }; + class Attribute { + public: + Attribute(const std::string& name, const std::string& ns) : name(name), ns(ns) { + } + + Attribute(const std::string& name, const std::string& ns, const std::string& prefix) : name(name), ns(ns), prefix(prefix) { + } + + const std::string& getName() const { + return name; + } + + const std::string& getNamespace() const { + return ns; + } + + const std::string& getPrefix() const { + return prefix; + } + + bool operator==(const Attribute& o) const { + return o.name == name && o.ns == ns; + } + + private: + std::string name; + std::string ns; + std::string prefix; + }; } diff --git a/Swiften/Parser/AttributeMap.cpp b/Swiften/Parser/AttributeMap.cpp index d508157..7814a64 100644 --- a/Swiften/Parser/AttributeMap.cpp +++ b/Swiften/Parser/AttributeMap.cpp @@ -1,55 +1,60 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/AttributeMap.h> #include <algorithm> + #include <boost/optional.hpp> -#include <boost/lambda/lambda.hpp> -#include <boost/lambda/bind.hpp> using namespace Swift; -namespace lambda = boost::lambda; AttributeMap::AttributeMap() { } std::string AttributeMap::getAttribute(const std::string& attribute, const std::string& ns) const { - AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), - lambda::bind(&AttributeMap::Entry::getAttribute, lambda::_1) == Attribute(attribute, ns)); - if (i == attributes.end()) { - return ""; - } - else { - return i->getValue(); - } + const auto i = std::find_if(attributes.begin(), attributes.end(), [&](const Entry& entry) { + return entry.getAttribute() == Attribute(attribute, ns); + }); + if (i == attributes.end()) { + return ""; + } + else { + return i->getValue(); + } } bool AttributeMap::getBoolAttribute(const std::string& attribute, bool defaultValue) const { - AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), - lambda::bind(&AttributeMap::Entry::getAttribute, lambda::_1) == Attribute(attribute, "")); - if (i == attributes.end()) { - return defaultValue; - } - else { - return i->getValue() == "true" || i->getValue() == "1"; - } + const auto i = std::find_if(attributes.begin(), attributes.end(), [&](const Entry& entry) { + return entry.getAttribute() == Attribute(attribute, ""); + }); + if (i == attributes.end()) { + return defaultValue; + } + else { + return i->getValue() == "true" || i->getValue() == "1"; + } } boost::optional<std::string> AttributeMap::getAttributeValue(const std::string& attribute) const { - AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), - lambda::bind(&AttributeMap::Entry::getAttribute, lambda::_1) == Attribute(attribute, "")); - if (i == attributes.end()) { - return boost::optional<std::string>(); - } - else { - return i->getValue(); - } + const auto i = std::find_if(attributes.begin(), attributes.end(), [&](const Entry& entry) { + return entry.getAttribute() == Attribute(attribute, ""); + }); + if (i == attributes.end()) { + return boost::optional<std::string>(); + } + else { + return i->getValue(); + } } void AttributeMap::addAttribute(const std::string& name, const std::string& ns, const std::string& value) { - attributes.push_back(Entry(Attribute(name, ns), value)); + attributes.push_back(Entry(Attribute(name, ns), value)); +} + +void AttributeMap::addAttribute(const std::string& name, const std::string& ns, const std::string& prefix, const std::string& value) { + attributes.push_back(Entry(Attribute(name, ns, prefix), value)); } diff --git a/Swiften/Parser/AttributeMap.h b/Swiften/Parser/AttributeMap.h index 77b9c23..26d5826 100644 --- a/Swiften/Parser/AttributeMap.h +++ b/Swiften/Parser/AttributeMap.h @@ -1,54 +1,56 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> -#include <string> #include <map> -#include <boost/optional/optional_fwd.hpp> +#include <string> +#include <vector> + +#include <boost/optional/optional.hpp> #include <Swiften/Base/API.h> #include <Swiften/Parser/Attribute.h> namespace Swift { - class SWIFTEN_API AttributeMap { - public: - class Entry { - public: - Entry(const Attribute& attribute, const std::string& value) : attribute(attribute), value(value) { - } - - const Attribute& getAttribute() const { - return attribute; - } - - const std::string& getValue() const { - return value; - } - - private: - Attribute attribute; - std::string value; - }; - - AttributeMap(); - - std::string getAttribute(const std::string& attribute, const std::string& ns = "") const; - bool getBoolAttribute(const std::string& attribute, bool defaultValue = false) const; - boost::optional<std::string> getAttributeValue(const std::string&) const; - - void addAttribute(const std::string& name, const std::string& ns, const std::string& value); - - const std::vector<Entry>& getEntries() const { - return attributes; - } - - private: - typedef std::vector<Entry> AttributeValueMap; - AttributeValueMap attributes; - }; + class SWIFTEN_API AttributeMap { + public: + class Entry { + public: + Entry(const Attribute& attribute, const std::string& value) : attribute(attribute), value(value) { + } + + const Attribute& getAttribute() const { + return attribute; + } + + const std::string& getValue() const { + return value; + } + + private: + Attribute attribute; + std::string value; + }; + + AttributeMap(); + + std::string getAttribute(const std::string& attribute, const std::string& ns = "") const; + bool getBoolAttribute(const std::string& attribute, bool defaultValue = false) const; + boost::optional<std::string> getAttributeValue(const std::string&) const; + + void addAttribute(const std::string& name, const std::string& ns, const std::string& value); + void addAttribute(const std::string& name, const std::string& ns, const std::string& prefix, const std::string& value); + + const std::vector<Entry>& getEntries() const { + return attributes; + } + + private: + typedef std::vector<Entry> AttributeValueMap; + AttributeValueMap attributes; + }; } diff --git a/Swiften/Parser/AuthChallengeParser.cpp b/Swiften/Parser/AuthChallengeParser.cpp index 7cb665a..cf69672 100644 --- a/Swiften/Parser/AuthChallengeParser.cpp +++ b/Swiften/Parser/AuthChallengeParser.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/AuthChallengeParser.h> + #include <Swiften/StringCodecs/Base64.h> namespace Swift { @@ -13,18 +14,18 @@ AuthChallengeParser::AuthChallengeParser() : GenericElementParser<AuthChallenge> } void AuthChallengeParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++depth; + ++depth; } void AuthChallengeParser::handleEndElement(const std::string&, const std::string&) { - --depth; - if (depth == 0) { - getElementGeneric()->setValue(Base64::decode(text)); - } + --depth; + if (depth == 0) { + getElementGeneric()->setValue(Base64::decode(text)); + } } void AuthChallengeParser::handleCharacterData(const std::string& text) { - this->text += text; + this->text += text; } } diff --git a/Swiften/Parser/AuthChallengeParser.h b/Swiften/Parser/AuthChallengeParser.h index 31b6d89..48e2bfb 100644 --- a/Swiften/Parser/AuthChallengeParser.h +++ b/Swiften/Parser/AuthChallengeParser.h @@ -1,26 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> -#include <Swiften/Elements/AuthChallenge.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/AuthChallenge.h> +#include <Swiften/Parser/GenericElementParser.h> + namespace Swift { - class AuthChallengeParser : public GenericElementParser<AuthChallenge> { - public: - AuthChallengeParser(); + class SWIFTEN_API AuthChallengeParser : public GenericElementParser<AuthChallenge> { + public: + AuthChallengeParser(); - virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); - virtual void handleEndElement(const std::string&, const std::string& ns); - virtual void handleCharacterData(const std::string&); + virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string& ns); + virtual void handleCharacterData(const std::string&); - private: - int depth; - std::string text; - }; + private: + int depth; + std::string text; + }; } diff --git a/Swiften/Parser/AuthFailureParser.h b/Swiften/Parser/AuthFailureParser.h index 1a71ea4..1706290 100644 --- a/Swiften/Parser/AuthFailureParser.h +++ b/Swiften/Parser/AuthFailureParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/AuthFailure.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class AuthFailureParser : public GenericElementParser<AuthFailure> { - public: - AuthFailureParser() : GenericElementParser<AuthFailure>() {} - }; + class SWIFTEN_API AuthFailureParser : public GenericElementParser<AuthFailure> { + public: + AuthFailureParser() : GenericElementParser<AuthFailure>() {} + }; } diff --git a/Swiften/Parser/AuthRequestParser.cpp b/Swiften/Parser/AuthRequestParser.cpp index 04d9e4f..a24be8d 100644 --- a/Swiften/Parser/AuthRequestParser.cpp +++ b/Swiften/Parser/AuthRequestParser.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/AuthRequestParser.h> + #include <Swiften/StringCodecs/Base64.h> namespace Swift { @@ -13,21 +14,21 @@ AuthRequestParser::AuthRequestParser() : GenericElementParser<AuthRequest>(), de } void AuthRequestParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attribute) { - if (depth_ == 0) { - getElementGeneric()->setMechanism(attribute.getAttribute("mechanism")); - } - ++depth_; + if (depth_ == 0) { + getElementGeneric()->setMechanism(attribute.getAttribute("mechanism")); + } + ++depth_; } void AuthRequestParser::handleEndElement(const std::string&, const std::string&) { - --depth_; - if (depth_ == 0) { - getElementGeneric()->setMessage(createSafeByteArray(Base64::decode(text_))); - } + --depth_; + if (depth_ == 0) { + getElementGeneric()->setMessage(createSafeByteArray(Base64::decode(text_))); + } } void AuthRequestParser::handleCharacterData(const std::string& text) { - text_ += text; + text_ += text; } } diff --git a/Swiften/Parser/AuthRequestParser.h b/Swiften/Parser/AuthRequestParser.h index 1562df7..ac94abf 100644 --- a/Swiften/Parser/AuthRequestParser.h +++ b/Swiften/Parser/AuthRequestParser.h @@ -1,26 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> -#include <Swiften/Elements/AuthRequest.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/AuthRequest.h> +#include <Swiften/Parser/GenericElementParser.h> + namespace Swift { - class AuthRequestParser : public GenericElementParser<AuthRequest> { - public: - AuthRequestParser(); + class SWIFTEN_API AuthRequestParser : public GenericElementParser<AuthRequest> { + public: + AuthRequestParser(); - virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); - virtual void handleEndElement(const std::string&, const std::string& ns); - virtual void handleCharacterData(const std::string&); + virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string& ns); + virtual void handleCharacterData(const std::string&); - private: - std::string text_; - int depth_; - }; + private: + std::string text_; + int depth_; + }; } diff --git a/Swiften/Parser/AuthResponseParser.cpp b/Swiften/Parser/AuthResponseParser.cpp index 7f9a530..59f6455 100644 --- a/Swiften/Parser/AuthResponseParser.cpp +++ b/Swiften/Parser/AuthResponseParser.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/AuthResponseParser.h> + #include <Swiften/StringCodecs/Base64.h> namespace Swift { @@ -13,18 +14,18 @@ AuthResponseParser::AuthResponseParser() : GenericElementParser<AuthResponse>(), } void AuthResponseParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++depth; + ++depth; } void AuthResponseParser::handleEndElement(const std::string&, const std::string&) { - --depth; - if (depth == 0) { - getElementGeneric()->setValue(createSafeByteArray(Base64::decode(text))); - } + --depth; + if (depth == 0) { + getElementGeneric()->setValue(createSafeByteArray(Base64::decode(text))); + } } void AuthResponseParser::handleCharacterData(const std::string& text) { - this->text += text; + this->text += text; } } diff --git a/Swiften/Parser/AuthResponseParser.h b/Swiften/Parser/AuthResponseParser.h index 3dc2282..6cbfa22 100644 --- a/Swiften/Parser/AuthResponseParser.h +++ b/Swiften/Parser/AuthResponseParser.h @@ -1,26 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> -#include <Swiften/Elements/AuthResponse.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/AuthResponse.h> +#include <Swiften/Parser/GenericElementParser.h> + namespace Swift { - class AuthResponseParser : public GenericElementParser<AuthResponse> { - public: - AuthResponseParser(); + class SWIFTEN_API AuthResponseParser : public GenericElementParser<AuthResponse> { + public: + AuthResponseParser(); - virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); - virtual void handleEndElement(const std::string&, const std::string& ns); - virtual void handleCharacterData(const std::string&); + virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string& ns); + virtual void handleCharacterData(const std::string&); - private: - int depth; - std::string text; - }; + private: + int depth; + std::string text; + }; } diff --git a/Swiften/Parser/AuthSuccessParser.cpp b/Swiften/Parser/AuthSuccessParser.cpp index 50246a4..964fd6c 100644 --- a/Swiften/Parser/AuthSuccessParser.cpp +++ b/Swiften/Parser/AuthSuccessParser.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/AuthSuccessParser.h> + #include <Swiften/StringCodecs/Base64.h> namespace Swift { @@ -13,18 +14,18 @@ AuthSuccessParser::AuthSuccessParser() : GenericElementParser<AuthSuccess>(), de } void AuthSuccessParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++depth; + ++depth; } void AuthSuccessParser::handleEndElement(const std::string&, const std::string&) { - --depth; - if (depth == 0) { - getElementGeneric()->setValue(Base64::decode(text)); - } + --depth; + if (depth == 0) { + getElementGeneric()->setValue(Base64::decode(text)); + } } void AuthSuccessParser::handleCharacterData(const std::string& text) { - this->text += text; + this->text += text; } } diff --git a/Swiften/Parser/AuthSuccessParser.h b/Swiften/Parser/AuthSuccessParser.h index b726b95..cedc8d1 100644 --- a/Swiften/Parser/AuthSuccessParser.h +++ b/Swiften/Parser/AuthSuccessParser.h @@ -1,26 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> -#include <Swiften/Elements/AuthSuccess.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/AuthSuccess.h> +#include <Swiften/Parser/GenericElementParser.h> + namespace Swift { - class AuthSuccessParser : public GenericElementParser<AuthSuccess> { - public: - AuthSuccessParser(); + class SWIFTEN_API AuthSuccessParser : public GenericElementParser<AuthSuccess> { + public: + AuthSuccessParser(); - virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); - virtual void handleEndElement(const std::string&, const std::string& ns); - virtual void handleCharacterData(const std::string&); + virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string& ns); + virtual void handleCharacterData(const std::string&); - private: - int depth; - std::string text; - }; + private: + int depth; + std::string text; + }; } diff --git a/Swiften/Parser/BOSHBodyExtractor.cpp b/Swiften/Parser/BOSHBodyExtractor.cpp index 715a448..ff56792 100644 --- a/Swiften/Parser/BOSHBodyExtractor.cpp +++ b/Swiften/Parser/BOSHBodyExtractor.cpp @@ -1,139 +1,140 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/BOSHBodyExtractor.h> -#include <boost/shared_ptr.hpp> -#include <boost/numeric/conversion/cast.hpp> +#include <memory> -#include <Swiften/Parser/XMLParserClient.h> #include <Swiften/Parser/XMLParser.h> +#include <Swiften/Parser/XMLParserClient.h> #include <Swiften/Parser/XMLParserFactory.h> namespace Swift { class BOSHBodyParserClient : public XMLParserClient { - public: - BOSHBodyParserClient(BOSHBodyExtractor* bodyExtractor) : bodyExtractor(bodyExtractor) { - } + public: + BOSHBodyParserClient(BOSHBodyExtractor* bodyExtractor) : bodyExtractor(bodyExtractor) { + } - virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { - bodyExtractor->body->attributes = attributes; - } + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { + bodyExtractor->body->attributes = attributes; + } - virtual void handleEndElement(const std::string&, const std::string&) { - } + virtual void handleEndElement(const std::string&, const std::string&) { + } - virtual void handleCharacterData(const std::string&) { - } + virtual void handleCharacterData(const std::string&) { + } - private: - BOSHBodyExtractor* bodyExtractor; + private: + BOSHBodyExtractor* bodyExtractor; }; inline bool isWhitespace(unsigned char c) { - return c == ' ' || c == '\n' || c == '\t' || c == '\r'; + return c == ' ' || c == '\n' || c == '\t' || c == '\r'; } BOSHBodyExtractor::BOSHBodyExtractor(XMLParserFactory* parserFactory, const ByteArray& data) { - // Look for the opening body element - ByteArray::const_iterator i = data.begin(); - while (i < data.end() && isWhitespace(*i)) { - ++i; - } - if (std::distance(i, data.end()) < 6 || *i != '<' || *(i+1) != 'b' || *(i+2) != 'o' || *(i+3) != 'd' || *(i+4) != 'y' || !(isWhitespace(*(i+5)) || *(i+5) == '>' || *(i+5) == '/')) { - return; - } - i += 5; - - // Parse until end of element - bool inSingleQuote = false; - bool inDoubleQuote = false; - bool endStartTagSeen = false; - bool endElementSeen = false; - for (; i != data.end(); ++i) { - char c = static_cast<char>(*i); - if (inSingleQuote) { - if (c == '\'') { - inSingleQuote = false; - } - } - else if (inDoubleQuote) { - if (c == '"') { - inDoubleQuote = false; - } - } - else if (c == '\'') { - inSingleQuote = true; - } - else if (c == '"') { - inDoubleQuote = true; - } - else if (c == '/') { - if (i + 1 == data.end() || *(i+1) != '>') { - return; - } - else { - endElementSeen = true; - endStartTagSeen = true; - i += 2; - break; - } - } - else if (c == '>') { - endStartTagSeen = true; - i += 1; - break; - } - } - - if (!endStartTagSeen) { - return; - } - - // Look for the end of the element - ByteArray::const_reverse_iterator j = data.rbegin(); - if (!endElementSeen) { - while (isWhitespace(*j) && j < data.rend()) { - ++j; - } - - if (j == data.rend() || *j != '>') { - return; - } - ++j; - - while (j < data.rend() && isWhitespace(*j)) { - ++j; - } - - if (std::distance(j, data.rend()) < 6 || *(j+5) != '<' || *(j+4) != '/' || *(j+3) != 'b' || *(j+2) != 'o' || *(j+1) != 'd' || *j != 'y') { - return; - } - j += 6; - } - - body = BOSHBody(); - if (!endElementSeen) { - body->content = std::string( - reinterpret_cast<const char*>(vecptr(data) + std::distance(data.begin(), i)), - boost::numeric_cast<size_t>(std::distance(i, j.base()))); - } - - // Parse the body element - BOSHBodyParserClient parserClient(this); - boost::shared_ptr<XMLParser> parser(parserFactory->createXMLParser(&parserClient)); - if (!parser->parse(std::string( - reinterpret_cast<const char*>(vecptr(data)), - boost::numeric_cast<size_t>(std::distance(data.begin(), i))))) { - /* TODO: This needs to be only validating the BOSH <body> element, so that XMPP parsing errors are caught at - the correct higher layer */ - body = boost::optional<BOSHBody>(); - return; - } + // Look for the opening body element + ByteArray::const_iterator i = data.begin(); + while (i < data.end() && isWhitespace(*i)) { + ++i; + } + if (std::distance(i, data.end()) < 6 || *i != '<' || *(i+1) != 'b' || *(i+2) != 'o' || *(i+3) != 'd' || *(i+4) != 'y' || !(isWhitespace(*(i+5)) || *(i+5) == '>' || *(i+5) == '/')) { + return; + } + i += 5; + + // Parse until end of element + bool inSingleQuote = false; + bool inDoubleQuote = false; + bool endStartTagSeen = false; + bool endElementSeen = false; + for (; i != data.end(); ++i) { + char c = static_cast<char>(*i); + if (inSingleQuote) { + if (c == '\'') { + inSingleQuote = false; + } + } + else if (inDoubleQuote) { + if (c == '"') { + inDoubleQuote = false; + } + } + else if (c == '\'') { + inSingleQuote = true; + } + else if (c == '"') { + inDoubleQuote = true; + } + else if (c == '/') { + if (i + 1 == data.end() || *(i+1) != '>') { + return; + } + else { + endElementSeen = true; + endStartTagSeen = true; + i += 2; + break; + } + } + else if (c == '>') { + endStartTagSeen = true; + i += 1; + break; + } + } + + if (!endStartTagSeen) { + return; + } + + // Look for the end of the element + ByteArray::const_reverse_iterator j = data.rbegin(); + if (!endElementSeen) { + while (isWhitespace(*j) && j < data.rend()) { + ++j; + } + + if (j == data.rend() || *j != '>') { + return; + } + ++j; + + while (j < data.rend() && isWhitespace(*j)) { + ++j; + } + + if (std::distance(j, data.rend()) < 6 || *(j+5) != '<' || *(j+4) != '/' || *(j+3) != 'b' || *(j+2) != 'o' || *(j+1) != 'd' || *j != 'y') { + return; + } + j += 6; + } + + body = BOSHBody(); + if (!endElementSeen) { + assert(i <= j.base()); + body->content = std::string( + reinterpret_cast<const char*>(vecptr(data) + std::distance(data.begin(), i)), + static_cast<size_t>(std::distance(i, j.base()))); + } + + // Parse the body element + BOSHBodyParserClient parserClient(this); + std::shared_ptr<XMLParser> parser(parserFactory->createXMLParser(&parserClient)); + assert(data.begin() <= i); + if (!parser->parse(std::string( + reinterpret_cast<const char*>(vecptr(data)), + static_cast<size_t>(std::distance(data.begin(), i))))) { + /* TODO: This needs to be only validating the BOSH <body> element, so that XMPP parsing errors are caught at + the correct higher layer */ + body = boost::optional<BOSHBody>(); + return; + } } } diff --git a/Swiften/Parser/BOSHBodyExtractor.h b/Swiften/Parser/BOSHBodyExtractor.h index 7510761..ba56b41 100644 --- a/Swiften/Parser/BOSHBodyExtractor.h +++ b/Swiften/Parser/BOSHBodyExtractor.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -13,23 +13,23 @@ #include <Swiften/Parser/XMLParserClient.h> namespace Swift { - class XMLParserFactory; - - class SWIFTEN_API BOSHBodyExtractor { - friend class BOSHBodyParserClient; - public: - struct BOSHBody { - AttributeMap attributes; - std::string content; - }; - - BOSHBodyExtractor(XMLParserFactory* parserFactory, const ByteArray& data); - - const boost::optional<BOSHBody>& getBody() const { - return body; - } - - private: - boost::optional<BOSHBody> body; - }; + class XMLParserFactory; + + class SWIFTEN_API BOSHBodyExtractor { + friend class BOSHBodyParserClient; + public: + struct BOSHBody { + AttributeMap attributes; + std::string content; + }; + + BOSHBodyExtractor(XMLParserFactory* parserFactory, const ByteArray& data); + + const boost::optional<BOSHBody>& getBody() const { + return body; + } + + private: + boost::optional<BOSHBody> body; + }; } diff --git a/Swiften/Parser/ComponentHandshakeParser.cpp b/Swiften/Parser/ComponentHandshakeParser.cpp index c58caf0..f98503d 100644 --- a/Swiften/Parser/ComponentHandshakeParser.cpp +++ b/Swiften/Parser/ComponentHandshakeParser.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/ComponentHandshakeParser.h> + #include <Swiften/StringCodecs/Base64.h> namespace Swift { @@ -13,18 +14,18 @@ ComponentHandshakeParser::ComponentHandshakeParser() : GenericElementParser<Comp } void ComponentHandshakeParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++depth; + ++depth; } void ComponentHandshakeParser::handleEndElement(const std::string&, const std::string&) { - --depth; - if (depth == 0) { - getElementGeneric()->setData(text); - } + --depth; + if (depth == 0) { + getElementGeneric()->setData(text); + } } void ComponentHandshakeParser::handleCharacterData(const std::string& text) { - this->text += text; + this->text += text; } } diff --git a/Swiften/Parser/ComponentHandshakeParser.h b/Swiften/Parser/ComponentHandshakeParser.h index 25cee6e..5f4af80 100644 --- a/Swiften/Parser/ComponentHandshakeParser.h +++ b/Swiften/Parser/ComponentHandshakeParser.h @@ -1,26 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> -#include <Swiften/Elements/ComponentHandshake.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ComponentHandshake.h> +#include <Swiften/Parser/GenericElementParser.h> + namespace Swift { - class ComponentHandshakeParser : public GenericElementParser<ComponentHandshake> { - public: - ComponentHandshakeParser(); + class SWIFTEN_API ComponentHandshakeParser : public GenericElementParser<ComponentHandshake> { + public: + ComponentHandshakeParser(); - virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); - virtual void handleEndElement(const std::string&, const std::string& ns); - virtual void handleCharacterData(const std::string&); + virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string& ns); + virtual void handleCharacterData(const std::string&); - private: - int depth; - std::string text; - }; + private: + int depth; + std::string text; + }; } diff --git a/Swiften/Parser/CompressFailureParser.h b/Swiften/Parser/CompressFailureParser.h index ed59324..5c171ee 100644 --- a/Swiften/Parser/CompressFailureParser.h +++ b/Swiften/Parser/CompressFailureParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/CompressFailure.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class CompressFailureParser : public GenericElementParser<CompressFailure> { - public: - CompressFailureParser() : GenericElementParser<CompressFailure>() {} - }; + class SWIFTEN_API CompressFailureParser : public GenericElementParser<CompressFailure> { + public: + CompressFailureParser() : GenericElementParser<CompressFailure>() {} + }; } diff --git a/Swiften/Parser/CompressParser.cpp b/Swiften/Parser/CompressParser.cpp index d8f773b..00f762f 100644 --- a/Swiften/Parser/CompressParser.cpp +++ b/Swiften/Parser/CompressParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/CompressParser.h> @@ -12,23 +12,23 @@ CompressParser::CompressParser() : GenericElementParser<CompressRequest>(), curr } void CompressParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap&) { - if (currentDepth_ == 1 && element == "method") { - inMethod_ = true; - currentText_ = ""; - } - ++currentDepth_; + if (currentDepth_ == 1 && element == "method") { + inMethod_ = true; + currentText_ = ""; + } + ++currentDepth_; } void CompressParser::handleEndElement(const std::string&, const std::string&) { - --currentDepth_; - if (currentDepth_ == 1 && inMethod_) { - getElementGeneric()->setMethod(currentText_); - inMethod_ = false; - } + --currentDepth_; + if (currentDepth_ == 1 && inMethod_) { + getElementGeneric()->setMethod(currentText_); + inMethod_ = false; + } } void CompressParser::handleCharacterData(const std::string& data) { - currentText_ += data; + currentText_ += data; } } diff --git a/Swiften/Parser/CompressParser.h b/Swiften/Parser/CompressParser.h index 51244c4..6f0a0cb 100644 --- a/Swiften/Parser/CompressParser.h +++ b/Swiften/Parser/CompressParser.h @@ -1,28 +1,30 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> -#include <Swiften/Parser/GenericElementParser.h> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/CompressRequest.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class CompressParser : public GenericElementParser<CompressRequest> { - public: - CompressParser(); + class SWIFTEN_API CompressParser : public GenericElementParser<CompressRequest> { + public: + CompressParser(); - private: - void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); - void handleEndElement(const std::string& element, const std::string& ns); - void handleCharacterData(const std::string& data); + private: + void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); + void handleEndElement(const std::string& element, const std::string& ns); + void handleCharacterData(const std::string& data); - private: - int currentDepth_; - std::string currentText_; - bool inMethod_; - }; + private: + int currentDepth_; + std::string currentText_; + bool inMethod_; + }; } diff --git a/Swiften/Parser/CompressedParser.h b/Swiften/Parser/CompressedParser.h index 5ba80eb..859b509 100644 --- a/Swiften/Parser/CompressedParser.h +++ b/Swiften/Parser/CompressedParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Compressed.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class CompressedParser : public GenericElementParser<Compressed> { - public: - CompressedParser() : GenericElementParser<Compressed>() {} - }; + class SWIFTEN_API CompressedParser : public GenericElementParser<Compressed> { + public: + CompressedParser() : GenericElementParser<Compressed>() {} + }; } diff --git a/Swiften/Parser/ElementParser.cpp b/Swiften/Parser/ElementParser.cpp index 1064f2e..4e0d27f 100644 --- a/Swiften/Parser/ElementParser.cpp +++ b/Swiften/Parser/ElementParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/ElementParser.h> diff --git a/Swiften/Parser/ElementParser.h b/Swiften/Parser/ElementParser.h index 1815240..71d4bce 100644 --- a/Swiften/Parser/ElementParser.h +++ b/Swiften/Parser/ElementParser.h @@ -1,27 +1,27 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> - +#include <memory> #include <string> + #include <Swiften/Base/API.h> -#include <Swiften/Elements/Element.h> +#include <Swiften/Elements/ToplevelElement.h> #include <Swiften/Parser/AttributeMap.h> namespace Swift { - class SWIFTEN_API ElementParser { - public: - virtual ~ElementParser(); + class SWIFTEN_API ElementParser { + public: + virtual ~ElementParser(); - virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) = 0; - virtual void handleEndElement(const std::string& element, const std::string& ns) = 0; - virtual void handleCharacterData(const std::string& data) = 0; + virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) = 0; + virtual void handleEndElement(const std::string& element, const std::string& ns) = 0; + virtual void handleCharacterData(const std::string& data) = 0; - virtual boost::shared_ptr<Element> getElement() const = 0; - }; + virtual std::shared_ptr<ToplevelElement> getElement() const = 0; + }; } diff --git a/Swiften/Parser/EnableStreamManagementParser.h b/Swiften/Parser/EnableStreamManagementParser.h index 530efd9..b010740 100644 --- a/Swiften/Parser/EnableStreamManagementParser.h +++ b/Swiften/Parser/EnableStreamManagementParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/EnableStreamManagement.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class EnableStreamManagementParser : public GenericElementParser<EnableStreamManagement> { - public: - EnableStreamManagementParser() : GenericElementParser<EnableStreamManagement>() {} - }; + class SWIFTEN_API EnableStreamManagementParser : public GenericElementParser<EnableStreamManagement> { + public: + EnableStreamManagementParser() : GenericElementParser<EnableStreamManagement>() {} + }; } diff --git a/Swiften/Parser/EnumParser.h b/Swiften/Parser/EnumParser.h index d7bdbbc..0da765e 100644 --- a/Swiften/Parser/EnumParser.h +++ b/Swiften/Parser/EnumParser.h @@ -1,37 +1,37 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <string> -#include <map> #include <cassert> +#include <map> +#include <string> + #include <boost/optional.hpp> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> namespace Swift { - template<typename T> - class SWIFTEN_API EnumParser { - public: - EnumParser() { - } - - EnumParser& operator()(T value, const std::string& text) { - values[text] = value; - return *this; - } - - boost::optional<T> parse(const std::string& value) { - typename std::map<std::string, T>::const_iterator i = values.find(value); - return i == values.end() ? boost::optional<T>() : i->second; - } - - private: - std::map<std::string, T> values; - }; + template<typename T> + class SWIFTEN_API EnumParser { + public: + EnumParser() { + } + + EnumParser& operator()(T value, const std::string& text) { + values[text] = value; + return *this; + } + + boost::optional<T> parse(const std::string& value) { + typename std::map<std::string, T>::const_iterator i = values.find(value); + return i == values.end() ? boost::optional<T>() : i->second; + } + + private: + std::map<std::string, T> values; + }; } diff --git a/Swiften/Parser/ExpatParser.cpp b/Swiften/Parser/ExpatParser.cpp index 8b7bf82..32d4f53 100644 --- a/Swiften/Parser/ExpatParser.cpp +++ b/Swiften/Parser/ExpatParser.cpp @@ -1,95 +1,142 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/ExpatParser.h> -#include <iostream> +#include <cassert> +#include <limits> +#include <memory> #include <string> + +#include <boost/algorithm/string.hpp> + #include <expat.h> -#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/String.h> #include <Swiften/Parser/XMLParserClient.h> #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" +namespace { +struct XmlInfo { + std::string prefix; + std::string uri; + std::string name; +}; + +XmlInfo splitExpatInfo(const std::string& s, char sep) { + // name + // uri|name + // uri|name|prefix + std::vector<std::string> v; + boost::split(v, s, [sep](char c) {return c == sep; }); + switch (v.size()) { + case 1: + return{ "", "", std::move(v[0]) }; + case 2: + return{ "", std::move(v[0]), std::move(v[1]) }; + case 3: + return{ std::move(v[2]), std::move(v[0]), std::move(v[1]) }; + default: + return{ "", "", "" }; + } +} +} + + namespace Swift { static const char NAMESPACE_SEPARATOR = '\x01'; struct ExpatParser::Private { - XML_Parser parser_; + XML_Parser parser_; }; static void handleStartElement(void* parser, const XML_Char* name, const XML_Char** attributes) { - std::pair<std::string,std::string> nsTagPair = String::getSplittedAtFirst(name, NAMESPACE_SEPARATOR); - if (nsTagPair.second == "") { - nsTagPair.second = nsTagPair.first; - nsTagPair.first = ""; - } - AttributeMap attributeValues; - const XML_Char** currentAttribute = attributes; - while (*currentAttribute) { - std::pair<std::string,std::string> nsAttributePair = String::getSplittedAtFirst(*currentAttribute, NAMESPACE_SEPARATOR); - if (nsAttributePair.second == "") { - nsAttributePair.second = nsAttributePair.first; - nsAttributePair.first = ""; - } - attributeValues.addAttribute(nsAttributePair.second, nsAttributePair.first, std::string(*(currentAttribute+1))); - currentAttribute += 2; - } - - static_cast<XMLParser*>(parser)->getClient()->handleStartElement(nsTagPair.second, nsTagPair.first, attributeValues); + auto elemInfo = splitExpatInfo(name, NAMESPACE_SEPARATOR); + + AttributeMap attributeValues; + const XML_Char** currentAttribute = attributes; + while (*currentAttribute) { + auto attribInfo = splitExpatInfo(*currentAttribute, NAMESPACE_SEPARATOR); + attributeValues.addAttribute(attribInfo.name, attribInfo.uri, attribInfo.prefix, std::string(*(currentAttribute+1))); + currentAttribute += 2; + } + + auto* client = static_cast<XMLParser*>(parser)->getClient(); + client->handleStartElementPrefix(elemInfo.prefix, elemInfo.uri, elemInfo.name, attributeValues); + client->handleStartElement(elemInfo.name, elemInfo.uri, attributeValues); } static void handleEndElement(void* parser, const XML_Char* name) { - std::pair<std::string,std::string> nsTagPair = String::getSplittedAtFirst(name, NAMESPACE_SEPARATOR); - if (nsTagPair.second == "") { - nsTagPair.second = nsTagPair.first; - nsTagPair.first = ""; - } - static_cast<XMLParser*>(parser)->getClient()->handleEndElement(nsTagPair.second, nsTagPair.first); + auto elemInfo = splitExpatInfo(name, NAMESPACE_SEPARATOR); + static_cast<XMLParser*>(parser)->getClient()->handleEndElement(elemInfo.name, elemInfo.uri); } static void handleCharacterData(void* parser, const XML_Char* data, int len) { - assert(len >= 0); - static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(data, static_cast<size_t>(len))); + assert(len >= 0); + static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(data, static_cast<size_t>(len))); } static void handleXMLDeclaration(void*, const XML_Char*, const XML_Char*, int) { } +static void handleNamespaceDeclaration(void* parser, const XML_Char* prefix, const XML_Char* uri) { + static_cast<XMLParser*>(parser)->getClient()->handleNamespaceDeclaration(std::string(prefix ? prefix : ""), std::string(uri ? uri : "")); +} + static void handleEntityDeclaration(void* parser, const XML_Char*, int, const XML_Char*, int, const XML_Char*, const XML_Char*, const XML_Char*, const XML_Char*) { - static_cast<ExpatParser*>(parser)->stopParser(); + static_cast<ExpatParser*>(parser)->stopParser(); +} + +static void handleComment(void* parser, const XML_Char* /*data*/) { + if (!static_cast<ExpatParser*>(parser)->allowsComments()) { + static_cast<ExpatParser*>(parser)->stopParser(); + } } +static void handleProcessingInstruction(void* parser, const XML_Char* /*target*/, const XML_Char* /*data*/) { + static_cast<ExpatParser*>(parser)->stopParser(); +} + +static void handleDoctypeDeclaration(void* parser, const XML_Char* /*doctypeName*/, const XML_Char* /*sysid*/, const XML_Char* /*pubid*/, int /*has_internal_subset*/) { + static_cast<ExpatParser*>(parser)->stopParser(); +} -ExpatParser::ExpatParser(XMLParserClient* client) : XMLParser(client), p(new Private()) { - p->parser_ = XML_ParserCreateNS("UTF-8", NAMESPACE_SEPARATOR); - XML_SetUserData(p->parser_, this); - XML_SetElementHandler(p->parser_, handleStartElement, handleEndElement); - XML_SetCharacterDataHandler(p->parser_, handleCharacterData); - XML_SetXmlDeclHandler(p->parser_, handleXMLDeclaration); - XML_SetEntityDeclHandler(p->parser_, handleEntityDeclaration); +ExpatParser::ExpatParser(XMLParserClient* client, bool allowComments) : XMLParser(client, allowComments), p(new Private()) { + p->parser_ = XML_ParserCreateNS("UTF-8", NAMESPACE_SEPARATOR); + XML_SetReturnNSTriplet(p->parser_, true); + XML_SetUserData(p->parser_, this); + XML_SetElementHandler(p->parser_, handleStartElement, handleEndElement); + XML_SetCharacterDataHandler(p->parser_, handleCharacterData); + XML_SetXmlDeclHandler(p->parser_, handleXMLDeclaration); + XML_SetEntityDeclHandler(p->parser_, handleEntityDeclaration); + XML_SetNamespaceDeclHandler(p->parser_, handleNamespaceDeclaration, nullptr); + XML_SetCommentHandler(p->parser_, handleComment); + XML_SetProcessingInstructionHandler(p->parser_, handleProcessingInstruction); + XML_SetDoctypeDeclHandler(p->parser_, handleDoctypeDeclaration, nullptr); } ExpatParser::~ExpatParser() { - XML_ParserFree(p->parser_); + XML_ParserFree(p->parser_); } -bool ExpatParser::parse(const std::string& data) { - bool success = XML_Parse(p->parser_, data.c_str(), boost::numeric_cast<int>(data.size()), false) == XML_STATUS_OK; - /*if (!success) { - std::cout << "ERROR: " << XML_ErrorString(XML_GetErrorCode(p->parser_)) << " while parsing " << data << std::endl; - }*/ - return success; +bool ExpatParser::parse(const std::string& data, bool finalData) { + if (data.size() > std::numeric_limits<int>::max()) { + return false; + } + bool success = XML_Parse(p->parser_, data.c_str(), static_cast<int>(data.size()), finalData) == XML_STATUS_OK; + /*if (!success) { + std::cout << "ERROR: " << XML_ErrorString(XML_GetErrorCode(p->parser_)) << " while parsing " << data << std::endl; + }*/ + return success; } void ExpatParser::stopParser() { - XML_StopParser(p->parser_, static_cast<XML_Bool>(0)); + XML_StopParser(p->parser_, static_cast<XML_Bool>(0)); } } diff --git a/Swiften/Parser/ExpatParser.h b/Swiften/Parser/ExpatParser.h index dcb0915..34d790d 100644 --- a/Swiften/Parser/ExpatParser.h +++ b/Swiften/Parser/ExpatParser.h @@ -1,29 +1,30 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> #include <Swiften/Parser/XMLParser.h> namespace Swift { - class SWIFTEN_API ExpatParser : public XMLParser, public boost::noncopyable { - public: - ExpatParser(XMLParserClient* client); - ~ExpatParser(); + class SWIFTEN_API ExpatParser : public XMLParser, public boost::noncopyable { + public: + ExpatParser(XMLParserClient* client, bool allowComments = false); + ~ExpatParser(); - bool parse(const std::string& data); + bool parse(const std::string& data, bool finalData = false); - void stopParser(); + void stopParser(); - private: - struct Private; - boost::shared_ptr<Private> p; - }; + private: + struct Private; + const std::unique_ptr<Private> p; + }; } diff --git a/Swiften/Parser/GenericElementParser.h b/Swiften/Parser/GenericElementParser.h index 224c59e..1092710 100644 --- a/Swiften/Parser/GenericElementParser.h +++ b/Swiften/Parser/GenericElementParser.h @@ -1,46 +1,44 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Parser/ElementParser.h> namespace Swift { - - class PayloadParserFactoryCollection; - template<typename ElementType> - class GenericElementParser : public ElementParser { - public: - GenericElementParser() { - stanza_ = boost::make_shared<ElementType>(); - } + template<typename ElementType> + class SWIFTEN_API GenericElementParser : public ElementParser { + public: + GenericElementParser() { + stanza_ = std::make_shared<ElementType>(); + } - virtual boost::shared_ptr<Element> getElement() const { - return stanza_; - } + virtual std::shared_ptr<ToplevelElement> getElement() const { + return stanza_; + } - virtual boost::shared_ptr<ElementType> getElementGeneric() const { - return stanza_; - } + virtual std::shared_ptr<ElementType> getElementGeneric() const { + return stanza_; + } - private: - virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - } + private: + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&) { + } - virtual void handleEndElement(const std::string&, const std::string&) { - } + virtual void handleEndElement(const std::string&, const std::string&) { + } - virtual void handleCharacterData(const std::string&) { - } + virtual void handleCharacterData(const std::string&) { + } - private: - boost::shared_ptr<ElementType> stanza_; - }; + private: + std::shared_ptr<ElementType> stanza_; + }; } diff --git a/Swiften/Parser/GenericPayloadParser.h b/Swiften/Parser/GenericPayloadParser.h index 572901b..b72189e 100644 --- a/Swiften/Parser/GenericPayloadParser.h +++ b/Swiften/Parser/GenericPayloadParser.h @@ -1,42 +1,39 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParser.h> namespace Swift { - - class FormParser; - - /** - * A generic payload parser for payloads of the given type. - * - * This class provides getPayloadInternal() for retrieving the actual - * payload. - */ - template<typename PAYLOAD_TYPE> - class GenericPayloadParser : public PayloadParser { - public: - GenericPayloadParser() : PayloadParser() { - payload_ = boost::make_shared<PAYLOAD_TYPE>(); - } - - virtual boost::shared_ptr<Payload> getPayload() const { - return payload_; - } - - virtual boost::shared_ptr<PAYLOAD_TYPE> getPayloadInternal() const { - return payload_; - } - - private: - boost::shared_ptr<PAYLOAD_TYPE> payload_; - }; + /** + * A generic payload parser for payloads of the given type. + * + * This class provides getPayloadInternal() for retrieving the actual + * payload. + */ + template<typename PAYLOAD_TYPE> + class GenericPayloadParser : public PayloadParser { + public: + GenericPayloadParser() : PayloadParser() { + payload_ = std::make_shared<PAYLOAD_TYPE>(); + } + + virtual std::shared_ptr<Payload> getPayload() const { + return payload_; + } + + virtual std::shared_ptr<PAYLOAD_TYPE> getPayloadInternal() const { + return payload_; + } + + private: + std::shared_ptr<PAYLOAD_TYPE> payload_; + }; } diff --git a/Swiften/Parser/GenericPayloadParserFactory.h b/Swiften/Parser/GenericPayloadParserFactory.h index 43042a1..fcdec62 100644 --- a/Swiften/Parser/GenericPayloadParserFactory.h +++ b/Swiften/Parser/GenericPayloadParserFactory.h @@ -1,37 +1,39 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/PayloadParserFactory.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Parser/PayloadParserFactory.h> + namespace Swift { - /** - * A generic class for PayloadParserFactories that parse a specific payload (given as the template parameter of the class). - */ - template<typename PARSER_TYPE> - class GenericPayloadParserFactory : public PayloadParserFactory { - public: - /** - * Construct a parser factory that can parse the given top-level tag in the given namespace. - */ - GenericPayloadParserFactory(const std::string& tag, const std::string& xmlns = "") : tag_(tag), xmlns_(xmlns) {} - - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return (tag_.empty() ? true : element == tag_) && (xmlns_.empty() ? true : xmlns_ == ns); - } - - virtual PayloadParser* createPayloadParser() { - return new PARSER_TYPE(); - } - - private: - std::string tag_; - std::string xmlns_; - }; + /** + * A generic class for PayloadParserFactories that parse a specific payload (given as the template parameter of the class). + */ + template<typename PARSER_TYPE> + class GenericPayloadParserFactory : public PayloadParserFactory { + public: + /** + * Construct a parser factory that can parse the given top-level tag in the given namespace. + */ + GenericPayloadParserFactory(const std::string& tag, const std::string& xmlns = "") : tag_(tag), xmlns_(xmlns) {} + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return (tag_.empty() ? true : element == tag_) && (xmlns_.empty() ? true : xmlns_ == ns); + } + + virtual PayloadParser* createPayloadParser() { + return new PARSER_TYPE(); + } + + private: + std::string tag_; + std::string xmlns_; + }; } diff --git a/Swiften/Parser/GenericPayloadParserFactory2.h b/Swiften/Parser/GenericPayloadParserFactory2.h index f24b64e..f55d317 100644 --- a/Swiften/Parser/GenericPayloadParserFactory2.h +++ b/Swiften/Parser/GenericPayloadParserFactory2.h @@ -1,39 +1,41 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/PayloadParserFactory.h> #include <string> +#include <Swiften/Base/API.h> +#include <Swiften/Parser/PayloadParserFactory.h> + namespace Swift { - class PayloadParserFactoryCollection; - - /** - * A generic class for PayloadParserFactories that parse a specific payload (given as the template parameter of the class). - */ - template<typename PARSER_TYPE> - class GenericPayloadParserFactory2 : public PayloadParserFactory { - public: - /** - * Construct a parser factory that can parse the given top-level tag in the given namespace. - */ - GenericPayloadParserFactory2(const std::string& tag, const std::string& xmlns, PayloadParserFactoryCollection* parsers) : tag_(tag), xmlns_(xmlns), parsers_(parsers) {} - - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return (tag_.empty() ? true : element == tag_) && (xmlns_.empty() ? true : xmlns_ == ns); - } - - virtual PayloadParser* createPayloadParser() { - return new PARSER_TYPE(parsers_); - } - - private: - std::string tag_; - std::string xmlns_; - PayloadParserFactoryCollection* parsers_; - }; + class PayloadParserFactoryCollection; + + /** + * A generic class for PayloadParserFactories that parse a specific payload (given as the template parameter of the class). + */ + template<typename PARSER_TYPE> + class GenericPayloadParserFactory2 : public PayloadParserFactory { + public: + /** + * Construct a parser factory that can parse the given top-level tag in the given namespace. + */ + GenericPayloadParserFactory2(const std::string& tag, const std::string& xmlns, PayloadParserFactoryCollection* parsers) : tag_(tag), xmlns_(xmlns), parsers_(parsers) {} + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return (tag_.empty() ? true : element == tag_) && (xmlns_.empty() ? true : xmlns_ == ns); + } + + virtual PayloadParser* createPayloadParser() { + return new PARSER_TYPE(parsers_); + } + + private: + std::string tag_; + std::string xmlns_; + PayloadParserFactoryCollection* parsers_; + }; } diff --git a/Swiften/Parser/GenericPayloadTreeParser.h b/Swiften/Parser/GenericPayloadTreeParser.h index df6d022..b4da1a9 100644 --- a/Swiften/Parser/GenericPayloadTreeParser.h +++ b/Swiften/Parser/GenericPayloadTreeParser.h @@ -1,53 +1,52 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <deque> +#include <memory> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> - +#include <Swiften/Base/API.h> #include <Swiften/Parser/GenericPayloadParser.h> #include <Swiften/Parser/Tree/ParserElement.h> namespace Swift { - /** - * Generic parser offering something a bit like a DOM to work with. - */ - template<typename PAYLOAD_TYPE> - class GenericPayloadTreeParser : public GenericPayloadParser<PAYLOAD_TYPE> { - public: - virtual void handleStartElement(const std::string& element, const std::string& xmlns, const AttributeMap& attributes) { - if (!root_) { - root_ = boost::make_shared<ParserElement>(element, xmlns, attributes); - elementStack_.push_back(root_); - } - else { - ParserElement::ref current = *elementStack_.rbegin(); - elementStack_.push_back(current->addChild(element, xmlns, attributes)); - } - } - - virtual void handleEndElement(const std::string& /*element*/, const std::string&) { - elementStack_.pop_back(); - if (elementStack_.empty()) { - handleTree(root_); - } - } - - virtual void handleCharacterData(const std::string& data) { - ParserElement::ref current = *elementStack_.rbegin(); - current->appendCharacterData(data); - } - - virtual void handleTree(ParserElement::ref root) = 0; - - private: - std::deque<ParserElement::ref> elementStack_; - ParserElement::ref root_; - }; + /** + * Generic parser offering something a bit like a DOM to work with. + */ + template<typename PAYLOAD_TYPE> + class GenericPayloadTreeParser : public GenericPayloadParser<PAYLOAD_TYPE> { + public: + virtual void handleStartElement(const std::string& element, const std::string& xmlns, const AttributeMap& attributes) { + if (!root_) { + root_ = std::make_shared<ParserElement>(element, xmlns, attributes); + elementStack_.push_back(root_); + } + else { + ParserElement::ref current = *elementStack_.rbegin(); + elementStack_.push_back(current->addChild(element, xmlns, attributes)); + } + } + + virtual void handleEndElement(const std::string& /*element*/, const std::string&) { + elementStack_.pop_back(); + if (elementStack_.empty()) { + handleTree(root_); + } + } + + virtual void handleCharacterData(const std::string& data) { + ParserElement::ref current = *elementStack_.rbegin(); + current->appendCharacterData(data); + } + + virtual void handleTree(ParserElement::ref root) = 0; + + private: + std::deque<ParserElement::ref> elementStack_; + ParserElement::ref root_; + }; } diff --git a/Swiften/Parser/GenericStanzaParser.h b/Swiften/Parser/GenericStanzaParser.h index c756c9a..2686f2f 100644 --- a/Swiften/Parser/GenericStanzaParser.h +++ b/Swiften/Parser/GenericStanzaParser.h @@ -1,37 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Parser/StanzaParser.h> namespace Swift { - - class PayloadParserFactoryCollection; - - template<typename STANZA_TYPE> - class GenericStanzaParser : public StanzaParser { - public: - GenericStanzaParser(PayloadParserFactoryCollection* collection) : - StanzaParser(collection) { - stanza_ = boost::make_shared<STANZA_TYPE>(); - } - - virtual boost::shared_ptr<Element> getElement() const { - return stanza_; - } - - virtual boost::shared_ptr<STANZA_TYPE> getStanzaGeneric() const { - return stanza_; - } - - private: - boost::shared_ptr<STANZA_TYPE> stanza_; - }; + + class PayloadParserFactoryCollection; + + template<typename STANZA_TYPE> + class SWIFTEN_API GenericStanzaParser : public StanzaParser { + public: + GenericStanzaParser(PayloadParserFactoryCollection* collection) : + StanzaParser(collection) { + stanza_ = std::make_shared<STANZA_TYPE>(); + } + + virtual std::shared_ptr<ToplevelElement> getElement() const { + return stanza_; + } + + virtual std::shared_ptr<STANZA_TYPE> getStanzaGeneric() const { + return stanza_; + } + + private: + std::shared_ptr<STANZA_TYPE> stanza_; + }; } diff --git a/Swiften/Parser/IQParser.cpp b/Swiften/Parser/IQParser.cpp index 62d775f..363f7ec 100644 --- a/Swiften/Parser/IQParser.cpp +++ b/Swiften/Parser/IQParser.cpp @@ -1,40 +1,41 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <iostream> +#include <Swiften/Parser/IQParser.h> + #include <boost/optional.hpp> -#include <Swiften/Parser/IQParser.h> +#include <Swiften/Base/Log.h> namespace Swift { -IQParser::IQParser(PayloadParserFactoryCollection* factories) : - GenericStanzaParser<IQ>(factories) { +IQParser::IQParser(PayloadParserFactoryCollection* factories) : + GenericStanzaParser<IQ>(factories) { } void IQParser::handleStanzaAttributes(const AttributeMap& attributes) { - boost::optional<std::string> type = attributes.getAttributeValue("type"); - if (type) { - if (*type == "set") { - getStanzaGeneric()->setType(IQ::Set); - } - else if (*type == "get") { - getStanzaGeneric()->setType(IQ::Get); - } - else if (*type == "result") { - getStanzaGeneric()->setType(IQ::Result); - } - else if (*type == "error") { - getStanzaGeneric()->setType(IQ::Error); - } - else { - std::cerr << "Unknown IQ type: " << *type << std::endl; - getStanzaGeneric()->setType(IQ::Get); - } - } + boost::optional<std::string> type = attributes.getAttributeValue("type"); + if (type) { + if (*type == "set") { + getStanzaGeneric()->setType(IQ::Set); + } + else if (*type == "get") { + getStanzaGeneric()->setType(IQ::Get); + } + else if (*type == "result") { + getStanzaGeneric()->setType(IQ::Result); + } + else if (*type == "error") { + getStanzaGeneric()->setType(IQ::Error); + } + else { + SWIFT_LOG(warning) << "Unknown IQ type: " << *type; + getStanzaGeneric()->setType(IQ::Get); + } + } } } diff --git a/Swiften/Parser/IQParser.h b/Swiften/Parser/IQParser.h index 9773835..5250bfb 100644 --- a/Swiften/Parser/IQParser.h +++ b/Swiften/Parser/IQParser.h @@ -1,21 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Parser/GenericStanzaParser.h> #include <Swiften/Elements/IQ.h> +#include <Swiften/Parser/GenericStanzaParser.h> namespace Swift { - class SWIFTEN_API IQParser : public GenericStanzaParser<IQ> { - public: - IQParser(PayloadParserFactoryCollection* factories); + class SWIFTEN_API IQParser : public GenericStanzaParser<IQ> { + public: + IQParser(PayloadParserFactoryCollection* factories); - private: - virtual void handleStanzaAttributes(const AttributeMap&); - }; + private: + virtual void handleStanzaAttributes(const AttributeMap&); + }; } diff --git a/Swiften/Parser/LibXMLParser.cpp b/Swiften/Parser/LibXMLParser.cpp index e4938e1..32b91a1 100644 --- a/Swiften/Parser/LibXMLParser.cpp +++ b/Swiften/Parser/LibXMLParser.cpp @@ -1,106 +1,165 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/LibXMLParser.h> -#include <iostream> -#include <boost/numeric/conversion/cast.hpp> #include <cassert> #include <cstring> -#include <libxml/parser.h> +#include <limits> +#include <memory> #include <string> +#include <libxml/parser.h> + +#include <Swiften/Base/Log.h> #include <Swiften/Parser/XMLParserClient.h> +namespace { +std::string asString(const unsigned char* s) { + return s ? std::string(reinterpret_cast<const char*>(s)) : std::string(); +} +} + namespace Swift { struct LibXMLParser::Private { - xmlSAXHandler handler_; - xmlParserCtxtPtr context_; + xmlSAXHandler handler_; + xmlParserCtxtPtr context_; }; -static void handleStartElement(void* parser, const xmlChar* name, const xmlChar*, const xmlChar* xmlns, int, const xmlChar**, int nbAttributes, int nbDefaulted, const xmlChar ** attributes) { - AttributeMap attributeValues; - if (nbDefaulted != 0) { - // Just because i don't understand what this means yet :-) - std::cerr << "Unexpected nbDefaulted on XML element" << std::endl; - } - for (int i = 0; i < nbAttributes*5; i += 5) { - std::string attributeNS = ""; - if (attributes[i+2]) { - attributeNS = std::string(reinterpret_cast<const char*>(attributes[i+2])); - } - attributeValues.addAttribute( - std::string(reinterpret_cast<const char*>(attributes[i])), - attributeNS, - std::string(reinterpret_cast<const char*>(attributes[i+3]), - boost::numeric_cast<size_t>(attributes[i+4]-attributes[i+3]))); - } - static_cast<XMLParser*>(parser)->getClient()->handleStartElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : std::string()), attributeValues); +static void handleStartElement(void* parser, const xmlChar* name, const xmlChar* prefix, const xmlChar* xmlns, int nbNamespaces, const xmlChar** namespaces, int nbAttributes, int nbDefaulted, const xmlChar ** attributes) { + AttributeMap attributeValues; + if (nbDefaulted != 0) { + // Just because i don't understand what this means yet :-) + SWIFT_LOG(error) << "Unexpected nbDefaulted on XML element"; + } + for (int i = 0; i < nbAttributes*5; i += 5) { + std::string attributeName = asString(attributes[i]); + std::string attributePrefix = asString(attributes[i+1]); + std::string attributeNS = asString(attributes[i+2]); + assert(attributes[i+4] >= attributes[i+3]); + attributeValues.addAttribute( + attributeName, + attributeNS, + attributePrefix, + std::string(reinterpret_cast<const char*>(attributes[i+3]), + static_cast<size_t>(attributes[i+4]-attributes[i+3]))); + } + auto* client = static_cast<XMLParser*>(parser)->getClient(); + for (auto i = 0; i < nbNamespaces * 2; i += 2) { + const auto prefix = asString(namespaces[i]); + const auto uri = asString(namespaces[i + 1]); + client->handleNamespaceDeclaration(prefix, uri); + } + auto nameStr = asString(name); + auto xmlsnsStr = asString(xmlns); + auto prefixStr = asString(prefix); + client->handleStartElementPrefix(prefixStr, xmlsnsStr, nameStr, attributeValues); + client->handleStartElement(nameStr, xmlsnsStr, attributeValues); } static void handleEndElement(void *parser, const xmlChar* name, const xmlChar*, const xmlChar* xmlns) { - static_cast<XMLParser*>(parser)->getClient()->handleEndElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : std::string())); + static_cast<XMLParser*>(parser)->getClient()->handleEndElement(asString(name), asString(xmlns)); } static void handleCharacterData(void* parser, const xmlChar* data, int len) { - static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(reinterpret_cast<const char*>(data), boost::numeric_cast<size_t>(len))); + assert(len >= 0); + static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(reinterpret_cast<const char*>(data), static_cast<size_t>(len))); +} + +static void handleComment(void* parser, const xmlChar* /*data*/) { + if (!static_cast<LibXMLParser*>(parser)->allowsComments()) { + static_cast<LibXMLParser*>(parser)->stopParser(); + } +} + +static void handleEntityDeclaration(void * parser, const xmlChar* /*name*/, int /*type*/, const xmlChar* /*publicId*/, const xmlChar* /*systemId*/, xmlChar* /*content*/) { + static_cast<LibXMLParser*>(parser)->stopParser(); +} + +static void handleProcessingInstruction(void* parser, const xmlChar* /*target*/, const xmlChar* /*data*/) { + static_cast<LibXMLParser*>(parser)->stopParser(); +} + +static void handleExternalSubset(void* parser, const xmlChar * /*name*/, const xmlChar * /*ExternalID*/, const xmlChar * /*SystemID*/) { + static_cast<LibXMLParser*>(parser)->stopParser(); } static void handleError(void*, const char* /*m*/, ... ) { - /* - va_list args; - va_start(args, m); - vfprintf(stdout, m, args); - va_end(args); - */ + /* + va_list args; + va_start(args, m); + vfprintf(stdout, m, args); + va_end(args); + */ } static void handleWarning(void*, const char*, ... ) { } -bool LibXMLParser::initialized = false; +static void handleGenericError(void*, const char*, ... ) { +} -LibXMLParser::LibXMLParser(XMLParserClient* client) : XMLParser(client), p(new Private()) { - // Initialize libXML for multithreaded applications - if (!initialized) { - xmlInitParser(); - initialized = true; - } +static void handleStructuredError(void*, xmlErrorPtr) { +} - memset(&p->handler_, 0, sizeof(p->handler_) ); - p->handler_.initialized = XML_SAX2_MAGIC; - p->handler_.startElementNs = &handleStartElement; - p->handler_.endElementNs = &handleEndElement; - p->handler_.characters = &handleCharacterData; - p->handler_.warning = &handleWarning; - p->handler_.error = &handleError; +bool LibXMLParser::initialized = false; - p->context_ = xmlCreatePushParserCtxt(&p->handler_, this, 0, 0, 0); - xmlCtxtUseOptions(p->context_, XML_PARSE_NOENT); - assert(p->context_); +LibXMLParser::LibXMLParser(XMLParserClient* client, bool allowComments) : XMLParser(client, allowComments), p(new Private()) { + // Initialize libXML for multithreaded applications + if (!initialized) { + xmlInitParser(); + xmlSetGenericErrorFunc(nullptr, handleGenericError); + xmlSetStructuredErrorFunc(nullptr, handleStructuredError); + initialized = true; + } + + memset(&p->handler_, 0, sizeof(p->handler_) ); + p->handler_.initialized = XML_SAX2_MAGIC; + p->handler_.startElementNs = &handleStartElement; + p->handler_.endElementNs = &handleEndElement; + p->handler_.characters = &handleCharacterData; + p->handler_.warning = &handleWarning; + p->handler_.error = &handleError; + p->handler_.comment = &handleComment; + p->handler_.entityDecl = &handleEntityDeclaration; + p->handler_.processingInstruction = &handleProcessingInstruction; + p->handler_.externalSubset = &handleExternalSubset; + + p->context_ = xmlCreatePushParserCtxt(&p->handler_, this, nullptr, 0, nullptr); + xmlCtxtUseOptions(p->context_, XML_PARSE_NOENT); + assert(p->context_); } LibXMLParser::~LibXMLParser() { - if (p->context_) { - xmlFreeParserCtxt(p->context_); - } -} - -bool LibXMLParser::parse(const std::string& data) { - if (xmlParseChunk(p->context_, data.c_str(), boost::numeric_cast<int>(data.size()), false) == XML_ERR_OK) { - return true; - } - xmlError* error = xmlCtxtGetLastError(p->context_); - if (error->code == XML_WAR_NS_URI || error->code == XML_WAR_NS_URI_RELATIVE) { - xmlCtxtResetLastError(p->context_); - p->context_->errNo = XML_ERR_OK; - return true; - } - return false; + if (p->context_) { + xmlFreeParserCtxt(p->context_); + } +} + +bool LibXMLParser::parse(const std::string& data, bool finalData) { + if (data.size() > std::numeric_limits<int>::max()) { + return false; + } + auto error = xmlParseChunk(p->context_, data.c_str(), static_cast<int>(data.size()), finalData); + if (error == XML_ERR_OK) { + return true; + } + if (stopped_) return false; + if (error == XML_WAR_NS_URI || error == XML_WAR_NS_URI_RELATIVE) { + xmlCtxtResetLastError(p->context_); + p->context_->errNo = XML_ERR_OK; + return true; + } + return false; +} + +void LibXMLParser::stopParser() { + stopped_ = true; + xmlStopParser(p->context_); } } diff --git a/Swiften/Parser/LibXMLParser.h b/Swiften/Parser/LibXMLParser.h index b8e1d7c..e21770d 100644 --- a/Swiften/Parser/LibXMLParser.h +++ b/Swiften/Parser/LibXMLParser.h @@ -1,32 +1,36 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> #include <Swiften/Parser/XMLParser.h> namespace Swift { - /** - * Warning: This constructor is not thread-safe, because it depends on global state to - * check whether it is initialized. - */ - class LibXMLParser : public XMLParser, public boost::noncopyable { - public: - LibXMLParser(XMLParserClient* client); - ~LibXMLParser(); - - bool parse(const std::string& data); - - private: - static bool initialized; - - struct Private; - boost::shared_ptr<Private> p; - }; + /** + * Warning: This constructor is not thread-safe, because it depends on global state to + * check whether it is initialized. + */ + class LibXMLParser : public XMLParser, public boost::noncopyable { + public: + LibXMLParser(XMLParserClient* client, bool allowComments = false); + virtual ~LibXMLParser(); + + bool parse(const std::string& data, bool finalData = false); + + void stopParser(); + + private: + static bool initialized; + bool stopped_ = false; + + struct Private; + const std::unique_ptr<Private> p; + }; } diff --git a/Swiften/Parser/MessageParser.cpp b/Swiften/Parser/MessageParser.cpp index 7f5e6d4..1dd7675 100644 --- a/Swiften/Parser/MessageParser.cpp +++ b/Swiften/Parser/MessageParser.cpp @@ -1,39 +1,39 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/optional.hpp> - #include <Swiften/Parser/MessageParser.h> +#include <boost/optional.hpp> + namespace Swift { -MessageParser::MessageParser(PayloadParserFactoryCollection* factories) : - GenericStanzaParser<Message>(factories) { - getStanzaGeneric()->setType(Message::Normal); +MessageParser::MessageParser(PayloadParserFactoryCollection* factories) : + GenericStanzaParser<Message>(factories) { + GenericStanzaParser<Message>::getStanzaGeneric()->setType(Message::Normal); } void MessageParser::handleStanzaAttributes(const AttributeMap& attributes) { - boost::optional<std::string> type = attributes.getAttributeValue("type"); - if (type) { - if (*type == "chat") { - getStanzaGeneric()->setType(Message::Chat); - } - else if (*type == "error") { - getStanzaGeneric()->setType(Message::Error); - } - else if (*type == "groupchat") { - getStanzaGeneric()->setType(Message::Groupchat); - } - else if (*type == "headline") { - getStanzaGeneric()->setType(Message::Headline); - } - else { - getStanzaGeneric()->setType(Message::Normal); - } - } + boost::optional<std::string> type = attributes.getAttributeValue("type"); + if (type) { + if (*type == "chat") { + getStanzaGeneric()->setType(Message::Chat); + } + else if (*type == "error") { + getStanzaGeneric()->setType(Message::Error); + } + else if (*type == "groupchat") { + getStanzaGeneric()->setType(Message::Groupchat); + } + else if (*type == "headline") { + getStanzaGeneric()->setType(Message::Headline); + } + else { + getStanzaGeneric()->setType(Message::Normal); + } + } } } diff --git a/Swiften/Parser/MessageParser.h b/Swiften/Parser/MessageParser.h index e908339..cfbfc38 100644 --- a/Swiften/Parser/MessageParser.h +++ b/Swiften/Parser/MessageParser.h @@ -1,21 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Parser/GenericStanzaParser.h> #include <Swiften/Elements/Message.h> +#include <Swiften/Parser/GenericStanzaParser.h> namespace Swift { - class SWIFTEN_API MessageParser : public GenericStanzaParser<Message> { - public: - MessageParser(PayloadParserFactoryCollection* factories); + class SWIFTEN_API MessageParser : public GenericStanzaParser<Message> { + public: + MessageParser(PayloadParserFactoryCollection* factories); - private: - virtual void handleStanzaAttributes(const AttributeMap&); - }; + private: + virtual void handleStanzaAttributes(const AttributeMap&); + }; } diff --git a/Swiften/Parser/PayloadParser.cpp b/Swiften/Parser/PayloadParser.cpp index 3680d63..3b93454 100644 --- a/Swiften/Parser/PayloadParser.cpp +++ b/Swiften/Parser/PayloadParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParser.h> diff --git a/Swiften/Parser/PayloadParser.h b/Swiften/Parser/PayloadParser.h index bb1ae3c..a824922 100644 --- a/Swiften/Parser/PayloadParser.h +++ b/Swiften/Parser/PayloadParser.h @@ -1,51 +1,50 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> - +#include <memory> #include <Swiften/Base/API.h> -#include <Swiften/Parser/AttributeMap.h> #include <Swiften/Elements/Payload.h> +#include <Swiften/Parser/AttributeMap.h> namespace Swift { - - - /** - * A parser for XMPP stanza payloads. - * - * The parser is event driven: handleStartElement, handleEndElement, and handleCharacterData will be called - * when the parser detects start and end of XML elements, or character data. - * After the data for the given top-level element is processed, getPayload() will be called to retrieve the - * payload. - */ - class SWIFTEN_API PayloadParser { - public: - virtual ~PayloadParser(); - - /** - * Handle the start of an XML element. - */ - virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) = 0; - - /** - * Handle the end of an XML element. - */ - virtual void handleEndElement(const std::string& element, const std::string& ns) = 0; - - /** - * Handle character data. - */ - virtual void handleCharacterData(const std::string& data) = 0; - - /** - * Retrieve a pointer to the payload. - */ - virtual boost::shared_ptr<Payload> getPayload() const = 0; - }; + + + /** + * A parser for XMPP stanza payloads. + * + * The parser is event driven: handleStartElement, handleEndElement, and handleCharacterData will be called + * when the parser detects start and end of XML elements, or character data. + * After the data for the given top-level element is processed, getPayload() will be called to retrieve the + * payload. + */ + class SWIFTEN_API PayloadParser { + public: + virtual ~PayloadParser(); + + /** + * Handle the start of an XML element. + */ + virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) = 0; + + /** + * Handle the end of an XML element. + */ + virtual void handleEndElement(const std::string& element, const std::string& ns) = 0; + + /** + * Handle character data. + */ + virtual void handleCharacterData(const std::string& data) = 0; + + /** + * Retrieve a pointer to the payload. + */ + virtual std::shared_ptr<Payload> getPayload() const = 0; + }; } diff --git a/Swiften/Parser/PayloadParserFactory.cpp b/Swiften/Parser/PayloadParserFactory.cpp index 4dac217..8c1d099 100644 --- a/Swiften/Parser/PayloadParserFactory.cpp +++ b/Swiften/Parser/PayloadParserFactory.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParserFactory.h> diff --git a/Swiften/Parser/PayloadParserFactory.h b/Swiften/Parser/PayloadParserFactory.h index e265e5b..84f11ff 100644 --- a/Swiften/Parser/PayloadParserFactory.h +++ b/Swiften/Parser/PayloadParserFactory.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,24 +10,24 @@ #include <Swiften/Parser/AttributeMap.h> namespace Swift { - - class PayloadParser; - /** - * A factory for PayloadParsers. - */ - class SWIFTEN_API PayloadParserFactory { - public: - virtual ~PayloadParserFactory(); + class PayloadParser; - /** - * Checks whether this factory can parse the given top-level element in the given namespace (with the given attributes). - */ - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap& attributes) const = 0; + /** + * A factory for PayloadParsers. + */ + class SWIFTEN_API PayloadParserFactory { + public: + virtual ~PayloadParserFactory(); - /** - * Creates a new payload parser. - */ - virtual PayloadParser* createPayloadParser() = 0; - }; + /** + * Checks whether this factory can parse the given top-level element in the given namespace (with the given attributes). + */ + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap& attributes) const = 0; + + /** + * Creates a new payload parser. + */ + virtual PayloadParser* createPayloadParser() = 0; + }; } diff --git a/Swiften/Parser/PayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParserFactoryCollection.cpp index e3efc3d..bca1e83 100644 --- a/Swiften/Parser/PayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParserFactoryCollection.cpp @@ -1,37 +1,42 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/bind.hpp> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> + #include <algorithm> -#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <boost/bind.hpp> + #include <Swiften/Parser/PayloadParserFactory.h> namespace Swift { -PayloadParserFactoryCollection::PayloadParserFactoryCollection() : defaultFactory_(NULL) { +PayloadParserFactoryCollection::PayloadParserFactoryCollection() : defaultFactory_(nullptr) { +} + +PayloadParserFactoryCollection::~PayloadParserFactoryCollection() { } void PayloadParserFactoryCollection::addFactory(PayloadParserFactory* factory) { - factories_.push_back(factory); + factories_.push_back(factory); } void PayloadParserFactoryCollection::removeFactory(PayloadParserFactory* factory) { - factories_.erase(remove(factories_.begin(), factories_.end(), factory), factories_.end()); + factories_.erase(std::remove(factories_.begin(), factories_.end(), factory), factories_.end()); } void PayloadParserFactoryCollection::setDefaultFactory(PayloadParserFactory* factory) { - defaultFactory_ = factory; + defaultFactory_ = factory; } PayloadParserFactory* PayloadParserFactoryCollection::getPayloadParserFactory(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - std::vector<PayloadParserFactory*>::reverse_iterator i = std::find_if( - factories_.rbegin(), factories_.rend(), - boost::bind(&PayloadParserFactory::canParse, _1, element, ns, attributes)); - return (i != factories_.rend() ? *i : defaultFactory_); + std::vector<PayloadParserFactory*>::reverse_iterator i = std::find_if( + factories_.rbegin(), factories_.rend(), + boost::bind(&PayloadParserFactory::canParse, _1, element, ns, attributes)); + return (i != factories_.rend() ? *i : defaultFactory_); } } diff --git a/Swiften/Parser/PayloadParserFactoryCollection.h b/Swiften/Parser/PayloadParserFactoryCollection.h index 1dbdd32..cc0db5a 100644 --- a/Swiften/Parser/PayloadParserFactoryCollection.h +++ b/Swiften/Parser/PayloadParserFactoryCollection.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <vector> -#include <Swiften/Parser/AttributeMap.h> #include <Swiften/Base/API.h> +#include <Swiften/Parser/AttributeMap.h> namespace Swift { - class PayloadParserFactory; + class PayloadParserFactory; - class SWIFTEN_API PayloadParserFactoryCollection { - public: - PayloadParserFactoryCollection(); + class SWIFTEN_API PayloadParserFactoryCollection { + public: + PayloadParserFactoryCollection(); + virtual ~PayloadParserFactoryCollection(); - void addFactory(PayloadParserFactory* factory); - void removeFactory(PayloadParserFactory* factory); - void setDefaultFactory(PayloadParserFactory* factory); + void addFactory(PayloadParserFactory* factory); + void removeFactory(PayloadParserFactory* factory); + void setDefaultFactory(PayloadParserFactory* factory); - PayloadParserFactory* getPayloadParserFactory(const std::string& element, const std::string& ns, const AttributeMap& attributes); + PayloadParserFactory* getPayloadParserFactory(const std::string& element, const std::string& ns, const AttributeMap& attributes); - private: - std::vector<PayloadParserFactory*> factories_; - PayloadParserFactory* defaultFactory_; - }; + private: + std::vector<PayloadParserFactory*> factories_; + PayloadParserFactory* defaultFactory_; + }; } diff --git a/Swiften/Parser/PayloadParsers/BlockParser.h b/Swiften/Parser/PayloadParsers/BlockParser.h index 6ee47a2..1724feb 100644 --- a/Swiften/Parser/PayloadParsers/BlockParser.h +++ b/Swiften/Parser/PayloadParsers/BlockParser.h @@ -1,40 +1,41 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Nickname.h> #include <Swiften/JID/JID.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - template<typename BLOCK_ELEMENT> - class BlockParser : public GenericPayloadParser<BLOCK_ELEMENT> { - public: - BlockParser() : GenericPayloadParser<BLOCK_ELEMENT>(), level(0) { - } + template<typename BLOCK_ELEMENT> + class SWIFTEN_API BlockParser : public GenericPayloadParser<BLOCK_ELEMENT> { + public: + BlockParser() : GenericPayloadParser<BLOCK_ELEMENT>(), level(0) { + } - virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level == 1 && element == "item") { - JID jid(attributes.getAttribute("jid")); - if (jid.isValid()) { - GenericPayloadParser<BLOCK_ELEMENT>::getPayloadInternal()->addItem(jid); - } - } - ++level; - } + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { + if (level == 1 && element == "item") { + JID jid(attributes.getAttribute("jid")); + if (jid.isValid()) { + GenericPayloadParser<BLOCK_ELEMENT>::getPayloadInternal()->addItem(jid); + } + } + ++level; + } - virtual void handleEndElement(const std::string&, const std::string&) { - --level; - } + virtual void handleEndElement(const std::string&, const std::string&) { + --level; + } - virtual void handleCharacterData(const std::string&) { - } + virtual void handleCharacterData(const std::string&) { + } - private: - int level; - }; + private: + int level; + }; } diff --git a/Swiften/Parser/PayloadParsers/BodyParser.cpp b/Swiften/Parser/PayloadParsers/BodyParser.cpp index ac8bdd5..5741c90 100644 --- a/Swiften/Parser/PayloadParsers/BodyParser.cpp +++ b/Swiften/Parser/PayloadParsers/BodyParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/BodyParser.h> @@ -12,18 +12,18 @@ BodyParser::BodyParser() : level_(0) { } void BodyParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++level_; + ++level_; } void BodyParser::handleEndElement(const std::string&, const std::string&) { - --level_; - if (level_ == 0) { - getPayloadInternal()->setText(text_); - } + --level_; + if (level_ == 0) { + getPayloadInternal()->setText(text_); + } } void BodyParser::handleCharacterData(const std::string& data) { - text_ += data; + text_ += data; } } diff --git a/Swiften/Parser/PayloadParsers/BodyParser.h b/Swiften/Parser/PayloadParsers/BodyParser.h index f571370..bcf762b 100644 --- a/Swiften/Parser/PayloadParsers/BodyParser.h +++ b/Swiften/Parser/PayloadParsers/BodyParser.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Body.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class BodyParser : public GenericPayloadParser<Body> { - public: - BodyParser(); + class SWIFTEN_API BodyParser : public GenericPayloadParser<Body> { + public: + BodyParser(); - 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); + 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: - int level_; - std::string text_; - }; + private: + int level_; + std::string text_; + }; } diff --git a/Swiften/Parser/PayloadParsers/BytestreamsParser.cpp b/Swiften/Parser/PayloadParsers/BytestreamsParser.cpp index fddc1c7..71bce54 100644 --- a/Swiften/Parser/PayloadParsers/BytestreamsParser.cpp +++ b/Swiften/Parser/PayloadParsers/BytestreamsParser.cpp @@ -1,14 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/BytestreamsParser.h> #include <boost/lexical_cast.hpp> - -#include <Swiften/Base/foreach.h> +#include <boost/numeric/conversion/cast.hpp> namespace Swift { @@ -19,26 +18,28 @@ BytestreamsParser::~BytestreamsParser() { } void BytestreamsParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level == TopLevel) { - getPayloadInternal()->setStreamID(attributes.getAttribute("sid")); - } - else if (level == PayloadLevel) { - if (element == "streamhost") { - try { - getPayloadInternal()->addStreamHost(Bytestreams::StreamHost(attributes.getAttribute("host"), JID(attributes.getAttribute("jid")), boost::lexical_cast<int>(attributes.getAttribute("port")))); - } - catch (boost::bad_lexical_cast&) { - } - } - else if (element == "streamhost-used") { - getPayloadInternal()->setUsedStreamHost(JID(attributes.getAttribute("jid"))); - } - } - ++level; + if (level == TopLevel) { + getPayloadInternal()->setStreamID(attributes.getAttribute("sid")); + } + else if (level == PayloadLevel) { + if (element == "streamhost") { + try { + getPayloadInternal()->addStreamHost(Bytestreams::StreamHost(attributes.getAttribute("host"), JID(attributes.getAttribute("jid")), boost::numeric_cast<unsigned short>(boost::lexical_cast<int>(attributes.getAttribute("port"))))); + } + catch (boost::numeric::bad_numeric_cast&) { + } + catch (boost::bad_lexical_cast&) { + } + } + else if (element == "streamhost-used") { + getPayloadInternal()->setUsedStreamHost(JID(attributes.getAttribute("jid"))); + } + } + ++level; } void BytestreamsParser::handleEndElement(const std::string&, const std::string&) { - --level; + --level; } void BytestreamsParser::handleCharacterData(const std::string&) { diff --git a/Swiften/Parser/PayloadParsers/BytestreamsParser.h b/Swiften/Parser/PayloadParsers/BytestreamsParser.h index 5c151c2..01cb60f 100644 --- a/Swiften/Parser/PayloadParsers/BytestreamsParser.h +++ b/Swiften/Parser/PayloadParsers/BytestreamsParser.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Bytestreams.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class BytestreamsParser : public GenericPayloadParser<Bytestreams> { - public: - BytestreamsParser(); - ~BytestreamsParser(); + class SWIFTEN_API BytestreamsParser : public GenericPayloadParser<Bytestreams> { + public: + BytestreamsParser(); + ~BytestreamsParser(); - 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); + 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 - }; - int level; - }; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + int level; + }; } diff --git a/Swiften/Parser/PayloadParsers/CapsInfoParser.cpp b/Swiften/Parser/PayloadParsers/CapsInfoParser.cpp index 770d98b..546df57 100644 --- a/Swiften/Parser/PayloadParsers/CapsInfoParser.cpp +++ b/Swiften/Parser/PayloadParsers/CapsInfoParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/CapsInfoParser.h> @@ -14,16 +14,16 @@ CapsInfoParser::CapsInfoParser() : level(0) { } void CapsInfoParser::handleStartElement(const std::string&, const std::string& /*ns*/, const AttributeMap& attributes) { - if (level == 0) { - getPayloadInternal()->setHash(attributes.getAttribute("hash")); - getPayloadInternal()->setNode(attributes.getAttribute("node")); - getPayloadInternal()->setVersion(attributes.getAttribute("ver")); - } - ++level; + if (level == 0) { + getPayloadInternal()->setHash(attributes.getAttribute("hash")); + getPayloadInternal()->setNode(attributes.getAttribute("node")); + getPayloadInternal()->setVersion(attributes.getAttribute("ver")); + } + ++level; } void CapsInfoParser::handleEndElement(const std::string&, const std::string&) { - --level; + --level; } void CapsInfoParser::handleCharacterData(const std::string&) { diff --git a/Swiften/Parser/PayloadParsers/CapsInfoParser.h b/Swiften/Parser/PayloadParsers/CapsInfoParser.h index 96aa734..9556a4d 100644 --- a/Swiften/Parser/PayloadParsers/CapsInfoParser.h +++ b/Swiften/Parser/PayloadParsers/CapsInfoParser.h @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/CapsInfo.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class CapsInfoParser : public GenericPayloadParser<CapsInfo> { - public: - CapsInfoParser(); + class SWIFTEN_API CapsInfoParser : public GenericPayloadParser<CapsInfo> { + public: + CapsInfoParser(); - 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); + 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: - int level; - }; + private: + int level; + }; } diff --git a/Swiften/Parser/PayloadParsers/CarbonsDisableParser.cpp b/Swiften/Parser/PayloadParsers/CarbonsDisableParser.cpp new file mode 100644 index 0000000..b8bd4b5 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/CarbonsDisableParser.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/CarbonsDisableParser.h> + +namespace Swift { + + CarbonsDisableParser::CarbonsDisableParser() : GenericPayloadParser<CarbonsDisable>() { + } + + CarbonsDisableParser::~CarbonsDisableParser() { + } + + void CarbonsDisableParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { + } + + void CarbonsDisableParser::handleEndElement(const std::string&, const std::string&) { + } + + void CarbonsDisableParser::handleCharacterData(const std::string&) { + } + +} diff --git a/Swiften/Parser/PayloadParsers/CarbonsDisableParser.h b/Swiften/Parser/PayloadParsers/CarbonsDisableParser.h new file mode 100644 index 0000000..7a5f4a4 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/CarbonsDisableParser.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsDisable.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class SWIFTEN_API CarbonsDisableParser : public GenericPayloadParser<CarbonsDisable> { + public: + CarbonsDisableParser(); + virtual ~CarbonsDisableParser(); + + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string&); + virtual void handleCharacterData(const std::string&); + }; +} diff --git a/Swiften/Parser/PayloadParsers/CarbonsEnableParser.cpp b/Swiften/Parser/PayloadParsers/CarbonsEnableParser.cpp new file mode 100644 index 0000000..700f939 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/CarbonsEnableParser.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/CarbonsEnableParser.h> + +namespace Swift { + + CarbonsEnableParser::CarbonsEnableParser() : GenericPayloadParser<CarbonsEnable>() { + } + + CarbonsEnableParser::~CarbonsEnableParser() { + } + + void CarbonsEnableParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { + } + + void CarbonsEnableParser::handleEndElement(const std::string&, const std::string&) { + } + + void CarbonsEnableParser::handleCharacterData(const std::string&) { + } + +} diff --git a/Swiften/Parser/PayloadParsers/CarbonsEnableParser.h b/Swiften/Parser/PayloadParsers/CarbonsEnableParser.h new file mode 100644 index 0000000..0488f97 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/CarbonsEnableParser.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsEnable.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class SWIFTEN_API CarbonsEnableParser : public GenericPayloadParser<CarbonsEnable> { + public: + CarbonsEnableParser(); + virtual ~CarbonsEnableParser(); + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string&); + virtual void handleCharacterData(const std::string&); + }; +} diff --git a/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.cpp b/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.cpp new file mode 100644 index 0000000..b2038db --- /dev/null +++ b/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h> + +namespace Swift { + + CarbonsPrivateParser::CarbonsPrivateParser() : GenericPayloadParser<CarbonsPrivate>() { + } + + CarbonsPrivateParser::~CarbonsPrivateParser() { + } + + void CarbonsPrivateParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { + } + + void CarbonsPrivateParser::handleEndElement(const std::string&, const std::string&) { + } + + void CarbonsPrivateParser::handleCharacterData(const std::string&) { + } + +} diff --git a/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h b/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h new file mode 100644 index 0000000..2ae3bae --- /dev/null +++ b/Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsPrivate.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class SWIFTEN_API CarbonsPrivateParser : public GenericPayloadParser<CarbonsPrivate> { + public: + CarbonsPrivateParser(); + virtual ~CarbonsPrivateParser(); + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string&); + virtual void handleCharacterData(const std::string&); + }; +} diff --git a/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.cpp b/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.cpp new file mode 100644 index 0000000..e4f8ab9 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h> + +namespace Swift { + CarbonsReceivedParser::CarbonsReceivedParser(PayloadParserFactoryCollection* factories) : GenericPayloadParser<CarbonsReceived>(), factories_(factories), level_(TopLevel) { + } + + CarbonsReceivedParser::~CarbonsReceivedParser() { + } + + void CarbonsReceivedParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + if (level_ == PayloadLevel) { + if (element == "forwarded") { + forwardedParser_ = std::dynamic_pointer_cast<ForwardedParser>(std::make_shared<ForwardedParser>(factories_)); + } + } + if (forwardedParser_) { + forwardedParser_->handleStartElement(element, ns, attributes); + } + ++level_; + } + + void CarbonsReceivedParser::handleEndElement(const std::string& element, const std::string& ns) { + --level_; + if (forwardedParser_ && level_ >= PayloadLevel) { + forwardedParser_->handleEndElement(element, ns); + } + if (forwardedParser_ && level_ == PayloadLevel) { + /* done parsing nested stanza */ + getPayloadInternal()->setForwarded(forwardedParser_->getPayloadInternal()); + forwardedParser_.reset(); + } + } + + void CarbonsReceivedParser::handleCharacterData(const std::string& data) { + if (forwardedParser_) { + forwardedParser_->handleCharacterData(data); + } + } +} diff --git a/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h b/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h new file mode 100644 index 0000000..6cc1f43 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsReceived.h> +#include <Swiften/Parser/GenericPayloadParser.h> +#include <Swiften/Parser/PayloadParsers/ForwardedParser.h> + +namespace Swift { + class SWIFTEN_API CarbonsReceivedParser : public GenericPayloadParser<CarbonsReceived> { + public: + CarbonsReceivedParser(PayloadParserFactoryCollection* factories); + virtual ~CarbonsReceivedParser(); + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap&); + virtual void handleEndElement(const std::string& element, const std::string&); + virtual void handleCharacterData(const std::string&); + + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + + + private: + PayloadParserFactoryCollection* factories_; + std::shared_ptr<ForwardedParser> forwardedParser_; + int level_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/CarbonsSentParser.cpp b/Swiften/Parser/PayloadParsers/CarbonsSentParser.cpp new file mode 100644 index 0000000..f446042 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/CarbonsSentParser.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/CarbonsSentParser.h> + +namespace Swift { + CarbonsSentParser::CarbonsSentParser(PayloadParserFactoryCollection* factories) : GenericPayloadParser<CarbonsSent>(), factories_(factories), level_(TopLevel) { + } + + CarbonsSentParser::~CarbonsSentParser() { + } + + void CarbonsSentParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + if (level_ == PayloadLevel) { + if (element == "forwarded") { + forwardedParser_ = std::dynamic_pointer_cast<ForwardedParser>(std::make_shared<ForwardedParser>(factories_)); + } + } + if (forwardedParser_) { + forwardedParser_->handleStartElement(element, ns, attributes); + } + ++level_; + } + + void CarbonsSentParser::handleEndElement(const std::string& element, const std::string& ns) { + --level_; + if (forwardedParser_ && level_ >= PayloadLevel) { + forwardedParser_->handleEndElement(element, ns); + } + if (forwardedParser_ && level_ == PayloadLevel) { + /* done parsing nested stanza */ + getPayloadInternal()->setForwarded(forwardedParser_->getPayloadInternal()); + forwardedParser_.reset(); + } + } + + void CarbonsSentParser::handleCharacterData(const std::string& data) { + if (forwardedParser_) { + forwardedParser_->handleCharacterData(data); + } + } +} diff --git a/Swiften/Parser/PayloadParsers/CarbonsSentParser.h b/Swiften/Parser/PayloadParsers/CarbonsSentParser.h new file mode 100644 index 0000000..d4e12ba --- /dev/null +++ b/Swiften/Parser/PayloadParsers/CarbonsSentParser.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsSent.h> +#include <Swiften/Parser/GenericPayloadParser.h> +#include <Swiften/Parser/PayloadParsers/ForwardedParser.h> + +namespace Swift { + class SWIFTEN_API CarbonsSentParser : public GenericPayloadParser<CarbonsSent> { + public: + CarbonsSentParser(PayloadParserFactoryCollection* factories); + virtual ~CarbonsSentParser(); + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap&); + virtual void handleEndElement(const std::string& element, const std::string&); + virtual void handleCharacterData(const std::string&); + + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + + + private: + PayloadParserFactoryCollection* factories_; + std::shared_ptr<ForwardedParser> forwardedParser_; + int level_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/ChatStateParser.cpp b/Swiften/Parser/PayloadParsers/ChatStateParser.cpp index a85dcf7..75ec699 100644 --- a/Swiften/Parser/PayloadParsers/ChatStateParser.cpp +++ b/Swiften/Parser/PayloadParsers/ChatStateParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/ChatStateParser.h> @@ -12,26 +12,26 @@ ChatStateParser::ChatStateParser() : level_(0) { } void ChatStateParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap&) { - if (level_ == 0) { - ChatState::ChatStateType state = ChatState::Active; - if (element == "active") { - state = ChatState::Active; - } else if (element == "composing") { - state = ChatState::Composing; - } else if (element == "inactive") { - state = ChatState::Inactive; - } else if (element == "paused") { - state = ChatState::Paused; - } else if (element == "gone") { - state = ChatState::Gone; - } - getPayloadInternal()->setChatState(state); - } - ++level_; + if (level_ == 0) { + ChatState::ChatStateType state = ChatState::Active; + if (element == "active") { + state = ChatState::Active; + } else if (element == "composing") { + state = ChatState::Composing; + } else if (element == "inactive") { + state = ChatState::Inactive; + } else if (element == "paused") { + state = ChatState::Paused; + } else if (element == "gone") { + state = ChatState::Gone; + } + getPayloadInternal()->setChatState(state); + } + ++level_; } void ChatStateParser::handleEndElement(const std::string&, const std::string&) { - --level_; + --level_; } void ChatStateParser::handleCharacterData(const std::string&) { diff --git a/Swiften/Parser/PayloadParsers/ChatStateParser.h b/Swiften/Parser/PayloadParsers/ChatStateParser.h index 4363d6b..b932a5c 100644 --- a/Swiften/Parser/PayloadParsers/ChatStateParser.h +++ b/Swiften/Parser/PayloadParsers/ChatStateParser.h @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/ChatState.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class ChatStateParser : public GenericPayloadParser<ChatState> { - public: - ChatStateParser(); + class SWIFTEN_API ChatStateParser : public GenericPayloadParser<ChatState> { + public: + ChatStateParser(); - 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); + 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: - int level_; - }; + private: + int level_; + }; } diff --git a/Swiften/Parser/PayloadParsers/ChatStateParserFactory.h b/Swiften/Parser/PayloadParsers/ChatStateParserFactory.h index 80d76c4..3f9b3d3 100644 --- a/Swiften/Parser/PayloadParsers/ChatStateParserFactory.h +++ b/Swiften/Parser/PayloadParsers/ChatStateParserFactory.h @@ -1,31 +1,30 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/ChatStateParser.h> namespace Swift { - class PayloadParserFactoryCollection; + class SWIFTEN_API ChatStateParserFactory : public PayloadParserFactory { + public: + ChatStateParserFactory() { + } - class ChatStateParserFactory : public PayloadParserFactory { - public: - ChatStateParserFactory() { - } + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return ns == "http://jabber.org/protocol/chatstates" && + (element == "active" || element == "composing" + || element == "paused" || element == "inactive" || element == "gone"); + } - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return ns == "http://jabber.org/protocol/chatstates" && - (element == "active" || element == "composing" - || element == "paused" || element == "inactive" || element == "gone"); - } + virtual PayloadParser* createPayloadParser() { + return new ChatStateParser(); + } - virtual PayloadParser* createPayloadParser() { - return new ChatStateParser(); - } - - }; + }; } diff --git a/Swiften/Parser/PayloadParsers/ClientStateParser.cpp b/Swiften/Parser/PayloadParsers/ClientStateParser.cpp new file mode 100644 index 0000000..8a6cc9c --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ClientStateParser.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/ClientStateParser.h> + +namespace Swift { + +ClientStateParser::ClientStateParser() { +} + +void ClientStateParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap&) { + if (level_ == 0) { + auto state = ClientState::ClientStateType::Active; + if (element == "active") { + state = ClientState::ClientStateType::Active; + } else if (element == "inactive") { + state = ClientState::ClientStateType::Inactive; + } + getPayloadInternal()->setClientState(state); + } + ++level_; +} + +void ClientStateParser::handleEndElement(const std::string&, const std::string&) { + --level_; +} + +void ClientStateParser::handleCharacterData(const std::string&) { + +} + +} diff --git a/Swiften/Parser/PayloadParsers/ClientStateParser.h b/Swiften/Parser/PayloadParsers/ClientStateParser.h new file mode 100644 index 0000000..039ae37 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ClientStateParser.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ClientState.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class SWIFTEN_API ClientStateParser : public GenericPayloadParser<ClientState> { + public: + ClientStateParser(); + + 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: + int level_ = 0; + }; +} diff --git a/Swiften/Parser/PayloadParsers/ClientStateParserFactory.h b/Swiften/Parser/PayloadParsers/ClientStateParserFactory.h new file mode 100644 index 0000000..61f7012 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ClientStateParserFactory.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/ClientStateParser.h> + +namespace Swift { + class SWIFTEN_API ClientStateParserFactory : public PayloadParserFactory { + public: + ClientStateParserFactory() { + } + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return ns == "urn:xmpp:csi:0" && + (element == "active" || element == "inactive"); + } + + virtual PayloadParser* createPayloadParser() { + return new ClientStateParser(); + } + + }; +} diff --git a/Swiften/Parser/PayloadParsers/CommandParser.cpp b/Swiften/Parser/PayloadParsers/CommandParser.cpp index 1af4074..80686d2 100644 --- a/Swiften/Parser/PayloadParsers/CommandParser.cpp +++ b/Swiften/Parser/PayloadParsers/CommandParser.cpp @@ -1,143 +1,145 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/CommandParser.h> +#include <cassert> + #include <boost/cast.hpp> -#include <Swiften/Parser/PayloadParsers/FormParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParser.h> +#include <Swiften/Parser/PayloadParsers/FormParserFactory.h> namespace Swift { -CommandParser::CommandParser() : level_(TopLevel), inNote_(false), inActions_(false), noteType_(Command::Note::Info), formParser_(0) { - formParserFactory_ = new FormParserFactory(); +CommandParser::CommandParser() : level_(TopLevel), inNote_(false), inActions_(false), noteType_(Command::Note::Info), formParser_(nullptr) { + formParserFactory_ = new FormParserFactory(); } CommandParser::~CommandParser() { - delete formParserFactory_; + delete formParserFactory_; } void CommandParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - ++level_; - if (level_ == PayloadLevel) { - boost::optional<Command::Action> action = parseAction(attributes.getAttribute("action")); - if (action) { - getPayloadInternal()->setAction(*action); - } - - std::string status = attributes.getAttribute("status"); - if (status == "executing") { - getPayloadInternal()->setStatus(Command::Executing); - } - else if (status == "completed") { - getPayloadInternal()->setStatus(Command::Completed); - } - else if (status == "canceled") { - getPayloadInternal()->setStatus(Command::Canceled); - } - - getPayloadInternal()->setNode(attributes.getAttribute("node")); - getPayloadInternal()->setSessionID(attributes.getAttribute("sessionid")); - } - else if (level_ == FormOrNoteOrActionsLevel) { - assert(!formParser_); - if (formParserFactory_->canParse(element, ns, attributes)) { - formParser_ = boost::polymorphic_downcast<FormParser*>(formParserFactory_->createPayloadParser()); - assert(formParser_); - } - else if (element == "note") { - inNote_ = true; - currentText_.clear(); - std::string noteType = attributes.getAttribute("type"); - if (noteType == "info") { - noteType_ = Command::Note::Info; - } - else if (noteType == "warn") { - noteType_ = Command::Note::Warn; - } - else if (noteType == "error") { - noteType_ = Command::Note::Error; - } - else { - noteType_ = Command::Note::Info; - } - } - else if (element == "actions") { - inActions_ = true; - boost::optional<Command::Action> action = parseAction(attributes.getAttribute("execute")); - if (action) { - getPayloadInternal()->setExecuteAction(*action); - } - } - } - else if (level_ == ActionsActionLevel) { - } - - if (formParser_) { - formParser_->handleStartElement(element, ns, attributes); - } + ++level_; + if (level_ == PayloadLevel) { + boost::optional<Command::Action> action = parseAction(attributes.getAttribute("action")); + if (action) { + getPayloadInternal()->setAction(*action); + } + + std::string status = attributes.getAttribute("status"); + if (status == "executing") { + getPayloadInternal()->setStatus(Command::Executing); + } + else if (status == "completed") { + getPayloadInternal()->setStatus(Command::Completed); + } + else if (status == "canceled") { + getPayloadInternal()->setStatus(Command::Canceled); + } + + getPayloadInternal()->setNode(attributes.getAttribute("node")); + getPayloadInternal()->setSessionID(attributes.getAttribute("sessionid")); + } + else if (level_ == FormOrNoteOrActionsLevel) { + assert(!formParser_); + if (formParserFactory_->canParse(element, ns, attributes)) { + formParser_ = boost::polymorphic_downcast<FormParser*>(formParserFactory_->createPayloadParser()); + assert(formParser_); + } + else if (element == "note") { + inNote_ = true; + currentText_.clear(); + std::string noteType = attributes.getAttribute("type"); + if (noteType == "info") { + noteType_ = Command::Note::Info; + } + else if (noteType == "warn") { + noteType_ = Command::Note::Warn; + } + else if (noteType == "error") { + noteType_ = Command::Note::Error; + } + else { + noteType_ = Command::Note::Info; + } + } + else if (element == "actions") { + inActions_ = true; + boost::optional<Command::Action> action = parseAction(attributes.getAttribute("execute")); + if (action) { + getPayloadInternal()->setExecuteAction(*action); + } + } + } + else if (level_ == ActionsActionLevel) { + } + + if (formParser_) { + formParser_->handleStartElement(element, ns, attributes); + } } void CommandParser::handleEndElement(const std::string& element, const std::string& ns) { - if (formParser_) { - formParser_->handleEndElement(element, ns); - } - - if (level_ == FormOrNoteOrActionsLevel) { - if (formParser_) { - Form::ref form(boost::dynamic_pointer_cast<Form>(formParser_->getPayload())); - assert(form); - getPayloadInternal()->setForm(form); - delete formParser_; - formParser_ = 0; - } - else if (inNote_) { - inNote_ = false; - getPayloadInternal()->addNote(Command::Note(currentText_, noteType_)); - } - else if (inActions_) { - inActions_ = false; - } - } - else if (level_ == ActionsActionLevel && inActions_) { - boost::optional<Command::Action> action = parseAction(element); - if (action) { - getPayloadInternal()->addAvailableAction(*action); - } - } - --level_; + if (formParser_) { + formParser_->handleEndElement(element, ns); + } + + if (level_ == FormOrNoteOrActionsLevel) { + if (formParser_) { + Form::ref form(std::dynamic_pointer_cast<Form>(formParser_->getPayload())); + assert(form); + getPayloadInternal()->setForm(form); + delete formParser_; + formParser_ = nullptr; + } + else if (inNote_) { + inNote_ = false; + getPayloadInternal()->addNote(Command::Note(currentText_, noteType_)); + } + else if (inActions_) { + inActions_ = false; + } + } + else if (level_ == ActionsActionLevel && inActions_) { + boost::optional<Command::Action> action = parseAction(element); + if (action) { + getPayloadInternal()->addAvailableAction(*action); + } + } + --level_; } void CommandParser::handleCharacterData(const std::string& data) { - if (formParser_) { - formParser_->handleCharacterData(data); - } - else { - currentText_ += data; - } + if (formParser_) { + formParser_->handleCharacterData(data); + } + else { + currentText_ += data; + } } boost::optional<Command::Action> CommandParser::parseAction(const std::string& action) { - if (action == "execute") { - return Command::Execute; - } - else if (action == "cancel") { - return Command::Cancel; - } - else if (action == "prev") { - return Command::Prev; - } - else if (action == "next") { - return Command::Next; - } - else if (action == "complete") { - return Command::Complete; - } - return boost::optional<Command::Action>(); + if (action == "execute") { + return Command::Execute; + } + else if (action == "cancel") { + return Command::Cancel; + } + else if (action == "prev") { + return Command::Prev; + } + else if (action == "next") { + return Command::Next; + } + else if (action == "complete") { + return Command::Complete; + } + return boost::optional<Command::Action>(); } } diff --git a/Swiften/Parser/PayloadParsers/CommandParser.h b/Swiften/Parser/PayloadParsers/CommandParser.h index 80cffc4..105953a 100644 --- a/Swiften/Parser/PayloadParsers/CommandParser.h +++ b/Swiften/Parser/PayloadParsers/CommandParser.h @@ -1,45 +1,46 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Command.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class FormParserFactory; - class FormParser; - - class CommandParser : public GenericPayloadParser<Command> { - public: - CommandParser(); - ~CommandParser(); - - 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: - static boost::optional<Command::Action> parseAction(const std::string& action); - - private: - enum Level { - TopLevel = 0, - PayloadLevel = 1, - FormOrNoteOrActionsLevel = 2, - ActionsActionLevel = 3 - }; - int level_; - bool inNote_; - bool inActions_; - Command::Note::Type noteType_; - FormParserFactory* formParserFactory_; - FormParser* formParser_; - std::string currentText_; - }; + class FormParserFactory; + class FormParser; + + class SWIFTEN_API CommandParser : public GenericPayloadParser<Command> { + public: + CommandParser(); + ~CommandParser(); + + 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: + static boost::optional<Command::Action> parseAction(const std::string& action); + + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1, + FormOrNoteOrActionsLevel = 2, + ActionsActionLevel = 3 + }; + int level_; + bool inNote_; + bool inActions_; + Command::Note::Type noteType_; + FormParserFactory* formParserFactory_; + FormParser* formParser_; + std::string currentText_; + }; } diff --git a/Swiften/Parser/PayloadParsers/DelayParser.cpp b/Swiften/Parser/PayloadParsers/DelayParser.cpp index e18d09d..95371b7 100644 --- a/Swiften/Parser/PayloadParsers/DelayParser.cpp +++ b/Swiften/Parser/PayloadParsers/DelayParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/DelayParser.h> @@ -14,19 +14,19 @@ DelayParser::DelayParser() : level_(0) { } void DelayParser::handleStartElement(const std::string& /*element*/, const std::string& /*ns*/, const AttributeMap& attributes) { - if (level_ == 0) { - boost::posix_time::ptime stamp = stringToDateTime(attributes.getAttribute("stamp")); - getPayloadInternal()->setStamp(stamp); - if (!attributes.getAttribute("from").empty()) { - std::string from = attributes.getAttribute("from"); - getPayloadInternal()->setFrom(JID(from)); - } - } - ++level_; + if (level_ == 0) { + boost::posix_time::ptime stamp = stringToDateTime(attributes.getAttribute("stamp")); + getPayloadInternal()->setStamp(stamp); + if (!attributes.getAttribute("from").empty()) { + std::string from = attributes.getAttribute("from"); + getPayloadInternal()->setFrom(JID(from)); + } + } + ++level_; } void DelayParser::handleEndElement(const std::string&, const std::string&) { - --level_; + --level_; } void DelayParser::handleCharacterData(const std::string&) { diff --git a/Swiften/Parser/PayloadParsers/DelayParser.h b/Swiften/Parser/PayloadParsers/DelayParser.h index 144220a..d9bf44b 100644 --- a/Swiften/Parser/PayloadParsers/DelayParser.h +++ b/Swiften/Parser/PayloadParsers/DelayParser.h @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Delay.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class DelayParser : public GenericPayloadParser<Delay> { - public: - DelayParser(); + class SWIFTEN_API DelayParser : public GenericPayloadParser<Delay> { + public: + DelayParser(); - 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); + 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: - int level_; - }; + private: + int level_; + }; } diff --git a/Swiften/Parser/PayloadParsers/DeliveryReceiptParser.cpp b/Swiften/Parser/PayloadParsers/DeliveryReceiptParser.cpp index 347200d..b6f0a86 100644 --- a/Swiften/Parser/PayloadParsers/DeliveryReceiptParser.cpp +++ b/Swiften/Parser/PayloadParsers/DeliveryReceiptParser.cpp @@ -14,18 +14,18 @@ DeliveryReceiptParser::DeliveryReceiptParser() : level_(0) { } void DeliveryReceiptParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributeMap) { - if (level_ == 0) { - if (element == "received") { - if (attributeMap.getAttributeValue("id").is_initialized()) { - getPayloadInternal()->setReceivedID(attributeMap.getAttributeValue("id").get()); - } - } - } - ++level_; + if (level_ == 0) { + if (element == "received") { + if (attributeMap.getAttributeValue("id").is_initialized()) { + getPayloadInternal()->setReceivedID(attributeMap.getAttributeValue("id").get()); + } + } + } + ++level_; } void DeliveryReceiptParser::handleEndElement(const std::string&, const std::string&) { - --level_; + --level_; } void DeliveryReceiptParser::handleCharacterData(const std::string&) { diff --git a/Swiften/Parser/PayloadParsers/DeliveryReceiptParser.h b/Swiften/Parser/PayloadParsers/DeliveryReceiptParser.h index 90a0921..5cc0009 100644 --- a/Swiften/Parser/PayloadParsers/DeliveryReceiptParser.h +++ b/Swiften/Parser/PayloadParsers/DeliveryReceiptParser.h @@ -4,21 +4,28 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/DeliveryReceipt.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class DeliveryReceiptParser : public GenericPayloadParser<DeliveryReceipt> { - public: - DeliveryReceiptParser(); + class SWIFTEN_API DeliveryReceiptParser : public GenericPayloadParser<DeliveryReceipt> { + public: + DeliveryReceiptParser(); - virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributeMap); - virtual void handleEndElement(const std::string& element, const std::string&); - virtual void handleCharacterData(const std::string& data); + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributeMap); + virtual void handleEndElement(const std::string& element, const std::string&); + virtual void handleCharacterData(const std::string& data); - private: - int level_; - }; + private: + int level_; + }; } diff --git a/Swiften/Parser/PayloadParsers/DeliveryReceiptParserFactory.h b/Swiften/Parser/PayloadParsers/DeliveryReceiptParserFactory.h index 259e04a..322ef94 100644 --- a/Swiften/Parser/PayloadParsers/DeliveryReceiptParserFactory.h +++ b/Swiften/Parser/PayloadParsers/DeliveryReceiptParserFactory.h @@ -4,26 +4,31 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/DeliveryReceiptParser.h> namespace Swift { - class PayloadParserFactoryCollection; - - class DeliveryReceiptParserFactory : public PayloadParserFactory { - public: - DeliveryReceiptParserFactory() { - } + class SWIFTEN_API DeliveryReceiptParserFactory : public PayloadParserFactory { + public: + DeliveryReceiptParserFactory() { + } - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return ns == "urn:xmpp:receipts" && element == "received"; - } + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return ns == "urn:xmpp:receipts" && element == "received"; + } - virtual PayloadParser* createPayloadParser() { - return new DeliveryReceiptParser(); - } + virtual PayloadParser* createPayloadParser() { + return new DeliveryReceiptParser(); + } - }; + }; } diff --git a/Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParser.h b/Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParser.h index 55f7997..d8a68b0 100644 --- a/Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParser.h +++ b/Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParser.h @@ -4,18 +4,25 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/DeliveryReceiptRequest.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class DeliveryReceiptRequestParser : public GenericPayloadParser<DeliveryReceiptRequest> { - public: - DeliveryReceiptRequestParser(); + class SWIFTEN_API DeliveryReceiptRequestParser : public GenericPayloadParser<DeliveryReceiptRequest> { + public: + DeliveryReceiptRequestParser(); - virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); - virtual void handleEndElement(const std::string&, const std::string&); - virtual void handleCharacterData(const std::string& data); - }; + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string&); + virtual void handleCharacterData(const std::string& data); + }; } diff --git a/Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParserFactory.h b/Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParserFactory.h index 9bd98c2..cef5d8f 100644 --- a/Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParserFactory.h +++ b/Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParserFactory.h @@ -4,26 +4,31 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParser.h> namespace Swift { - class PayloadParserFactoryCollection; - - class DeliveryReceiptRequestParserFactory : public PayloadParserFactory { - public: - DeliveryReceiptRequestParserFactory() { - } + class SWIFTEN_API DeliveryReceiptRequestParserFactory : public PayloadParserFactory { + public: + DeliveryReceiptRequestParserFactory() { + } - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return ns == "urn:xmpp:receipts" && element == "request"; - } + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return ns == "urn:xmpp:receipts" && element == "request"; + } - virtual PayloadParser* createPayloadParser() { - return new DeliveryReceiptRequestParser(); - } + virtual PayloadParser* createPayloadParser() { + return new DeliveryReceiptRequestParser(); + } - }; + }; } diff --git a/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp b/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp index aeb0db8..6ded2e2 100644 --- a/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp +++ b/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp @@ -1,59 +1,62 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/DiscoInfoParser.h> +#include <cassert> + #include <boost/optional.hpp> + #include <Swiften/Parser/PayloadParsers/FormParser.h> namespace Swift { -DiscoInfoParser::DiscoInfoParser() : level_(TopLevel), formParser_(NULL) { +DiscoInfoParser::DiscoInfoParser() : level_(TopLevel), formParser_(nullptr) { } void DiscoInfoParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level_ == TopLevel) { - if (attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributes.getAttributeValue("node")); - } - } - else if (level_ == PayloadLevel) { - if (element == "identity") { - getPayloadInternal()->addIdentity(DiscoInfo::Identity(attributes.getAttribute("name"), attributes.getAttribute("category"), attributes.getAttribute("type"), attributes.getAttribute("lang", "http://www.w3.org/XML/1998/namespace"))); - } - else if (element == "feature") { - getPayloadInternal()->addFeature(attributes.getAttribute("var")); - } - else if (element == "x" && ns == "jabber:x:data") { - assert(!formParser_); - formParser_ = new FormParser(); - } - } - if (formParser_) { - formParser_->handleStartElement(element, ns, attributes); - } - ++level_; + if (level_ == TopLevel) { + if (attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributes.getAttributeValue("node")); + } + } + else if (level_ == PayloadLevel) { + if (element == "identity") { + getPayloadInternal()->addIdentity(DiscoInfo::Identity(attributes.getAttribute("name"), attributes.getAttribute("category"), attributes.getAttribute("type"), attributes.getAttribute("lang", "http://www.w3.org/XML/1998/namespace"))); + } + else if (element == "feature") { + getPayloadInternal()->addFeature(attributes.getAttribute("var")); + } + else if (element == "x" && ns == "jabber:x:data") { + assert(!formParser_); + formParser_ = new FormParser(); + } + } + if (formParser_) { + formParser_->handleStartElement(element, ns, attributes); + } + ++level_; } void DiscoInfoParser::handleEndElement(const std::string& element, const std::string& ns) { - --level_; - if (formParser_) { - formParser_->handleEndElement(element, ns); - } - if (level_ == PayloadLevel && formParser_) { - getPayloadInternal()->addExtension(formParser_->getPayloadInternal()); - delete formParser_; - formParser_ = NULL; - } + --level_; + if (formParser_) { + formParser_->handleEndElement(element, ns); + } + if (level_ == PayloadLevel && formParser_) { + getPayloadInternal()->addExtension(formParser_->getPayloadInternal()); + delete formParser_; + formParser_ = nullptr; + } } void DiscoInfoParser::handleCharacterData(const std::string& data) { - if (formParser_) { - formParser_->handleCharacterData(data); - } + if (formParser_) { + formParser_->handleCharacterData(data); + } } } diff --git a/Swiften/Parser/PayloadParsers/DiscoInfoParser.h b/Swiften/Parser/PayloadParsers/DiscoInfoParser.h index 1f93a88..9c26310 100644 --- a/Swiften/Parser/PayloadParsers/DiscoInfoParser.h +++ b/Swiften/Parser/PayloadParsers/DiscoInfoParser.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,20 +11,22 @@ #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class SWIFTEN_API DiscoInfoParser : public GenericPayloadParser<DiscoInfo> { - public: - DiscoInfoParser(); + class FormParser; - 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); + class SWIFTEN_API DiscoInfoParser : public GenericPayloadParser<DiscoInfo> { + public: + DiscoInfoParser(); - private: - enum Level { - TopLevel = 0, - PayloadLevel = 1 - }; - int level_; - FormParser* formParser_; - }; + 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 + }; + int level_; + FormParser* formParser_; + }; } diff --git a/Swiften/Parser/PayloadParsers/DiscoItemsParser.cpp b/Swiften/Parser/PayloadParsers/DiscoItemsParser.cpp index a56dc5a..a3b9245 100644 --- a/Swiften/Parser/PayloadParsers/DiscoItemsParser.cpp +++ b/Swiften/Parser/PayloadParsers/DiscoItemsParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/DiscoItemsParser.h> @@ -12,21 +12,21 @@ DiscoItemsParser::DiscoItemsParser() : level_(TopLevel) { } void DiscoItemsParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level_ == PayloadLevel) { - if (element == "item") { - getPayloadInternal()->addItem(DiscoItems::Item(attributes.getAttribute("name"), JID(attributes.getAttribute("jid")), attributes.getAttribute("node"))); - } - } - else if (level_ == TopLevel) { - if (element == "query") { - getPayloadInternal()->setNode(attributes.getAttribute("node")); - } - } - ++level_; + if (level_ == PayloadLevel) { + if (element == "item") { + getPayloadInternal()->addItem(DiscoItems::Item(attributes.getAttribute("name"), JID(attributes.getAttribute("jid")), attributes.getAttribute("node"))); + } + } + else if (level_ == TopLevel) { + if (element == "query") { + getPayloadInternal()->setNode(attributes.getAttribute("node")); + } + } + ++level_; } void DiscoItemsParser::handleEndElement(const std::string&, const std::string&) { - --level_; + --level_; } void DiscoItemsParser::handleCharacterData(const std::string&) { diff --git a/Swiften/Parser/PayloadParsers/DiscoItemsParser.h b/Swiften/Parser/PayloadParsers/DiscoItemsParser.h index ae799cb..3197b79 100644 --- a/Swiften/Parser/PayloadParsers/DiscoItemsParser.h +++ b/Swiften/Parser/PayloadParsers/DiscoItemsParser.h @@ -1,29 +1,30 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/DiscoItems.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class DiscoItemsParser : public GenericPayloadParser<DiscoItems> { - public: - DiscoItemsParser(); + class SWIFTEN_API DiscoItemsParser : public GenericPayloadParser<DiscoItems> { + public: + DiscoItemsParser(); - 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); + 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 - }; - int level_; - }; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + int level_; + }; } diff --git a/Swiften/Parser/PayloadParsers/ErrorParser.cpp b/Swiften/Parser/PayloadParsers/ErrorParser.cpp index 8a02317..222bcbd 100644 --- a/Swiften/Parser/PayloadParsers/ErrorParser.cpp +++ b/Swiften/Parser/PayloadParsers/ErrorParser.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/ErrorParser.h> -#include <Swiften/Parser/PayloadParserFactoryCollection.h> + #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> namespace Swift { @@ -14,132 +15,132 @@ ErrorParser::ErrorParser(PayloadParserFactoryCollection* factories) : factories( } void ErrorParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level_ == TopLevel) { - std::string type = attributes.getAttribute("type"); - if (type == "continue") { - getPayloadInternal()->setType(ErrorPayload::Continue); - } - else if (type == "modify") { - getPayloadInternal()->setType(ErrorPayload::Modify); - } - else if (type == "auth") { - getPayloadInternal()->setType(ErrorPayload::Auth); - } - else if (type == "wait") { - getPayloadInternal()->setType(ErrorPayload::Wait); - } - else { - getPayloadInternal()->setType(ErrorPayload::Cancel); - } - } - else if (level_ == PayloadLevel) { - if (element == "text") { + if (level_ == TopLevel) { + std::string type = attributes.getAttribute("type"); + if (type == "continue") { + getPayloadInternal()->setType(ErrorPayload::Continue); + } + else if (type == "modify") { + getPayloadInternal()->setType(ErrorPayload::Modify); + } + else if (type == "auth") { + getPayloadInternal()->setType(ErrorPayload::Auth); + } + else if (type == "wait") { + getPayloadInternal()->setType(ErrorPayload::Wait); + } + else { + getPayloadInternal()->setType(ErrorPayload::Cancel); + } + } + else if (level_ == PayloadLevel) { + if (element == "text") { - } - else if (element == "bad-request") { - getPayloadInternal()->setCondition(ErrorPayload::BadRequest); - } - else if (element == "conflict") { - getPayloadInternal()->setCondition(ErrorPayload::Conflict); - } - else if (element == "feature-not-implemented") { - getPayloadInternal()->setCondition(ErrorPayload::FeatureNotImplemented); - } - else if (element == "forbidden") { - getPayloadInternal()->setCondition(ErrorPayload::Forbidden); - } - else if (element == "gone") { - getPayloadInternal()->setCondition(ErrorPayload::Gone); - } - else if (element == "internal-server-error") { - getPayloadInternal()->setCondition(ErrorPayload::InternalServerError); - } - else if (element == "item-not-found") { - getPayloadInternal()->setCondition(ErrorPayload::ItemNotFound); - } - else if (element == "jid-malformed") { - getPayloadInternal()->setCondition(ErrorPayload::JIDMalformed); - } - else if (element == "not-acceptable") { - getPayloadInternal()->setCondition(ErrorPayload::NotAcceptable); - } - else if (element == "not-allowed") { - getPayloadInternal()->setCondition(ErrorPayload::NotAllowed); - } - else if (element == "not-authorized") { - getPayloadInternal()->setCondition(ErrorPayload::NotAuthorized); - } - else if (element == "payment-required") { - getPayloadInternal()->setCondition(ErrorPayload::PaymentRequired); - } - else if (element == "recipient-unavailable") { - getPayloadInternal()->setCondition(ErrorPayload::RecipientUnavailable); - } - else if (element == "redirect") { - getPayloadInternal()->setCondition(ErrorPayload::Redirect); - } - else if (element == "registration-required") { - getPayloadInternal()->setCondition(ErrorPayload::RegistrationRequired); - } - else if (element == "remote-server-not-found") { - getPayloadInternal()->setCondition(ErrorPayload::RemoteServerNotFound); - } - else if (element == "remote-server-timeout") { - getPayloadInternal()->setCondition(ErrorPayload::RemoteServerTimeout); - } - else if (element == "resource-constraint") { - getPayloadInternal()->setCondition(ErrorPayload::ResourceConstraint); - } - else if (element == "service-unavailable") { - getPayloadInternal()->setCondition(ErrorPayload::ServiceUnavailable); - } - else if (element == "subscription-required") { - getPayloadInternal()->setCondition(ErrorPayload::SubscriptionRequired); - } - else if (element == "unexpected-request") { - getPayloadInternal()->setCondition(ErrorPayload::UnexpectedRequest); - } - else { - PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); - if (payloadParserFactory) { - currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); - } else { - getPayloadInternal()->setCondition(ErrorPayload::UndefinedCondition); - } - } - } - if (level_ >= PayloadLevel && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level_; + } + else if (element == "bad-request") { + getPayloadInternal()->setCondition(ErrorPayload::BadRequest); + } + else if (element == "conflict") { + getPayloadInternal()->setCondition(ErrorPayload::Conflict); + } + else if (element == "feature-not-implemented") { + getPayloadInternal()->setCondition(ErrorPayload::FeatureNotImplemented); + } + else if (element == "forbidden") { + getPayloadInternal()->setCondition(ErrorPayload::Forbidden); + } + else if (element == "gone") { + getPayloadInternal()->setCondition(ErrorPayload::Gone); + } + else if (element == "internal-server-error") { + getPayloadInternal()->setCondition(ErrorPayload::InternalServerError); + } + else if (element == "item-not-found") { + getPayloadInternal()->setCondition(ErrorPayload::ItemNotFound); + } + else if (element == "jid-malformed") { + getPayloadInternal()->setCondition(ErrorPayload::JIDMalformed); + } + else if (element == "not-acceptable") { + getPayloadInternal()->setCondition(ErrorPayload::NotAcceptable); + } + else if (element == "not-allowed") { + getPayloadInternal()->setCondition(ErrorPayload::NotAllowed); + } + else if (element == "not-authorized") { + getPayloadInternal()->setCondition(ErrorPayload::NotAuthorized); + } + else if (element == "payment-required") { + getPayloadInternal()->setCondition(ErrorPayload::PaymentRequired); + } + else if (element == "recipient-unavailable") { + getPayloadInternal()->setCondition(ErrorPayload::RecipientUnavailable); + } + else if (element == "redirect") { + getPayloadInternal()->setCondition(ErrorPayload::Redirect); + } + else if (element == "registration-required") { + getPayloadInternal()->setCondition(ErrorPayload::RegistrationRequired); + } + else if (element == "remote-server-not-found") { + getPayloadInternal()->setCondition(ErrorPayload::RemoteServerNotFound); + } + else if (element == "remote-server-timeout") { + getPayloadInternal()->setCondition(ErrorPayload::RemoteServerTimeout); + } + else if (element == "resource-constraint") { + getPayloadInternal()->setCondition(ErrorPayload::ResourceConstraint); + } + else if (element == "service-unavailable") { + getPayloadInternal()->setCondition(ErrorPayload::ServiceUnavailable); + } + else if (element == "subscription-required") { + getPayloadInternal()->setCondition(ErrorPayload::SubscriptionRequired); + } + else if (element == "unexpected-request") { + getPayloadInternal()->setCondition(ErrorPayload::UnexpectedRequest); + } + else { + PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); + if (payloadParserFactory) { + currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); + } else { + getPayloadInternal()->setCondition(ErrorPayload::UndefinedCondition); + } + } + } + if (level_ >= PayloadLevel && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level_; } void ErrorParser::handleEndElement(const std::string& element, const std::string& ns) { - --level_; - if (currentPayloadParser) { - if (level_ >= PayloadLevel) { - currentPayloadParser->handleEndElement(element, ns); - } + --level_; + if (currentPayloadParser) { + if (level_ >= PayloadLevel) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level_ == PayloadLevel) { - getPayloadInternal()->setPayload(currentPayloadParser->getPayload()); - currentPayloadParser.reset(); - } - } - else if (level_ == PayloadLevel) { - if (element == "text") { - getPayloadInternal()->setText(currentText_); - } - } + if (level_ == PayloadLevel) { + getPayloadInternal()->setPayload(currentPayloadParser->getPayload()); + currentPayloadParser.reset(); + } + } + else if (level_ == PayloadLevel) { + if (element == "text") { + getPayloadInternal()->setText(currentText_); + } + } } void ErrorParser::handleCharacterData(const std::string& data) { - if (level_ > PayloadLevel && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } - else { - currentText_ += data; - } + if (level_ > PayloadLevel && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } + else { + currentText_ += data; + } } } diff --git a/Swiften/Parser/PayloadParsers/ErrorParser.h b/Swiften/Parser/PayloadParsers/ErrorParser.h index b2d05cf..10f5431 100644 --- a/Swiften/Parser/PayloadParsers/ErrorParser.h +++ b/Swiften/Parser/PayloadParsers/ErrorParser.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/ErrorPayload.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class ErrorParser : public GenericPayloadParser<ErrorPayload> { - public: - ErrorParser(PayloadParserFactoryCollection* factories); + class PayloadParserFactoryCollection; + class SWIFTEN_API ErrorParser : public GenericPayloadParser<ErrorPayload> { + public: + ErrorParser(PayloadParserFactoryCollection* factories); - 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); + 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 - }; - PayloadParserFactoryCollection* factories; - int level_; - std::string currentText_; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + PayloadParserFactoryCollection* factories; + int level_; + std::string currentText_; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/ErrorParserFactory.h b/Swiften/Parser/PayloadParsers/ErrorParserFactory.h index 1463807..d8f09bf 100644 --- a/Swiften/Parser/PayloadParsers/ErrorParserFactory.h +++ b/Swiften/Parser/PayloadParsers/ErrorParserFactory.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/ErrorParser.h> namespace Swift { - class PayloadParserFactoryCollection; + class PayloadParserFactoryCollection; - class ErrorParserFactory : public PayloadParserFactory { - public: - ErrorParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { - } + class SWIFTEN_API ErrorParserFactory : public PayloadParserFactory { + public: + ErrorParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { + } - virtual bool canParse(const std::string& element, const std::string& /*ns*/, const AttributeMap&) const { - return element == "error"; - } + virtual bool canParse(const std::string& element, const std::string& /*ns*/, const AttributeMap&) const { + return element == "error"; + } - virtual PayloadParser* createPayloadParser() { - return new ErrorParser(factories); - } + virtual PayloadParser* createPayloadParser() { + return new ErrorParser(factories); + } - private: - PayloadParserFactoryCollection* factories; + private: + PayloadParserFactoryCollection* factories; - }; + }; } diff --git a/Swiften/Parser/PayloadParsers/FormParser.cpp b/Swiften/Parser/PayloadParsers/FormParser.cpp index 7c29189..dff45df 100644 --- a/Swiften/Parser/PayloadParsers/FormParser.cpp +++ b/Swiften/Parser/PayloadParsers/FormParser.cpp @@ -1,170 +1,252 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ - #include <Swiften/Parser/PayloadParsers/FormParser.h> -#include <Swiften/Base/foreach.h> +#include <map> namespace Swift { -FormParser::FormParser() : level_(TopLevel), parsingItem_(false), parsingReported_(false), parsingOption_(false) { +FormParser::FormParser() : level_(TopLevel), parsingItem_(false), parsingReported_(false), parsingOption_(false), hasReportedRef_(false){ } void FormParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level_ == TopLevel) { - std::string type = attributes.getAttribute("type"); - if (type == "form") { - getPayloadInternal()->setType(Form::FormType); - } - else if (type == "submit") { - getPayloadInternal()->setType(Form::SubmitType); - } - else if (type == "cancel") { - getPayloadInternal()->setType(Form::CancelType); - } - else if (type == "result") { - getPayloadInternal()->setType(Form::ResultType); - } - } - else if (level_ == PayloadLevel) { - if (element == "title") { - currentText_.clear(); - } - else if (element == "instructions") { - currentText_.clear(); - } - else if (element == "reported") { - parsingReported_ = true; - } - else if (element == "item") { - parsingItem_ = true; - } - } - else if (level_ == FieldLevel && currentField_) { - currentText_.clear(); - if (element == "option") { - currentOptionLabel_ = attributes.getAttribute("label"); - currentOptionValue_ = ""; - parsingOption_ = true; - } - } - if (level_ >= PayloadLevel) { - if (element == "field") { - currentField_ = boost::make_shared<FormField>(); - std::string type = attributes.getAttribute("type"); - FormField::Type fieldType = FormField::UnknownType; - if (type == "boolean") { - fieldType = FormField::BooleanType; - } - if (type == "fixed") { - fieldType = FormField::FixedType; - } - if (type == "hidden") { - fieldType = FormField::HiddenType; - } - if (type == "list-single") { - fieldType = FormField::ListSingleType; - } - if (type == "text-multi") { - fieldType = FormField::TextMultiType; - } - if (type == "text-private") { - fieldType = FormField::TextPrivateType; - } - if (type == "text-single") { - fieldType = FormField::TextSingleType; - } - if (type == "jid-single") { - fieldType = FormField::JIDSingleType; - } - if (type == "jid-multi") { - fieldType = FormField::JIDMultiType; - } - if (type == "list-multi") { - fieldType = FormField::ListMultiType; - } - currentField_->setType(fieldType); - currentField_->setName(attributes.getAttribute("var")); - currentField_->setLabel(attributes.getAttribute("label")); - } - else if (element == "value") { - currentText_.clear(); - } - } - ++level_; + if (level_ == TopLevel) { + std::string type = attributes.getAttribute("type"); + if (type == "form") { + getPayloadInternal()->setType(Form::FormType); + } + else if (type == "submit") { + getPayloadInternal()->setType(Form::SubmitType); + } + else if (type == "cancel") { + getPayloadInternal()->setType(Form::CancelType); + } + else if (type == "result") { + getPayloadInternal()->setType(Form::ResultType); + } + } + else if (level_ == PayloadLevel) { + if (element == "title") { + currentText_.clear(); + } + else if (element == "instructions") { + currentText_.clear(); + } + else if (element == "reported") { + parsingReported_ = true; + } + else if (element == "item") { + parsingItem_ = true; + } + else if (element == "page") { + currentPage_ = std::make_shared<FormPage>(); + currentPage_->setLabel(attributes.getAttribute("label")); + } + } + else if (level_ == FieldLevel && currentField_) { + currentText_.clear(); + if (element == "option") { + currentOptionLabel_ = attributes.getAttribute("label"); + currentOptionValue_ = ""; + parsingOption_ = true; + } + } + if (level_ >= PayloadLevel) { + if (element == "field") { + currentField_ = std::make_shared<FormField>(); + std::string type = attributes.getAttribute("type"); + FormField::Type fieldType = FormField::UnknownType; + if (type == "boolean") { + fieldType = FormField::BooleanType; + } + if (type == "fixed") { + fieldType = FormField::FixedType; + } + if (type == "hidden") { + fieldType = FormField::HiddenType; + } + if (type == "list-single") { + fieldType = FormField::ListSingleType; + } + if (type == "text-multi") { + fieldType = FormField::TextMultiType; + } + if (type == "text-private") { + fieldType = FormField::TextPrivateType; + } + if (type == "text-single") { + fieldType = FormField::TextSingleType; + } + if (type == "jid-single") { + fieldType = FormField::JIDSingleType; + } + if (type == "jid-multi") { + fieldType = FormField::JIDMultiType; + } + if (type == "list-multi") { + fieldType = FormField::ListMultiType; + } + currentField_->setType(fieldType); + currentField_->setName(attributes.getAttribute("var")); + currentField_->setLabel(attributes.getAttribute("label")); + } + else if (element == "value") { + currentText_.clear(); + } + } + if (level_ > PayloadLevel) { + if (element == "section") { + currentSection_ = std::make_shared<FormSection>(); + currentSection_->setLabel(attributes.getAttribute("label")); + sectionStack_.push_back(currentSection_); + currentSections_.push_back(currentSection_); + } + if (element == "reportedref") { + currentReportedRef_ = std::make_shared<FormReportedRef>(); + } + if (element == "fieldref") { + currentText_.clear(); + currentFieldRef_ = attributes.getAttribute("var"); + if (sectionStack_.size() > 0) { + sectionStack_.at(sectionStack_.size()-1)->addFieldRef(currentFieldRef_); + } else if (currentPage_) { + currentPage_->addFieldRef(currentFieldRef_); + } + } + if (element == "text") { + currentText_.clear(); + currentTextElement_ = std::make_shared<FormText>(); + } + } + ++level_; } void FormParser::handleEndElement(const std::string& element, const std::string&) { - --level_; - if (level_ == PayloadLevel) { - if (element == "title") { - std::string currentTitle = getPayloadInternal()->getTitle(); - if (currentTitle.empty()) { - getPayloadInternal()->setTitle(currentText_); - } - else { - getPayloadInternal()->setTitle(currentTitle + "\n" + currentText_); - } - } - else if (element == "instructions") { - std::string currentInstructions = getPayloadInternal()->getInstructions(); - if (currentInstructions.empty()) { - getPayloadInternal()->setInstructions(currentText_); - } - else { - getPayloadInternal()->setInstructions(currentInstructions + "\n" + currentText_); - } - } - else if (element == "reported") { - parsingReported_ = false; - } - else if (element == "item") { - parsingItem_ = false; - getPayloadInternal()->addItem(currentFields_); - currentFields_.clear(); - } - } - else if (currentField_) { - if (element == "required") { - currentField_->setRequired(true); - } - else if (element == "desc") { - currentField_->setDescription(currentText_); - } - else if (element == "option") { - currentField_->addOption(FormField::Option(currentOptionLabel_, currentOptionValue_)); - parsingOption_ = false; - } - else if (element == "value") { - if (parsingOption_) { - currentOptionValue_ = currentText_; - } - else { - currentField_->addValue(currentText_); - } - } - } - if (level_ >= PayloadLevel && currentField_) { - if (element == "field") { - if (parsingReported_) { - getPayloadInternal()->addReportedField(currentField_); - } - else if (parsingItem_) { - currentFields_.push_back(currentField_); - } - else { - getPayloadInternal()->addField(currentField_); - } - currentField_.reset(); - } - } + --level_; + if (level_ == PayloadLevel) { + if (element == "title") { + std::string currentTitle = getPayloadInternal()->getTitle(); + if (currentTitle.empty()) { + getPayloadInternal()->setTitle(currentText_); + } + else { + getPayloadInternal()->setTitle(currentTitle + "\n" + currentText_); + } + } + else if (element == "instructions") { + std::string currentInstructions = getPayloadInternal()->getInstructions(); + if (currentInstructions.empty()) { + getPayloadInternal()->setInstructions(currentText_); + } + else { + getPayloadInternal()->setInstructions(currentInstructions + "\n" + currentText_); + } + } + else if (element == "reported") { + parsingReported_ = false; + } + else if (element == "item") { + parsingItem_ = false; + getPayloadInternal()->addItem(currentFields_); + currentFields_.clear(); + } + else if (element == "page") { + getPayloadInternal()->addPage(currentPage_); + currentPages_.push_back(currentPage_); + } + } + else if (currentField_) { + if (element == "required") { + currentField_->setRequired(true); + } + else if (element == "desc") { + currentField_->setDescription(currentText_); + } + else if (element == "option") { + currentField_->addOption(FormField::Option(currentOptionLabel_, currentOptionValue_)); + parsingOption_ = false; + } + else if (element == "value") { + if (parsingOption_) { + currentOptionValue_ = currentText_; + } + else { + currentField_->addValue(currentText_); + } + } + } + if (level_ >= PayloadLevel && currentField_) { + if (element == "field") { + if (parsingReported_) { + getPayloadInternal()->addReportedField(currentField_); + } + else if (parsingItem_) { + currentFields_.push_back(currentField_); + } + else { + if (currentPages_.size() > 0) { + for (const auto& page : currentPages_) { + for (const auto& pageRef : page->getFieldRefs()) { + if (pageRef == currentField_->getName()) { + page->addField(currentField_); + } + } + } + for (const auto& section : currentSections_) { + for (const auto& sectionRef : section->getFieldRefs()) { + if (sectionRef == currentField_->getName()) { + section->addField(currentField_); + } + } + } + } else { + getPayloadInternal()->addField(currentField_); + } + } + currentField_.reset(); + } + } + if (level_ > PayloadLevel) { + if (element == "section") { + if (sectionStack_.size() > 1) { + // Add the section at the top of the stack to the level below + sectionStack_.at(sectionStack_.size()-2)->addChildSection(sectionStack_.at(sectionStack_.size()-1)); + sectionStack_.pop_back(); + } + else if (sectionStack_.size() == 1) { + // Add the remaining section on the stack to its parent page + currentPage_->addChildSection(sectionStack_.at(sectionStack_.size()-1)); + sectionStack_.pop_back(); + } + } + if (currentReportedRef_ && !hasReportedRef_) { + if (sectionStack_.size() > 0) { + sectionStack_.at(sectionStack_.size()-1)->addReportedRef(currentReportedRef_); + } else if (currentPage_) { + currentPage_->addReportedRef(currentReportedRef_); + } + hasReportedRef_ = true; + currentReportedRef_.reset(); + } + if (currentTextElement_) { + if (element == "text") { + currentTextElement_->setTextString(currentText_); + } + if (sectionStack_.size() > 0) { + sectionStack_.at(sectionStack_.size()-1)->addTextElement(currentTextElement_); + } else if (currentPage_) { + currentPage_->addTextElement(currentTextElement_); + } + currentTextElement_.reset(); + } + } } void FormParser::handleCharacterData(const std::string& text) { - currentText_ += text; + currentText_ += text; } } diff --git a/Swiften/Parser/PayloadParsers/FormParser.h b/Swiften/Parser/PayloadParsers/FormParser.h index 0b23a81..e1491b1 100644 --- a/Swiften/Parser/PayloadParsers/FormParser.h +++ b/Swiften/Parser/PayloadParsers/FormParser.h @@ -1,36 +1,46 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Form.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class FormParser : public GenericPayloadParser<Form> { - public: - FormParser(); + class SWIFTEN_API FormParser : public GenericPayloadParser<Form> { + public: + FormParser(); - 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); + 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); - enum Level { - TopLevel = 0, - PayloadLevel = 1, - FieldLevel = 2 - }; - int level_; - std::string currentText_; - std::string currentOptionLabel_; - std::string currentOptionValue_; - bool parsingItem_; - bool parsingReported_; - bool parsingOption_; - FormField::ref currentField_; - std::vector<FormField::ref> currentFields_; - }; + enum Level { + TopLevel = 0, + PayloadLevel = 1, + FieldLevel = 2 + }; + int level_; + std::string currentText_; + std::string currentOptionLabel_; + std::string currentOptionValue_; + std::string currentFieldRef_; + bool parsingItem_; + bool parsingReported_; + bool parsingOption_; + bool hasReportedRef_; + FormField::ref currentField_; + std::vector<FormField::ref> currentFields_; + FormText::text currentTextElement_; + FormReportedRef::ref currentReportedRef_; + FormPage::page currentPage_; + FormSection::section currentSection_; + std::vector<std::shared_ptr<FormPage> > currentPages_; + std::vector<std::shared_ptr<FormSection> > sectionStack_; + std::vector<std::shared_ptr<FormSection> > currentSections_; + }; } diff --git a/Swiften/Parser/PayloadParsers/FormParserFactory.h b/Swiften/Parser/PayloadParsers/FormParserFactory.h index 9e1794a..296fcd1 100644 --- a/Swiften/Parser/PayloadParsers/FormParserFactory.h +++ b/Swiften/Parser/PayloadParsers/FormParserFactory.h @@ -1,29 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParser.h> namespace Swift { - class PayloadParserFactoryCollection; + class SWIFTEN_API FormParserFactory : public PayloadParserFactory { + public: + FormParserFactory() { + } - class FormParserFactory : public PayloadParserFactory { - public: - FormParserFactory() { - } + virtual bool canParse(const std::string& /*element*/, const std::string& ns, const AttributeMap&) const { + return ns == "jabber:x:data"; + } - virtual bool canParse(const std::string& /*element*/, const std::string& ns, const AttributeMap&) const { - return ns == "jabber:x:data"; - } + virtual PayloadParser* createPayloadParser() { + return new FormParser(); + } - virtual PayloadParser* createPayloadParser() { - return new FormParser(); - } - - }; + }; } diff --git a/Swiften/Parser/PayloadParsers/ForwardedParser.cpp b/Swiften/Parser/PayloadParsers/ForwardedParser.cpp new file mode 100644 index 0000000..72a665a --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ForwardedParser.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/ForwardedParser.h> + +#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/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_ = std::dynamic_pointer_cast<StanzaParser>(std::make_shared<IQParser>(factories_)); + } else if (element == "message" && ns == "jabber:client") { + childParser_ = std::dynamic_pointer_cast<StanzaParser>(std::make_shared<MessageParser>(factories_)); + } else if (element == "presence" && ns == "jabber:client") { + childParser_ = std::dynamic_pointer_cast<StanzaParser>(std::make_shared<PresenceParser>(factories_)); + } else if (element == "delay" && ns == "urn:xmpp:delay") { /* nested delay payload */ + delayParser_ = std::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(std::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..c9f13df --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ForwardedParser.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#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) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + + private: + PayloadParserFactoryCollection* factories_; + std::shared_ptr<StanzaParser> childParser_; + std::shared_ptr<DelayParser> delayParser_; + int level_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index 3ec5a7a..9e56b63 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -1,161 +1,208 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h> -#include <Swiften/Base/foreach.h> + +#include <Swiften/Elements/BlockListPayload.h> #include <Swiften/Elements/BlockPayload.h> #include <Swiften/Elements/UnblockPayload.h> -#include <Swiften/Elements/BlockListPayload.h> #include <Swiften/Parser/GenericPayloadParser.h> #include <Swiften/Parser/GenericPayloadParserFactory.h> #include <Swiften/Parser/GenericPayloadParserFactory2.h> #include <Swiften/Parser/PayloadParserFactory.h> -#include <Swiften/Parser/PayloadParsers/ErrorParser.h> -#include <Swiften/Parser/PayloadParsers/ErrorParserFactory.h> -#include <Swiften/Parser/PayloadParsers/BodyParser.h> #include <Swiften/Parser/PayloadParsers/BlockParser.h> -#include <Swiften/Parser/PayloadParsers/SubjectParser.h> +#include <Swiften/Parser/PayloadParsers/BodyParser.h> +#include <Swiften/Parser/PayloadParsers/BytestreamsParser.h> +#include <Swiften/Parser/PayloadParsers/CapsInfoParser.h> +#include <Swiften/Parser/PayloadParsers/CarbonsDisableParser.h> +#include <Swiften/Parser/PayloadParsers/CarbonsEnableParser.h> +#include <Swiften/Parser/PayloadParsers/CarbonsPrivateParser.h> +#include <Swiften/Parser/PayloadParsers/CarbonsReceivedParser.h> +#include <Swiften/Parser/PayloadParsers/CarbonsSentParser.h> #include <Swiften/Parser/PayloadParsers/ChatStateParserFactory.h> -#include <Swiften/Parser/PayloadParsers/PriorityParser.h> -#include <Swiften/Parser/PayloadParsers/ResourceBindParser.h> -#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> +#include <Swiften/Parser/PayloadParsers/ClientStateParserFactory.h> +#include <Swiften/Parser/PayloadParsers/CommandParser.h> +#include <Swiften/Parser/PayloadParsers/DelayParser.h> +#include <Swiften/Parser/PayloadParsers/DeliveryReceiptParserFactory.h> +#include <Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParserFactory.h> #include <Swiften/Parser/PayloadParsers/DiscoInfoParser.h> #include <Swiften/Parser/PayloadParsers/DiscoItemsParser.h> -#include <Swiften/Parser/PayloadParsers/CapsInfoParser.h> -#include <Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h> -#include <Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h> +#include <Swiften/Parser/PayloadParsers/ErrorParser.h> +#include <Swiften/Parser/PayloadParsers/ErrorParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParserFactory.h> -#include <Swiften/Parser/PayloadParsers/CommandParser.h> -#include <Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h> -#include <Swiften/Parser/PayloadParsers/SearchPayloadParser.h> -#include <Swiften/Parser/PayloadParsers/StreamInitiationParser.h> -#include <Swiften/Parser/PayloadParsers/BytestreamsParser.h> +#include <Swiften/Parser/PayloadParsers/ForwardedParser.h> #include <Swiften/Parser/PayloadParsers/IBBParser.h> -#include <Swiften/Parser/PayloadParsers/VCardUpdateParser.h> -#include <Swiften/Parser/PayloadParsers/VCardParser.h> -#include <Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h> -#include <Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h> -#include <Swiften/Parser/PayloadParsers/DelayParser.h> -#include <Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/IdleParser.h> +#include <Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h> +#include <Swiften/Parser/PayloadParsers/IsodeIQDelegationParser.h> +#include <Swiften/Parser/PayloadParsers/JingleContentPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h> +#include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h> +#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h> +#include <Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h> +#include <Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h> +#include <Swiften/Parser/PayloadParsers/JingleParserFactory.h> +#include <Swiften/Parser/PayloadParsers/JingleReasonParser.h> +#include <Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.h> +#include <Swiften/Parser/PayloadParsers/LastParser.h> +#include <Swiften/Parser/PayloadParsers/MAMFinParser.h> +#include <Swiften/Parser/PayloadParsers/MAMQueryParser.h> +#include <Swiften/Parser/PayloadParsers/MAMResultParser.h> +#include <Swiften/Parser/PayloadParsers/MIXParticipantParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MIXCreateParser.h> +#include <Swiften/Parser/PayloadParsers/MIXRegisterNickParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MIXSetNickParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MIXDestroyParser.h> +#include <Swiften/Parser/PayloadParsers/MIXUpdateSubscriptionParser.h> +#include <Swiften/Parser/PayloadParsers/MIXJoinParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MIXPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MIXUserPreferenceParser.h> +#include <Swiften/Parser/PayloadParsers/MIXLeaveParser.h> #include <Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h> -#include <Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.h> #include <Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.h> #include <Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.h> +#include <Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.h> #include <Swiften/Parser/PayloadParsers/MUCOwnerPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/NicknameParser.h> +#include <Swiften/Parser/PayloadParsers/PriorityParser.h> +#include <Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h> +#include <Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h> +#include <Swiften/Parser/PayloadParsers/PubSubEventParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubParser.h> +#include <Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/ReferencePayloadParser.h> #include <Swiften/Parser/PayloadParsers/ReplaceParser.h> -#include <Swiften/Parser/PayloadParsers/LastParser.h> -#include <Swiften/Parser/PayloadParsers/JingleParserFactory.h> -#include <Swiften/Parser/PayloadParsers/JingleReasonParser.h> -#include <Swiften/Parser/PayloadParsers/JingleContentPayloadParserFactory.h> -#include <Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h> -#include <Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.h> -#include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h> -#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h> -#include <Swiften/Parser/PayloadParsers/JingleFileTransferReceivedParser.h> -#include <Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h> +#include <Swiften/Parser/PayloadParsers/ResourceBindParser.h> +#include <Swiften/Parser/PayloadParsers/ResultSetParser.h> +#include <Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h> +#include <Swiften/Parser/PayloadParsers/RosterParser.h> #include <Swiften/Parser/PayloadParsers/S5BProxyRequestParser.h> -#include <Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h> -#include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h> -#include <Swiften/Parser/PayloadParsers/DeliveryReceiptParserFactory.h> -#include <Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParserFactory.h> -#include <Swiften/Parser/PayloadParsers/WhiteboardParser.h> -#include <Swiften/Parser/PayloadParsers/IdleParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubEventParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h> +#include <Swiften/Parser/PayloadParsers/SearchPayloadParser.h> +#include <Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h> +#include <Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h> +#include <Swiften/Parser/PayloadParsers/SoftwareVersionParser.h> +#include <Swiften/Parser/PayloadParsers/StartSessionParser.h> +#include <Swiften/Parser/PayloadParsers/StatusParser.h> +#include <Swiften/Parser/PayloadParsers/StatusShowParser.h> +#include <Swiften/Parser/PayloadParsers/StorageParser.h> +#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h> +#include <Swiften/Parser/PayloadParsers/StreamInitiationParser.h> +#include <Swiften/Parser/PayloadParsers/SubjectParser.h> +#include <Swiften/Parser/PayloadParsers/ThreadParser.h> #include <Swiften/Parser/PayloadParsers/UserLocationParser.h> - -using namespace boost; +#include <Swiften/Parser/PayloadParsers/UserTuneParser.h> +#include <Swiften/Parser/PayloadParsers/VCardParser.h> +#include <Swiften/Parser/PayloadParsers/VCardUpdateParser.h> +#include <Swiften/Parser/PayloadParsers/WhiteboardParser.h> namespace Swift { FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() { - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<IBBParser> >("", "http://jabber.org/protocol/ibb")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<StatusShowParser> >("show")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<StatusParser> >("status")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<ReplaceParser> >("replace", "http://swift.im/protocol/replace")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<ReplaceParser> >("replace", "urn:xmpp:message-correct:0")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<LastParser> >("query", "jabber:iq:last")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<BodyParser> >("body")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<SubjectParser> >("subject")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<PriorityParser> >("priority")); - factories_.push_back(boost::make_shared<ErrorParserFactory>(this)); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<DelayParser> >("delay", "urn:xmpp:delay")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<SoftwareVersionParser> >("query", "jabber:iq:version")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<StorageParser> >("storage", "storage:bookmarks")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<RosterItemExchangeParser> >("x", "http://jabber.org/protocol/rosterx")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<RosterParser> >("query", "jabber:iq:roster")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<DiscoInfoParser> >("query", "http://jabber.org/protocol/disco#info")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<DiscoItemsParser> >("query", "http://jabber.org/protocol/disco#items")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<CapsInfoParser> >("c", "http://jabber.org/protocol/caps")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<ResourceBindParser> >("bind", "urn:ietf:params:xml:ns:xmpp-bind")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<StartSessionParser> >("session", "urn:ietf:params:xml:ns:xmpp-session")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<BlockParser<BlockPayload> > >("block", "urn:xmpp:blocking")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<BlockParser<BlockListPayload> > >("blocklist", "urn:xmpp:blocking")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<BlockParser<UnblockPayload> > >("unblock", "urn:xmpp:blocking")); - factories_.push_back(boost::make_shared<SecurityLabelParserFactory>()); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<SecurityLabelsCatalogParser> >("catalog", "urn:xmpp:sec-label:catalog:2")); - factories_.push_back(boost::make_shared<FormParserFactory>()); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<CommandParser> >("command", "http://jabber.org/protocol/commands")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<InBandRegistrationPayloadParser> >("query", "jabber:iq:register")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<SearchPayloadParser> >("query", "jabber:iq:search")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<StreamInitiationParser> >("si", "http://jabber.org/protocol/si")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<BytestreamsParser> >("query", "http://jabber.org/protocol/bytestreams")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<VCardUpdateParser> >("x", "vcard-temp:x:update")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<VCardParser> >("vCard", "vcard-temp")); - factories_.push_back(boost::make_shared<PrivateStorageParserFactory>(this)); - factories_.push_back(boost::make_shared<ChatStateParserFactory>()); - factories_.push_back(boost::make_shared<MUCUserPayloadParserFactory>(this)); - factories_.push_back(boost::make_shared<MUCOwnerPayloadParserFactory>(this)); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<MUCInvitationPayloadParser> >("x", "jabber:x:conference")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<MUCAdminPayloadParser> >("query", "http://jabber.org/protocol/muc#admin")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<MUCDestroyPayloadParser> >("destroy", "http://jabber.org/protocol/muc#user")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<MUCDestroyPayloadParser> >("destroy", "http://jabber.org/protocol/muc#owner")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<NicknameParser> >("nick", "http://jabber.org/protocol/nick")); - factories_.push_back(boost::make_shared<JingleParserFactory>(this)); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleReasonParser> >("reason", "urn:xmpp:jingle:1")); - factories_.push_back(boost::make_shared<JingleContentPayloadParserFactory>(this)); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleIBBTransportMethodPayloadParser> >("transport", "urn:xmpp:jingle:transports:ibb:1")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleS5BTransportMethodPayloadParser> >("transport", "urn:xmpp:jingle:transports:s5b:1")); - factories_.push_back(boost::make_shared<JingleFileTransferDescriptionParserFactory>(this)); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<StreamInitiationFileInfoParser> >("file", "http://jabber.org/protocol/si/profile/file-transfer")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleFileTransferReceivedParser> >("received", "urn:xmpp:jingle:apps:file-transfer:3")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleFileTransferHashParser> >("checksum")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<S5BProxyRequestParser> >("query", "http://jabber.org/protocol/bytestreams")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<WhiteboardParser> >("wb", "http://swift.im/whiteboard")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<UserLocationParser> >("geoloc", "http://jabber.org/protocol/geoloc")); - factories_.push_back(boost::make_shared<DeliveryReceiptParserFactory>()); - factories_.push_back(boost::make_shared<DeliveryReceiptRequestParserFactory>()); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory<IdleParser> >("idle", "urn:xmpp:idle:1")); - factories_.push_back(boost::make_shared<GenericPayloadParserFactory2<PubSubParser> >("pubsub", "http://jabber.org/protocol/pubsub", this)); - 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(std::make_shared<GenericPayloadParserFactory<IBBParser> >("", "http://jabber.org/protocol/ibb")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<StatusShowParser> >("show")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<StatusParser> >("status")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<ReplaceParser> >("replace", "http://swift.im/protocol/replace")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<ReplaceParser> >("replace", "urn:xmpp:message-correct:0")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<LastParser> >("query", "jabber:iq:last")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<BodyParser> >("body")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<SubjectParser> >("subject")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<ThreadParser> >("thread")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<PriorityParser> >("priority")); + factories_.push_back(std::make_shared<ErrorParserFactory>(this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<DelayParser> >("delay", "urn:xmpp:delay")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<SoftwareVersionParser> >("query", "jabber:iq:version")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<StorageParser> >("storage", "storage:bookmarks")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<RosterItemExchangeParser> >("x", "http://jabber.org/protocol/rosterx")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<RosterParser> >("query", "jabber:iq:roster")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<DiscoInfoParser> >("query", "http://jabber.org/protocol/disco#info")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<DiscoItemsParser> >("query", "http://jabber.org/protocol/disco#items")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<CapsInfoParser> >("c", "http://jabber.org/protocol/caps")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<ResourceBindParser> >("bind", "urn:ietf:params:xml:ns:xmpp-bind")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<StartSessionParser> >("session", "urn:ietf:params:xml:ns:xmpp-session")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<BlockParser<BlockPayload> > >("block", "urn:xmpp:blocking")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<BlockParser<BlockListPayload> > >("blocklist", "urn:xmpp:blocking")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<BlockParser<UnblockPayload> > >("unblock", "urn:xmpp:blocking")); + factories_.push_back(std::make_shared<SecurityLabelParserFactory>()); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<SecurityLabelsCatalogParser> >("catalog", "urn:xmpp:sec-label:catalog:2")); + factories_.push_back(std::make_shared<FormParserFactory>()); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<CommandParser> >("command", "http://jabber.org/protocol/commands")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<InBandRegistrationPayloadParser> >("query", "jabber:iq:register")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<SearchPayloadParser> >("query", "jabber:iq:search")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<StreamInitiationParser> >("si", "http://jabber.org/protocol/si")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<BytestreamsParser> >("query", "http://jabber.org/protocol/bytestreams")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<VCardUpdateParser> >("x", "vcard-temp:x:update")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<VCardParser> >("vCard", "vcard-temp")); + factories_.push_back(std::make_shared<PrivateStorageParserFactory>(this)); + factories_.push_back(std::make_shared<ChatStateParserFactory>()); + factories_.push_back(std::make_shared<ClientStateParserFactory>()); + factories_.push_back(std::make_shared<MIXParticipantParserFactory>()); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MIXDestroyParser> >("destroy", "urn:xmpp:mix:0")); + factories_.push_back(std::make_shared<MIXRegisterNickParserFactory>()); + factories_.push_back(std::make_shared<MIXSetNickParserFactory>()); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MIXCreateParser> >("create", "urn:xmpp:mix:0")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MIXUpdateSubscriptionParser> >("update-subscription", "urn:xmpp:mix:0")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MIXUserPreferenceParser> >("user-preference", "urn:xmpp:mix:0")); + factories_.push_back(std::make_shared<MIXPayloadParserFactory>()); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MIXLeaveParser> >("leave", "urn:xmpp:mix:0")); + factories_.push_back(std::make_shared<MUCUserPayloadParserFactory>(this)); + factories_.push_back(std::make_shared<MUCOwnerPayloadParserFactory>(this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MUCInvitationPayloadParser> >("x", "jabber:x:conference")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MUCAdminPayloadParser> >("query", "http://jabber.org/protocol/muc#admin")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MUCDestroyPayloadParser> >("destroy", "http://jabber.org/protocol/muc#user")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MUCDestroyPayloadParser> >("destroy", "http://jabber.org/protocol/muc#owner")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<NicknameParser> >("nick", "http://jabber.org/protocol/nick")); + factories_.push_back(std::make_shared<JingleParserFactory>(this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<JingleReasonParser> >("reason", "urn:xmpp:jingle:1")); + factories_.push_back(std::make_shared<JingleContentPayloadParserFactory>(this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<JingleIBBTransportMethodPayloadParser> >("transport", "urn:xmpp:jingle:transports:ibb:1")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<JingleS5BTransportMethodPayloadParser> >("transport", "urn:xmpp:jingle:transports:s5b:1")); + factories_.push_back(std::make_shared<JingleFileTransferDescriptionParserFactory>(this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<StreamInitiationFileInfoParser> >("file", "http://jabber.org/protocol/si/profile/file-transfer")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<JingleFileTransferFileInfoParser> >("file", "urn:xmpp:jingle:apps:file-transfer:4")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<JingleFileTransferHashParser> >("checksum")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<S5BProxyRequestParser> >("query", "http://jabber.org/protocol/bytestreams")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<WhiteboardParser> >("wb", "http://swift.im/whiteboard")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<UserLocationParser> >("geoloc", "http://jabber.org/protocol/geoloc")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<UserTuneParser> >("tune", "http://jabber.org/protocol/tune")); + factories_.push_back(std::make_shared<DeliveryReceiptParserFactory>()); + factories_.push_back(std::make_shared<DeliveryReceiptRequestParserFactory>()); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<IdleParser> >("idle", "urn:xmpp:idle:1")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory2<PubSubParser> >("pubsub", "http://jabber.org/protocol/pubsub", this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory2<PubSubOwnerPubSubParser> >("pubsub", "http://jabber.org/protocol/pubsub#owner", this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory2<PubSubEventParser> >("event", "http://jabber.org/protocol/pubsub#event", this)); + factories_.push_back(std::make_shared<PubSubErrorParserFactory>()); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<ResultSetParser> >("set", "http://jabber.org/protocol/rsm")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory2<ForwardedParser> >("forwarded", "urn:xmpp:forward:0", this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory2<MAMResultParser> >("result", "urn:xmpp:mam:0", this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MAMQueryParser> >("query", "urn:xmpp:mam:0")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<MAMFinParser> >("fin", "urn:xmpp:mam:0")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory2<IsodeIQDelegationParser> >("delegate", "http://isode.com/iq_delegation", this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<CarbonsEnableParser> >("enable", "urn:xmpp:carbons:2")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<CarbonsDisableParser> >("disable", "urn:xmpp:carbons:2")); + factories_.push_back(std::make_shared<GenericPayloadParserFactory2<CarbonsReceivedParser> >("received", "urn:xmpp:carbons:2", this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory2<CarbonsSentParser> >("sent", "urn:xmpp:carbons:2", this)); + factories_.push_back(std::make_shared<GenericPayloadParserFactory<CarbonsPrivateParser> >("private", "urn:xmpp:carbons:2")); + factories_.push_back(std::make_shared<MIXJoinParserFactory>()); + factories_.push_back(std::make_shared<GenericPayloadParserFactory2<ReferencePayloadParser> >("reference", "urn:xmpp:reference:0", this)); - foreach(shared_ptr<PayloadParserFactory> factory, factories_) { - addFactory(factory.get()); - } - defaultFactory_ = new RawXMLPayloadParserFactory(); - setDefaultFactory(defaultFactory_); + for (auto& factory : factories_) { + addFactory(factory.get()); + } + defaultFactory_ = new RawXMLPayloadParserFactory(); + setDefaultFactory(defaultFactory_); } FullPayloadParserFactoryCollection::~FullPayloadParserFactoryCollection() { - setDefaultFactory(NULL); - delete defaultFactory_; - foreach(shared_ptr<PayloadParserFactory> factory, factories_) { - removeFactory(factory.get()); - } + setDefaultFactory(nullptr); + delete defaultFactory_; + for (auto& factory : factories_) { + removeFactory(factory.get()); + } } } diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h index 91302b1..e59a6e0 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h @@ -1,26 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <vector> #include <Swiften/Base/API.h> -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> namespace Swift { - class SWIFTEN_API FullPayloadParserFactoryCollection : public PayloadParserFactoryCollection { - public: - FullPayloadParserFactoryCollection(); - ~FullPayloadParserFactoryCollection(); + class SWIFTEN_API FullPayloadParserFactoryCollection : public PayloadParserFactoryCollection { + public: + FullPayloadParserFactoryCollection(); + ~FullPayloadParserFactoryCollection(); - private: - std::vector< boost::shared_ptr<PayloadParserFactory> > factories_; - PayloadParserFactory* defaultFactory_; - }; + private: + std::vector< std::shared_ptr<PayloadParserFactory> > factories_; + PayloadParserFactory* defaultFactory_; + }; } diff --git a/Swiften/Parser/PayloadParsers/IBBParser.cpp b/Swiften/Parser/PayloadParsers/IBBParser.cpp index 20a1ce9..1ba44e1 100644 --- a/Swiften/Parser/PayloadParsers/IBBParser.cpp +++ b/Swiften/Parser/PayloadParsers/IBBParser.cpp @@ -1,14 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/IBBParser.h> #include <boost/lexical_cast.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/StringCodecs/Base64.h> namespace Swift { @@ -20,57 +19,56 @@ IBBParser::~IBBParser() { } void IBBParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level == TopLevel) { - if (element == "data") { - getPayloadInternal()->setAction(IBB::Data); - getPayloadInternal()->setStreamID(attributes.getAttribute("sid")); - try { - getPayloadInternal()->setSequenceNumber(boost::lexical_cast<int>(attributes.getAttribute("seq"))); - } - catch (boost::bad_lexical_cast&) { - } - } - else if (element == "open") { - getPayloadInternal()->setAction(IBB::Open); - getPayloadInternal()->setStreamID(attributes.getAttribute("sid")); - if (attributes.getAttribute("stanza") == "message") { - getPayloadInternal()->setStanzaType(IBB::MessageStanza); - } - else { - getPayloadInternal()->setStanzaType(IBB::IQStanza); - } - try { - getPayloadInternal()->setBlockSize(boost::lexical_cast<int>(attributes.getAttribute("block-size"))); - } - catch (boost::bad_lexical_cast&) { - } - } - else if (element == "close") { - getPayloadInternal()->setAction(IBB::Close); - getPayloadInternal()->setStreamID(attributes.getAttribute("sid")); - } - } - ++level; + if (level == TopLevel) { + if (element == "data") { + getPayloadInternal()->setAction(IBB::Data); + getPayloadInternal()->setStreamID(attributes.getAttribute("sid")); + try { + getPayloadInternal()->setSequenceNumber(boost::lexical_cast<int>(attributes.getAttribute("seq"))); + } + catch (boost::bad_lexical_cast&) { + } + } + else if (element == "open") { + getPayloadInternal()->setAction(IBB::Open); + getPayloadInternal()->setStreamID(attributes.getAttribute("sid")); + if (attributes.getAttribute("stanza") == "message") { + getPayloadInternal()->setStanzaType(IBB::MessageStanza); + } + else { + getPayloadInternal()->setStanzaType(IBB::IQStanza); + } + try { + getPayloadInternal()->setBlockSize(boost::lexical_cast<unsigned int>(attributes.getAttribute("block-size"))); + } + catch (boost::bad_lexical_cast&) { + } + } + else if (element == "close") { + getPayloadInternal()->setAction(IBB::Close); + getPayloadInternal()->setStreamID(attributes.getAttribute("sid")); + } + } + ++level; } void IBBParser::handleEndElement(const std::string& element, const std::string&) { - --level; - if (level == TopLevel) { - if (element == "data") { - std::vector<char> data; - for (size_t i = 0; i < currentText.size(); ++i) { - char c = currentText[i]; - if ((c >= 48 && c <= 122) || c == 47 || c == 43) { - data.push_back(c); - } - } - getPayloadInternal()->setData(Base64::decode(std::string(&data[0], data.size()))); - } - } + --level; + if (level == TopLevel) { + if (element == "data") { + std::vector<char> data; + for (char c : currentText) { + if ((c >= 48 && c <= 122) || c == 47 || c == 43) { + data.push_back(c); + } + } + getPayloadInternal()->setData(Base64::decode(std::string(&data[0], data.size()))); + } + } } void IBBParser::handleCharacterData(const std::string& data) { - currentText += data; + currentText += data; } diff --git a/Swiften/Parser/PayloadParsers/IBBParser.h b/Swiften/Parser/PayloadParsers/IBBParser.h index 59011b4..7ef3e6f 100644 --- a/Swiften/Parser/PayloadParsers/IBBParser.h +++ b/Swiften/Parser/PayloadParsers/IBBParser.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/IBB.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class IBBParser : public GenericPayloadParser<IBB> { - public: - IBBParser(); - ~IBBParser(); + class SWIFTEN_API IBBParser : public GenericPayloadParser<IBB> { + public: + IBBParser(); + ~IBBParser(); - 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); + 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 - }; - int level; - std::string currentText; - }; + private: + enum Level { + TopLevel = 0 + }; + int level; + std::string currentText; + }; } diff --git a/Swiften/Parser/PayloadParsers/IdleParser.cpp b/Swiften/Parser/PayloadParsers/IdleParser.cpp index 51aa34b..e985576 100644 --- a/Swiften/Parser/PayloadParsers/IdleParser.cpp +++ b/Swiften/Parser/PayloadParsers/IdleParser.cpp @@ -14,15 +14,15 @@ IdleParser::IdleParser() : level_(0) { } void IdleParser::handleStartElement(const std::string& /*element*/, const std::string& /*ns*/, const AttributeMap& attributes) { - if (level_ == 0) { - boost::posix_time::ptime since = stringToDateTime(attributes.getAttribute("since")); - getPayloadInternal()->setSince(since); - } - ++level_; + if (level_ == 0) { + boost::posix_time::ptime since = stringToDateTime(attributes.getAttribute("since")); + getPayloadInternal()->setSince(since); + } + ++level_; } void IdleParser::handleEndElement(const std::string&, const std::string&) { - --level_; + --level_; } void IdleParser::handleCharacterData(const std::string&) { diff --git a/Swiften/Parser/PayloadParsers/IdleParser.h b/Swiften/Parser/PayloadParsers/IdleParser.h index 38001b2..c1922c0 100644 --- a/Swiften/Parser/PayloadParsers/IdleParser.h +++ b/Swiften/Parser/PayloadParsers/IdleParser.h @@ -4,21 +4,28 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Idle.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class IdleParser : public GenericPayloadParser<Idle> { - public: - IdleParser(); + class SWIFTEN_API IdleParser : public GenericPayloadParser<Idle> { + public: + IdleParser(); - 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); + 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: - int level_; - }; + private: + int level_; + }; } diff --git a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp index 06759cb..f0241b0 100644 --- a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp @@ -1,131 +1,133 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h> +#include <cassert> + #include <boost/cast.hpp> -#include <Swiften/Parser/PayloadParsers/FormParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParser.h> +#include <Swiften/Parser/PayloadParsers/FormParserFactory.h> namespace Swift { -InBandRegistrationPayloadParser::InBandRegistrationPayloadParser() : level(TopLevel), formParser(NULL) { - formParserFactory = new FormParserFactory(); +InBandRegistrationPayloadParser::InBandRegistrationPayloadParser() : level(TopLevel), formParser(nullptr) { + formParserFactory = new FormParserFactory(); } InBandRegistrationPayloadParser::~InBandRegistrationPayloadParser() { - delete formParserFactory; + delete formParserFactory; } void InBandRegistrationPayloadParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == TopLevel) { - } - else if (level == PayloadLevel) { - if (element == "x" && ns == "jabber:x:data") { - assert(!formParser); - formParser = boost::polymorphic_downcast<FormParser*>(formParserFactory->createPayloadParser()); - } - else { - currentText.clear(); - } - } + if (level == TopLevel) { + } + else if (level == PayloadLevel) { + if (element == "x" && ns == "jabber:x:data") { + assert(!formParser); + formParser = boost::polymorphic_downcast<FormParser*>(formParserFactory->createPayloadParser()); + } + else { + currentText.clear(); + } + } - if (formParser) { - formParser->handleStartElement(element, ns, attributes); - } + if (formParser) { + formParser->handleStartElement(element, ns, attributes); + } - ++level; + ++level; } void InBandRegistrationPayloadParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; + --level; - if (formParser) { - formParser->handleEndElement(element, ns); - } + if (formParser) { + formParser->handleEndElement(element, ns); + } - if (level == TopLevel) { - } - else if (level == PayloadLevel) { - if (formParser) { - getPayloadInternal()->setForm(formParser->getPayloadInternal()); - delete formParser; - formParser = NULL; - } - else if (element == "registered") { - getPayloadInternal()->setRegistered(true); - } - else if (element == "remove") { - getPayloadInternal()->setRemove(true); - } - else if (element == "instructions") { - getPayloadInternal()->setInstructions(currentText); - } - else if (element == "username") { - getPayloadInternal()->setUsername(currentText); - } - else if (element == "nick") { - getPayloadInternal()->setNick(currentText); - } - else if (element == "password") { - getPayloadInternal()->setPassword(currentText); - } - else if (element == "name") { - getPayloadInternal()->setName(currentText); - } - else if (element == "first") { - getPayloadInternal()->setFirst(currentText); - } - else if (element == "last") { - getPayloadInternal()->setLast(currentText); - } - else if (element == "email") { - getPayloadInternal()->setEMail(currentText); - } - else if (element == "address") { - getPayloadInternal()->setAddress(currentText); - } - else if (element == "city") { - getPayloadInternal()->setCity(currentText); - } - else if (element == "state") { - getPayloadInternal()->setState(currentText); - } - else if (element == "zip") { - getPayloadInternal()->setZip(currentText); - } - else if (element == "phone") { - getPayloadInternal()->setPhone(currentText); - } - else if (element == "url") { - getPayloadInternal()->setURL(currentText); - } - else if (element == "date") { - getPayloadInternal()->setDate(currentText); - } - else if (element == "misc") { - getPayloadInternal()->setMisc(currentText); - } - else if (element == "text") { - getPayloadInternal()->setText(currentText); - } - else if (element == "key") { - getPayloadInternal()->setKey(currentText); - } - } + if (level == TopLevel) { + } + else if (level == PayloadLevel) { + if (formParser) { + getPayloadInternal()->setForm(formParser->getPayloadInternal()); + delete formParser; + formParser = nullptr; + } + else if (element == "registered") { + getPayloadInternal()->setRegistered(true); + } + else if (element == "remove") { + getPayloadInternal()->setRemove(true); + } + else if (element == "instructions") { + getPayloadInternal()->setInstructions(currentText); + } + else if (element == "username") { + getPayloadInternal()->setUsername(currentText); + } + else if (element == "nick") { + getPayloadInternal()->setNick(currentText); + } + else if (element == "password") { + getPayloadInternal()->setPassword(currentText); + } + else if (element == "name") { + getPayloadInternal()->setName(currentText); + } + else if (element == "first") { + getPayloadInternal()->setFirst(currentText); + } + else if (element == "last") { + getPayloadInternal()->setLast(currentText); + } + else if (element == "email") { + getPayloadInternal()->setEMail(currentText); + } + else if (element == "address") { + getPayloadInternal()->setAddress(currentText); + } + else if (element == "city") { + getPayloadInternal()->setCity(currentText); + } + else if (element == "state") { + getPayloadInternal()->setState(currentText); + } + else if (element == "zip") { + getPayloadInternal()->setZip(currentText); + } + else if (element == "phone") { + getPayloadInternal()->setPhone(currentText); + } + else if (element == "url") { + getPayloadInternal()->setURL(currentText); + } + else if (element == "date") { + getPayloadInternal()->setDate(currentText); + } + else if (element == "misc") { + getPayloadInternal()->setMisc(currentText); + } + else if (element == "text") { + getPayloadInternal()->setText(currentText); + } + else if (element == "key") { + getPayloadInternal()->setKey(currentText); + } + } } void InBandRegistrationPayloadParser::handleCharacterData(const std::string& data) { - if (formParser) { - formParser->handleCharacterData(data); - } - else { - currentText += data; - } + if (formParser) { + formParser->handleCharacterData(data); + } + else { + currentText += data; + } } } diff --git a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h index 1f85c85..7e2a4a4 100644 --- a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/InBandRegistrationPayload.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class FormParserFactory; - class FormParser; + class FormParserFactory; + class FormParser; - class InBandRegistrationPayloadParser : public GenericPayloadParser<InBandRegistrationPayload> { - public: - InBandRegistrationPayloadParser(); - ~InBandRegistrationPayloadParser(); + class SWIFTEN_API InBandRegistrationPayloadParser : public GenericPayloadParser<InBandRegistrationPayload> { + public: + InBandRegistrationPayloadParser(); + ~InBandRegistrationPayloadParser(); - 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); + 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 - }; - int level; - FormParserFactory* formParserFactory; - FormParser* formParser; - std::string currentText; - }; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + int level; + FormParserFactory* formParserFactory; + FormParser* formParser; + std::string currentText; + }; } diff --git a/Swiften/Parser/PayloadParsers/IsodeIQDelegationParser.cpp b/Swiften/Parser/PayloadParsers/IsodeIQDelegationParser.cpp new file mode 100644 index 0000000..2efe3c8 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/IsodeIQDelegationParser.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/IsodeIQDelegationParser.h> + +#include <boost/optional.hpp> + +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> + +using namespace Swift; + +IsodeIQDelegationParser::IsodeIQDelegationParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +IsodeIQDelegationParser::~IsodeIQDelegationParser() { +} + +void IsodeIQDelegationParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + + + if (level == 1) { + if (PayloadParserFactory* factory = parsers->getPayloadParserFactory(element, ns, attributes)) { + currentPayloadParser.reset(factory->createPayloadParser()); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; +} + +void IsodeIQDelegationParser::handleEndElement(const std::string& element, const std::string& ns) { + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + getPayloadInternal()->setForward(std::dynamic_pointer_cast<Forwarded>(currentPayloadParser->getPayload())); + currentPayloadParser.reset(); + } + } +} + +void IsodeIQDelegationParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/IsodeIQDelegationParser.h b/Swiften/Parser/PayloadParsers/IsodeIQDelegationParser.h new file mode 100644 index 0000000..af2f061 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/IsodeIQDelegationParser.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/IsodeIQDelegation.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class PayloadParserFactoryCollection; + class PayloadParser; + + class SWIFTEN_API IsodeIQDelegationParser : public GenericPayloadParser<IsodeIQDelegation> { + public: + IsodeIQDelegationParser(PayloadParserFactoryCollection* parsers); + virtual ~IsodeIQDelegationParser() override; + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/JingleContentPayloadParser.cpp b/Swiften/Parser/PayloadParsers/JingleContentPayloadParser.cpp index 1431b9e..3a01676 100644 --- a/Swiften/Parser/PayloadParsers/JingleContentPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleContentPayloadParser.cpp @@ -4,71 +4,77 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "JingleContentPayloadParser.h" -#include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Parser/PayloadParserFactory.h> -#include <Swiften/Elements/JinglePayload.h> +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/JingleContentPayloadParser.h> #include <Swiften/Base/Log.h> +#include <Swiften/Elements/JinglePayload.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> namespace Swift { - JingleContentPayloadParser::JingleContentPayloadParser(PayloadParserFactoryCollection* factories) : factories(factories), level(0) { - - } - - void JingleContentPayloadParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - std::string creator = attributes.getAttributeValue("creator").get_value_or(""); - if (creator == "initiator") { - getPayloadInternal()->setCreator(JingleContentPayload::InitiatorCreator); - } else if (creator == "responder") { - getPayloadInternal()->setCreator(JingleContentPayload::ResponderCreator); - } else { - getPayloadInternal()->setCreator(JingleContentPayload::UnknownCreator); - } - - getPayloadInternal()->setName(attributes.getAttributeValue("name").get_value_or("")); - } - - if (level == 1) { - PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); - if (payloadParserFactory) { - currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); - } - } - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - - ++level; - } - - void JingleContentPayloadParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - boost::shared_ptr<JingleTransportPayload> transport = boost::dynamic_pointer_cast<JingleTransportPayload>(currentPayloadParser->getPayload()); - if (transport) { - getPayloadInternal()->addTransport(transport); - } - - boost::shared_ptr<JingleDescription> description = boost::dynamic_pointer_cast<JingleDescription>(currentPayloadParser->getPayload()); - if (description) { - getPayloadInternal()->addDescription(description); - } - } - } - } - - void JingleContentPayloadParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } - } + JingleContentPayloadParser::JingleContentPayloadParser(PayloadParserFactoryCollection* factories) : factories(factories), level(0) { + + } + + void JingleContentPayloadParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + if (level == 0) { + std::string creator = attributes.getAttributeValue("creator").get_value_or(""); + if (creator == "initiator") { + getPayloadInternal()->setCreator(JingleContentPayload::InitiatorCreator); + } else if (creator == "responder") { + getPayloadInternal()->setCreator(JingleContentPayload::ResponderCreator); + } else { + getPayloadInternal()->setCreator(JingleContentPayload::UnknownCreator); + } + + getPayloadInternal()->setName(attributes.getAttributeValue("name").get_value_or("")); + } + + if (level == 1) { + PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); + if (payloadParserFactory) { + currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + + ++level; + } + + void JingleContentPayloadParser::handleEndElement(const std::string& element, const std::string& ns) { + --level; + + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + std::shared_ptr<JingleTransportPayload> transport = std::dynamic_pointer_cast<JingleTransportPayload>(currentPayloadParser->getPayload()); + if (transport) { + getPayloadInternal()->addTransport(transport); + } + + std::shared_ptr<JingleDescription> description = std::dynamic_pointer_cast<JingleDescription>(currentPayloadParser->getPayload()); + if (description) { + getPayloadInternal()->addDescription(description); + } + } + } + } + + void JingleContentPayloadParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } + } } diff --git a/Swiften/Parser/PayloadParsers/JingleContentPayloadParser.h b/Swiften/Parser/PayloadParsers/JingleContentPayloadParser.h index a871cc4..fde07cb 100644 --- a/Swiften/Parser/PayloadParsers/JingleContentPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/JingleContentPayloadParser.h @@ -4,8 +4,15 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleContentPayload.h> #include <Swiften/Parser/GenericPayloadParser.h> @@ -13,18 +20,18 @@ namespace Swift { class PayloadParserFactoryCollection; -class JingleContentPayloadParser : public GenericPayloadParser<JingleContentPayload> { - public: - JingleContentPayloadParser(PayloadParserFactoryCollection* factories); +class SWIFTEN_API JingleContentPayloadParser : public GenericPayloadParser<JingleContentPayload> { + public: + JingleContentPayloadParser(PayloadParserFactoryCollection* factories); - 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); + 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: - PayloadParserFactoryCollection* factories; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; + private: + PayloadParserFactoryCollection* factories; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; }; } diff --git a/Swiften/Parser/PayloadParsers/JingleContentPayloadParserFactory.h b/Swiften/Parser/PayloadParsers/JingleContentPayloadParserFactory.h index 6d66e74..8e9741d 100644 --- a/Swiften/Parser/PayloadParsers/JingleContentPayloadParserFactory.h +++ b/Swiften/Parser/PayloadParsers/JingleContentPayloadParserFactory.h @@ -4,32 +4,39 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/GenericPayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/JingleContentPayloadParser.h> namespace Swift { - - class PayloadParserFactoryCollection; - - class JingleContentPayloadParserFactory : public PayloadParserFactory { - public: - JingleContentPayloadParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { - } - - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return element == "content" && ns == "urn:xmpp:jingle:1"; - } - - virtual PayloadParser* createPayloadParser() { - return new JingleContentPayloadParser(factories); - } - - private: - PayloadParserFactoryCollection* factories; - - }; + + class PayloadParserFactoryCollection; + + class SWIFTEN_API JingleContentPayloadParserFactory : public PayloadParserFactory { + public: + JingleContentPayloadParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { + } + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return element == "content" && ns == "urn:xmpp:jingle:1"; + } + + virtual PayloadParser* createPayloadParser() { + return new JingleContentPayloadParser(factories); + } + + private: + PayloadParserFactoryCollection* factories; + + }; } diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp index b394115..1e433a6 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp @@ -4,72 +4,59 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "JingleFileTransferDescriptionParser.h" +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h> + +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> + +#include <Swiften/Base/DateTime.h> #include <Swiften/Parser/PayloadParserFactory.h> -#include <Swiften/Base/Log.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/StringCodecs/Base64.h> namespace Swift { -JingleFileTransferDescriptionParser::JingleFileTransferDescriptionParser(PayloadParserFactoryCollection* factories) : factories(factories), level(0), - currentElement(UnknownElement) { - +JingleFileTransferDescriptionParser::JingleFileTransferDescriptionParser(PayloadParserFactoryCollection* factories) : factories(factories), level(0) { } void JingleFileTransferDescriptionParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - - } - - if (level == 1) { - if (element == "offer") { - currentElement = OfferElement; - } else if (element == "request") { - currentElement = RequestElement; - } else { - currentElement = UnknownElement; - } - } - - if (level == 2) { - PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); - if (payloadParserFactory) { - currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); - } - } - - if (level >= 2 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - - ++level; + if (level == 1) { + PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); + if (payloadParserFactory) { + currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void JingleFileTransferDescriptionParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 2) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 2) { - boost::shared_ptr<StreamInitiationFileInfo> info = boost::dynamic_pointer_cast<StreamInitiationFileInfo>(currentPayloadParser->getPayload()); - if (info) { - if (currentElement == OfferElement) { - getPayloadInternal()->addOffer(*info); - } else if (currentElement == RequestElement) { - getPayloadInternal()->addRequest(*info); - } - } - } - } + --level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 0) { + std::shared_ptr<JingleFileTransferFileInfo> info = std::dynamic_pointer_cast<JingleFileTransferFileInfo>(currentPayloadParser->getPayload()); + if (info) { + getPayloadInternal()->setFileInfo(*info); + } + } } void JingleFileTransferDescriptionParser::handleCharacterData(const std::string& data) { - if (level >= 2 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } - + } diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h index 7ea22b4..b148d9b 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h @@ -4,8 +4,15 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleFileTransferDescription.h> #include <Swiften/Parser/GenericPayloadParser.h> #include <Swiften/Parser/PayloadParser.h> @@ -14,25 +21,18 @@ namespace Swift { class PayloadParserFactoryCollection; -class JingleFileTransferDescriptionParser : public GenericPayloadParser<JingleFileTransferDescription> { - public: - JingleFileTransferDescriptionParser(PayloadParserFactoryCollection* factories); - - 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 CurrentParseElement { - UnknownElement, - RequestElement, - OfferElement - }; - - PayloadParserFactoryCollection* factories; - int level; - CurrentParseElement currentElement; - boost::shared_ptr<PayloadParser> currentPayloadParser; +class SWIFTEN_API JingleFileTransferDescriptionParser : public GenericPayloadParser<JingleFileTransferDescription> { + public: + JingleFileTransferDescriptionParser(PayloadParserFactoryCollection* factories); + + 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: + PayloadParserFactoryCollection* factories; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; }; } diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h index b997c1d..c75125f 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h @@ -4,32 +4,39 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/GenericPayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h> namespace Swift { - - class PayloadParserFactoryCollection; - - class JingleFileTransferDescriptionParserFactory : public PayloadParserFactory { - public: - JingleFileTransferDescriptionParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { - } - - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return element == "description" && ns == "urn:xmpp:jingle:apps:file-transfer:3"; - } - - virtual PayloadParser* createPayloadParser() { - return new JingleFileTransferDescriptionParser(factories); - } - - private: - PayloadParserFactoryCollection* factories; - - }; + + class PayloadParserFactoryCollection; + + class SWIFTEN_API JingleFileTransferDescriptionParserFactory : public PayloadParserFactory { + public: + JingleFileTransferDescriptionParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { + } + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return element == "description" && ns == "urn:xmpp:jingle:apps:file-transfer:4"; + } + + virtual PayloadParser* createPayloadParser() { + return new JingleFileTransferDescriptionParser(factories); + } + + private: + PayloadParserFactoryCollection* factories; + + }; } diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.cpp b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.cpp new file mode 100644 index 0000000..4f8b9a9 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h> + +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/StringCodecs/Base64.h> + +namespace Swift { + +JingleFileTransferFileInfoParser::JingleFileTransferFileInfoParser() : level(0) { +} + +template<typename T> boost::optional<T> safeLexicalCast(const std::string& str) { + boost::optional<T> ret; + try { + ret = boost::lexical_cast<T>(str); + } catch (boost::bad_lexical_cast &) { + + } + return ret; +} + +void JingleFileTransferFileInfoParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { + charData.clear(); + if (element == "hash") { + hashAlg = attributes.getAttributeValue("algo").get_value_or(""); + } + else if (element == "range") { + rangeOffset = safeLexicalCast<boost::uintmax_t>(attributes.getAttributeValue("offset").get_value_or("")); + } + + ++level; +} + +void JingleFileTransferFileInfoParser::handleEndElement(const std::string& element, const std::string&) { + --level; + if (level == 1) { + if (element == "date") { + getPayloadInternal()->setDate(stringToDateTime(charData)); + } + else if (element == "desc") { + getPayloadInternal()->setDescription(charData); + } + else if (element == "media-type") { + getPayloadInternal()->setMediaType(charData); + } + else if (element == "name") { + getPayloadInternal()->setName(charData); + } + else if (element == "size") { + boost::optional<boost::uintmax_t> size = safeLexicalCast<boost::uintmax_t>(charData); + if (size) { + getPayloadInternal()->setSize(size.get()); + } + } + else if (element == "range") { + getPayloadInternal()->setSupportsRangeRequests(true); + if (rangeOffset) { + getPayloadInternal()->setRangeOffset(rangeOffset.get_value_or(0)); + } + } + else if (element == "hash") { + getPayloadInternal()->addHash(HashElement(hashAlg, Base64::decode(charData))); + } + } +} + +void JingleFileTransferFileInfoParser::handleCharacterData(const std::string& data) { + charData += data; +} + +} diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h new file mode 100644 index 0000000..237f105 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + +class SWIFTEN_API JingleFileTransferFileInfoParser : public GenericPayloadParser<JingleFileTransferFileInfo> { + public: + JingleFileTransferFileInfoParser(); + + 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: + int level; + std::string charData; + std::string hashAlg; + boost::optional<boost::uintmax_t> rangeOffset; +}; + +} diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp index 87f8317..4adf3bd 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp @@ -4,40 +4,56 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "JingleFileTransferHashParser.h" +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h> + +#include <memory> -#include <boost/shared_ptr.hpp> #include <boost/algorithm/string.hpp> -#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h> #include <Swiften/Parser/GenericPayloadParserFactory.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h> namespace Swift { -JingleFileTransferHashParser::JingleFileTransferHashParser() { +JingleFileTransferHashParser::JingleFileTransferHashParser() : level(0) { } - -void JingleFileTransferHashParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (element == "hash") { - algo = attributes.getAttribute("algo"); - } + +void JingleFileTransferHashParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + if (level == 1 && element == "file") { + currentPayloadParser = std::make_shared<JingleFileTransferFileInfoParser>(); + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } -void JingleFileTransferHashParser::handleEndElement(const std::string& element, const std::string& ) { - if (element == "hash" && !algo.empty() && !hash.empty()) { - getPayloadInternal()->setHash(algo, hash); - algo.clear(); - hash.clear(); - } +void JingleFileTransferHashParser::handleEndElement(const std::string& element, const std::string& ns) { + --level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + std::shared_ptr<JingleFileTransferFileInfo> info = std::dynamic_pointer_cast<JingleFileTransferFileInfo>(currentPayloadParser->getPayload()); + if (info) { + getPayloadInternal()->setFileInfo(*info); + } + } } void JingleFileTransferHashParser::handleCharacterData(const std::string& data) { - if (!algo.empty()) { - std::string new_data(data); - boost::trim(new_data); - hash += new_data; - } + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } } diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h index 35e4a05..1b47921 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h @@ -4,24 +4,31 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleFileTransferHash.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { -class JingleFileTransferHashParser : public GenericPayloadParser<JingleFileTransferHash> { +class SWIFTEN_API JingleFileTransferHashParser : public GenericPayloadParser<JingleFileTransferHash> { public: - JingleFileTransferHashParser(); - - 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); - + JingleFileTransferHashParser(); + + 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: - std::string algo; - std::string hash; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; }; } diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferReceivedParser.cpp b/Swiften/Parser/PayloadParsers/JingleFileTransferReceivedParser.cpp deleted file mode 100644 index ae56981..0000000 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferReceivedParser.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2011 Tobias Markmann - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. - */ - -#include <Swiften/Parser/PayloadParsers/JingleFileTransferReceivedParser.h> - -#include <boost/shared_ptr.hpp> -#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h> -#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h> -#include <Swiften/Parser/GenericPayloadParserFactory.h> -#include <Swiften/Parser/PayloadParserFactory.h> - -namespace Swift { - -JingleFileTransferReceivedParser::JingleFileTransferReceivedParser() : level(0) { -} - -void JingleFileTransferReceivedParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 1 && element == "file") { - PayloadParserFactory* payloadParserFactory = new GenericPayloadParserFactory<StreamInitiationFileInfoParser>("file", "http://jabber.org/protocol/si/profile/file-transfer"); - if (payloadParserFactory) { - currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); - } - } - - if (currentPayloadParser && level >= 1) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - - ++level; -} - -void JingleFileTransferReceivedParser::handleEndElement(const std::string& element, const std::string& ) { - --level; - if (element == "file") { - boost::shared_ptr<StreamInitiationFileInfo> fileInfo = boost::dynamic_pointer_cast<StreamInitiationFileInfo>(currentPayloadParser->getPayload()); - if (fileInfo) { - getPayloadInternal()->setFileInfo(*fileInfo); - } - } -} - -void JingleFileTransferReceivedParser::handleCharacterData(const std::string& ) { - -} - -} diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferReceivedParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferReceivedParser.h deleted file mode 100644 index d5333ad..0000000 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferReceivedParser.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2011 Tobias Markmann - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. - */ - -#pragma once - -#include <Swiften/Elements/JingleFileTransferReceived.h> -#include <Swiften/Parser/GenericPayloadParser.h> - -namespace Swift { - -class JingleFileTransferReceivedParser : public GenericPayloadParser<JingleFileTransferReceived> { -public: - JingleFileTransferReceivedParser(); - - 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: - boost::shared_ptr<PayloadParser> currentPayloadParser; - int level; -}; - -} - diff --git a/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp b/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp index d140368..438420b 100644 --- a/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp @@ -5,43 +5,43 @@ */ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ +#include <Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h> + #include <boost/lexical_cast.hpp> #include <boost/optional.hpp> -#include "JingleIBBTransportMethodPayloadParser.h" - #include <Swiften/Base/Log.h> namespace Swift { - JingleIBBTransportMethodPayloadParser::JingleIBBTransportMethodPayloadParser() : level(0) { - - } - - void JingleIBBTransportMethodPayloadParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { - try { - boost::optional<std::string> blockSize = attributes.getAttributeValue("block-size"); - if (blockSize) { - getPayloadInternal()->setBlockSize(boost::lexical_cast<unsigned int>(*blockSize)); - } - } - catch (boost::bad_lexical_cast &) { - } - getPayloadInternal()->setSessionID(attributes.getAttributeValue("sid").get_value_or("")); - ++level; - } - - void JingleIBBTransportMethodPayloadParser::handleEndElement(const std::string&, const std::string&) { - --level; - - - } - - void JingleIBBTransportMethodPayloadParser::handleCharacterData(const std::string&) { - - } + JingleIBBTransportMethodPayloadParser::JingleIBBTransportMethodPayloadParser() : level(0) { + + } + + void JingleIBBTransportMethodPayloadParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { + try { + boost::optional<std::string> blockSize = attributes.getAttributeValue("block-size"); + if (blockSize) { + getPayloadInternal()->setBlockSize(boost::lexical_cast<unsigned int>(*blockSize)); + } + } + catch (boost::bad_lexical_cast &) { + } + getPayloadInternal()->setSessionID(attributes.getAttributeValue("sid").get_value_or("")); + ++level; + } + + void JingleIBBTransportMethodPayloadParser::handleEndElement(const std::string&, const std::string&) { + --level; + + + } + + void JingleIBBTransportMethodPayloadParser::handleCharacterData(const std::string&) { + + } } diff --git a/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h b/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h index 311cc5b..e406b9f 100644 --- a/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h @@ -4,23 +4,30 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { -class JingleIBBTransportMethodPayloadParser : public GenericPayloadParser<JingleIBBTransportPayload> { - public: - JingleIBBTransportMethodPayloadParser(); +class SWIFTEN_API JingleIBBTransportMethodPayloadParser : public GenericPayloadParser<JingleIBBTransportPayload> { + public: + JingleIBBTransportMethodPayloadParser(); - 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); + 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: - int level; + private: + int level; }; } diff --git a/Swiften/Parser/PayloadParsers/JingleParser.cpp b/Swiften/Parser/PayloadParsers/JingleParser.cpp index dd34458..a88a5b2 100644 --- a/Swiften/Parser/PayloadParsers/JingleParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleParser.cpp @@ -4,116 +4,117 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Parser/PayloadParsers/JingleParser.h> -#include <Swiften/Parser/PayloadParserFactory.h> -#include <Swiften/Elements/JingleContentPayload.h> -#include <Swiften/Elements/JingleFileTransferReceived.h> -#include <Swiften/Elements/JingleFileTransferHash.h> -#include <Swiften/Base/Log.h> #include <boost/intrusive_ptr.hpp> +#include <Swiften/Base/Log.h> +#include <Swiften/Elements/JingleContentPayload.h> +#include <Swiften/Elements/JingleFileTransferHash.h> +#include <Swiften/Parser/PayloadParserFactory.h> + namespace Swift { - JingleParser::JingleParser(PayloadParserFactoryCollection* factories) : factories(factories), level(0) { - - } - - void JingleParser::handleStartElement(const std::string& element, const std::string &ns, const AttributeMap& attributes) { - if (level == 0) { - // <jingle > tag - JinglePayload::ref payload = getPayloadInternal(); - payload->setAction(stringToAction(attributes.getAttributeValue("action").get_value_or(""))); - payload->setInitiator(JID(attributes.getAttributeValue("initiator").get_value_or(""))); - payload->setResponder(JID(attributes.getAttributeValue("responder").get_value_or(""))); - payload->setSessionID(attributes.getAttributeValue("sid").get_value_or("")); - } - - if (level == 1) { - PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); - if (payloadParserFactory) { - currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); - } - } - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - - ++level; - } - - void JingleParser::handleEndElement(const std::string& element, const std::string &ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - boost::shared_ptr<JinglePayload::Reason> reason = boost::dynamic_pointer_cast<JinglePayload::Reason>(currentPayloadParser->getPayload()); - if (reason) { - getPayloadInternal()->setReason(*reason); - } - - boost::shared_ptr<JingleContentPayload> payload = boost::dynamic_pointer_cast<JingleContentPayload>(currentPayloadParser->getPayload()); - if (payload) { - getPayloadInternal()->addContent(payload); - } - - boost::shared_ptr<JingleFileTransferReceived> received = boost::dynamic_pointer_cast<JingleFileTransferReceived>(currentPayloadParser->getPayload()); - if (received) { - getPayloadInternal()->addPayload(received); - } - - boost::shared_ptr<JingleFileTransferHash> hash = boost::dynamic_pointer_cast<JingleFileTransferHash>(currentPayloadParser->getPayload()); - if (hash) { - getPayloadInternal()->addPayload(hash); - } - } - } - } - - void JingleParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } - } - - JinglePayload::Action JingleParser::stringToAction(const std::string &str) const { - if (str == "content-accept") { - return JinglePayload::ContentAccept; - } else if (str == "content-add") { - return JinglePayload::ContentAdd; - } else if (str == "content-modify") { - return JinglePayload::ContentModify; - } else if (str == "content-reject") { - return JinglePayload::ContentReject; - } else if (str == "content-remove") { - return JinglePayload::ContentRemove; - } else if (str == "description-info") { - return JinglePayload::DescriptionInfo; - } else if (str == "security-info") { - return JinglePayload::SecurityInfo; - } else if (str == "session-accept") { - return JinglePayload::SessionAccept; - } else if (str == "session-info") { - return JinglePayload::SessionInfo; - } else if (str == "session-initiate") { - return JinglePayload::SessionInitiate; - } else if (str == "session-terminate") { - return JinglePayload::SessionTerminate; - } else if (str == "transport-accept") { - return JinglePayload::TransportAccept; - } else if (str == "transport-info") { - return JinglePayload::TransportInfo; - } else if (str == "transport-reject") { - return JinglePayload::TransportReject; - } else if (str == "transport-replace") { - return JinglePayload::TransportReplace; - } else { - return JinglePayload::UnknownAction; - } - - } + JingleParser::JingleParser(PayloadParserFactoryCollection* factories) : factories(factories), level(0) { + + } + + void JingleParser::handleStartElement(const std::string& element, const std::string &ns, const AttributeMap& attributes) { + if (level == 0) { + // <jingle > tag + JinglePayload::ref payload = getPayloadInternal(); + payload->setAction(stringToAction(attributes.getAttributeValue("action").get_value_or(""))); + payload->setInitiator(JID(attributes.getAttributeValue("initiator").get_value_or(""))); + payload->setResponder(JID(attributes.getAttributeValue("responder").get_value_or(""))); + payload->setSessionID(attributes.getAttributeValue("sid").get_value_or("")); + } + + if (level == 1) { + PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); + if (payloadParserFactory) { + currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + + ++level; + } + + void JingleParser::handleEndElement(const std::string& element, const std::string &ns) { + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + std::shared_ptr<JinglePayload::Reason> reason = std::dynamic_pointer_cast<JinglePayload::Reason>(currentPayloadParser->getPayload()); + if (reason) { + getPayloadInternal()->setReason(*reason); + } + + std::shared_ptr<JingleContentPayload> payload = std::dynamic_pointer_cast<JingleContentPayload>(currentPayloadParser->getPayload()); + if (payload) { + getPayloadInternal()->addContent(payload); + } + + std::shared_ptr<JingleFileTransferHash> hash = std::dynamic_pointer_cast<JingleFileTransferHash>(currentPayloadParser->getPayload()); + if (hash) { + getPayloadInternal()->addPayload(hash); + } + } + } + } + + void JingleParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } + } + + JinglePayload::Action JingleParser::stringToAction(const std::string &str) const { + if (str == "content-accept") { + return JinglePayload::ContentAccept; + } else if (str == "content-add") { + return JinglePayload::ContentAdd; + } else if (str == "content-modify") { + return JinglePayload::ContentModify; + } else if (str == "content-reject") { + return JinglePayload::ContentReject; + } else if (str == "content-remove") { + return JinglePayload::ContentRemove; + } else if (str == "description-info") { + return JinglePayload::DescriptionInfo; + } else if (str == "security-info") { + return JinglePayload::SecurityInfo; + } else if (str == "session-accept") { + return JinglePayload::SessionAccept; + } else if (str == "session-info") { + return JinglePayload::SessionInfo; + } else if (str == "session-initiate") { + return JinglePayload::SessionInitiate; + } else if (str == "session-terminate") { + return JinglePayload::SessionTerminate; + } else if (str == "transport-accept") { + return JinglePayload::TransportAccept; + } else if (str == "transport-info") { + return JinglePayload::TransportInfo; + } else if (str == "transport-reject") { + return JinglePayload::TransportReject; + } else if (str == "transport-replace") { + return JinglePayload::TransportReplace; + } else { + return JinglePayload::UnknownAction; + } + + } } diff --git a/Swiften/Parser/PayloadParsers/JingleParser.h b/Swiften/Parser/PayloadParsers/JingleParser.h index c7bd58c..1dcc9e7 100644 --- a/Swiften/Parser/PayloadParsers/JingleParser.h +++ b/Swiften/Parser/PayloadParsers/JingleParser.h @@ -4,29 +4,36 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/JinglePayload.h> #include <Swiften/Parser/GenericPayloadParser.h> #include <Swiften/Parser/PayloadParserFactoryCollection.h> namespace Swift { -class JingleParser : public GenericPayloadParser<JinglePayload> { - public: - JingleParser(PayloadParserFactoryCollection* factories); - - 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: - JinglePayload::Action stringToAction(const std::string &str) const; - - private: - PayloadParserFactoryCollection* factories; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; +class SWIFTEN_API JingleParser : public GenericPayloadParser<JinglePayload> { + public: + JingleParser(PayloadParserFactoryCollection* factories); + + 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: + JinglePayload::Action stringToAction(const std::string &str) const; + + private: + PayloadParserFactoryCollection* factories; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; }; } diff --git a/Swiften/Parser/PayloadParsers/JingleParserFactory.h b/Swiften/Parser/PayloadParsers/JingleParserFactory.h index fa25aeb..5f9b45b 100644 --- a/Swiften/Parser/PayloadParsers/JingleParserFactory.h +++ b/Swiften/Parser/PayloadParsers/JingleParserFactory.h @@ -4,32 +4,39 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/GenericPayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/JingleParser.h> namespace Swift { - - class PayloadParserFactoryCollection; - - class JingleParserFactory : public PayloadParserFactory { - public: - JingleParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { - } - - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return element == "jingle" && ns == "urn:xmpp:jingle:1"; - } - - virtual PayloadParser* createPayloadParser() { - return new JingleParser(factories); - } - - private: - PayloadParserFactoryCollection* factories; - - }; + + class PayloadParserFactoryCollection; + + class SWIFTEN_API JingleParserFactory : public PayloadParserFactory { + public: + JingleParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { + } + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return element == "jingle" && ns == "urn:xmpp:jingle:1"; + } + + virtual PayloadParser* createPayloadParser() { + return new JingleParser(factories); + } + + private: + PayloadParserFactoryCollection* factories; + + }; } diff --git a/Swiften/Parser/PayloadParsers/JingleReasonParser.cpp b/Swiften/Parser/PayloadParsers/JingleReasonParser.cpp index 3df82ae..9a81e5f 100644 --- a/Swiften/Parser/PayloadParsers/JingleReasonParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleReasonParser.cpp @@ -4,78 +4,84 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "JingleReasonParser.h" +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/JingleReasonParser.h> #include <Swiften/Base/Log.h> namespace Swift { - JingleReasonParser::JingleReasonParser() : level(0), parseText(false) { - - } - - void JingleReasonParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap&) { - if (level == 1) { - if (element == "text") { - parseText = true; - } else { - // reason type - getPayloadInternal()->type = stringToReasonType(element); - } - } - ++level; - } - - void JingleReasonParser::handleEndElement(const std::string& element, const std::string&) { - --level; - if (element == "text") { - parseText = false; - getPayloadInternal()->text = text; - } - } - - void JingleReasonParser::handleCharacterData(const std::string& data) { - if (parseText) { - text += data; - } - } - - JinglePayload::Reason::Type JingleReasonParser::stringToReasonType(const std::string& type) const { - if (type == "alternative-session") { - return JinglePayload::Reason::AlternativeSession; - } else if (type == "busy") { - return JinglePayload::Reason::Busy; - } else if (type == "cancel") { - return JinglePayload::Reason::Cancel; - } else if (type == "connectivity-error") { - return JinglePayload::Reason::ConnectivityError; - } else if (type == "decline") { - return JinglePayload::Reason::Decline; - } else if (type == "expired") { - return JinglePayload::Reason::Expired; - } else if (type == "failed-application") { - return JinglePayload::Reason::FailedApplication; - } else if (type == "failed-transport") { - return JinglePayload::Reason::FailedTransport; - } else if (type == "general-error") { - return JinglePayload::Reason::GeneralError; - } else if (type == "gone") { - return JinglePayload::Reason::Gone; - } else if (type == "incompatible-parameters") { - return JinglePayload::Reason::IncompatibleParameters; - } else if (type == "media-error") { - return JinglePayload::Reason::MediaError; - } else if (type == "security-error") { - return JinglePayload::Reason::SecurityError; - } else if (type == "success") { - return JinglePayload::Reason::Success; - } else if (type == "timeout") { - return JinglePayload::Reason::Timeout; - } else if (type == "unsupported-applications") { - return JinglePayload::Reason::UnsupportedApplications; - } else if (type == "unsupported-transports") { - return JinglePayload::Reason::UnsupportedTransports; - } else { - return JinglePayload::Reason::UnknownType; - } - } + JingleReasonParser::JingleReasonParser() : level(0), parseText(false) { + + } + + void JingleReasonParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap&) { + if (level == 1) { + if (element == "text") { + parseText = true; + } else { + // reason type + getPayloadInternal()->type = stringToReasonType(element); + } + } + ++level; + } + + void JingleReasonParser::handleEndElement(const std::string& element, const std::string&) { + --level; + if (element == "text") { + parseText = false; + getPayloadInternal()->text = text; + } + } + + void JingleReasonParser::handleCharacterData(const std::string& data) { + if (parseText) { + text += data; + } + } + + JinglePayload::Reason::Type JingleReasonParser::stringToReasonType(const std::string& type) const { + if (type == "alternative-session") { + return JinglePayload::Reason::AlternativeSession; + } else if (type == "busy") { + return JinglePayload::Reason::Busy; + } else if (type == "cancel") { + return JinglePayload::Reason::Cancel; + } else if (type == "connectivity-error") { + return JinglePayload::Reason::ConnectivityError; + } else if (type == "decline") { + return JinglePayload::Reason::Decline; + } else if (type == "expired") { + return JinglePayload::Reason::Expired; + } else if (type == "failed-application") { + return JinglePayload::Reason::FailedApplication; + } else if (type == "failed-transport") { + return JinglePayload::Reason::FailedTransport; + } else if (type == "general-error") { + return JinglePayload::Reason::GeneralError; + } else if (type == "gone") { + return JinglePayload::Reason::Gone; + } else if (type == "incompatible-parameters") { + return JinglePayload::Reason::IncompatibleParameters; + } else if (type == "media-error") { + return JinglePayload::Reason::MediaError; + } else if (type == "security-error") { + return JinglePayload::Reason::SecurityError; + } else if (type == "success") { + return JinglePayload::Reason::Success; + } else if (type == "timeout") { + return JinglePayload::Reason::Timeout; + } else if (type == "unsupported-applications") { + return JinglePayload::Reason::UnsupportedApplications; + } else if (type == "unsupported-transports") { + return JinglePayload::Reason::UnsupportedTransports; + } else { + return JinglePayload::Reason::UnknownType; + } + } } diff --git a/Swiften/Parser/PayloadParsers/JingleReasonParser.h b/Swiften/Parser/PayloadParsers/JingleReasonParser.h index 08af31a..a445448 100644 --- a/Swiften/Parser/PayloadParsers/JingleReasonParser.h +++ b/Swiften/Parser/PayloadParsers/JingleReasonParser.h @@ -4,27 +4,34 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/JinglePayload.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { -class JingleReasonParser : public GenericPayloadParser<JinglePayload::Reason> { - public: - JingleReasonParser(); +class SWIFTEN_API JingleReasonParser : public GenericPayloadParser<JinglePayload::Reason> { + public: + JingleReasonParser(); - 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: - JinglePayload::Reason::Type stringToReasonType(const std::string& type) const; + 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: + JinglePayload::Reason::Type stringToReasonType(const std::string& type) const; - private: - int level; - bool parseText; - std::string text; + private: + int level; + bool parseText; + std::string text; }; } diff --git a/Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.cpp b/Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.cpp index 14a80e6..a405e0e 100644 --- a/Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.cpp @@ -4,85 +4,91 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2014-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.h> + #include <boost/lexical_cast.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <boost/optional.hpp> -#include "JingleS5BTransportMethodPayloadParser.h" - #include <Swiften/Base/Log.h> namespace Swift { - JingleS5BTransportMethodPayloadParser::JingleS5BTransportMethodPayloadParser() : level(0) { - - } - - void JingleS5BTransportMethodPayloadParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level == 0) { - getPayloadInternal()->setSessionID(attributes.getAttributeValue("sid").get_value_or("")); - std::string mode = attributes.getAttributeValue("mode").get_value_or("tcp"); - if (mode == "tcp") { - getPayloadInternal()->setMode(JingleS5BTransportPayload::TCPMode); - } else if(mode == "udp") { - getPayloadInternal()->setMode(JingleS5BTransportPayload::UDPMode); - } else { - std::cerr << "Unknown S5B mode; falling back to defaul!" << std::endl; - getPayloadInternal()->setMode(JingleS5BTransportPayload::TCPMode); - } - } else if (level == 1) { - if (element == "candidate") { - JingleS5BTransportPayload::Candidate candidate; - candidate.cid = attributes.getAttributeValue("cid").get_value_or(""); + JingleS5BTransportMethodPayloadParser::JingleS5BTransportMethodPayloadParser() : level(0) { + + } + + void JingleS5BTransportMethodPayloadParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { + if (level == 0) { + getPayloadInternal()->setSessionID(attributes.getAttributeValue("sid").get_value_or("")); + std::string mode = attributes.getAttributeValue("mode").get_value_or("tcp"); + if (mode == "tcp") { + getPayloadInternal()->setMode(JingleS5BTransportPayload::TCPMode); + } else if(mode == "udp") { + getPayloadInternal()->setMode(JingleS5BTransportPayload::UDPMode); + } else { + SWIFT_LOG(warning) << "Unknown S5B mode; falling back to defaul!"; + getPayloadInternal()->setMode(JingleS5BTransportPayload::TCPMode); + } + getPayloadInternal()->setDstAddr(attributes.getAttributeValue("dstaddr").get_value_or("")); + } else if (level == 1) { + if (element == "candidate") { + JingleS5BTransportPayload::Candidate candidate; + candidate.cid = attributes.getAttributeValue("cid").get_value_or(""); + + unsigned short port = 0; + try { + port = boost::numeric_cast<unsigned short>(boost::lexical_cast<int>(attributes.getAttributeValue("port").get_value_or("0"))); + } catch(...) { } + candidate.hostPort = HostAddressPort(HostAddress::fromString(attributes.getAttributeValue("host").get_value_or("")).get_value_or(HostAddress()), port); + candidate.jid = JID(attributes.getAttributeValue("jid").get_value_or("")); + int priority = -1; + try { + priority = boost::lexical_cast<int>(attributes.getAttributeValue("priority").get_value_or("-1")); + } catch(boost::bad_lexical_cast &) { } + candidate.priority = priority; + candidate.type = stringToType(attributes.getAttributeValue("type").get_value_or("direct")); - int port = -1; - try { - port = boost::lexical_cast<int>(attributes.getAttributeValue("port").get_value_or("-1")); - } catch(boost::bad_lexical_cast &) { } - candidate.hostPort = HostAddressPort(HostAddress(attributes.getAttributeValue("host").get_value_or("")), port); - candidate.jid = JID(attributes.getAttributeValue("jid").get_value_or("")); - int priority = -1; - try { - priority = boost::lexical_cast<int>(attributes.getAttributeValue("priority").get_value_or("-1")); - } catch(boost::bad_lexical_cast &) { } - candidate.priority = priority; - candidate.type = stringToType(attributes.getAttributeValue("type").get_value_or("direct")); + getPayloadInternal()->addCandidate(candidate); + } else if (element == "candidate-used") { + getPayloadInternal()->setCandidateUsed(attributes.getAttributeValue("cid").get_value_or("")); + } else if (element == "candidate-error") { + getPayloadInternal()->setCandidateError(true); + } else if (element == "activated") { + getPayloadInternal()->setActivated(attributes.getAttributeValue("cid").get_value_or("")); + } else if (element == "proxy-error") { + getPayloadInternal()->setProxyError(true); + } + } - getPayloadInternal()->addCandidate(candidate); - } else if (element == "candidate-used") { - getPayloadInternal()->setCandidateUsed(attributes.getAttributeValue("cid").get_value_or("")); - } else if (element == "candidate-error") { - getPayloadInternal()->setCandidateError(true); - } else if (element == "activated") { - getPayloadInternal()->setActivated(attributes.getAttributeValue("cid").get_value_or("")); - } else if (element == "proxy-error") { - getPayloadInternal()->setProxyError(true); - } - } + ++level; + } - ++level; - } - - void JingleS5BTransportMethodPayloadParser::handleEndElement(const std::string&, const std::string&) { - --level; - + void JingleS5BTransportMethodPayloadParser::handleEndElement(const std::string&, const std::string&) { + --level; + } - } - - void JingleS5BTransportMethodPayloadParser::handleCharacterData(const std::string&) { + void JingleS5BTransportMethodPayloadParser::handleCharacterData(const std::string&) { - } + } - JingleS5BTransportPayload::Candidate::Type JingleS5BTransportMethodPayloadParser::stringToType(const std::string &str) const { - if (str == "direct") { - return JingleS5BTransportPayload::Candidate::DirectType; - } else if (str == "assisted") { - return JingleS5BTransportPayload::Candidate::AssistedType; - } else if (str == "tunnel") { - return JingleS5BTransportPayload::Candidate::TunnelType; - } else if (str == "proxy") { - return JingleS5BTransportPayload::Candidate::ProxyType; - } else { - std::cerr << "Unknown candidate type; falling back to default!" << std::endl; - return JingleS5BTransportPayload::Candidate::DirectType; - } - } + JingleS5BTransportPayload::Candidate::Type JingleS5BTransportMethodPayloadParser::stringToType(const std::string &str) const { + if (str == "direct") { + return JingleS5BTransportPayload::Candidate::DirectType; + } else if (str == "assisted") { + return JingleS5BTransportPayload::Candidate::AssistedType; + } else if (str == "tunnel") { + return JingleS5BTransportPayload::Candidate::TunnelType; + } else if (str == "proxy") { + return JingleS5BTransportPayload::Candidate::ProxyType; + } else { + SWIFT_LOG(warning) << "Unknown candidate type; falling back to default!"; + return JingleS5BTransportPayload::Candidate::DirectType; + } + } } diff --git a/Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.h b/Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.h index 1987d3f..f48c4b5 100644 --- a/Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.h @@ -4,26 +4,33 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { -class JingleS5BTransportMethodPayloadParser : public GenericPayloadParser<JingleS5BTransportPayload> { - public: - JingleS5BTransportMethodPayloadParser(); +class SWIFTEN_API JingleS5BTransportMethodPayloadParser : public GenericPayloadParser<JingleS5BTransportPayload> { + public: + JingleS5BTransportMethodPayloadParser(); - 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); + 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: - JingleS5BTransportPayload::Candidate::Type stringToType(const std::string &str) const; + private: + JingleS5BTransportPayload::Candidate::Type stringToType(const std::string &str) const; - private: - int level; + private: + int level; }; } diff --git a/Swiften/Parser/PayloadParsers/LastParser.cpp b/Swiften/Parser/PayloadParsers/LastParser.cpp index 77ebba8..89d39ac 100644 --- a/Swiften/Parser/PayloadParsers/LastParser.cpp +++ b/Swiften/Parser/PayloadParsers/LastParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/LastParser.h> @@ -14,16 +14,16 @@ LastParser::LastParser() : level_(0) { } void LastParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { - if (level_ == 0) { - int seconds = 0; - try { - seconds = boost::lexical_cast<int>(attributes.getAttribute("seconds")); - } - catch (boost::bad_lexical_cast&) { - } - getPayloadInternal()->setSeconds(seconds); - } - ++level_; + if (level_ == 0) { + int seconds = 0; + try { + seconds = boost::lexical_cast<int>(attributes.getAttribute("seconds")); + } + catch (boost::bad_lexical_cast&) { + } + getPayloadInternal()->setSeconds(seconds); + } + ++level_; } diff --git a/Swiften/Parser/PayloadParsers/LastParser.h b/Swiften/Parser/PayloadParsers/LastParser.h index 7c5c707..70bfdcb 100644 --- a/Swiften/Parser/PayloadParsers/LastParser.h +++ b/Swiften/Parser/PayloadParsers/LastParser.h @@ -1,24 +1,25 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Last.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class LastParser : public GenericPayloadParser<Last> { - public: - LastParser(); + class SWIFTEN_API LastParser : public GenericPayloadParser<Last> { + public: + LastParser(); - 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); + 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: - int level_; - }; + private: + int level_; + }; } diff --git a/Swiften/Parser/PayloadParsers/MAMFinParser.cpp b/Swiften/Parser/PayloadParsers/MAMFinParser.cpp new file mode 100644 index 0000000..88dd571 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMFinParser.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MAMFinParser.h> + +#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/ResultSetParser.h> + +using namespace Swift; + +MAMFinParser::MAMFinParser() : level_(TopLevel) { +} + +void MAMFinParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + if (level_ == TopLevel) { + getPayloadInternal()->setComplete(attributes.getBoolAttribute("complete", false)); + getPayloadInternal()->setStable(attributes.getBoolAttribute("stable", true)); + boost::optional<std::string> attributeValue; + if ((attributeValue = attributes.getAttributeValue("queryid"))) { + getPayloadInternal()->setQueryID(*attributeValue); + } + } + else if (level_ == PayloadLevel) { + if (element == "set" && ns == "http://jabber.org/protocol/rsm") { + resultSetParser_ = std::make_shared<ResultSetParser>(); + } + } + + if (resultSetParser_) { /* parsing a nested ResultSet */ + resultSetParser_->handleStartElement(element, ns, attributes); + } + + ++level_; +} + +void MAMFinParser::handleEndElement(const std::string& element, const std::string& ns) { + --level_; + + if (resultSetParser_ && level_ >= PayloadLevel) { + resultSetParser_->handleEndElement(element, ns); + } + if (resultSetParser_ && level_ == PayloadLevel) { + /* done parsing nested ResultSet */ + getPayloadInternal()->setResultSet(std::dynamic_pointer_cast<ResultSet>(resultSetParser_->getPayload())); + resultSetParser_.reset(); + } +} + +void MAMFinParser::handleCharacterData(const std::string& data) { + if (resultSetParser_) { + resultSetParser_->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/MAMFinParser.h b/Swiften/Parser/PayloadParsers/MAMFinParser.h new file mode 100644 index 0000000..419d542 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMFinParser.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MAMFin.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class ResultSetParser; + + class SWIFTEN_API MAMFinParser : public GenericPayloadParser<MAMFin> { + public: + MAMFinParser(); + + virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + + private: + std::shared_ptr<ResultSetParser> resultSetParser_; + int level_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MAMQueryParser.cpp b/Swiften/Parser/PayloadParsers/MAMQueryParser.cpp new file mode 100644 index 0000000..4919d22 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMQueryParser.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MAMQueryParser.h> + +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Parser/PayloadParsers/FormParser.h> +#include <Swiften/Parser/PayloadParsers/ResultSetParser.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); + } + if ((attributeValue = attributes.getAttributeValue("node"))) { + getPayloadInternal()->setNode(*attributeValue); + } + } else if (level_ == PayloadLevel) { + if (element == "x" && ns == "jabber:x:data") { + formParser_ = std::make_shared<FormParser>(); + } else if (element == "set" && ns == "http://jabber.org/protocol/rsm") { + resultSetParser_ = std::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(std::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(std::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..ab062c5 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMQueryParser.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MAMQuery.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + 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) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + + private: + std::shared_ptr<FormParser> formParser_; + std::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..b810b87 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMResultParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MAMResultParser.h> + +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Parser/PayloadParsers/ForwardedParser.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_ = std::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(std::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..f058e15 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MAMResultParser.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#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) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + + private: + std::shared_ptr<ForwardedParser> payloadParser_; + PayloadParserFactoryCollection* factories_; + int level_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXCreateParser.cpp b/Swiften/Parser/PayloadParsers/MIXCreateParser.cpp new file mode 100644 index 0000000..8c4ec8a --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXCreateParser.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MIXCreateParser.h> + +#include <boost/optional.hpp> + +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/FormParser.h> + +using namespace Swift; + +MIXCreateParser::MIXCreateParser() : level_(0) { +} + +MIXCreateParser::~MIXCreateParser() { +} + +void MIXCreateParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + if (level_ == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("channel")) { + getPayloadInternal()->setChannel(*attributeValue); + } + } + + if (level_ == 1) { + if (element == "x" && ns == "jabber:x:data") { + currentPayloadParser_ = std::make_shared<FormParser>(); + } + } + + if (level_ >= 1 && currentPayloadParser_) { + currentPayloadParser_->handleStartElement(element, ns, attributes); + } + ++level_; +} + +void MIXCreateParser::handleEndElement(const std::string& element, const std::string& ns) { + --level_; + if (currentPayloadParser_) { + if (level_ >= 1) { + currentPayloadParser_->handleEndElement(element, ns); + } + + if (level_ == 1) { + if (element == "x" && ns == "jabber:x:data") { + getPayloadInternal()->setData(std::dynamic_pointer_cast<Form>(currentPayloadParser_->getPayload())); + } + currentPayloadParser_.reset(); + } + } +} + +void MIXCreateParser::handleCharacterData(const std::string& data) { + if (level_ > 1 && currentPayloadParser_) { + currentPayloadParser_->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/MIXCreateParser.h b/Swiften/Parser/PayloadParsers/MIXCreateParser.h new file mode 100644 index 0000000..ef123e1 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXCreateParser.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXCreate.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class PayloadParser; + + class SWIFTEN_API MIXCreateParser : public GenericPayloadParser<MIXCreate> { + public: + MIXCreateParser(); + virtual ~MIXCreateParser() override; + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + private: + int level_; + std::shared_ptr<PayloadParser> currentPayloadParser_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXDestroyParser.cpp b/Swiften/Parser/PayloadParsers/MIXDestroyParser.cpp new file mode 100644 index 0000000..0437b48 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXDestroyParser.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MIXDestroyParser.h> + +#include <boost/optional.hpp> + +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/FormParser.h> + +using namespace Swift; + +MIXDestroyParser::MIXDestroyParser() : level_(0) { +} + +MIXDestroyParser::~MIXDestroyParser() { +} + +void MIXDestroyParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { + if (level_ == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("channel")) { + getPayloadInternal()->setChannel(*attributeValue); + } + } + ++level_; +} + +void MIXDestroyParser::handleEndElement(const std::string&, const std::string&) { + --level_; +} + +void MIXDestroyParser::handleCharacterData(const std::string&) { +} diff --git a/Swiften/Parser/PayloadParsers/MIXDestroyParser.h b/Swiften/Parser/PayloadParsers/MIXDestroyParser.h new file mode 100644 index 0000000..8cfd91e --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXDestroyParser.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXDestroy.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class PayloadParser; + + class SWIFTEN_API MIXDestroyParser : public GenericPayloadParser<MIXDestroy> { + public: + MIXDestroyParser(); + virtual ~MIXDestroyParser() override; + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + private: + int level_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXJoinParser.cpp b/Swiften/Parser/PayloadParsers/MIXJoinParser.cpp new file mode 100644 index 0000000..6e72f90 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXJoinParser.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MIXJoinParser.h> + +#include <boost/optional.hpp> + +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/FormParser.h> + +using namespace Swift; + +MIXJoinParser::MIXJoinParser() : level_(0) { +} + +MIXJoinParser::~MIXJoinParser() { +} + +void MIXJoinParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + if (level_ == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("channel")) { + if (boost::optional<JID> jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setChannel(*jid); + } + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { + if (boost::optional<JID> jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setJID(*jid); + } + } + } + + if (level_ == 1) { + if (element == "subscribe" && ns == "urn:xmpp:mix:0") { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->addSubscription(*attributeValue); + } + } + if (element == "x" && ns == "jabber:x:data") { + currentPayloadParser_ = std::make_shared<FormParser>(); + } + } + + if (level_ >= 1 && currentPayloadParser_) { + currentPayloadParser_->handleStartElement(element, ns, attributes); + } + ++level_; +} + +void MIXJoinParser::handleEndElement(const std::string& element, const std::string& ns) { + --level_; + if (currentPayloadParser_) { + if (level_ >= 1) { + currentPayloadParser_->handleEndElement(element, ns); + } + + if (level_ == 1) { + if (element == "x" && ns == "jabber:x:data") { + getPayloadInternal()->setForm(std::dynamic_pointer_cast<Form>(currentPayloadParser_->getPayload())); + } + currentPayloadParser_.reset(); + } + } +} + +void MIXJoinParser::handleCharacterData(const std::string& data) { + if (level_ > 1 && currentPayloadParser_) { + currentPayloadParser_->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/MIXJoinParser.h b/Swiften/Parser/PayloadParsers/MIXJoinParser.h new file mode 100644 index 0000000..f371d6f --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXJoinParser.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXJoin.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class PayloadParser; + + class SWIFTEN_API MIXJoinParser : public GenericPayloadParser<MIXJoin> { + public: + MIXJoinParser(); + virtual ~MIXJoinParser() override; + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + private: + int level_; + std::shared_ptr<PayloadParser> currentPayloadParser_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXJoinParserFactory.h b/Swiften/Parser/PayloadParsers/MIXJoinParserFactory.h new file mode 100644 index 0000000..8432c61 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXJoinParserFactory.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Parser/GenericPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MIXJoinParser.h> + +namespace Swift { + class SWIFTEN_API MIXJoinParserFactory : public PayloadParserFactory { + public: + MIXJoinParserFactory() { + } + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return element == "join" && ns == "urn:xmpp:mix:0"; + } + + virtual PayloadParser* createPayloadParser() { + return new MIXJoinParser(); + } + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXLeaveParser.cpp b/Swiften/Parser/PayloadParsers/MIXLeaveParser.cpp new file mode 100644 index 0000000..6330925 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXLeaveParser.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MIXLeaveParser.h> + +#include <boost/optional.hpp> + +namespace Swift { + +MIXLeaveParser::MIXLeaveParser() : level_(0) { +} + +MIXLeaveParser::~MIXLeaveParser() { +} + +void MIXLeaveParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { + if (level_ == 0) { + if (auto attributeValue = attributes.getAttributeValue("channel")) { + if (auto jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setChannel(*jid); + } + } + } + ++level_; +} + +void MIXLeaveParser::handleEndElement(const std::string&, const std::string&) { + --level_; +} + +void MIXLeaveParser::handleCharacterData(const std::string&) { + +} +} diff --git a/Swiften/Parser/PayloadParsers/MIXLeaveParser.h b/Swiften/Parser/PayloadParsers/MIXLeaveParser.h new file mode 100644 index 0000000..b0798b4 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXLeaveParser.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXLeave.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + + class SWIFTEN_API MIXLeaveParser : public GenericPayloadParser<MIXLeave> { + public: + MIXLeaveParser(); + virtual ~MIXLeaveParser() override; + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + private: + int level_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXParticipantParser.cpp b/Swiften/Parser/PayloadParsers/MIXParticipantParser.cpp new file mode 100644 index 0000000..0ab2b87 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXParticipantParser.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MIXParticipantParser.h> + +namespace Swift { + +void MIXParticipantParser::handleTree(ParserElement::ref root) { + for (const auto& child : root->getAllChildren()) { + if (child->getName() == "nick" && child->getNamespace() == root->getNamespace()) { + getPayloadInternal()->setNick(child->getText()); + } + else if (child->getName() == "jid" && child->getNamespace() == root->getNamespace()) { + if (boost::optional<JID> jid = JID::parse(child->getText())) { + getPayloadInternal()->setJID(*jid); + } + } + } +} + +} diff --git a/Swiften/Parser/PayloadParsers/MIXParticipantParser.h b/Swiften/Parser/PayloadParsers/MIXParticipantParser.h new file mode 100644 index 0000000..0a3ea57 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXParticipantParser.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXParticipant.h> +#include <Swiften/Parser/GenericPayloadTreeParser.h> + +namespace Swift { + class SWIFTEN_API MIXParticipantParser : public GenericPayloadTreeParser<MIXParticipant> { + public: + MIXParticipantParser() {} + virtual void handleTree(ParserElement::ref root); + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXParticipantParserFactory.h b/Swiften/Parser/PayloadParsers/MIXParticipantParserFactory.h new file mode 100644 index 0000000..cd7c17e --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXParticipantParserFactory.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Parser/GenericPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MIXParticipantParser.h> + +namespace Swift { + class SWIFTEN_API MIXParticipantParserFactory : public PayloadParserFactory { + public: + MIXParticipantParserFactory() { + } + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return element == "participant" && ns == "urn:xmpp:mix:0"; + } + + virtual PayloadParser* createPayloadParser() { + return new MIXParticipantParser(); + } + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MIXPayloadParser.cpp new file mode 100644 index 0000000..51ef584 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXPayloadParser.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MIXPayloadParser.h> + +namespace Swift { + +void MIXPayloadParser::handleTree(ParserElement::ref root) { + for (const auto& child : root->getAllChildren()) { + if (child->getName() == "nick" && child->getNamespace() == root->getNamespace()) { + getPayloadInternal()->setNick(child->getText()); + } else if (child->getName() == "jid" && child->getNamespace() == root->getNamespace()) { + if (boost::optional<JID> jid = JID::parse(child->getText())) { + getPayloadInternal()->setJID(*jid); + } + } else if (child->getName() == "submission-id" && child->getNamespace() == root->getNamespace()) { + getPayloadInternal()->setSubmissionID(child->getText()); + } + } +} + +} diff --git a/Swiften/Parser/PayloadParsers/MIXPayloadParser.h b/Swiften/Parser/PayloadParsers/MIXPayloadParser.h new file mode 100644 index 0000000..9133e8b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXPayloadParser.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXPayload.h> +#include <Swiften/Parser/GenericPayloadTreeParser.h> + +namespace Swift { + class SWIFTEN_API MIXPayloadParser : public GenericPayloadTreeParser<MIXPayload> { + public: + MIXPayloadParser() {} + virtual void handleTree(ParserElement::ref root) override; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXPayloadParserFactory.h b/Swiften/Parser/PayloadParsers/MIXPayloadParserFactory.h new file mode 100644 index 0000000..8397b78 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXPayloadParserFactory.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Parser/GenericPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MIXPayloadParser.h> + +namespace Swift { + class SWIFTEN_API MIXPayloadParserFactory : public PayloadParserFactory { + public: + MIXPayloadParserFactory() { + } + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const override { + return element == "mix" && ns == "urn:xmpp:mix:0"; + } + + virtual PayloadParser* createPayloadParser() override { + return new MIXPayloadParser(); + } + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXRegisterNickParser.cpp b/Swiften/Parser/PayloadParsers/MIXRegisterNickParser.cpp new file mode 100644 index 0000000..945e9b2 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXRegisterNickParser.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MIXRegisterNickParser.h> + +namespace Swift { + +void MIXRegisterNickParser::handleTree(ParserElement::ref root) { + for (const auto& child : root->getAllChildren()) { + if (child->getName() == "nick" && child->getNamespace() == root->getNamespace()) { + getPayloadInternal()->setNick(child->getText()); + } + } +} + +} diff --git a/Swiften/Parser/PayloadParsers/MIXRegisterNickParser.h b/Swiften/Parser/PayloadParsers/MIXRegisterNickParser.h new file mode 100644 index 0000000..cfb618e --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXRegisterNickParser.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXRegisterNick.h> +#include <Swiften/Parser/GenericPayloadTreeParser.h> + +namespace Swift { + class SWIFTEN_API MIXRegisterNickParser : public GenericPayloadTreeParser<MIXRegisterNick> { + public: + MIXRegisterNickParser() {} + virtual void handleTree(ParserElement::ref root) override; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXRegisterNickParserFactory.h b/Swiften/Parser/PayloadParsers/MIXRegisterNickParserFactory.h new file mode 100644 index 0000000..e03392c --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXRegisterNickParserFactory.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Parser/GenericPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MIXRegisterNickParser.h> + +namespace Swift { + class SWIFTEN_API MIXRegisterNickParserFactory : public PayloadParserFactory { + public: + MIXRegisterNickParserFactory() { + } + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const override { + return element == "register" && ns == "urn:xmpp:mix:0"; + } + + virtual PayloadParser* createPayloadParser() override { + return new MIXRegisterNickParser(); + } + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXSetNickParser.cpp b/Swiften/Parser/PayloadParsers/MIXSetNickParser.cpp new file mode 100644 index 0000000..34fec70 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXSetNickParser.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MIXSetNickParser.h> + +namespace Swift { + +void MIXSetNickParser::handleTree(ParserElement::ref root) { + for (const auto& child : root->getAllChildren()) { + if (child->getName() == "nick" && child->getNamespace() == root->getNamespace()) { + getPayloadInternal()->setNick(child->getText()); + } + } +} + +} diff --git a/Swiften/Parser/PayloadParsers/MIXSetNickParser.h b/Swiften/Parser/PayloadParsers/MIXSetNickParser.h new file mode 100644 index 0000000..6d552c8 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXSetNickParser.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXSetNick.h> +#include <Swiften/Parser/GenericPayloadTreeParser.h> + +namespace Swift { + class SWIFTEN_API MIXSetNickParser : public GenericPayloadTreeParser<MIXSetNick> { + public: + MIXSetNickParser() {} + virtual void handleTree(ParserElement::ref root) override; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXSetNickParserFactory.h b/Swiften/Parser/PayloadParsers/MIXSetNickParserFactory.h new file mode 100644 index 0000000..e028873 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXSetNickParserFactory.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Parser/GenericPayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/MIXSetNickParser.h> + +namespace Swift { + class SWIFTEN_API MIXSetNickParserFactory : public PayloadParserFactory { + public: + MIXSetNickParserFactory() { + } + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const override { + return element == "setnick" && ns == "urn:xmpp:mix:0"; + } + + virtual PayloadParser* createPayloadParser() override { + return new MIXSetNickParser(); + } + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXUpdateSubscriptionParser.cpp b/Swiften/Parser/PayloadParsers/MIXUpdateSubscriptionParser.cpp new file mode 100644 index 0000000..d530e49 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXUpdateSubscriptionParser.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MIXUpdateSubscriptionParser.h> + +#include <boost/optional.hpp> + +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/FormParser.h> + +namespace Swift { + +MIXUpdateSubscriptionParser::MIXUpdateSubscriptionParser() : level_(0) { +} + +MIXUpdateSubscriptionParser::~MIXUpdateSubscriptionParser() { +} + +void MIXUpdateSubscriptionParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + if (level_ == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { + if (boost::optional<JID> jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setJID(*jid); + } + } + } + + if (level_ == 1) { + if (element == "subscribe" && ns == "urn:xmpp:mix:0") { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->addSubscription(*attributeValue); + } + } + } + + ++level_; +} + +void MIXUpdateSubscriptionParser::handleEndElement(const std::string&, const std::string&) { + --level_; +} + +void MIXUpdateSubscriptionParser::handleCharacterData(const std::string&) { +} + +} diff --git a/Swiften/Parser/PayloadParsers/MIXUpdateSubscriptionParser.h b/Swiften/Parser/PayloadParsers/MIXUpdateSubscriptionParser.h new file mode 100644 index 0000000..47966ff --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXUpdateSubscriptionParser.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXUpdateSubscription.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class PayloadParser; + + class SWIFTEN_API MIXUpdateSubscriptionParser : public GenericPayloadParser<MIXUpdateSubscription> { + public: + MIXUpdateSubscriptionParser(); + virtual ~MIXUpdateSubscriptionParser() override; + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + private: + int level_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MIXUserPreferenceParser.cpp b/Swiften/Parser/PayloadParsers/MIXUserPreferenceParser.cpp new file mode 100644 index 0000000..f40547d --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXUserPreferenceParser.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/MIXUserPreferenceParser.h> + +#include <boost/optional.hpp> + +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/FormParser.h> + +namespace Swift { + +MIXUserPreferenceParser::MIXUserPreferenceParser() : level_(0) { +} + +MIXUserPreferenceParser::~MIXUserPreferenceParser() { +} + +void MIXUserPreferenceParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + + + if (level_ == 1) { + if (element == "x" && ns == "jabber:x:data") { + currentPayloadParser_ = std::make_shared<FormParser>(); + } + } + + if (level_ >= 1 && currentPayloadParser_) { + currentPayloadParser_->handleStartElement(element, ns, attributes); + } + ++level_; +} + +void MIXUserPreferenceParser::handleEndElement(const std::string& element, const std::string& ns) { + --level_; + if (currentPayloadParser_) { + if (level_ >= 1) { + currentPayloadParser_->handleEndElement(element, ns); + } + + if (level_ == 1) { + if (element == "x" && ns == "jabber:x:data") { + getPayloadInternal()->setData(std::dynamic_pointer_cast<Form>(currentPayloadParser_->getPayload())); + } + currentPayloadParser_.reset(); + } + } +} + +void MIXUserPreferenceParser::handleCharacterData(const std::string& data) { + if (level_ > 1 && currentPayloadParser_) { + currentPayloadParser_->handleCharacterData(data); + } +} +} diff --git a/Swiften/Parser/PayloadParsers/MIXUserPreferenceParser.h b/Swiften/Parser/PayloadParsers/MIXUserPreferenceParser.h new file mode 100644 index 0000000..b2a2c10 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MIXUserPreferenceParser.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXUserPreference.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class PayloadParser; + + class SWIFTEN_API MIXUserPreferenceParser : public GenericPayloadParser<MIXUserPreference> { + public: + MIXUserPreferenceParser(); + virtual ~MIXUserPreferenceParser() override; + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + private: + int level_; + std::shared_ptr<PayloadParser> currentPayloadParser_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp index 137ead4..bac2a78 100644 --- a/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp @@ -1,23 +1,22 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h> #include <boost/lexical_cast.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/Elements/MUCOccupant.h> namespace Swift { void MUCAdminPayloadParser::handleTree(ParserElement::ref root) { - foreach (ParserElement::ref itemElement, root->getChildren("item", "http://jabber.org/protocol/muc#admin")) { - MUCItem item = MUCItemParser::itemFromTree(itemElement); - getPayloadInternal()->addItem(item); - } + for (const auto& itemElement : root->getChildren("item", "http://jabber.org/protocol/muc#admin")) { + MUCItem item = MUCItemParser::itemFromTree(itemElement); + getPayloadInternal()->addItem(item); + } } } diff --git a/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h index dfa26da..de46690 100644 --- a/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h @@ -1,20 +1,21 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCAdminPayload.h> #include <Swiften/Parser/GenericPayloadTreeParser.h> #include <Swiften/Parser/PayloadParsers/MUCItemParser.h> namespace Swift { - class MUCAdminPayloadParser : public GenericPayloadTreeParser<MUCAdminPayload> { - public: - virtual void handleTree(ParserElement::ref root); - }; + class SWIFTEN_API MUCAdminPayloadParser : public GenericPayloadTreeParser<MUCAdminPayload> { + public: + virtual void handleTree(ParserElement::ref root); + }; } diff --git a/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.cpp index a8d29d0..46bc9c5 100644 --- a/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.cpp @@ -1,22 +1,20 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.h> -#include <Swiften/Base/foreach.h> - namespace Swift { void MUCDestroyPayloadParser::handleTree(ParserElement::ref root) { - std::string ns = root->getNamespace(); - std::string jid = root->getAttributes().getAttribute("jid"); - if (!jid.empty()) { - getPayloadInternal()->setNewVenue(JID(jid)); - } - getPayloadInternal()->setReason(root->getChild("reason", ns)->getText()); + std::string ns = root->getNamespace(); + std::string jid = root->getAttributes().getAttribute("jid"); + if (!jid.empty()) { + getPayloadInternal()->setNewVenue(JID(jid)); + } + getPayloadInternal()->setReason(root->getChild("reason", ns)->getText()); } } diff --git a/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.h index 714651f..e79d9a6 100644 --- a/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.h @@ -1,19 +1,20 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCDestroyPayload.h> #include <Swiften/Parser/GenericPayloadTreeParser.h> namespace Swift { - class MUCDestroyPayloadParser : public GenericPayloadTreeParser<MUCDestroyPayload> { - public: - virtual void handleTree(ParserElement::ref root); - }; + class SWIFTEN_API MUCDestroyPayloadParser : public GenericPayloadTreeParser<MUCDestroyPayload> { + public: + virtual void handleTree(ParserElement::ref root); + }; } diff --git a/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.cpp index c1cf33d..14d6d16 100644 --- a/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.cpp @@ -1,23 +1,24 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.h> - +#include <Swiften/Parser/Tree/NullParserElement.h> namespace Swift { void MUCInvitationPayloadParser::handleTree(ParserElement::ref root) { - MUCInvitationPayload::ref invite = getPayloadInternal(); - invite->setIsContinuation(root->getAttributes().getBoolAttribute("continue", false)); - invite->setJID(JID(root->getAttributes().getAttribute("jid"))); - invite->setPassword(root->getAttributes().getAttribute("password")); - invite->setReason(root->getAttributes().getAttribute("reason")); - invite->setThread(root->getAttributes().getAttribute("thread")); - invite->setIsImpromptu(root->getChild("impromptu", "http://swift.im/impromptu") ? true : false); + MUCInvitationPayload::ref invite = getPayloadInternal(); + invite->setIsContinuation(root->getAttributes().getBoolAttribute("continue", false)); + invite->setJID(JID(root->getAttributes().getAttribute("jid"))); + invite->setPassword(root->getAttributes().getAttribute("password")); + invite->setReason(root->getAttributes().getAttribute("reason")); + invite->setThread(root->getAttributes().getAttribute("thread")); + ParserElement::ref impromptuNode = root->getChild("impromptu", "http://swift.im/impromptu"); + invite->setIsImpromptu(!std::dynamic_pointer_cast<NullParserElement>(impromptuNode)); } } diff --git a/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.h index 2cd3535..7b76166 100644 --- a/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCInvitationPayload.h> #include <Swiften/Parser/GenericPayloadTreeParser.h> namespace Swift { - class MUCInvitationPayloadParser : public GenericPayloadTreeParser<MUCInvitationPayload> { - public: - virtual void handleTree(ParserElement::ref root); - }; + class SWIFTEN_API MUCInvitationPayloadParser : public GenericPayloadTreeParser<MUCInvitationPayload> { + public: + virtual void handleTree(ParserElement::ref root); + }; } diff --git a/Swiften/Parser/PayloadParsers/MUCItemParser.cpp b/Swiften/Parser/PayloadParsers/MUCItemParser.cpp index 2eb9997..ce74671 100644 --- a/Swiften/Parser/PayloadParsers/MUCItemParser.cpp +++ b/Swiften/Parser/PayloadParsers/MUCItemParser.cpp @@ -1,80 +1,79 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/MUCItemParser.h> +#include <cassert> + #include <boost/lexical_cast.hpp> #include <Swiften/Elements/MUCOccupant.h> -#include <cassert> -#include <iostream> - namespace Swift { MUCItem MUCItemParser::itemFromTree(ParserElement::ref root) { - MUCItem item; - std::string affiliation = root->getAttributes().getAttribute("affiliation"); - std::string role = root->getAttributes().getAttribute("role"); - std::string nick = root->getAttributes().getAttribute("nick"); - std::string jid = root->getAttributes().getAttribute("jid"); - item.affiliation = parseAffiliation(affiliation); - item.role = parseRole(role); - if (!jid.empty()) { - item.realJID = JID(jid); - } - if (!nick.empty()) { - item.nick = nick; - } - std::string xmlns = root->getNamespace(); - std::string reason = root->getChild("reason", xmlns)->getText(); - std::string actor = root->getChild("actor", xmlns)->getAttributes().getAttribute("jid"); - if (!reason.empty()) { - item.reason = reason; - } - if (!actor.empty()) { - item.actor = JID(actor); - } + MUCItem item; + std::string affiliation = root->getAttributes().getAttribute("affiliation"); + std::string role = root->getAttributes().getAttribute("role"); + std::string nick = root->getAttributes().getAttribute("nick"); + std::string jid = root->getAttributes().getAttribute("jid"); + item.affiliation = parseAffiliation(affiliation); + item.role = parseRole(role); + if (!jid.empty()) { + item.realJID = JID(jid); + } + if (!nick.empty()) { + item.nick = nick; + } + std::string xmlns = root->getNamespace(); + std::string reason = root->getChild("reason", xmlns)->getText(); + std::string actor = root->getChild("actor", xmlns)->getAttributes().getAttribute("jid"); + if (!reason.empty()) { + item.reason = reason; + } + if (!actor.empty()) { + item.actor = JID(actor); + } - return item; + return item; } boost::optional<MUCOccupant::Role> MUCItemParser::parseRole(const std::string& roleString) { - if (roleString == "moderator") { - return MUCOccupant::Moderator; - } - if (roleString == "participant") { - return MUCOccupant::Participant; - } - if (roleString == "visitor") { - return MUCOccupant::Visitor; - } - if (roleString == "none") { - return MUCOccupant::NoRole; - } - return boost::optional<MUCOccupant::Role>(); + if (roleString == "moderator") { + return MUCOccupant::Moderator; + } + if (roleString == "participant") { + return MUCOccupant::Participant; + } + if (roleString == "visitor") { + return MUCOccupant::Visitor; + } + if (roleString == "none") { + return MUCOccupant::NoRole; + } + return boost::optional<MUCOccupant::Role>(); } boost::optional<MUCOccupant::Affiliation> MUCItemParser::parseAffiliation(const std::string& affiliationString) { - if (affiliationString == "owner") { - return MUCOccupant::Owner; - } - if (affiliationString == "admin") { - return MUCOccupant::Admin; - } - if (affiliationString == "member") { - return MUCOccupant::Member; - } - if (affiliationString == "outcast") { - return MUCOccupant::Outcast; - } - if (affiliationString == "none") { - return MUCOccupant::NoAffiliation; - } - return boost::optional<MUCOccupant::Affiliation>(); + if (affiliationString == "owner") { + return MUCOccupant::Owner; + } + if (affiliationString == "admin") { + return MUCOccupant::Admin; + } + if (affiliationString == "member") { + return MUCOccupant::Member; + } + if (affiliationString == "outcast") { + return MUCOccupant::Outcast; + } + if (affiliationString == "none") { + return MUCOccupant::NoAffiliation; + } + return boost::optional<MUCOccupant::Affiliation>(); } } diff --git a/Swiften/Parser/PayloadParsers/MUCItemParser.h b/Swiften/Parser/PayloadParsers/MUCItemParser.h index a0ea060..6f80d54 100644 --- a/Swiften/Parser/PayloadParsers/MUCItemParser.h +++ b/Swiften/Parser/PayloadParsers/MUCItemParser.h @@ -1,20 +1,21 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCItem.h> #include <Swiften/Parser/GenericPayloadTreeParser.h> namespace Swift { - class MUCItemParser { - public: - static MUCItem itemFromTree(ParserElement::ref root); - private: - static boost::optional<MUCOccupant::Role> parseRole(const std::string& itemString); - static boost::optional<MUCOccupant::Affiliation> parseAffiliation(const std::string& statusString); - }; + class SWIFTEN_API MUCItemParser { + public: + static MUCItem itemFromTree(ParserElement::ref root); + private: + static boost::optional<MUCOccupant::Role> parseRole(const std::string& itemString); + static boost::optional<MUCOccupant::Affiliation> parseAffiliation(const std::string& statusString); + }; } diff --git a/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.cpp index d7ae789..7e7c0d4 100644 --- a/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.h> -#include <Swiften/Parser/PayloadParserFactoryCollection.h> + #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> namespace Swift { @@ -14,36 +15,36 @@ MUCOwnerPayloadParser::MUCOwnerPayloadParser(PayloadParserFactoryCollection* fac } void MUCOwnerPayloadParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 1) { - PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); - if (payloadParserFactory) { - currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); - } - } - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 1) { + PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); + if (payloadParserFactory) { + currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void MUCOwnerPayloadParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - getPayloadInternal()->setPayload(currentPayloadParser->getPayload()); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + getPayloadInternal()->setPayload(currentPayloadParser->getPayload()); + } + } } void MUCOwnerPayloadParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } } diff --git a/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.h index 2761981..4c1f048 100644 --- a/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCOwnerPayload.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; + class PayloadParserFactoryCollection; - class MUCOwnerPayloadParser : public GenericPayloadParser<MUCOwnerPayload> { - public: - MUCOwnerPayloadParser(PayloadParserFactoryCollection* factories); + class SWIFTEN_API MUCOwnerPayloadParser : public GenericPayloadParser<MUCOwnerPayload> { + public: + MUCOwnerPayloadParser(PayloadParserFactoryCollection* factories); - private: - 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: + 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: - PayloadParserFactoryCollection* factories; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* factories; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParserFactory.h b/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParserFactory.h index 918c72c..d6399e7 100644 --- a/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParserFactory.h +++ b/Swiften/Parser/PayloadParsers/MUCOwnerPayloadParserFactory.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/MUCOwnerPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; + class PayloadParserFactoryCollection; - class MUCOwnerPayloadParserFactory : public PayloadParserFactory { - public: - MUCOwnerPayloadParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { - } + class SWIFTEN_API MUCOwnerPayloadParserFactory : public PayloadParserFactory { + public: + MUCOwnerPayloadParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { + } - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return element == "query" && ns == "http://jabber.org/protocol/muc#owner"; - } + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return element == "query" && ns == "http://jabber.org/protocol/muc#owner"; + } - virtual PayloadParser* createPayloadParser() { - return new MUCOwnerPayloadParser(factories); - } + virtual PayloadParser* createPayloadParser() { + return new MUCOwnerPayloadParser(factories); + } - private: - PayloadParserFactoryCollection* factories; + private: + PayloadParserFactoryCollection* factories; - }; + }; } diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp index d206010..b1bf78e 100644 --- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp @@ -1,58 +1,57 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h> #include <boost/lexical_cast.hpp> -#include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Parser/PayloadParserFactory.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Elements/MUCOccupant.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/Tree/TreeReparser.h> namespace Swift { void MUCUserPayloadParser::handleTree(ParserElement::ref root) { - foreach (ParserElement::ref child, root->getAllChildren()) { - if (child->getName() == "item" && child->getNamespace() == root->getNamespace()) { - MUCItem item = MUCItemParser::itemFromTree(child); - getPayloadInternal()->addItem(item); - } - else if (child->getName() == "password" && child->getNamespace() == root->getNamespace()) { - getPayloadInternal()->setPassword(child->getText()); - } - else if (child->getName() == "invite" && child->getNamespace() == root->getNamespace()) { - MUCUserPayload::Invite invite; - std::string to = child->getAttributes().getAttribute("to"); - if (!to.empty()) { - invite.to = to; - } - std::string from = child->getAttributes().getAttribute("from"); - if (!from.empty()) { - invite.from = from; - } - ParserElement::ref reason = child->getChild("reason", root->getNamespace()); - if (reason) { - invite.reason = reason->getText(); - } - getPayloadInternal()->setInvite(invite); - } - else if (child->getName() == "status" && child->getNamespace() == root->getNamespace()) { - MUCUserPayload::StatusCode status; - try { - status.code = boost::lexical_cast<int>(child->getAttributes().getAttribute("code").c_str()); - getPayloadInternal()->addStatusCode(status); - } catch (boost::bad_lexical_cast&) { - } - } - else { - getPayloadInternal()->setPayload(TreeReparser::parseTree(child, factories)); - } - } + for (const auto& child : root->getAllChildren()) { + if (child->getName() == "item" && child->getNamespace() == root->getNamespace()) { + MUCItem item = MUCItemParser::itemFromTree(child); + getPayloadInternal()->addItem(item); + } + else if (child->getName() == "password" && child->getNamespace() == root->getNamespace()) { + getPayloadInternal()->setPassword(child->getText()); + } + else if (child->getName() == "invite" && child->getNamespace() == root->getNamespace()) { + MUCUserPayload::Invite invite; + std::string to = child->getAttributes().getAttribute("to"); + if (!to.empty()) { + invite.to = to; + } + std::string from = child->getAttributes().getAttribute("from"); + if (!from.empty()) { + invite.from = from; + } + ParserElement::ref reason = child->getChild("reason", root->getNamespace()); + if (reason) { + invite.reason = reason->getText(); + } + getPayloadInternal()->setInvite(invite); + } + else if (child->getName() == "status" && child->getNamespace() == root->getNamespace()) { + MUCUserPayload::StatusCode status; + try { + status.code = boost::lexical_cast<int>(child->getAttributes().getAttribute("code").c_str()); + getPayloadInternal()->addStatusCode(status); + } catch (boost::bad_lexical_cast&) { + } + } + else { + getPayloadInternal()->setPayload(TreeReparser::parseTree(child, factories)); + } + } } } diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h index 66e63a8..3d6dbab 100644 --- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCUserPayload.h> #include <Swiften/Parser/GenericPayloadTreeParser.h> #include <Swiften/Parser/PayloadParsers/MUCItemParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class MUCUserPayloadParser : public GenericPayloadTreeParser<MUCUserPayload> { - public: - MUCUserPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {} - virtual void handleTree(ParserElement::ref root); - private: - PayloadParserFactoryCollection* factories; - }; + class PayloadParserFactoryCollection; + class SWIFTEN_API MUCUserPayloadParser : public GenericPayloadTreeParser<MUCUserPayload> { + public: + MUCUserPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {} + virtual void handleTree(ParserElement::ref root); + private: + PayloadParserFactoryCollection* factories; + }; } diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h b/Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h index 2c1c915..4a0380d 100644 --- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h +++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h @@ -1,29 +1,30 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/GenericPayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h> namespace Swift { - class MUCUserPayloadParserFactory : public PayloadParserFactory { - public: - MUCUserPayloadParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { - } + class SWIFTEN_API MUCUserPayloadParserFactory : public PayloadParserFactory { + public: + MUCUserPayloadParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { + } - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return element == "x" && ns == "http://jabber.org/protocol/muc#user"; - } + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return element == "x" && ns == "http://jabber.org/protocol/muc#user"; + } - virtual PayloadParser* createPayloadParser() { - return new MUCUserPayloadParser(factories); - } + virtual PayloadParser* createPayloadParser() { + return new MUCUserPayloadParser(factories); + } - private: - PayloadParserFactoryCollection* factories; - }; + private: + PayloadParserFactoryCollection* factories; + }; } diff --git a/Swiften/Parser/PayloadParsers/NicknameParser.cpp b/Swiften/Parser/PayloadParsers/NicknameParser.cpp index b647b4d..331355a 100644 --- a/Swiften/Parser/PayloadParsers/NicknameParser.cpp +++ b/Swiften/Parser/PayloadParsers/NicknameParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/NicknameParser.h> @@ -12,18 +12,18 @@ NicknameParser::NicknameParser() : level(0) { } void NicknameParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++level; + ++level; } void NicknameParser::handleEndElement(const std::string&, const std::string&) { - --level; - if (level == 0) { - getPayloadInternal()->setNickname(text); - } + --level; + if (level == 0) { + getPayloadInternal()->setNickname(text); + } } void NicknameParser::handleCharacterData(const std::string& data) { - text += data; + text += data; } } diff --git a/Swiften/Parser/PayloadParsers/NicknameParser.h b/Swiften/Parser/PayloadParsers/NicknameParser.h index a89f835..1bdd600 100644 --- a/Swiften/Parser/PayloadParsers/NicknameParser.h +++ b/Swiften/Parser/PayloadParsers/NicknameParser.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Nickname.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class NicknameParser : public GenericPayloadParser<Nickname> { - public: - NicknameParser(); + class SWIFTEN_API NicknameParser : public GenericPayloadParser<Nickname> { + public: + NicknameParser(); - 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); + 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: - int level; - std::string text; - }; + private: + int level; + std::string text; + }; } diff --git a/Swiften/Parser/PayloadParsers/PriorityParser.cpp b/Swiften/Parser/PayloadParsers/PriorityParser.cpp index b440444..88eef0d 100644 --- a/Swiften/Parser/PayloadParsers/PriorityParser.cpp +++ b/Swiften/Parser/PayloadParsers/PriorityParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/PriorityParser.h> @@ -14,24 +14,24 @@ PriorityParser::PriorityParser() : level_(0) { } void PriorityParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++level_; + ++level_; } void PriorityParser::handleEndElement(const std::string&, const std::string&) { - --level_; - if (level_ == 0) { - int priority = 0; - try { - priority = boost::lexical_cast<int>(text_); - } - catch (boost::bad_lexical_cast&) { - } - getPayloadInternal()->setPriority(priority); - } + --level_; + if (level_ == 0) { + int priority = 0; + try { + priority = boost::lexical_cast<int>(text_); + } + catch (boost::bad_lexical_cast&) { + } + getPayloadInternal()->setPriority(priority); + } } void PriorityParser::handleCharacterData(const std::string& data) { - text_ += data; + text_ += data; } } diff --git a/Swiften/Parser/PayloadParsers/PriorityParser.h b/Swiften/Parser/PayloadParsers/PriorityParser.h index 8d6bf86..e6bf059 100644 --- a/Swiften/Parser/PayloadParsers/PriorityParser.h +++ b/Swiften/Parser/PayloadParsers/PriorityParser.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Priority.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PriorityParser : public GenericPayloadParser<Priority> { - public: - PriorityParser(); + class SWIFTEN_API PriorityParser : public GenericPayloadParser<Priority> { + public: + PriorityParser(); - 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); + 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: - int level_; - std::string text_; - }; + private: + int level_; + std::string text_; + }; } diff --git a/Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp b/Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp index bf16394..e40249a 100644 --- a/Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp +++ b/Swiften/Parser/PayloadParsers/PrivateStorageParser.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/PrivateStorageParser.h> -#include <Swiften/Parser/PayloadParserFactoryCollection.h> + #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> namespace Swift { @@ -14,36 +15,36 @@ PrivateStorageParser::PrivateStorageParser(PayloadParserFactoryCollection* facto } void PrivateStorageParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 1) { - PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); - if (payloadParserFactory) { - currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); - } - } - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 1) { + PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes); + if (payloadParserFactory) { + currentPayloadParser.reset(payloadParserFactory->createPayloadParser()); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PrivateStorageParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - getPayloadInternal()->setPayload(currentPayloadParser->getPayload()); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + getPayloadInternal()->setPayload(currentPayloadParser->getPayload()); + } + } } void PrivateStorageParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } } diff --git a/Swiften/Parser/PayloadParsers/PrivateStorageParser.h b/Swiften/Parser/PayloadParsers/PrivateStorageParser.h index d350593..c1d695c 100644 --- a/Swiften/Parser/PayloadParsers/PrivateStorageParser.h +++ b/Swiften/Parser/PayloadParsers/PrivateStorageParser.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/PrivateStorage.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; + class PayloadParserFactoryCollection; - class PrivateStorageParser : public GenericPayloadParser<PrivateStorage> { - public: - PrivateStorageParser(PayloadParserFactoryCollection* factories); + class SWIFTEN_API PrivateStorageParser : public GenericPayloadParser<PrivateStorage> { + public: + PrivateStorageParser(PayloadParserFactoryCollection* factories); - private: - 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: + 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: - PayloadParserFactoryCollection* factories; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* factories; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h b/Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h index 5b93aef..550177c 100644 --- a/Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h +++ b/Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/PrivateStorageParser.h> namespace Swift { - class PayloadParserFactoryCollection; + class PayloadParserFactoryCollection; - class PrivateStorageParserFactory : public PayloadParserFactory { - public: - PrivateStorageParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { - } + class SWIFTEN_API PrivateStorageParserFactory : public PayloadParserFactory { + public: + PrivateStorageParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { + } - virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { - return element == "query" && ns == "jabber:iq:private"; - } + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return element == "query" && ns == "jabber:iq:private"; + } - virtual PayloadParser* createPayloadParser() { - return new PrivateStorageParser(factories); - } + virtual PayloadParser* createPayloadParser() { + return new PrivateStorageParser(factories); + } - private: - PayloadParserFactoryCollection* factories; - - }; + private: + PayloadParserFactoryCollection* factories; + + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.cpp b/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.cpp index 05fa119..764b3a7 100644 --- a/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.cpp @@ -1,64 +1,58 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubAffiliationParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/EnumParser.h> +#include <Swiften/Parser/PayloadParserFactory.h> using namespace Swift; -PubSubAffiliationParser::PubSubAffiliationParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubAffiliationParser::PubSubAffiliationParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubAffiliationParser::~PubSubAffiliationParser() { } void PubSubAffiliationParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("affiliation")) { - if (boost::optional<PubSubAffiliation::Type> value = EnumParser<PubSubAffiliation::Type>()(PubSubAffiliation::None, "none")(PubSubAffiliation::Member, "member")(PubSubAffiliation::Outcast, "outcast")(PubSubAffiliation::Owner, "owner")(PubSubAffiliation::Publisher, "publisher")(PubSubAffiliation::PublishOnly, "publish-only").parse(*attributeValue)) { - getPayloadInternal()->setType(*value); - } - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("affiliation")) { + if (boost::optional<PubSubAffiliation::Type> value = EnumParser<PubSubAffiliation::Type>()(PubSubAffiliation::None, "none")(PubSubAffiliation::Member, "member")(PubSubAffiliation::Outcast, "outcast")(PubSubAffiliation::Owner, "owner")(PubSubAffiliation::Publisher, "publisher")(PubSubAffiliation::PublishOnly, "publish-only").parse(*attributeValue)) { + getPayloadInternal()->setType(*value); + } + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubAffiliationParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { - if (level == 1) { - - currentPayloadParser.reset(); - } - } + currentPayloadParser.reset(); + } + } } void PubSubAffiliationParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.h b/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.h index 43c619d..383ceae 100644 --- a/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubAffiliation.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubAffiliationParser : public GenericPayloadParser<PubSubAffiliation> { - public: - PubSubAffiliationParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubAffiliationParser(); + class SWIFTEN_API PubSubAffiliationParser : public GenericPayloadParser<PubSubAffiliation> { + public: + PubSubAffiliationParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubAffiliationParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.cpp index b75e339..ffa5d2d 100644 --- a/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.cpp @@ -1,18 +1,15 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubAffiliationParser.h> using namespace Swift; @@ -24,42 +21,42 @@ PubSubAffiliationsParser::~PubSubAffiliationsParser() { } void PubSubAffiliationsParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } - - if (level == 1) { - if (element == "affiliation" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubAffiliationParser>(parsers); - } - } - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } + + if (level == 1) { + if (element == "affiliation" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubAffiliationParser>(parsers); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubAffiliationsParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - if (element == "affiliation" && ns == "http://jabber.org/protocol/pubsub") { - getPayloadInternal()->addAffiliation(boost::dynamic_pointer_cast<PubSubAffiliation>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + if (element == "affiliation" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->addAffiliation(std::dynamic_pointer_cast<PubSubAffiliation>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubAffiliationsParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.h b/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.h index 646e7a8..48e3825 100644 --- a/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubAffiliations.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubAffiliationsParser : public GenericPayloadParser<PubSubAffiliations> { - public: - PubSubAffiliationsParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubAffiliationsParser(); + class SWIFTEN_API PubSubAffiliationsParser : public GenericPayloadParser<PubSubAffiliations> { + public: + PubSubAffiliationsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubAffiliationsParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubConfigureParser.cpp b/Swiften/Parser/PayloadParsers/PubSubConfigureParser.cpp index 773c1c7..e0a5847 100644 --- a/Swiften/Parser/PayloadParsers/PubSubConfigureParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubConfigureParser.cpp @@ -1,61 +1,57 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubConfigureParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParser.h> using namespace Swift; -PubSubConfigureParser::PubSubConfigureParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubConfigureParser::PubSubConfigureParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubConfigureParser::~PubSubConfigureParser() { } void PubSubConfigureParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - - - if (level == 1) { - if (element == "x" && ns == "jabber:x:data") { - currentPayloadParser = boost::make_shared<FormParser>(); - } - } - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + + + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + currentPayloadParser = std::make_shared<FormParser>(); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubConfigureParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - if (element == "x" && ns == "jabber:x:data") { - getPayloadInternal()->setData(boost::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + getPayloadInternal()->setData(std::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubConfigureParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubConfigureParser.h b/Swiften/Parser/PayloadParsers/PubSubConfigureParser.h index 8300140..e53d477 100644 --- a/Swiften/Parser/PayloadParsers/PubSubConfigureParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubConfigureParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubConfigure.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubConfigureParser : public GenericPayloadParser<PubSubConfigure> { - public: - PubSubConfigureParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubConfigureParser(); + class SWIFTEN_API PubSubConfigureParser : public GenericPayloadParser<PubSubConfigure> { + public: + PubSubConfigureParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubConfigureParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubCreateParser.cpp b/Swiften/Parser/PayloadParsers/PubSubCreateParser.cpp index 47f35c9..4f03e29 100644 --- a/Swiften/Parser/PayloadParsers/PubSubCreateParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubCreateParser.cpp @@ -1,59 +1,52 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubCreateParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - using namespace Swift; -PubSubCreateParser::PubSubCreateParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubCreateParser::PubSubCreateParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubCreateParser::~PubSubCreateParser() { } void PubSubCreateParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubCreateParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } } void PubSubCreateParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubCreateParser.h b/Swiften/Parser/PayloadParsers/PubSubCreateParser.h index 865b8ec..626419c 100644 --- a/Swiften/Parser/PayloadParsers/PubSubCreateParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubCreateParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubCreate.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubCreateParser : public GenericPayloadParser<PubSubCreate> { - public: - PubSubCreateParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubCreateParser(); + class SWIFTEN_API PubSubCreateParser : public GenericPayloadParser<PubSubCreate> { + public: + PubSubCreateParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubCreateParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubDefaultParser.cpp b/Swiften/Parser/PayloadParsers/PubSubDefaultParser.cpp index 7a370cd..a6d751c 100644 --- a/Swiften/Parser/PayloadParsers/PubSubDefaultParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubDefaultParser.cpp @@ -1,64 +1,58 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubDefaultParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/EnumParser.h> +#include <Swiften/Parser/PayloadParserFactory.h> using namespace Swift; -PubSubDefaultParser::PubSubDefaultParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubDefaultParser::PubSubDefaultParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubDefaultParser::~PubSubDefaultParser() { } void PubSubDefaultParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("type")) { - if (boost::optional<PubSubDefault::Type> value = EnumParser<PubSubDefault::Type>()(PubSubDefault::None, "none")(PubSubDefault::Collection, "collection")(PubSubDefault::Leaf, "leaf").parse(*attributeValue)) { - getPayloadInternal()->setType(*value); - } - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("type")) { + if (boost::optional<PubSubDefault::Type> value = EnumParser<PubSubDefault::Type>()(PubSubDefault::None, "none")(PubSubDefault::Collection, "collection")(PubSubDefault::Leaf, "leaf").parse(*attributeValue)) { + getPayloadInternal()->setType(*value); + } + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubDefaultParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { - if (level == 1) { - - currentPayloadParser.reset(); - } - } + currentPayloadParser.reset(); + } + } } void PubSubDefaultParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubDefaultParser.h b/Swiften/Parser/PayloadParsers/PubSubDefaultParser.h index 7bd8d66..08f6b43 100644 --- a/Swiften/Parser/PayloadParsers/PubSubDefaultParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubDefaultParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubDefault.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubDefaultParser : public GenericPayloadParser<PubSubDefault> { - public: - PubSubDefaultParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubDefaultParser(); + class SWIFTEN_API PubSubDefaultParser : public GenericPayloadParser<PubSubDefault> { + public: + PubSubDefaultParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubDefaultParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubErrorParser.cpp b/Swiften/Parser/PayloadParsers/PubSubErrorParser.cpp index 9752cd2..99a306d 100644 --- a/Swiften/Parser/PayloadParsers/PubSubErrorParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubErrorParser.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -9,95 +9,95 @@ using namespace Swift; PubSubErrorParser::PubSubErrorParser() : level(0) { - typeParser - (PubSubError::ClosedNode, "closed-node") - (PubSubError::ConfigurationRequired, "configuration-required") - (PubSubError::InvalidJID, "invalid-jid") - (PubSubError::InvalidOptions, "invalid-options") - (PubSubError::InvalidPayload, "invalid-payload") - (PubSubError::InvalidSubscriptionID, "invalid-subid") - (PubSubError::ItemForbidden, "item-forbidden") - (PubSubError::ItemRequired, "item-required") - (PubSubError::JIDRequired, "jid-required") - (PubSubError::MaximumItemsExceeded, "max-items-exceeded") - (PubSubError::MaximumNodesExceeded, "max-nodes-exceeded") - (PubSubError::NodeIDRequired, "nodeid-required") - (PubSubError::NotInRosterGroup, "not-in-roster-group") - (PubSubError::NotSubscribed, "not-subscribed") - (PubSubError::PayloadTooBig, "payload-too-big") - (PubSubError::PayloadRequired, "payload-required") - (PubSubError::PendingSubscription, "pending-subscription") - (PubSubError::PresenceSubscriptionRequired, "presence-subscription-required") - (PubSubError::SubscriptionIDRequired, "subid-required") - (PubSubError::TooManySubscriptions, "too-many-subscriptions") - (PubSubError::Unsupported, "unsupported") - (PubSubError::UnsupportedAccessModel, "unsupported-access-model"); - unsupportedTypeParser - (PubSubError::AccessAuthorize, "access-authorize") - (PubSubError::AccessOpen, "access-open") - (PubSubError::AccessPresence, "access-presence") - (PubSubError::AccessRoster, "access-roster") - (PubSubError::AccessWhitelist, "access-whitelist") - (PubSubError::AutoCreate, "auto-create") - (PubSubError::AutoSubscribe, "auto-subscribe") - (PubSubError::Collections, "collections") - (PubSubError::ConfigNode, "config-node") - (PubSubError::CreateAndConfigure, "create-and-configure") - (PubSubError::CreateNodes, "create-nodes") - (PubSubError::DeleteItems, "delete-items") - (PubSubError::DeleteNodes, "delete-nodes") - (PubSubError::FilteredNotifications, "filtered-notifications") - (PubSubError::GetPending, "get-pending") - (PubSubError::InstantNodes, "instant-nodes") - (PubSubError::ItemIDs, "item-ids") - (PubSubError::LastPublished, "last-published") - (PubSubError::LeasedSubscription, "leased-subscription") - (PubSubError::ManageSubscriptions, "manage-subscriptions") - (PubSubError::MemberAffiliation, "member-affiliation") - (PubSubError::MetaData, "meta-data") - (PubSubError::ModifyAffiliations, "modify-affiliations") - (PubSubError::MultiCollection, "multi-collection") - (PubSubError::MultiSubscribe, "multi-subscribe") - (PubSubError::OutcastAffiliation, "outcast-affiliation") - (PubSubError::PersistentItems, "persistent-items") - (PubSubError::PresenceNotifications, "presence-notifications") - (PubSubError::PresenceSubscribe, "presence-subscribe") - (PubSubError::Publish, "publish") - (PubSubError::PublishOptions, "publish-options") - (PubSubError::PublishOnlyAffiliation, "publish-only-affiliation") - (PubSubError::PublisherAffiliation, "publisher-affiliation") - (PubSubError::PurgeNodes, "purge-nodes") - (PubSubError::RetractItems, "retract-items") - (PubSubError::RetrieveAffiliations, "retrieve-affiliations") - (PubSubError::RetrieveDefault, "retrieve-default") - (PubSubError::RetrieveItems, "retrieve-items") - (PubSubError::RetrieveSubscriptions, "retrieve-subscriptions") - (PubSubError::Subscribe, "subscribe") - (PubSubError::SubscriptionOptions, "subscription-options") - (PubSubError::SubscriptionNotifications, "subscription-notifications"); + typeParser + (PubSubError::ClosedNode, "closed-node") + (PubSubError::ConfigurationRequired, "configuration-required") + (PubSubError::InvalidJID, "invalid-jid") + (PubSubError::InvalidOptions, "invalid-options") + (PubSubError::InvalidPayload, "invalid-payload") + (PubSubError::InvalidSubscriptionID, "invalid-subid") + (PubSubError::ItemForbidden, "item-forbidden") + (PubSubError::ItemRequired, "item-required") + (PubSubError::JIDRequired, "jid-required") + (PubSubError::MaximumItemsExceeded, "max-items-exceeded") + (PubSubError::MaximumNodesExceeded, "max-nodes-exceeded") + (PubSubError::NodeIDRequired, "nodeid-required") + (PubSubError::NotInRosterGroup, "not-in-roster-group") + (PubSubError::NotSubscribed, "not-subscribed") + (PubSubError::PayloadTooBig, "payload-too-big") + (PubSubError::PayloadRequired, "payload-required") + (PubSubError::PendingSubscription, "pending-subscription") + (PubSubError::PresenceSubscriptionRequired, "presence-subscription-required") + (PubSubError::SubscriptionIDRequired, "subid-required") + (PubSubError::TooManySubscriptions, "too-many-subscriptions") + (PubSubError::Unsupported, "unsupported") + (PubSubError::UnsupportedAccessModel, "unsupported-access-model"); + unsupportedTypeParser + (PubSubError::AccessAuthorize, "access-authorize") + (PubSubError::AccessOpen, "access-open") + (PubSubError::AccessPresence, "access-presence") + (PubSubError::AccessRoster, "access-roster") + (PubSubError::AccessWhitelist, "access-whitelist") + (PubSubError::AutoCreate, "auto-create") + (PubSubError::AutoSubscribe, "auto-subscribe") + (PubSubError::Collections, "collections") + (PubSubError::ConfigNode, "config-node") + (PubSubError::CreateAndConfigure, "create-and-configure") + (PubSubError::CreateNodes, "create-nodes") + (PubSubError::DeleteItems, "delete-items") + (PubSubError::DeleteNodes, "delete-nodes") + (PubSubError::FilteredNotifications, "filtered-notifications") + (PubSubError::GetPending, "get-pending") + (PubSubError::InstantNodes, "instant-nodes") + (PubSubError::ItemIDs, "item-ids") + (PubSubError::LastPublished, "last-published") + (PubSubError::LeasedSubscription, "leased-subscription") + (PubSubError::ManageSubscriptions, "manage-subscriptions") + (PubSubError::MemberAffiliation, "member-affiliation") + (PubSubError::MetaData, "meta-data") + (PubSubError::ModifyAffiliations, "modify-affiliations") + (PubSubError::MultiCollection, "multi-collection") + (PubSubError::MultiSubscribe, "multi-subscribe") + (PubSubError::OutcastAffiliation, "outcast-affiliation") + (PubSubError::PersistentItems, "persistent-items") + (PubSubError::PresenceNotifications, "presence-notifications") + (PubSubError::PresenceSubscribe, "presence-subscribe") + (PubSubError::Publish, "publish") + (PubSubError::PublishOptions, "publish-options") + (PubSubError::PublishOnlyAffiliation, "publish-only-affiliation") + (PubSubError::PublisherAffiliation, "publisher-affiliation") + (PubSubError::PurgeNodes, "purge-nodes") + (PubSubError::RetractItems, "retract-items") + (PubSubError::RetrieveAffiliations, "retrieve-affiliations") + (PubSubError::RetrieveDefault, "retrieve-default") + (PubSubError::RetrieveItems, "retrieve-items") + (PubSubError::RetrieveSubscriptions, "retrieve-subscriptions") + (PubSubError::Subscribe, "subscribe") + (PubSubError::SubscriptionOptions, "subscription-options") + (PubSubError::SubscriptionNotifications, "subscription-notifications"); } PubSubErrorParser::~PubSubErrorParser() { } void PubSubErrorParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level == 1) { - if (boost::optional<PubSubError::Type> type = typeParser.parse(element)) { - getPayloadInternal()->setType(*type); - if (type == PubSubError::Unsupported) { - if (boost::optional<std::string> feature = attributes.getAttributeValue("feature")) { - if (boost::optional<PubSubError::UnsupportedFeatureType> unsupportedType = unsupportedTypeParser.parse(*feature)) { - getPayloadInternal()->setUnsupportedFeatureType(*unsupportedType); - } - } - } - } - } - ++level; + if (level == 1) { + if (boost::optional<PubSubError::Type> type = typeParser.parse(element)) { + getPayloadInternal()->setType(*type); + if (type == PubSubError::Unsupported) { + if (boost::optional<std::string> feature = attributes.getAttributeValue("feature")) { + if (boost::optional<PubSubError::UnsupportedFeatureType> unsupportedType = unsupportedTypeParser.parse(*feature)) { + getPayloadInternal()->setUnsupportedFeatureType(*unsupportedType); + } + } + } + } + } + ++level; } void PubSubErrorParser::handleEndElement(const std::string&, const std::string&) { - --level; + --level; } void PubSubErrorParser::handleCharacterData(const std::string&) { diff --git a/Swiften/Parser/PayloadParsers/PubSubErrorParser.h b/Swiften/Parser/PayloadParsers/PubSubErrorParser.h index eb7dcfe..273da82 100644 --- a/Swiften/Parser/PayloadParsers/PubSubErrorParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubErrorParser.h @@ -1,35 +1,31 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubError.h> -#include <Swiften/Parser/GenericPayloadParser.h> #include <Swiften/Parser/EnumParser.h> +#include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; - - class SWIFTEN_API PubSubErrorParser : public GenericPayloadParser<PubSubError> { - public: - PubSubErrorParser(); - virtual ~PubSubErrorParser(); + class SWIFTEN_API PubSubErrorParser : public GenericPayloadParser<PubSubError> { + public: + PubSubErrorParser(); + virtual ~PubSubErrorParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - int level; - EnumParser<PubSubError::Type> typeParser; - EnumParser<PubSubError::UnsupportedFeatureType> unsupportedTypeParser; - }; + private: + int level; + EnumParser<PubSubError::Type> typeParser; + EnumParser<PubSubError::UnsupportedFeatureType> unsupportedTypeParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.cpp b/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.cpp index 10dfd63..0e94c14 100644 --- a/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h b/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h index e2386da..c7a3614 100644 --- a/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h +++ b/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h @@ -1,29 +1,30 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2015 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/PubSubErrorParser.h> namespace Swift { - class PubSubErrorParserFactory : public PayloadParserFactory { - public: - PubSubErrorParserFactory() { - } - ~PubSubErrorParserFactory(); + class SWIFTEN_API PubSubErrorParserFactory : public PayloadParserFactory { + public: + PubSubErrorParserFactory() { + } + ~PubSubErrorParserFactory(); - virtual bool canParse(const std::string&, const std::string& ns, const AttributeMap&) const { - return ns == "http://jabber.org/protocol/pubsub#errors"; - } + virtual bool canParse(const std::string&, const std::string& ns, const AttributeMap&) const { + return ns == "http://jabber.org/protocol/pubsub#errors"; + } - virtual PayloadParser* createPayloadParser() { - return new PubSubErrorParser(); - } - }; + virtual PayloadParser* createPayloadParser() { + return new PubSubErrorParser(); + } + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.cpp index f187be8..8ca1d7d 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.cpp @@ -1,59 +1,54 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - using namespace Swift; -PubSubEventAssociateParser::PubSubEventAssociateParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubEventAssociateParser::PubSubEventAssociateParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubEventAssociateParser::~PubSubEventAssociateParser() { } void PubSubEventAssociateParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } + + + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventAssociateParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } } void PubSubEventAssociateParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.h b/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.h index 000edf2..f4d6327 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventAssociate.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventAssociateParser : public GenericPayloadParser<PubSubEventAssociate> { - public: - PubSubEventAssociateParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventAssociateParser(); + class SWIFTEN_API PubSubEventAssociateParser : public GenericPayloadParser<PubSubEventAssociate> { + public: + PubSubEventAssociateParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventAssociateParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.cpp index 08b9c65..4452601 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.cpp @@ -1,18 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.h> #include <Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.h> @@ -25,48 +24,48 @@ PubSubEventCollectionParser::~PubSubEventCollectionParser() { } void PubSubEventCollectionParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } - if (level == 1) { - if (element == "disassociate" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventDisassociateParser>(parsers); - } - if (element == "associate" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventAssociateParser>(parsers); - } - } + if (level == 1) { + if (element == "disassociate" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventDisassociateParser>(parsers); + } + if (element == "associate" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventAssociateParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventCollectionParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "disassociate" && ns == "http://jabber.org/protocol/pubsub#event") { - getPayloadInternal()->setDisassociate(boost::dynamic_pointer_cast<PubSubEventDisassociate>(currentPayloadParser->getPayload())); - } - if (element == "associate" && ns == "http://jabber.org/protocol/pubsub#event") { - getPayloadInternal()->setAssociate(boost::dynamic_pointer_cast<PubSubEventAssociate>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "disassociate" && ns == "http://jabber.org/protocol/pubsub#event") { + getPayloadInternal()->setDisassociate(std::dynamic_pointer_cast<PubSubEventDisassociate>(currentPayloadParser->getPayload())); + } + if (element == "associate" && ns == "http://jabber.org/protocol/pubsub#event") { + getPayloadInternal()->setAssociate(std::dynamic_pointer_cast<PubSubEventAssociate>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubEventCollectionParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.h b/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.h index aad97d2..ffa1deb 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventCollection.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventCollectionParser : public GenericPayloadParser<PubSubEventCollection> { - public: - PubSubEventCollectionParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventCollectionParser(); + class SWIFTEN_API PubSubEventCollectionParser : public GenericPayloadParser<PubSubEventCollection> { + public: + PubSubEventCollectionParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventCollectionParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.cpp index f905299..9bde91b 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.cpp @@ -1,65 +1,61 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParser.h> using namespace Swift; -PubSubEventConfigurationParser::PubSubEventConfigurationParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubEventConfigurationParser::PubSubEventConfigurationParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubEventConfigurationParser::~PubSubEventConfigurationParser() { } void PubSubEventConfigurationParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } - - if (level == 1) { - if (element == "x" && ns == "jabber:x:data") { - currentPayloadParser = boost::make_shared<FormParser>(); - } - } - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } + + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + currentPayloadParser = std::make_shared<FormParser>(); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventConfigurationParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - if (element == "x" && ns == "jabber:x:data") { - getPayloadInternal()->setData(boost::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + getPayloadInternal()->setData(std::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubEventConfigurationParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.h b/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.h index 7189460..6b68d86 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventConfiguration.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventConfigurationParser : public GenericPayloadParser<PubSubEventConfiguration> { - public: - PubSubEventConfigurationParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventConfigurationParser(); + class SWIFTEN_API PubSubEventConfigurationParser : public GenericPayloadParser<PubSubEventConfiguration> { + public: + PubSubEventConfigurationParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventConfigurationParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.cpp index 03c7423..1569b90 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.cpp @@ -1,18 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.h> using namespace Swift; @@ -24,42 +23,42 @@ PubSubEventDeleteParser::~PubSubEventDeleteParser() { } void PubSubEventDeleteParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } - if (level == 1) { - if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventRedirectParser>(parsers); - } - } + if (level == 1) { + if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventRedirectParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventDeleteParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#event") { - getPayloadInternal()->setRedirects(boost::dynamic_pointer_cast<PubSubEventRedirect>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#event") { + getPayloadInternal()->setRedirects(std::dynamic_pointer_cast<PubSubEventRedirect>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubEventDeleteParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.h b/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.h index 36f8e0b..54a1913 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventDelete.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventDeleteParser : public GenericPayloadParser<PubSubEventDelete> { - public: - PubSubEventDeleteParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventDeleteParser(); + class SWIFTEN_API PubSubEventDeleteParser : public GenericPayloadParser<PubSubEventDelete> { + public: + PubSubEventDeleteParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventDeleteParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.cpp index 287ac35..4e72d85 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.cpp @@ -1,59 +1,52 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - using namespace Swift; -PubSubEventDisassociateParser::PubSubEventDisassociateParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubEventDisassociateParser::PubSubEventDisassociateParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubEventDisassociateParser::~PubSubEventDisassociateParser() { } void PubSubEventDisassociateParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventDisassociateParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } } void PubSubEventDisassociateParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.h b/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.h index 9015100..6a0a7ce 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventDisassociate.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventDisassociateParser : public GenericPayloadParser<PubSubEventDisassociate> { - public: - PubSubEventDisassociateParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventDisassociateParser(); + class SWIFTEN_API PubSubEventDisassociateParser : public GenericPayloadParser<PubSubEventDisassociate> { + public: + PubSubEventDisassociateParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventDisassociateParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventItemParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventItemParser.cpp index 8903545..ba8f714 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventItemParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventItemParser.cpp @@ -1,19 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubEventItemParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - +#include <Swiften/Parser/PayloadParserFactoryCollection.h> using namespace Swift; @@ -24,46 +22,46 @@ PubSubEventItemParser::~PubSubEventItemParser() { } void PubSubEventItemParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("publisher")) { - getPayloadInternal()->setPublisher(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("id")) { - getPayloadInternal()->setID(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("publisher")) { + getPayloadInternal()->setPublisher(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("id")) { + getPayloadInternal()->setID(*attributeValue); + } + } - if (level == 1) { - if (PayloadParserFactory* factory = parsers->getPayloadParserFactory(element, ns, attributes)) { - currentPayloadParser.reset(factory->createPayloadParser()); - } - } + if (level == 1) { + if (PayloadParserFactory* factory = parsers->getPayloadParserFactory(element, ns, attributes)) { + currentPayloadParser.reset(factory->createPayloadParser()); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventItemParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - getPayloadInternal()->addData(currentPayloadParser->getPayload()); - currentPayloadParser.reset(); - } - } + if (level == 1) { + getPayloadInternal()->addData(currentPayloadParser->getPayload()); + currentPayloadParser.reset(); + } + } } void PubSubEventItemParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventItemParser.h b/Swiften/Parser/PayloadParsers/PubSubEventItemParser.h index 6c16043..e9a986d 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventItemParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventItemParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventItem.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventItemParser : public GenericPayloadParser<PubSubEventItem> { - public: - PubSubEventItemParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventItemParser(); + class SWIFTEN_API PubSubEventItemParser : public GenericPayloadParser<PubSubEventItem> { + public: + PubSubEventItemParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventItemParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.cpp index fa155e9..ae4f668 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.cpp @@ -1,20 +1,19 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubEventItemsParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> -#include <Swiften/Parser/PayloadParsers/PubSubEventRetractParser.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubEventItemParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubEventRetractParser.h> using namespace Swift; @@ -25,48 +24,48 @@ PubSubEventItemsParser::~PubSubEventItemsParser() { } void PubSubEventItemsParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } - if (level == 1) { - if (element == "item" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventItemParser>(parsers); - } - if (element == "retract" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventRetractParser>(parsers); - } - } + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventItemParser>(parsers); + } + if (element == "retract" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventRetractParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventItemsParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "item" && ns == "http://jabber.org/protocol/pubsub#event") { - getPayloadInternal()->addItem(boost::dynamic_pointer_cast<PubSubEventItem>(currentPayloadParser->getPayload())); - } - if (element == "retract" && ns == "http://jabber.org/protocol/pubsub#event") { - getPayloadInternal()->addRetract(boost::dynamic_pointer_cast<PubSubEventRetract>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub#event") { + getPayloadInternal()->addItem(std::dynamic_pointer_cast<PubSubEventItem>(currentPayloadParser->getPayload())); + } + if (element == "retract" && ns == "http://jabber.org/protocol/pubsub#event") { + getPayloadInternal()->addRetract(std::dynamic_pointer_cast<PubSubEventRetract>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubEventItemsParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.h b/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.h index 60ecb25..067a9f7 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventItems.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventItemsParser : public GenericPayloadParser<PubSubEventItems> { - public: - PubSubEventItemsParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventItemsParser(); + class SWIFTEN_API PubSubEventItemsParser : public GenericPayloadParser<PubSubEventItems> { + public: + PubSubEventItemsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventItemsParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventParser.cpp index c4406a9..d92730a 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventParser.cpp @@ -1,24 +1,23 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubEventParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> -#include <Swiften/Parser/PayloadParsers/PubSubEventItemsParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.h> #include <Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubEventItemsParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.h> using namespace Swift; @@ -29,53 +28,53 @@ PubSubEventParser::~PubSubEventParser() { } void PubSubEventParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - - if (level == 1) { - if (element == "items" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventItemsParser>(parsers); - } - if (element == "collection" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventCollectionParser>(parsers); - } - if (element == "purge" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventPurgeParser>(parsers); - } - if (element == "configuration" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventConfigurationParser>(parsers); - } - if (element == "delete" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventDeleteParser>(parsers); - } - if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub#event") { - currentPayloadParser = boost::make_shared<PubSubEventSubscriptionParser>(parsers); - } - } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 1) { + if (element == "items" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventItemsParser>(parsers); + } + if (element == "collection" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventCollectionParser>(parsers); + } + if (element == "purge" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventPurgeParser>(parsers); + } + if (element == "configuration" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventConfigurationParser>(parsers); + } + if (element == "delete" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventDeleteParser>(parsers); + } + if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = std::make_shared<PubSubEventSubscriptionParser>(parsers); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (currentPayloadParser) { - getPayloadInternal()->setPayload(boost::dynamic_pointer_cast<PubSubEventPayload>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (currentPayloadParser) { + getPayloadInternal()->setPayload(std::dynamic_pointer_cast<PubSubEventPayload>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubEventParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventParser.h b/Swiften/Parser/PayloadParsers/PubSubEventParser.h index 1042e75..02cf01f 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEvent.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventParser : public GenericPayloadParser<PubSubEvent> { - public: - PubSubEventParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventParser(); + class SWIFTEN_API PubSubEventParser : public GenericPayloadParser<PubSubEvent> { + public: + PubSubEventParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.cpp index 14d1e96..30a4d6c 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.cpp @@ -1,59 +1,52 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - using namespace Swift; -PubSubEventPurgeParser::PubSubEventPurgeParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubEventPurgeParser::PubSubEventPurgeParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubEventPurgeParser::~PubSubEventPurgeParser() { } void PubSubEventPurgeParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventPurgeParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } } void PubSubEventPurgeParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.h b/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.h index 740bff3..1c9e623 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventPurge.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventPurgeParser : public GenericPayloadParser<PubSubEventPurge> { - public: - PubSubEventPurgeParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventPurgeParser(); + class SWIFTEN_API PubSubEventPurgeParser : public GenericPayloadParser<PubSubEventPurge> { + public: + PubSubEventPurgeParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventPurgeParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.cpp index f053117..46f1922 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.cpp @@ -1,59 +1,52 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - using namespace Swift; -PubSubEventRedirectParser::PubSubEventRedirectParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubEventRedirectParser::PubSubEventRedirectParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubEventRedirectParser::~PubSubEventRedirectParser() { } void PubSubEventRedirectParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("uri")) { - getPayloadInternal()->setURI(*attributeValue); - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("uri")) { + getPayloadInternal()->setURI(*attributeValue); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventRedirectParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } } void PubSubEventRedirectParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.h b/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.h index 33880ed..be7593e 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventRedirect.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventRedirectParser : public GenericPayloadParser<PubSubEventRedirect> { - public: - PubSubEventRedirectParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventRedirectParser(); + class SWIFTEN_API PubSubEventRedirectParser : public GenericPayloadParser<PubSubEventRedirect> { + public: + PubSubEventRedirectParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventRedirectParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.cpp index da3dea3..226bb33 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.cpp @@ -1,59 +1,53 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubEventRetractParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - +#include <Swiften/Parser/PayloadParserFactoryCollection.h> using namespace Swift; -PubSubEventRetractParser::PubSubEventRetractParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubEventRetractParser::PubSubEventRetractParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubEventRetractParser::~PubSubEventRetractParser() { } void PubSubEventRetractParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("id")) { - getPayloadInternal()->setID(*attributeValue); - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("id")) { + getPayloadInternal()->setID(*attributeValue); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventRetractParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } } void PubSubEventRetractParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.h b/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.h index 115bb7a..83a8e66 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventRetract.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventRetractParser : public GenericPayloadParser<PubSubEventRetract> { - public: - PubSubEventRetractParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventRetractParser(); + class SWIFTEN_API PubSubEventRetractParser : public GenericPayloadParser<PubSubEventRetract> { + public: + PubSubEventRetractParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventRetractParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.cpp index 3367202..45c16f6 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.cpp @@ -1,76 +1,70 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Base/DateTime.h> #include <Swiften/Parser/EnumParser.h> +#include <Swiften/Parser/PayloadParserFactory.h> using namespace Swift; -PubSubEventSubscriptionParser::PubSubEventSubscriptionParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubEventSubscriptionParser::PubSubEventSubscriptionParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubEventSubscriptionParser::~PubSubEventSubscriptionParser() { } void PubSubEventSubscriptionParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { - if (boost::optional<JID> jid = JID::parse(*attributeValue)) { - getPayloadInternal()->setJID(*jid); - } - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subscription")) { - if (boost::optional<PubSubEventSubscription::SubscriptionType> value = EnumParser<PubSubEventSubscription::SubscriptionType>()(PubSubEventSubscription::None, "none")(PubSubEventSubscription::Pending, "pending")(PubSubEventSubscription::Subscribed, "subscribed")(PubSubEventSubscription::Unconfigured, "unconfigured").parse(*attributeValue)) { - getPayloadInternal()->setSubscription(*value); - } - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subid")) { - getPayloadInternal()->setSubscriptionID(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("expiry")) { - getPayloadInternal()->setExpiry(stringToDateTime(*attributeValue)); - } - } - - + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { + if (boost::optional<JID> jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setJID(*jid); + } + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subscription")) { + if (boost::optional<PubSubEventSubscription::SubscriptionType> value = EnumParser<PubSubEventSubscription::SubscriptionType>()(PubSubEventSubscription::None, "none")(PubSubEventSubscription::Pending, "pending")(PubSubEventSubscription::Subscribed, "subscribed")(PubSubEventSubscription::Unconfigured, "unconfigured").parse(*attributeValue)) { + getPayloadInternal()->setSubscription(*value); + } + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subid")) { + getPayloadInternal()->setSubscriptionID(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("expiry")) { + getPayloadInternal()->setExpiry(stringToDateTime(*attributeValue)); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubEventSubscriptionParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { - if (level == 1) { - - currentPayloadParser.reset(); - } - } + currentPayloadParser.reset(); + } + } } void PubSubEventSubscriptionParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.h b/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.h index 1469920..6f2eeeb 100644 --- a/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubEventSubscription.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubEventSubscriptionParser : public GenericPayloadParser<PubSubEventSubscription> { - public: - PubSubEventSubscriptionParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubEventSubscriptionParser(); + class SWIFTEN_API PubSubEventSubscriptionParser : public GenericPayloadParser<PubSubEventSubscription> { + public: + PubSubEventSubscriptionParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventSubscriptionParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubItemParser.cpp b/Swiften/Parser/PayloadParsers/PubSubItemParser.cpp index 2e7d01a..ff5bfc7 100644 --- a/Swiften/Parser/PayloadParsers/PubSubItemParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubItemParser.cpp @@ -1,19 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubItemParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - +#include <Swiften/Parser/PayloadParserFactoryCollection.h> using namespace Swift; @@ -24,40 +22,40 @@ PubSubItemParser::~PubSubItemParser() { } void PubSubItemParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("id")) { - getPayloadInternal()->setID(*attributeValue); - } - } - - if (level == 1) { - if (PayloadParserFactory* factory = parsers->getPayloadParserFactory(element, ns, attributes)) { - currentPayloadParser.reset(factory->createPayloadParser()); - } - } - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("id")) { + getPayloadInternal()->setID(*attributeValue); + } + } + + if (level == 1) { + if (PayloadParserFactory* factory = parsers->getPayloadParserFactory(element, ns, attributes)) { + currentPayloadParser.reset(factory->createPayloadParser()); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubItemParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - getPayloadInternal()->addData(currentPayloadParser->getPayload()); - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + getPayloadInternal()->addData(currentPayloadParser->getPayload()); + currentPayloadParser.reset(); + } + } } void PubSubItemParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubItemParser.h b/Swiften/Parser/PayloadParsers/PubSubItemParser.h index 4f02211..cbbd3a5 100644 --- a/Swiften/Parser/PayloadParsers/PubSubItemParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubItemParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubItem.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubItemParser : public GenericPayloadParser<PubSubItem> { - public: - PubSubItemParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubItemParser(); + class SWIFTEN_API PubSubItemParser : public GenericPayloadParser<PubSubItem> { + public: + PubSubItemParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubItemParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubItemsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubItemsParser.cpp index 615f05d..2edfddb 100644 --- a/Swiften/Parser/PayloadParsers/PubSubItemsParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubItemsParser.cpp @@ -1,18 +1,18 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubItemsParser.h> -#include <boost/optional.hpp> #include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubItemParser.h> using namespace Swift; @@ -24,52 +24,52 @@ PubSubItemsParser::~PubSubItemsParser() { } void PubSubItemsParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("max_items")) { - try { - getPayloadInternal()->setMaximumItems(boost::lexical_cast<unsigned int>(*attributeValue)); - } - catch (boost::bad_lexical_cast&) { - } - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subid")) { - getPayloadInternal()->setSubscriptionID(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("max_items")) { + try { + getPayloadInternal()->setMaximumItems(boost::lexical_cast<unsigned int>(*attributeValue)); + } + catch (boost::bad_lexical_cast&) { + } + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subid")) { + getPayloadInternal()->setSubscriptionID(*attributeValue); + } + } - if (level == 1) { - if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubItemParser>(parsers); - } - } + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubItemParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubItemsParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { - getPayloadInternal()->addItem(boost::dynamic_pointer_cast<PubSubItem>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->addItem(std::dynamic_pointer_cast<PubSubItem>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubItemsParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubItemsParser.h b/Swiften/Parser/PayloadParsers/PubSubItemsParser.h index 895863f..d792e1b 100644 --- a/Swiften/Parser/PayloadParsers/PubSubItemsParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubItemsParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubItems.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubItemsParser : public GenericPayloadParser<PubSubItems> { - public: - PubSubItemsParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubItemsParser(); + class SWIFTEN_API PubSubItemsParser : public GenericPayloadParser<PubSubItems> { + public: + PubSubItemsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubItemsParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOptionsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOptionsParser.cpp index 3bf4998..2098d8f 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOptionsParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOptionsParser.cpp @@ -1,73 +1,69 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubOptionsParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParser.h> using namespace Swift; -PubSubOptionsParser::PubSubOptionsParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubOptionsParser::PubSubOptionsParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubOptionsParser::~PubSubOptionsParser() { } void PubSubOptionsParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { - if (boost::optional<JID> jid = JID::parse(*attributeValue)) { - getPayloadInternal()->setJID(*jid); - } - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subid")) { - getPayloadInternal()->setSubscriptionID(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { + if (boost::optional<JID> jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setJID(*jid); + } + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subid")) { + getPayloadInternal()->setSubscriptionID(*attributeValue); + } + } - if (level == 1) { - if (element == "x" && ns == "jabber:x:data") { - currentPayloadParser = boost::make_shared<FormParser>(); - } - } + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + currentPayloadParser = std::make_shared<FormParser>(); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOptionsParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "x" && ns == "jabber:x:data") { - getPayloadInternal()->setData(boost::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + getPayloadInternal()->setData(std::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubOptionsParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOptionsParser.h b/Swiften/Parser/PayloadParsers/PubSubOptionsParser.h index 3c8754b..ee11f70 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOptionsParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOptionsParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOptions.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOptionsParser : public GenericPayloadParser<PubSubOptions> { - public: - PubSubOptionsParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOptionsParser(); + class SWIFTEN_API PubSubOptionsParser : public GenericPayloadParser<PubSubOptions> { + public: + PubSubOptionsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOptionsParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.cpp index a648862..d868ef6 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.cpp @@ -1,66 +1,61 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/EnumParser.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> using namespace Swift; -PubSubOwnerAffiliationParser::PubSubOwnerAffiliationParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubOwnerAffiliationParser::PubSubOwnerAffiliationParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubOwnerAffiliationParser::~PubSubOwnerAffiliationParser() { } void PubSubOwnerAffiliationParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { - if (boost::optional<JID> jid = JID::parse(*attributeValue)) { - getPayloadInternal()->setJID(*jid); - } - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("affiliation")) { - if (boost::optional<PubSubOwnerAffiliation::Type> value = EnumParser<PubSubOwnerAffiliation::Type>()(PubSubOwnerAffiliation::None, "none")(PubSubOwnerAffiliation::Member, "member")(PubSubOwnerAffiliation::Outcast, "outcast")(PubSubOwnerAffiliation::Owner, "owner")(PubSubOwnerAffiliation::Publisher, "publisher")(PubSubOwnerAffiliation::PublishOnly, "publish-only").parse(*attributeValue)) { - getPayloadInternal()->setType(*value); - } - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { + if (boost::optional<JID> jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setJID(*jid); + } + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("affiliation")) { + if (boost::optional<PubSubOwnerAffiliation::Type> value = EnumParser<PubSubOwnerAffiliation::Type>()(PubSubOwnerAffiliation::None, "none")(PubSubOwnerAffiliation::Member, "member")(PubSubOwnerAffiliation::Outcast, "outcast")(PubSubOwnerAffiliation::Owner, "owner")(PubSubOwnerAffiliation::Publisher, "publisher")(PubSubOwnerAffiliation::PublishOnly, "publish-only").parse(*attributeValue)) { + getPayloadInternal()->setType(*value); + } + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOwnerAffiliationParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { - if (level == 1) { - - currentPayloadParser.reset(); - } - } + currentPayloadParser.reset(); + } + } } void PubSubOwnerAffiliationParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.h index ae54b5f..7bb93f1 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOwnerAffiliation.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOwnerAffiliationParser : public GenericPayloadParser<PubSubOwnerAffiliation> { - public: - PubSubOwnerAffiliationParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOwnerAffiliationParser(); + class SWIFTEN_API PubSubOwnerAffiliationParser : public GenericPayloadParser<PubSubOwnerAffiliation> { + public: + PubSubOwnerAffiliationParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerAffiliationParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.cpp index b824279..2f21b7a 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.cpp @@ -1,18 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.h> using namespace Swift; @@ -24,42 +23,42 @@ PubSubOwnerAffiliationsParser::~PubSubOwnerAffiliationsParser() { } void PubSubOwnerAffiliationsParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } - if (level == 1) { - if (element == "affiliation" && ns == "http://jabber.org/protocol/pubsub#owner") { - currentPayloadParser = boost::make_shared<PubSubOwnerAffiliationParser>(parsers); - } - } + if (level == 1) { + if (element == "affiliation" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = std::make_shared<PubSubOwnerAffiliationParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOwnerAffiliationsParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "affiliation" && ns == "http://jabber.org/protocol/pubsub#owner") { - getPayloadInternal()->addAffiliation(boost::dynamic_pointer_cast<PubSubOwnerAffiliation>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "affiliation" && ns == "http://jabber.org/protocol/pubsub#owner") { + getPayloadInternal()->addAffiliation(std::dynamic_pointer_cast<PubSubOwnerAffiliation>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubOwnerAffiliationsParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.h index 755d58c..20df72f 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOwnerAffiliations.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOwnerAffiliationsParser : public GenericPayloadParser<PubSubOwnerAffiliations> { - public: - PubSubOwnerAffiliationsParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOwnerAffiliationsParser(); + class SWIFTEN_API PubSubOwnerAffiliationsParser : public GenericPayloadParser<PubSubOwnerAffiliations> { + public: + PubSubOwnerAffiliationsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerAffiliationsParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.cpp index 43d262f..7fa6506 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.cpp @@ -1,65 +1,61 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParser.h> using namespace Swift; -PubSubOwnerConfigureParser::PubSubOwnerConfigureParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubOwnerConfigureParser::PubSubOwnerConfigureParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubOwnerConfigureParser::~PubSubOwnerConfigureParser() { } void PubSubOwnerConfigureParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } - - if (level == 1) { - if (element == "x" && ns == "jabber:x:data") { - currentPayloadParser = boost::make_shared<FormParser>(); - } - } - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } + + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + currentPayloadParser = std::make_shared<FormParser>(); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOwnerConfigureParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - if (element == "x" && ns == "jabber:x:data") { - getPayloadInternal()->setData(boost::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + getPayloadInternal()->setData(std::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubOwnerConfigureParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.h index f9a8553..f11f357 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOwnerConfigure.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOwnerConfigureParser : public GenericPayloadParser<PubSubOwnerConfigure> { - public: - PubSubOwnerConfigureParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOwnerConfigureParser(); + class SWIFTEN_API PubSubOwnerConfigureParser : public GenericPayloadParser<PubSubOwnerConfigure> { + public: + PubSubOwnerConfigureParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerConfigureParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.cpp index 4c284bf..e453230 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.cpp @@ -1,61 +1,55 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParser.h> using namespace Swift; -PubSubOwnerDefaultParser::PubSubOwnerDefaultParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubOwnerDefaultParser::PubSubOwnerDefaultParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubOwnerDefaultParser::~PubSubOwnerDefaultParser() { } void PubSubOwnerDefaultParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - - - if (level == 1) { - if (element == "x" && ns == "jabber:x:data") { - currentPayloadParser = boost::make_shared<FormParser>(); - } - } - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + currentPayloadParser = std::make_shared<FormParser>(); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOwnerDefaultParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - if (element == "x" && ns == "jabber:x:data") { - getPayloadInternal()->setData(boost::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + getPayloadInternal()->setData(std::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubOwnerDefaultParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.h index 5207bc5..2f80b85 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOwnerDefault.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOwnerDefaultParser : public GenericPayloadParser<PubSubOwnerDefault> { - public: - PubSubOwnerDefaultParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOwnerDefaultParser(); + class SWIFTEN_API PubSubOwnerDefaultParser : public GenericPayloadParser<PubSubOwnerDefault> { + public: + PubSubOwnerDefaultParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerDefaultParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.cpp index a2b7a9d..c30e404 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.cpp @@ -1,18 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.h> using namespace Swift; @@ -24,42 +23,42 @@ PubSubOwnerDeleteParser::~PubSubOwnerDeleteParser() { } void PubSubOwnerDeleteParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } - if (level == 1) { - if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#owner") { - currentPayloadParser = boost::make_shared<PubSubOwnerRedirectParser>(parsers); - } - } + if (level == 1) { + if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = std::make_shared<PubSubOwnerRedirectParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOwnerDeleteParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#owner") { - getPayloadInternal()->setRedirect(boost::dynamic_pointer_cast<PubSubOwnerRedirect>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#owner") { + getPayloadInternal()->setRedirect(std::dynamic_pointer_cast<PubSubOwnerRedirect>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubOwnerDeleteParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.h index c171ab8..4484329 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOwnerDelete.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOwnerDeleteParser : public GenericPayloadParser<PubSubOwnerDelete> { - public: - PubSubOwnerDeleteParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOwnerDeleteParser(); + class SWIFTEN_API PubSubOwnerDeleteParser : public GenericPayloadParser<PubSubOwnerDelete> { + public: + PubSubOwnerDeleteParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerDeleteParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.cpp index 5262997..e26f291 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.cpp @@ -1,24 +1,23 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.h> #include <Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.h> #include <Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.h> #include <Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.h> using namespace Swift; @@ -29,53 +28,53 @@ PubSubOwnerPubSubParser::~PubSubOwnerPubSubParser() { } void PubSubOwnerPubSubParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - - if (level == 1) { - if (element == "configure" && ns == "http://jabber.org/protocol/pubsub#owner") { - currentPayloadParser = boost::make_shared<PubSubOwnerConfigureParser>(parsers); - } - if (element == "subscriptions" && ns == "http://jabber.org/protocol/pubsub#owner") { - currentPayloadParser = boost::make_shared<PubSubOwnerSubscriptionsParser>(parsers); - } - if (element == "default" && ns == "http://jabber.org/protocol/pubsub#owner") { - currentPayloadParser = boost::make_shared<PubSubOwnerDefaultParser>(parsers); - } - if (element == "purge" && ns == "http://jabber.org/protocol/pubsub#owner") { - currentPayloadParser = boost::make_shared<PubSubOwnerPurgeParser>(parsers); - } - if (element == "affiliations" && ns == "http://jabber.org/protocol/pubsub#owner") { - currentPayloadParser = boost::make_shared<PubSubOwnerAffiliationsParser>(parsers); - } - if (element == "delete" && ns == "http://jabber.org/protocol/pubsub#owner") { - currentPayloadParser = boost::make_shared<PubSubOwnerDeleteParser>(parsers); - } - } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 1) { + if (element == "configure" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = std::make_shared<PubSubOwnerConfigureParser>(parsers); + } + if (element == "subscriptions" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = std::make_shared<PubSubOwnerSubscriptionsParser>(parsers); + } + if (element == "default" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = std::make_shared<PubSubOwnerDefaultParser>(parsers); + } + if (element == "purge" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = std::make_shared<PubSubOwnerPurgeParser>(parsers); + } + if (element == "affiliations" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = std::make_shared<PubSubOwnerAffiliationsParser>(parsers); + } + if (element == "delete" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = std::make_shared<PubSubOwnerDeleteParser>(parsers); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOwnerPubSubParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (currentPayloadParser) { - getPayloadInternal()->setPayload(boost::dynamic_pointer_cast<PubSubOwnerPayload>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (currentPayloadParser) { + getPayloadInternal()->setPayload(std::dynamic_pointer_cast<PubSubOwnerPayload>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubOwnerPubSubParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.h index 25fee8a..cfacc97 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOwnerPubSub.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOwnerPubSubParser : public GenericPayloadParser<PubSubOwnerPubSub> { - public: - PubSubOwnerPubSubParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOwnerPubSubParser(); + class SWIFTEN_API PubSubOwnerPubSubParser : public GenericPayloadParser<PubSubOwnerPubSub> { + public: + PubSubOwnerPubSubParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerPubSubParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.cpp index ebea0a7..7c637cf 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.cpp @@ -1,59 +1,53 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - +#include <Swiften/Parser/PayloadParserFactoryCollection.h> using namespace Swift; -PubSubOwnerPurgeParser::PubSubOwnerPurgeParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubOwnerPurgeParser::PubSubOwnerPurgeParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubOwnerPurgeParser::~PubSubOwnerPurgeParser() { } void PubSubOwnerPurgeParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOwnerPurgeParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } } void PubSubOwnerPurgeParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.h index 0b85d3d..8d233b6 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOwnerPurge.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOwnerPurgeParser : public GenericPayloadParser<PubSubOwnerPurge> { - public: - PubSubOwnerPurgeParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOwnerPurgeParser(); + class SWIFTEN_API PubSubOwnerPurgeParser : public GenericPayloadParser<PubSubOwnerPurge> { + public: + PubSubOwnerPurgeParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerPurgeParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.cpp index bc54e86..6d0b2a7 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.cpp @@ -1,59 +1,52 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - using namespace Swift; -PubSubOwnerRedirectParser::PubSubOwnerRedirectParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubOwnerRedirectParser::PubSubOwnerRedirectParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubOwnerRedirectParser::~PubSubOwnerRedirectParser() { } void PubSubOwnerRedirectParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("uri")) { - getPayloadInternal()->setURI(*attributeValue); - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("uri")) { + getPayloadInternal()->setURI(*attributeValue); + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOwnerRedirectParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } } void PubSubOwnerRedirectParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.h index 9a97d74..ebb6436 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOwnerRedirect.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOwnerRedirectParser : public GenericPayloadParser<PubSubOwnerRedirect> { - public: - PubSubOwnerRedirectParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOwnerRedirectParser(); + class SWIFTEN_API PubSubOwnerRedirectParser : public GenericPayloadParser<PubSubOwnerRedirect> { + public: + PubSubOwnerRedirectParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerRedirectParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.cpp index 7c91526..92b81f3 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.cpp @@ -1,66 +1,60 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/EnumParser.h> +#include <Swiften/Parser/PayloadParserFactory.h> using namespace Swift; -PubSubOwnerSubscriptionParser::PubSubOwnerSubscriptionParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubOwnerSubscriptionParser::PubSubOwnerSubscriptionParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubOwnerSubscriptionParser::~PubSubOwnerSubscriptionParser() { } void PubSubOwnerSubscriptionParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { - if (boost::optional<JID> jid = JID::parse(*attributeValue)) { - getPayloadInternal()->setJID(*jid); - } - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subscription")) { - if (boost::optional<PubSubOwnerSubscription::SubscriptionType> value = EnumParser<PubSubOwnerSubscription::SubscriptionType>()(PubSubOwnerSubscription::None, "none")(PubSubOwnerSubscription::Pending, "pending")(PubSubOwnerSubscription::Subscribed, "subscribed")(PubSubOwnerSubscription::Unconfigured, "unconfigured").parse(*attributeValue)) { - getPayloadInternal()->setSubscription(*value); - } - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { + if (boost::optional<JID> jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setJID(*jid); + } + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subscription")) { + if (boost::optional<PubSubOwnerSubscription::SubscriptionType> value = EnumParser<PubSubOwnerSubscription::SubscriptionType>()(PubSubOwnerSubscription::None, "none")(PubSubOwnerSubscription::Pending, "pending")(PubSubOwnerSubscription::Subscribed, "subscribed")(PubSubOwnerSubscription::Unconfigured, "unconfigured").parse(*attributeValue)) { + getPayloadInternal()->setSubscription(*value); + } + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOwnerSubscriptionParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { - if (level == 1) { - - currentPayloadParser.reset(); - } - } + currentPayloadParser.reset(); + } + } } void PubSubOwnerSubscriptionParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.h index 8ef8d5b..d68d910 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOwnerSubscription.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOwnerSubscriptionParser : public GenericPayloadParser<PubSubOwnerSubscription> { - public: - PubSubOwnerSubscriptionParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOwnerSubscriptionParser(); + class SWIFTEN_API PubSubOwnerSubscriptionParser : public GenericPayloadParser<PubSubOwnerSubscription> { + public: + PubSubOwnerSubscriptionParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerSubscriptionParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.cpp index ebe90d8..6d5e43c 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.cpp @@ -1,18 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.h> using namespace Swift; @@ -24,42 +23,42 @@ PubSubOwnerSubscriptionsParser::~PubSubOwnerSubscriptionsParser() { } void PubSubOwnerSubscriptionsParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } - if (level == 1) { - if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub#owner") { - currentPayloadParser = boost::make_shared<PubSubOwnerSubscriptionParser>(parsers); - } - } + if (level == 1) { + if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = std::make_shared<PubSubOwnerSubscriptionParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubOwnerSubscriptionsParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub#owner") { - getPayloadInternal()->addSubscription(boost::dynamic_pointer_cast<PubSubOwnerSubscription>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub#owner") { + getPayloadInternal()->addSubscription(std::dynamic_pointer_cast<PubSubOwnerSubscription>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubOwnerSubscriptionsParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.h index a5459a9..ca868e6 100644 --- a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubOwnerSubscriptions.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubOwnerSubscriptionsParser : public GenericPayloadParser<PubSubOwnerSubscriptions> { - public: - PubSubOwnerSubscriptionsParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubOwnerSubscriptionsParser(); + class SWIFTEN_API PubSubOwnerSubscriptionsParser : public GenericPayloadParser<PubSubOwnerSubscriptions> { + public: + PubSubOwnerSubscriptionsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerSubscriptionsParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubParser.cpp b/Swiften/Parser/PayloadParsers/PubSubParser.cpp index 5b1462b..eef6e5e 100644 --- a/Swiften/Parser/PayloadParsers/PubSubParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubParser.cpp @@ -1,31 +1,29 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> -#include <Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.h> #include <Swiften/Parser/PayloadParsers/PubSubConfigureParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubDefaultParser.h> #include <Swiften/Parser/PayloadParsers/PubSubCreateParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubDefaultParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubItemsParser.h> #include <Swiften/Parser/PayloadParsers/PubSubOptionsParser.h> #include <Swiften/Parser/PayloadParsers/PubSubPublishParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubOptionsParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubSubscribeParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.h> -#include <Swiften/Parser/PayloadParsers/PubSubItemsParser.h> #include <Swiften/Parser/PayloadParsers/PubSubRetractParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubSubscribeParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h> #include <Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.h> using namespace Swift; @@ -36,90 +34,90 @@ PubSubParser::~PubSubParser() { } void PubSubParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 1) { - if (element == "items" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubItemsParser>(parsers); - } - if (element == "create" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubCreateParser>(parsers); - } - if (element == "publish" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubPublishParser>(parsers); - } - if (element == "affiliations" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubAffiliationsParser>(parsers); - } - if (element == "retract" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubRetractParser>(parsers); - } - if (element == "options" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubOptionsParser>(parsers); - } - if (element == "configure" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubConfigureParser>(parsers); - } - if (element == "default" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubDefaultParser>(parsers); - } - if (element == "subscriptions" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubSubscriptionsParser>(parsers); - } - if (element == "subscribe" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubSubscribeParser>(parsers); - } - if (element == "unsubscribe" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubUnsubscribeParser>(parsers); - } - if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubSubscriptionParser>(parsers); - } - } + if (level == 1) { + if (element == "items" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubItemsParser>(parsers); + } + if (element == "create" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubCreateParser>(parsers); + } + if (element == "publish" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubPublishParser>(parsers); + } + if (element == "affiliations" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubAffiliationsParser>(parsers); + } + if (element == "retract" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubRetractParser>(parsers); + } + if (element == "options" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubOptionsParser>(parsers); + } + if (element == "configure" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubConfigureParser>(parsers); + } + if (element == "default" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubDefaultParser>(parsers); + } + if (element == "subscriptions" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubSubscriptionsParser>(parsers); + } + if (element == "subscribe" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubSubscribeParser>(parsers); + } + if (element == "unsubscribe" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubUnsubscribeParser>(parsers); + } + if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubSubscriptionParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (currentPayloadParser) { - if (element == "options" && ns == "http://jabber.org/protocol/pubsub") { - optionsPayload = boost::dynamic_pointer_cast<PubSubOptions>(currentPayloadParser->getPayload()); - } - else if (element == "configure" && ns == "http://jabber.org/protocol/pubsub") { - configurePayload = boost::dynamic_pointer_cast<PubSubConfigure>(currentPayloadParser->getPayload()); - } - else { - getPayloadInternal()->setPayload(boost::dynamic_pointer_cast<PubSubPayload>(currentPayloadParser->getPayload())); - } - } - currentPayloadParser.reset(); - } + if (level == 1) { + if (currentPayloadParser) { + if (element == "options" && ns == "http://jabber.org/protocol/pubsub") { + optionsPayload = std::dynamic_pointer_cast<PubSubOptions>(currentPayloadParser->getPayload()); + } + else if (element == "configure" && ns == "http://jabber.org/protocol/pubsub") { + configurePayload = std::dynamic_pointer_cast<PubSubConfigure>(currentPayloadParser->getPayload()); + } + else { + getPayloadInternal()->setPayload(std::dynamic_pointer_cast<PubSubPayload>(currentPayloadParser->getPayload())); + } + } + currentPayloadParser.reset(); + } - if (level == 0) { - if (boost::shared_ptr<PubSubCreate> create = boost::dynamic_pointer_cast<PubSubCreate>(getPayloadInternal()->getPayload())) { - if (configurePayload) { - create->setConfigure(configurePayload); - } - } - if (boost::shared_ptr<PubSubSubscribe> subscribe = boost::dynamic_pointer_cast<PubSubSubscribe>(getPayloadInternal()->getPayload())) { - if (optionsPayload) { - subscribe->setOptions(optionsPayload); - } - } - } - } + if (level == 0) { + if (std::shared_ptr<PubSubCreate> create = std::dynamic_pointer_cast<PubSubCreate>(getPayloadInternal()->getPayload())) { + if (configurePayload) { + create->setConfigure(configurePayload); + } + } + if (std::shared_ptr<PubSubSubscribe> subscribe = std::dynamic_pointer_cast<PubSubSubscribe>(getPayloadInternal()->getPayload())) { + if (optionsPayload) { + subscribe->setOptions(optionsPayload); + } + } + } + } } void PubSubParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubParser.h b/Swiften/Parser/PayloadParsers/PubSubParser.h index 0618361..5cc50e1 100644 --- a/Swiften/Parser/PayloadParsers/PubSubParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubParser.h @@ -1,38 +1,37 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSub.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; - class PubSubOptions; - class PubSubConfigure; + class PayloadParserFactoryCollection; + class PayloadParser; + class PubSubOptions; + class PubSubConfigure; - class SWIFTEN_API PubSubParser : public GenericPayloadParser<PubSub> { - public: - PubSubParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubParser(); + class SWIFTEN_API PubSubParser : public GenericPayloadParser<PubSub> { + public: + PubSubParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - boost::shared_ptr<PubSubConfigure> configurePayload; - boost::shared_ptr<PubSubOptions> optionsPayload; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + std::shared_ptr<PubSubConfigure> configurePayload; + std::shared_ptr<PubSubOptions> optionsPayload; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubPublishParser.cpp b/Swiften/Parser/PayloadParsers/PubSubPublishParser.cpp index ca358c3..8c8db3d 100644 --- a/Swiften/Parser/PayloadParsers/PubSubPublishParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubPublishParser.cpp @@ -1,18 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubPublishParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubItemParser.h> using namespace Swift; @@ -24,42 +23,42 @@ PubSubPublishParser::~PubSubPublishParser() { } void PubSubPublishParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } - if (level == 1) { - if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubItemParser>(parsers); - } - } + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubItemParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubPublishParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { - getPayloadInternal()->addItem(boost::dynamic_pointer_cast<PubSubItem>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->addItem(std::dynamic_pointer_cast<PubSubItem>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubPublishParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubPublishParser.h b/Swiften/Parser/PayloadParsers/PubSubPublishParser.h index 3d64e9d..e3b05ff 100644 --- a/Swiften/Parser/PayloadParsers/PubSubPublishParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubPublishParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubPublish.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubPublishParser : public GenericPayloadParser<PubSubPublish> { - public: - PubSubPublishParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubPublishParser(); + class SWIFTEN_API PubSubPublishParser : public GenericPayloadParser<PubSubPublish> { + public: + PubSubPublishParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubPublishParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubRetractParser.cpp b/Swiften/Parser/PayloadParsers/PubSubRetractParser.cpp index f4a42d0..d5d5c0a 100644 --- a/Swiften/Parser/PayloadParsers/PubSubRetractParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubRetractParser.cpp @@ -1,18 +1,15 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubRetractParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubItemParser.h> using namespace Swift; @@ -24,45 +21,49 @@ PubSubRetractParser::~PubSubRetractParser() { } void PubSubRetractParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("notify")) { - getPayloadInternal()->setNotify(*attributeValue == "true" ? true : false); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("notify")) { + boost::optional<bool> notify; + if (attributeValue.is_initialized()) { + notify = (attributeValue.get() == "true" || attributeValue.get() == "1") ? true : false; + } + getPayloadInternal()->setNotify(notify); + } + } - if (level == 1) { - if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubItemParser>(parsers); - } - } + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubItemParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubRetractParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { - getPayloadInternal()->addItem(boost::dynamic_pointer_cast<PubSubItem>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->addItem(std::dynamic_pointer_cast<PubSubItem>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubRetractParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubRetractParser.h b/Swiften/Parser/PayloadParsers/PubSubRetractParser.h index 2b5e633..aa9bbcc 100644 --- a/Swiften/Parser/PayloadParsers/PubSubRetractParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubRetractParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubRetract.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubRetractParser : public GenericPayloadParser<PubSubRetract> { - public: - PubSubRetractParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubRetractParser(); + class SWIFTEN_API PubSubRetractParser : public GenericPayloadParser<PubSubRetract> { + public: + PubSubRetractParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubRetractParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.cpp index caed681..88b7758 100644 --- a/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.cpp @@ -1,57 +1,48 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - using namespace Swift; -PubSubSubscribeOptionsParser::PubSubSubscribeOptionsParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubSubscribeOptionsParser::PubSubSubscribeOptionsParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubSubscribeOptionsParser::~PubSubSubscribeOptionsParser() { } void PubSubSubscribeOptionsParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubSubscribeOptionsParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } - - if (level == 1) { - if (element == "required") { - getPayloadInternal()->setRequired(true); - } - currentPayloadParser.reset(); - } - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + if (element == "required") { + getPayloadInternal()->setRequired(true); + } + currentPayloadParser.reset(); + } + } } void PubSubSubscribeOptionsParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.h b/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.h index c9ac1ca..9deae2d 100644 --- a/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubSubscribeOptions.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubSubscribeOptionsParser : public GenericPayloadParser<PubSubSubscribeOptions> { - public: - PubSubSubscribeOptionsParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubSubscribeOptionsParser(); + class SWIFTEN_API PubSubSubscribeOptionsParser : public GenericPayloadParser<PubSubSubscribeOptions> { + public: + PubSubSubscribeOptionsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubSubscribeOptionsParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.cpp b/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.cpp index 093c2c4..1de39e7 100644 --- a/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.cpp @@ -1,64 +1,57 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubSubscribeParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - using namespace Swift; -PubSubSubscribeParser::PubSubSubscribeParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubSubscribeParser::PubSubSubscribeParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubSubscribeParser::~PubSubSubscribeParser() { } void PubSubSubscribeParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { - if (boost::optional<JID> jid = JID::parse(*attributeValue)) { - getPayloadInternal()->setJID(*jid); - } - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { + if (boost::optional<JID> jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setJID(*jid); + } + } + } + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubSubscribeParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { - if (level == 1) { - - currentPayloadParser.reset(); - } - } + currentPayloadParser.reset(); + } + } } void PubSubSubscribeParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.h b/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.h index f0ad09d..ccd8ac8 100644 --- a/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubSubscribe.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubSubscribeParser : public GenericPayloadParser<PubSubSubscribe> { - public: - PubSubSubscribeParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubSubscribeParser(); + class SWIFTEN_API PubSubSubscribeParser : public GenericPayloadParser<PubSubSubscribe> { + public: + PubSubSubscribeParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubSubscribeParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.cpp b/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.cpp index be06ec8..0f27cb2 100644 --- a/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.cpp @@ -1,19 +1,18 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/EnumParser.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.h> using namespace Swift; @@ -25,55 +24,55 @@ PubSubSubscriptionParser::~PubSubSubscriptionParser() { } void PubSubSubscriptionParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subid")) { - getPayloadInternal()->setSubscriptionID(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { - if (boost::optional<JID> jid = JID::parse(*attributeValue)) { - getPayloadInternal()->setJID(*jid); - } - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subscription")) { - if (boost::optional<PubSubSubscription::SubscriptionType> value = EnumParser<PubSubSubscription::SubscriptionType>()(PubSubSubscription::None, "none")(PubSubSubscription::Pending, "pending")(PubSubSubscription::Subscribed, "subscribed")(PubSubSubscription::Unconfigured, "unconfigured").parse(*attributeValue)) { - getPayloadInternal()->setSubscription(*value); - } - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subid")) { + getPayloadInternal()->setSubscriptionID(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { + if (boost::optional<JID> jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setJID(*jid); + } + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subscription")) { + if (boost::optional<PubSubSubscription::SubscriptionType> value = EnumParser<PubSubSubscription::SubscriptionType>()(PubSubSubscription::None, "none")(PubSubSubscription::Pending, "pending")(PubSubSubscription::Subscribed, "subscribed")(PubSubSubscription::Unconfigured, "unconfigured").parse(*attributeValue)) { + getPayloadInternal()->setSubscription(*value); + } + } + } - if (level == 1) { - if (element == "subscribe-options" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubSubscribeOptionsParser>(parsers); - } - } + if (level == 1) { + if (element == "subscribe-options" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubSubscribeOptionsParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubSubscriptionParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "subscribe-options" && ns == "http://jabber.org/protocol/pubsub") { - getPayloadInternal()->setOptions(boost::dynamic_pointer_cast<PubSubSubscribeOptions>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "subscribe-options" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->setOptions(std::dynamic_pointer_cast<PubSubSubscribeOptions>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubSubscriptionParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h b/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h index 49290c2..3d9be23 100644 --- a/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubSubscription.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubSubscriptionParser : public GenericPayloadParser<PubSubSubscription> { - public: - PubSubSubscriptionParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubSubscriptionParser(); + class SWIFTEN_API PubSubSubscriptionParser : public GenericPayloadParser<PubSubSubscription> { + public: + PubSubSubscriptionParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubSubscriptionParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.cpp index 3ac3ca0..8b0fbef 100644 --- a/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.cpp @@ -1,18 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h> using namespace Swift; @@ -24,42 +23,42 @@ PubSubSubscriptionsParser::~PubSubSubscriptionsParser() { } void PubSubSubscriptionsParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - } + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + } - if (level == 1) { - if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub") { - currentPayloadParser = boost::make_shared<PubSubSubscriptionParser>(parsers); - } - } + if (level == 1) { + if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = std::make_shared<PubSubSubscriptionParser>(parsers); + } + } - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubSubscriptionsParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } - if (level == 1) { - if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub") { - getPayloadInternal()->addSubscription(boost::dynamic_pointer_cast<PubSubSubscription>(currentPayloadParser->getPayload())); - } - currentPayloadParser.reset(); - } - } + if (level == 1) { + if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->addSubscription(std::dynamic_pointer_cast<PubSubSubscription>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } } void PubSubSubscriptionsParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.h b/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.h index b08db93..c7169ae 100644 --- a/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.h @@ -1,34 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubSubscriptions.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubSubscriptionsParser : public GenericPayloadParser<PubSubSubscriptions> { - public: - PubSubSubscriptionsParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubSubscriptionsParser(); + class SWIFTEN_API PubSubSubscriptionsParser : public GenericPayloadParser<PubSubSubscriptions> { + public: + PubSubSubscriptionsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubSubscriptionsParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + PayloadParserFactoryCollection* parsers; + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.cpp b/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.cpp index 53b4fae..ea3b46d 100644 --- a/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.cpp +++ b/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.cpp @@ -1,67 +1,62 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.h> #include <boost/optional.hpp> - -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> - using namespace Swift; -PubSubUnsubscribeParser::PubSubUnsubscribeParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +PubSubUnsubscribeParser::PubSubUnsubscribeParser(PayloadParserFactoryCollection* /*parsers*/) : level(0) { } PubSubUnsubscribeParser::~PubSubUnsubscribeParser() { } void PubSubUnsubscribeParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { - getPayloadInternal()->setNode(*attributeValue); - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { - if (boost::optional<JID> jid = JID::parse(*attributeValue)) { - getPayloadInternal()->setJID(*jid); - } - } - if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subid")) { - getPayloadInternal()->setSubscriptionID(*attributeValue); - } - } - - - - if (level >= 1 && currentPayloadParser) { - currentPayloadParser->handleStartElement(element, ns, attributes); - } - ++level; + if (level == 0) { + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("node")) { + getPayloadInternal()->setNode(*attributeValue); + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("jid")) { + if (boost::optional<JID> jid = JID::parse(*attributeValue)) { + getPayloadInternal()->setJID(*jid); + } + } + if (boost::optional<std::string> attributeValue = attributes.getAttributeValue("subid")) { + getPayloadInternal()->setSubscriptionID(*attributeValue); + } + } + + + + if (level >= 1 && currentPayloadParser) { + currentPayloadParser->handleStartElement(element, ns, attributes); + } + ++level; } void PubSubUnsubscribeParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (currentPayloadParser) { - if (level >= 1) { - currentPayloadParser->handleEndElement(element, ns); - } + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { - if (level == 1) { - - currentPayloadParser.reset(); - } - } + currentPayloadParser.reset(); + } + } } void PubSubUnsubscribeParser::handleCharacterData(const std::string& data) { - if (level > 1 && currentPayloadParser) { - currentPayloadParser->handleCharacterData(data); - } + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } } diff --git a/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.h b/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.h index a9e5ed0..21d5599 100644 --- a/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.h +++ b/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.h @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/Elements/PubSubUnsubscribe.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class PayloadParser; + class PayloadParserFactoryCollection; + class PayloadParser; - class SWIFTEN_API PubSubUnsubscribeParser : public GenericPayloadParser<PubSubUnsubscribe> { - public: - PubSubUnsubscribeParser(PayloadParserFactoryCollection* parsers); - virtual ~PubSubUnsubscribeParser(); + class SWIFTEN_API PubSubUnsubscribeParser : public GenericPayloadParser<PubSubUnsubscribe> { + public: + PubSubUnsubscribeParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubUnsubscribeParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - PayloadParserFactoryCollection* parsers; - int level; - boost::shared_ptr<PayloadParser> currentPayloadParser; - }; + private: + int level; + std::shared_ptr<PayloadParser> currentPayloadParser; + }; } diff --git a/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.cpp b/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.cpp index 0837ae8..97abce3 100644 --- a/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h> + #include <Swiften/Parser/SerializingParser.h> namespace Swift { @@ -13,20 +14,20 @@ RawXMLPayloadParser::RawXMLPayloadParser() : level_(0) { } void RawXMLPayloadParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - ++level_; - serializingParser_.handleStartElement(element, ns, attributes); + ++level_; + serializingParser_.handleStartElement(element, ns, attributes); } void RawXMLPayloadParser::handleEndElement(const std::string& element, const std::string& ns) { - serializingParser_.handleEndElement(element, ns); - --level_; - if (level_ == 0) { - getPayloadInternal()->setRawXML(serializingParser_.getResult()); - } + serializingParser_.handleEndElement(element, ns); + --level_; + if (level_ == 0) { + getPayloadInternal()->setRawXML(serializingParser_.getResult()); + } } void RawXMLPayloadParser::handleCharacterData(const std::string& data) { - serializingParser_.handleCharacterData(data); + serializingParser_.handleCharacterData(data); } } diff --git a/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h b/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h index 2e16d00..1f20105 100644 --- a/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -12,18 +12,18 @@ #include <Swiften/Parser/SerializingParser.h> namespace Swift { - class SerializingParser; + class SerializingParser; - class SWIFTEN_API RawXMLPayloadParser : public GenericPayloadParser<RawXMLPayload> { - public: - RawXMLPayloadParser(); + class SWIFTEN_API RawXMLPayloadParser : public GenericPayloadParser<RawXMLPayload> { + public: + RawXMLPayloadParser(); - 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); + 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: - int level_; - SerializingParser serializingParser_; - }; + private: + int level_; + SerializingParser serializingParser_; + }; } diff --git a/Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h b/Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h index d777caa..f7b7601 100644 --- a/Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h +++ b/Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h @@ -1,26 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <string> + +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/RawXMLPayloadParser.h> -#include <string> namespace Swift { - class RawXMLPayloadParserFactory : public PayloadParserFactory { - public: - RawXMLPayloadParserFactory() {} + class SWIFTEN_API RawXMLPayloadParserFactory : public PayloadParserFactory { + public: + RawXMLPayloadParserFactory() {} - virtual bool canParse(const std::string&, const std::string&, const AttributeMap&) const { - return true; - } + virtual bool canParse(const std::string&, const std::string&, const AttributeMap&) const { + return true; + } - virtual PayloadParser* createPayloadParser() { - return new RawXMLPayloadParser(); - } - }; + virtual PayloadParser* createPayloadParser() { + return new RawXMLPayloadParser(); + } + }; } diff --git a/Swiften/Parser/PayloadParsers/ReferencePayloadParser.cpp b/Swiften/Parser/PayloadParsers/ReferencePayloadParser.cpp new file mode 100644 index 0000000..a337a29 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ReferencePayloadParser.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/ReferencePayloadParser.h> + +#include <cassert> +#include <iostream> + +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> + +namespace Swift { + +ReferencePayloadParser::ReferencePayloadParser(PayloadParserFactoryCollection* factories) : factories_(factories) { +} + +ReferencePayload::Type ReferencePayloadParser::getTypeFromString(const std::string& typeString) const { + if (typeString == "data") { + return ReferencePayload::Type::Data; + } + else if (typeString == "mention") { + return ReferencePayload::Type::Mention; + } + else if (typeString == "pubsub") { + return ReferencePayload::Type::PubSub; + } + else { + return ReferencePayload::Type::Unknown; + } +} + +void ReferencePayloadParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + if (level_ == topLevel_) { + if (element == "reference") { + getPayloadInternal()->setType(getTypeFromString(attributes.getAttribute("type"))); + getPayloadInternal()->setUri(attributes.getAttributeValue("uri")); + getPayloadInternal()->setBegin(attributes.getAttributeValue("begin")); + getPayloadInternal()->setEnd(attributes.getAttributeValue("end")); + getPayloadInternal()->setAnchor(attributes.getAttributeValue("anchor")); + } + } + else if (level_ == payloadLevel_) { + PayloadParserFactory* payloadParserFactory = factories_->getPayloadParserFactory(element, ns, attributes); + if (payloadParserFactory) { + currentPayloadParser_.reset(payloadParserFactory->createPayloadParser()); + } + } + + if (level_ >= payloadLevel_ && currentPayloadParser_) { + currentPayloadParser_->handleStartElement(element, ns, attributes); + } + + ++level_; +} + +void ReferencePayloadParser::handleEndElement(const std::string& element, const std::string& ns) { + --level_; + if (currentPayloadParser_) { + if (level_ >= payloadLevel_) { + currentPayloadParser_->handleEndElement(element, ns); + } + + if (level_ == payloadLevel_) { + getPayloadInternal()->addPayload(currentPayloadParser_->getPayload()); + currentPayloadParser_.reset(); + } + } +} + +void ReferencePayloadParser::handleCharacterData(const std::string& data) { + if (level_ > payloadLevel_ && currentPayloadParser_) { + currentPayloadParser_->handleCharacterData(data); + } +} + +} diff --git a/Swiften/Parser/PayloadParsers/ReferencePayloadParser.h b/Swiften/Parser/PayloadParsers/ReferencePayloadParser.h new file mode 100644 index 0000000..3afd181 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ReferencePayloadParser.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ReferencePayload.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + + class PayloadParserFactoryCollection; + + class SWIFTEN_API ReferencePayloadParser : public GenericPayloadParser<ReferencePayload> { + public: + + ReferencePayloadParser(PayloadParserFactoryCollection* factories); + + virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); + virtual void handleEndElement(const std::string& element, const std::string& ns); + virtual void handleCharacterData(const std::string& data); + + private: + + ReferencePayload::Type getTypeFromString(const std::string& typeString) const; + int level_ = 0; + const int topLevel_ = 0; + const int payloadLevel_ = 1; + PayloadParserFactoryCollection* factories_; + std::shared_ptr<PayloadParser> currentPayloadParser_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/ReplaceParser.cpp b/Swiften/Parser/PayloadParsers/ReplaceParser.cpp index 728ed63..66e219a 100644 --- a/Swiften/Parser/PayloadParsers/ReplaceParser.cpp +++ b/Swiften/Parser/PayloadParsers/ReplaceParser.cpp @@ -5,9 +5,9 @@ */ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ @@ -16,22 +16,22 @@ namespace Swift { - ReplaceParser::ReplaceParser() : level_(0) { - } + ReplaceParser::ReplaceParser() : level_(0) { + } - void ReplaceParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { - if (level_ == 0) { - std::string id = attributes.getAttribute("id"); - getPayloadInternal()->setID(id); - } - level_++; - } + void ReplaceParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { + if (level_ == 0) { + std::string id = attributes.getAttribute("id"); + getPayloadInternal()->setID(id); + } + level_++; + } - void ReplaceParser::handleEndElement(const std::string&, const std::string&) { - --level_; - } + void ReplaceParser::handleEndElement(const std::string&, const std::string&) { + --level_; + } - void ReplaceParser::handleCharacterData(const std::string&) { - } + void ReplaceParser::handleCharacterData(const std::string&) { + } } diff --git a/Swiften/Parser/PayloadParsers/ReplaceParser.h b/Swiften/Parser/PayloadParsers/ReplaceParser.h index 4d73459..21d7322 100644 --- a/Swiften/Parser/PayloadParsers/ReplaceParser.h +++ b/Swiften/Parser/PayloadParsers/ReplaceParser.h @@ -4,20 +4,27 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Replace.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class ReplaceParser : public GenericPayloadParser<Replace> { - public: - ReplaceParser(); - 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); + class SWIFTEN_API ReplaceParser : public GenericPayloadParser<Replace> { + public: + ReplaceParser(); + 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: - int level_; - }; + private: + int level_; + }; } diff --git a/Swiften/Parser/PayloadParsers/ResourceBindParser.cpp b/Swiften/Parser/PayloadParsers/ResourceBindParser.cpp index 81378df..2965d66 100644 --- a/Swiften/Parser/PayloadParsers/ResourceBindParser.cpp +++ b/Swiften/Parser/PayloadParsers/ResourceBindParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/ResourceBindParser.h> @@ -12,32 +12,32 @@ ResourceBindParser::ResourceBindParser() : level_(0), inJID_(false), inResource_ } void ResourceBindParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap&) { - if (level_ == 1) { - text_ = ""; - if (element == "resource") { - inResource_ = true; - } - if (element == "jid") { - inJID_ = true; - } - } - ++level_; + if (level_ == 1) { + text_ = ""; + if (element == "resource") { + inResource_ = true; + } + if (element == "jid") { + inJID_ = true; + } + } + ++level_; } void ResourceBindParser::handleEndElement(const std::string&, const std::string&) { - --level_; - if (level_ == 1) { - if (inJID_) { - getPayloadInternal()->setJID(JID(text_)); - } - else if (inResource_) { - getPayloadInternal()->setResource(text_); - } - } + --level_; + if (level_ == 1) { + if (inJID_) { + getPayloadInternal()->setJID(JID(text_)); + } + else if (inResource_) { + getPayloadInternal()->setResource(text_); + } + } } void ResourceBindParser::handleCharacterData(const std::string& data) { - text_ += data; + text_ += data; } } diff --git a/Swiften/Parser/PayloadParsers/ResourceBindParser.h b/Swiften/Parser/PayloadParsers/ResourceBindParser.h index e604751..3619c0b 100644 --- a/Swiften/Parser/PayloadParsers/ResourceBindParser.h +++ b/Swiften/Parser/PayloadParsers/ResourceBindParser.h @@ -1,27 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/ResourceBind.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class ResourceBindParser : public GenericPayloadParser<ResourceBind> { - public: - ResourceBindParser(); + class SWIFTEN_API ResourceBindParser : public GenericPayloadParser<ResourceBind> { + public: + ResourceBindParser(); - 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); + 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: - int level_; - bool inJID_; - bool inResource_; - std::string text_; - }; + private: + int level_; + bool inJID_; + bool inResource_; + std::string text_; + }; } diff --git a/Swiften/Parser/PayloadParsers/ResultSetParser.cpp b/Swiften/Parser/PayloadParsers/ResultSetParser.cpp new file mode 100644 index 0000000..80d89d7 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ResultSetParser.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/ResultSetParser.h> + +#include <boost/lexical_cast.hpp> +#include <boost/optional.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 == "index") { + try { + getPayloadInternal()->setIndex(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 == "before") { + getPayloadInternal()->setBefore(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..edf6f2f --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ResultSetParser.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ResultSet.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class SWIFTEN_API ResultSetParser : public GenericPayloadParser<ResultSet> { + public: + ResultSetParser(); + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + + private: + std::string currentText_; + int level_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp index 32be2c7..f99f592 100644 --- a/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp +++ b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.cpp @@ -4,7 +4,14 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h> + #include <Swiften/Parser/SerializingParser.h> namespace Swift { @@ -13,56 +20,56 @@ RosterItemExchangeParser::RosterItemExchangeParser() : level_(TopLevel), inItem_ } void RosterItemExchangeParser::handleStartElement(const std::string& element, const std::string& /*ns*/, const AttributeMap& attributes) { - if (level_ == PayloadLevel) { - if (element == "item") { - inItem_ = true; + if (level_ == PayloadLevel) { + if (element == "item") { + inItem_ = true; - currentItem_ = RosterItemExchangePayload::Item(); + currentItem_ = RosterItemExchangePayload::Item(); - currentItem_.setJID(JID(attributes.getAttribute("jid"))); - currentItem_.setName(attributes.getAttribute("name")); + currentItem_.setJID(JID(attributes.getAttribute("jid"))); + currentItem_.setName(attributes.getAttribute("name")); - std::string action = attributes.getAttribute("action"); - if (action == "add") { - currentItem_.setAction(RosterItemExchangePayload::Item::Add); - } - else if (action == "modify") { - currentItem_.setAction(RosterItemExchangePayload::Item::Modify); - } - else if (action == "delete") { - currentItem_.setAction(RosterItemExchangePayload::Item::Delete); - } - else { - // Add is default action according to XEP - currentItem_.setAction(RosterItemExchangePayload::Item::Add); - } - } - } - else if (level_ == ItemLevel) { - if (element == "group") { - currentText_ = ""; - } - } - ++level_; + std::string action = attributes.getAttribute("action"); + if (action == "add") { + currentItem_.setAction(RosterItemExchangePayload::Item::Add); + } + else if (action == "modify") { + currentItem_.setAction(RosterItemExchangePayload::Item::Modify); + } + else if (action == "delete") { + currentItem_.setAction(RosterItemExchangePayload::Item::Delete); + } + else { + // Add is default action according to XEP + currentItem_.setAction(RosterItemExchangePayload::Item::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_.addGroup(currentText_); - } - } + --level_; + if (level_ == PayloadLevel) { + if (inItem_) { + getPayloadInternal()->addItem(currentItem_); + inItem_ = false; + } + } + else if (level_ == ItemLevel) { + if (element == "group") { + currentItem_.addGroup(currentText_); + } + } } void RosterItemExchangeParser::handleCharacterData(const std::string& data) { - currentText_ += data; + currentText_ += data; } } diff --git a/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h index 5652b94..1fd1113 100644 --- a/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h +++ b/Swiften/Parser/PayloadParsers/RosterItemExchangeParser.h @@ -4,31 +4,36 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/RosterItemExchangePayload.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class SerializingParser; - - class RosterItemExchangeParser : public GenericPayloadParser<RosterItemExchangePayload> { - public: - RosterItemExchangeParser(); + class SWIFTEN_API 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); + 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_; - }; + 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/RosterParser.cpp b/Swiften/Parser/PayloadParsers/RosterParser.cpp index 53c433a..90fb518 100644 --- a/Swiften/Parser/PayloadParsers/RosterParser.cpp +++ b/Swiften/Parser/PayloadParsers/RosterParser.cpp @@ -1,104 +1,106 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/RosterParser.h> +#include <cassert> + #include <boost/optional.hpp> #include <Swiften/Parser/SerializingParser.h> namespace Swift { -RosterParser::RosterParser() : level_(TopLevel), inItem_(false), unknownContentParser_(0) { +RosterParser::RosterParser() : level_(TopLevel), inItem_(false), unknownContentParser_(nullptr) { } void RosterParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level_ == TopLevel) { - boost::optional<std::string> ver = attributes.getAttributeValue("ver"); - if (ver) { - getPayloadInternal()->setVersion(*ver); - } - } - else if (level_ == PayloadLevel) { - if (element == "item") { - inItem_ = true; - currentItem_ = RosterItemPayload(); + if (level_ == TopLevel) { + boost::optional<std::string> ver = attributes.getAttributeValue("ver"); + if (ver) { + getPayloadInternal()->setVersion(*ver); + } + } + else if (level_ == PayloadLevel) { + if (element == "item") { + inItem_ = true; + currentItem_ = RosterItemPayload(); - currentItem_.setJID(JID(attributes.getAttribute("jid"))); - currentItem_.setName(attributes.getAttribute("name")); + currentItem_.setJID(JID(attributes.getAttribute("jid"))); + currentItem_.setName(attributes.getAttribute("name")); - std::string subscription = attributes.getAttribute("subscription"); - if (subscription == "both") { - currentItem_.setSubscription(RosterItemPayload::Both); - } - else if (subscription == "to") { - currentItem_.setSubscription(RosterItemPayload::To); - } - else if (subscription == "from") { - currentItem_.setSubscription(RosterItemPayload::From); - } - else if (subscription == "remove") { - currentItem_.setSubscription(RosterItemPayload::Remove); - } - else { - currentItem_.setSubscription(RosterItemPayload::None); - } + std::string subscription = attributes.getAttribute("subscription"); + if (subscription == "both") { + currentItem_.setSubscription(RosterItemPayload::Both); + } + else if (subscription == "to") { + currentItem_.setSubscription(RosterItemPayload::To); + } + else if (subscription == "from") { + currentItem_.setSubscription(RosterItemPayload::From); + } + else if (subscription == "remove") { + currentItem_.setSubscription(RosterItemPayload::Remove); + } + else { + currentItem_.setSubscription(RosterItemPayload::None); + } - if (attributes.getAttribute("ask") == "subscribe") { - currentItem_.setSubscriptionRequested(); - } - } - } - else if (level_ == ItemLevel) { - if (element == "group") { - currentText_ = ""; - } - else { - assert(!unknownContentParser_); - unknownContentParser_ = new SerializingParser(); - unknownContentParser_->handleStartElement(element, ns, attributes); - } - } - else if (unknownContentParser_) { - unknownContentParser_->handleStartElement(element, ns, attributes); - } - ++level_; + if (attributes.getAttribute("ask") == "subscribe") { + currentItem_.setSubscriptionRequested(); + } + } + } + else if (level_ == ItemLevel) { + if (element == "group") { + currentText_ = ""; + } + else { + assert(!unknownContentParser_); + unknownContentParser_ = new SerializingParser(); + unknownContentParser_->handleStartElement(element, ns, attributes); + } + } + else if (unknownContentParser_) { + unknownContentParser_->handleStartElement(element, ns, attributes); + } + ++level_; } void RosterParser::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 (unknownContentParser_) { - unknownContentParser_->handleEndElement(element, ns); - currentItem_.addUnknownContent(unknownContentParser_->getResult()); - delete unknownContentParser_; - unknownContentParser_ = NULL; - } - else if (element == "group") { - currentItem_.addGroup(currentText_); - } - } - else if (unknownContentParser_) { - unknownContentParser_->handleEndElement(element, ns); - } + --level_; + if (level_ == PayloadLevel) { + if (inItem_) { + getPayloadInternal()->addItem(currentItem_); + inItem_ = false; + } + } + else if (level_ == ItemLevel) { + if (unknownContentParser_) { + unknownContentParser_->handleEndElement(element, ns); + currentItem_.addUnknownContent(unknownContentParser_->getResult()); + delete unknownContentParser_; + unknownContentParser_ = nullptr; + } + else if (element == "group") { + currentItem_.addGroup(currentText_); + } + } + else if (unknownContentParser_) { + unknownContentParser_->handleEndElement(element, ns); + } } void RosterParser::handleCharacterData(const std::string& data) { - if (unknownContentParser_) { - unknownContentParser_->handleCharacterData(data); - } - else { - currentText_ += data; - } + if (unknownContentParser_) { + unknownContentParser_->handleCharacterData(data); + } + else { + currentText_ += data; + } } } diff --git a/Swiften/Parser/PayloadParsers/RosterParser.h b/Swiften/Parser/PayloadParsers/RosterParser.h index 3b62f0b..2989f46 100644 --- a/Swiften/Parser/PayloadParsers/RosterParser.h +++ b/Swiften/Parser/PayloadParsers/RosterParser.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,26 +11,26 @@ #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class SerializingParser; + class SerializingParser; - class SWIFTEN_API RosterParser : public GenericPayloadParser<RosterPayload> { - public: - RosterParser(); + class SWIFTEN_API RosterParser : public GenericPayloadParser<RosterPayload> { + public: + RosterParser(); - 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); + 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_; - RosterItemPayload currentItem_; - std::string currentText_; - SerializingParser* unknownContentParser_; - }; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1, + ItemLevel = 2 + }; + int level_; + bool inItem_; + RosterItemPayload currentItem_; + std::string currentText_; + SerializingParser* unknownContentParser_; + }; } diff --git a/Swiften/Parser/PayloadParsers/S5BProxyRequestParser.cpp b/Swiften/Parser/PayloadParsers/S5BProxyRequestParser.cpp index 6e33f16..7a5a1fd 100644 --- a/Swiften/Parser/PayloadParsers/S5BProxyRequestParser.cpp +++ b/Swiften/Parser/PayloadParsers/S5BProxyRequestParser.cpp @@ -4,9 +4,16 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "S5BProxyRequestParser.h" +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/S5BProxyRequestParser.h> #include <boost/lexical_cast.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <boost/optional.hpp> namespace Swift { @@ -18,47 +25,47 @@ S5BProxyRequestParser::~S5BProxyRequestParser() { } void S5BProxyRequestParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (element == "streamhost") { - if (attributes.getAttributeValue("host") && attributes.getAttributeValue("jid") && attributes.getAttributeValue("port")) { - HostAddress address = attributes.getAttributeValue("host").get_value_or(""); - int port = -1; - JID jid = attributes.getAttributeValue("jid").get_value_or(""); + if (element == "streamhost") { + if (attributes.getAttributeValue("host") && attributes.getAttributeValue("jid") && attributes.getAttributeValue("port")) { + std::string host = attributes.getAttributeValue("host").get_value_or(""); + unsigned short port = 0; + JID jid = attributes.getAttributeValue("jid").get_value_or(""); - try { - port = boost::lexical_cast<int>(attributes.getAttributeValue("port").get()); - } catch (boost::bad_lexical_cast &) { - port = -1; - } - if (address.isValid() && port != -1 && jid.isValid()) { - S5BProxyRequest::StreamHost streamHost; - streamHost.addressPort = HostAddressPort(address, port); - streamHost.jid = jid; - getPayloadInternal()->setStreamHost(streamHost); - } - } - } else if (element == "activate") { - parseActivate = true; - } else if (element == "query") { - if (attributes.getAttributeValue("sid")) { - getPayloadInternal()->setSID(attributes.getAttributeValue("sid").get()); - } - } + try { + port = boost::numeric_cast<unsigned short>(boost::lexical_cast<int>(attributes.getAttributeValue("port").get())); + } catch (...) { + } + if (!host.empty() && port != 0 && jid.isValid()) { + S5BProxyRequest::StreamHost streamHost; + streamHost.host = host; + streamHost.port = port; + streamHost.jid = jid; + getPayloadInternal()->setStreamHost(streamHost); + } + } + } else if (element == "activate") { + parseActivate = true; + } else if (element == "query") { + if (attributes.getAttributeValue("sid")) { + getPayloadInternal()->setSID(attributes.getAttributeValue("sid").get()); + } + } } void S5BProxyRequestParser::handleEndElement(const std::string& element, const std::string&) { - if (element == "activate") { - JID activate = JID(activateJID); - if (activate.isValid()) { - getPayloadInternal()->setActivate(activate); - } - parseActivate = false; - } + if (element == "activate") { + JID activate = JID(activateJID); + if (activate.isValid()) { + getPayloadInternal()->setActivate(activate); + } + parseActivate = false; + } } void S5BProxyRequestParser::handleCharacterData(const std::string& data) { - if (parseActivate) { - activateJID = activateJID + data; - } + if (parseActivate) { + activateJID = activateJID + data; + } } } diff --git a/Swiften/Parser/PayloadParsers/S5BProxyRequestParser.h b/Swiften/Parser/PayloadParsers/S5BProxyRequestParser.h index 0bf1a26..1d5fd64 100644 --- a/Swiften/Parser/PayloadParsers/S5BProxyRequestParser.h +++ b/Swiften/Parser/PayloadParsers/S5BProxyRequestParser.h @@ -4,27 +4,34 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <string> +#include <Swiften/Base/API.h> #include <Swiften/Elements/S5BProxyRequest.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { -class S5BProxyRequestParser : public GenericPayloadParser<S5BProxyRequest> { +class SWIFTEN_API S5BProxyRequestParser : public GenericPayloadParser<S5BProxyRequest> { public: - S5BProxyRequestParser(); - virtual ~S5BProxyRequestParser(); + S5BProxyRequestParser(); + virtual ~S5BProxyRequestParser(); - 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); + 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: - bool parseActivate; - std::string activateJID; + bool parseActivate; + std::string activateJID; }; } diff --git a/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp b/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp index f4de503..0d79204 100644 --- a/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp @@ -1,113 +1,115 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/SearchPayloadParser.h> +#include <cassert> + #include <boost/cast.hpp> -#include <Swiften/Parser/PayloadParsers/FormParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParser.h> +#include <Swiften/Parser/PayloadParsers/FormParserFactory.h> namespace Swift { -SearchPayloadParser::SearchPayloadParser() : level(TopLevel), formParser(NULL) { - formParserFactory = new FormParserFactory(); +SearchPayloadParser::SearchPayloadParser() : level(TopLevel), formParser(nullptr) { + formParserFactory = new FormParserFactory(); } SearchPayloadParser::~SearchPayloadParser() { - delete formParserFactory; + delete formParserFactory; } void SearchPayloadParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == TopLevel) { - } - else if (level == PayloadLevel) { - if (element == "x" && ns == "jabber:x:data") { - assert(!formParser); - formParser = boost::polymorphic_downcast<FormParser*>(formParserFactory->createPayloadParser()); - } - else if (element == "item") { - assert(!currentItem); - currentItem.reset(SearchPayload::Item()); - currentItem->jid = JID(attributes.getAttribute("jid")); - } - else { - currentText.clear(); - } - } - else if (level == ItemLevel && currentItem) { - currentText.clear(); - } + if (level == TopLevel) { + } + else if (level == PayloadLevel) { + if (element == "x" && ns == "jabber:x:data") { + assert(!formParser); + formParser = boost::polymorphic_downcast<FormParser*>(formParserFactory->createPayloadParser()); + } + else if (element == "item") { + assert(!currentItem); + currentItem.reset(SearchPayload::Item()); + currentItem->jid = JID(attributes.getAttribute("jid")); + } + else { + currentText.clear(); + } + } + else if (level == ItemLevel && currentItem) { + currentText.clear(); + } - if (formParser) { - formParser->handleStartElement(element, ns, attributes); - } + if (formParser) { + formParser->handleStartElement(element, ns, attributes); + } - ++level; + ++level; } void SearchPayloadParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; + --level; - if (formParser) { - formParser->handleEndElement(element, ns); - } + if (formParser) { + formParser->handleEndElement(element, ns); + } - if (level == TopLevel) { - } - else if (level == PayloadLevel) { - if (formParser) { - getPayloadInternal()->setForm(formParser->getPayloadInternal()); - delete formParser; - formParser = NULL; - } - else if (element == "item") { - assert(currentItem); - getPayloadInternal()->addItem(*currentItem); - currentItem.reset(); - } - else if (element == "instructions") { - getPayloadInternal()->setInstructions(currentText); - } - else if (element == "nick") { - getPayloadInternal()->setNick(currentText); - } - else if (element == "first") { - getPayloadInternal()->setFirst(currentText); - } - else if (element == "last") { - getPayloadInternal()->setLast(currentText); - } - else if (element == "email") { - getPayloadInternal()->setEMail(currentText); - } - } - else if (level == ItemLevel && currentItem) { - if (element == "nick") { - currentItem->nick = currentText; - } - else if (element == "first") { - currentItem->first = currentText; - } - else if (element == "last") { - currentItem->last = currentText; - } - else if (element == "email") { - currentItem->email = currentText; - } - } + if (level == TopLevel) { + } + else if (level == PayloadLevel) { + if (formParser) { + getPayloadInternal()->setForm(formParser->getPayloadInternal()); + delete formParser; + formParser = nullptr; + } + else if (element == "item") { + assert(currentItem); + getPayloadInternal()->addItem(*currentItem); + currentItem.reset(); + } + else if (element == "instructions") { + getPayloadInternal()->setInstructions(currentText); + } + else if (element == "nick") { + getPayloadInternal()->setNick(currentText); + } + else if (element == "first") { + getPayloadInternal()->setFirst(currentText); + } + else if (element == "last") { + getPayloadInternal()->setLast(currentText); + } + else if (element == "email") { + getPayloadInternal()->setEMail(currentText); + } + } + else if (level == ItemLevel && currentItem) { + if (element == "nick") { + currentItem->nick = currentText; + } + else if (element == "first") { + currentItem->first = currentText; + } + else if (element == "last") { + currentItem->last = currentText; + } + else if (element == "email") { + currentItem->email = currentText; + } + } } void SearchPayloadParser::handleCharacterData(const std::string& data) { - if (formParser) { - formParser->handleCharacterData(data); - } - else { - currentText += data; - } + if (formParser) { + formParser->handleCharacterData(data); + } + else { + currentText += data; + } } } diff --git a/Swiften/Parser/PayloadParsers/SearchPayloadParser.h b/Swiften/Parser/PayloadParsers/SearchPayloadParser.h index d456eb8..aa0cf4a 100644 --- a/Swiften/Parser/PayloadParsers/SearchPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/SearchPayloadParser.h @@ -1,39 +1,40 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/SearchPayload.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class FormParserFactory; - class FormParser; + class FormParserFactory; + class FormParser; - class SearchPayloadParser : public GenericPayloadParser<SearchPayload> { - public: - SearchPayloadParser(); - ~SearchPayloadParser(); + class SWIFTEN_API SearchPayloadParser : public GenericPayloadParser<SearchPayload> { + public: + SearchPayloadParser(); + ~SearchPayloadParser(); - 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); + 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; - FormParserFactory* formParserFactory; - FormParser* formParser; - std::string currentText; - boost::optional<SearchPayload::Item> currentItem; - }; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1, + ItemLevel = 2 + }; + int level; + FormParserFactory* formParserFactory; + FormParser* formParser; + std::string currentText; + boost::optional<SearchPayload::Item> currentItem; + }; } diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelParser.cpp b/Swiften/Parser/PayloadParsers/SecurityLabelParser.cpp index 4177baa..6e2319f 100644 --- a/Swiften/Parser/PayloadParsers/SecurityLabelParser.cpp +++ b/Swiften/Parser/PayloadParsers/SecurityLabelParser.cpp @@ -1,69 +1,72 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/SecurityLabelParser.h> + +#include <cassert> + #include <Swiften/Parser/SerializingParser.h> namespace Swift { -SecurityLabelParser::SecurityLabelParser() : level_(TopLevel), labelParser_(0) { +SecurityLabelParser::SecurityLabelParser() : level_(TopLevel), labelParser_(nullptr) { } void SecurityLabelParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - ++level_; - if (level_ == DisplayMarkingOrLabelLevel) { - if (element == "displaymarking") { - currentText_ = ""; - getPayloadInternal()->setBackgroundColor(attributes.getAttribute("bgcolor")); - getPayloadInternal()->setForegroundColor(attributes.getAttribute("fgcolor")); - } - else if (element == "label" || element == "equivalentlabel") { - assert(!labelParser_); - labelParser_ = new SerializingParser(); - } - } - else if (level_ >= SecurityLabelLevel && labelParser_) { - labelParser_->handleStartElement(element, ns, attributes); - } + ++level_; + if (level_ == DisplayMarkingOrLabelLevel) { + if (element == "displaymarking") { + currentText_ = ""; + getPayloadInternal()->setBackgroundColor(attributes.getAttribute("bgcolor")); + getPayloadInternal()->setForegroundColor(attributes.getAttribute("fgcolor")); + } + else if (element == "label" || element == "equivalentlabel") { + assert(!labelParser_); + labelParser_ = new SerializingParser(); + } + } + else if (level_ >= SecurityLabelLevel && labelParser_) { + labelParser_->handleStartElement(element, ns, attributes); + } } void SecurityLabelParser::handleEndElement(const std::string& element, const std::string& ns) { - if (level_ == DisplayMarkingOrLabelLevel) { - if (element == "displaymarking") { - getPayloadInternal()->setDisplayMarking(currentText_); - } - else if (labelParser_) { - if (element == "label") { - getPayloadInternal()->setLabel(labelParser_->getResult()); - } - else { - getPayloadInternal()->addEquivalentLabel(labelParser_->getResult()); - } - delete labelParser_; - labelParser_ = 0; - } - } - else if (labelParser_ && level_ >= SecurityLabelLevel) { - labelParser_->handleEndElement(element, ns); - } - --level_; + if (level_ == DisplayMarkingOrLabelLevel) { + if (element == "displaymarking") { + getPayloadInternal()->setDisplayMarking(currentText_); + } + else if (labelParser_) { + if (element == "label") { + getPayloadInternal()->setLabel(labelParser_->getResult()); + } + else { + getPayloadInternal()->addEquivalentLabel(labelParser_->getResult()); + } + delete labelParser_; + labelParser_ = nullptr; + } + } + else if (labelParser_ && level_ >= SecurityLabelLevel) { + labelParser_->handleEndElement(element, ns); + } + --level_; } void SecurityLabelParser::handleCharacterData(const std::string& data) { - if (labelParser_) { - labelParser_->handleCharacterData(data); - } - else { - currentText_ += data; - } + if (labelParser_) { + labelParser_->handleCharacterData(data); + } + else { + currentText_ += data; + } } -boost::shared_ptr<SecurityLabel> SecurityLabelParser::getLabelPayload() const { - return getPayloadInternal(); +std::shared_ptr<SecurityLabel> SecurityLabelParser::getLabelPayload() const { + return getPayloadInternal(); } } diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelParser.h b/Swiften/Parser/PayloadParsers/SecurityLabelParser.h index 5357028..cc444a4 100644 --- a/Swiften/Parser/PayloadParsers/SecurityLabelParser.h +++ b/Swiften/Parser/PayloadParsers/SecurityLabelParser.h @@ -1,34 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/SecurityLabel.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class SerializingParser; + class SerializingParser; - class SecurityLabelParser : public GenericPayloadParser<SecurityLabel> { - public: - SecurityLabelParser(); + class SWIFTEN_API SecurityLabelParser : public GenericPayloadParser<SecurityLabel> { + public: + SecurityLabelParser(); - 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); - boost::shared_ptr<SecurityLabel> getLabelPayload() const; - private: - enum Level { - TopLevel = 0, - PayloadLevel = 1, - DisplayMarkingOrLabelLevel = 2, - SecurityLabelLevel = 3 - }; - int level_; - SerializingParser* labelParser_; - std::string currentText_; - }; + 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); + std::shared_ptr<SecurityLabel> getLabelPayload() const; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1, + DisplayMarkingOrLabelLevel = 2, + SecurityLabelLevel = 3 + }; + int level_; + SerializingParser* labelParser_; + std::string currentText_; + }; } diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h b/Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h index 47c4a0c..7e6d4fd 100644 --- a/Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h +++ b/Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/GenericPayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/SecurityLabelParser.h> namespace Swift { - class SecurityLabelParserFactory : public GenericPayloadParserFactory<SecurityLabelParser> { - public: - SecurityLabelParserFactory() : GenericPayloadParserFactory<SecurityLabelParser>("securitylabel", "urn:xmpp:sec-label:0") {} - }; + class SWIFTEN_API SecurityLabelParserFactory : public GenericPayloadParserFactory<SecurityLabelParser> { + public: + SecurityLabelParserFactory() : GenericPayloadParserFactory<SecurityLabelParser>("securitylabel", "urn:xmpp:sec-label:0") {} + }; } diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.cpp b/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.cpp index 922a00e..58b0af0 100644 --- a/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.cpp +++ b/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.cpp @@ -1,74 +1,76 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h> -#include <Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h> + +#include <cassert> +#include <memory> + #include <Swiften/Parser/PayloadParsers/SecurityLabelParser.h> +#include <Swiften/Parser/PayloadParsers/SecurityLabelParserFactory.h> namespace Swift { -SecurityLabelsCatalogParser::SecurityLabelsCatalogParser() : level_(TopLevel), labelParser_(0) { - labelParserFactory_ = new SecurityLabelParserFactory(); +SecurityLabelsCatalogParser::SecurityLabelsCatalogParser() : level_(TopLevel), labelParser_(nullptr) { + labelParserFactory_ = new SecurityLabelParserFactory(); } SecurityLabelsCatalogParser::~SecurityLabelsCatalogParser() { - delete labelParserFactory_; + delete labelParserFactory_; } void SecurityLabelsCatalogParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - ++level_; - if (level_ == PayloadLevel) { - getPayloadInternal()->setTo(JID(attributes.getAttribute("to"))); - getPayloadInternal()->setName(attributes.getAttribute("name")); - getPayloadInternal()->setDescription(attributes.getAttribute("desc")); - } - else if (level_ == ItemLevel && element == "item" && ns == "urn:xmpp:sec-label:catalog:2") { - currentItem_ = boost::make_shared<SecurityLabelsCatalog::Item>(); - currentItem_->setSelector(attributes.getAttribute("selector")); - currentItem_->setIsDefault(attributes.getBoolAttribute("default", false)); - } - else if (level_ == LabelLevel) { - assert(!labelParser_); - if (labelParserFactory_->canParse(element, ns, attributes)) { - labelParser_ = dynamic_cast<SecurityLabelParser*>(labelParserFactory_->createPayloadParser()); - assert(labelParser_); - } - } + ++level_; + if (level_ == PayloadLevel) { + getPayloadInternal()->setTo(JID(attributes.getAttribute("to"))); + getPayloadInternal()->setName(attributes.getAttribute("name")); + getPayloadInternal()->setDescription(attributes.getAttribute("desc")); + } + else if (level_ == ItemLevel && element == "item" && ns == "urn:xmpp:sec-label:catalog:2") { + currentItem_ = std::make_shared<SecurityLabelsCatalog::Item>(); + currentItem_->setSelector(attributes.getAttribute("selector")); + currentItem_->setIsDefault(attributes.getBoolAttribute("default", false)); + } + else if (level_ == LabelLevel && currentItem_) { + assert(!labelParser_); + if (labelParserFactory_->canParse(element, ns, attributes)) { + labelParser_ = dynamic_cast<SecurityLabelParser*>(labelParserFactory_->createPayloadParser()); + assert(labelParser_); + } + } - if (labelParser_) { - labelParser_->handleStartElement(element, ns, attributes); - } + if (labelParser_) { + labelParser_->handleStartElement(element, ns, attributes); + } } void SecurityLabelsCatalogParser::handleEndElement(const std::string& element, const std::string& ns) { - if (labelParser_) { - labelParser_->handleEndElement(element, ns); - } - if (level_ == LabelLevel && labelParser_ && currentItem_) { - boost::shared_ptr<SecurityLabel> currentLabel = labelParser_->getLabelPayload(); - assert(currentLabel); - currentItem_->setLabel(currentLabel); - delete labelParser_; - labelParser_ = 0; - } - else if (level_ == ItemLevel && element == "item" && ns == "urn:xmpp:sec-label:catalog:2") { - if (currentItem_) { - getPayloadInternal()->addItem(SecurityLabelsCatalog::Item(*currentItem_)); - currentItem_.reset(); - } - } - --level_; + if (labelParser_) { + labelParser_->handleEndElement(element, ns); + } + if (level_ == LabelLevel && labelParser_ && currentItem_) { + std::shared_ptr<SecurityLabel> currentLabel = labelParser_->getLabelPayload(); + assert(currentLabel); + currentItem_->setLabel(currentLabel); + delete labelParser_; + labelParser_ = nullptr; + } + else if (level_ == ItemLevel && element == "item" && ns == "urn:xmpp:sec-label:catalog:2") { + if (currentItem_) { + getPayloadInternal()->addItem(SecurityLabelsCatalog::Item(*currentItem_)); + currentItem_.reset(); + } + } + --level_; } void SecurityLabelsCatalogParser::handleCharacterData(const std::string& data) { - if (labelParser_) { - labelParser_->handleCharacterData(data); - } + if (labelParser_) { + labelParser_->handleCharacterData(data); + } } } diff --git a/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h b/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h index d50faa4..edfa86b 100644 --- a/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h +++ b/Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParser.h @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/SecurityLabelsCatalog.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class SecurityLabelParserFactory; - class SecurityLabelParser; + class SecurityLabelParserFactory; + class SecurityLabelParser; - class SecurityLabelsCatalogParser : public GenericPayloadParser<SecurityLabelsCatalog> { - public: - SecurityLabelsCatalogParser(); - ~SecurityLabelsCatalogParser(); + class SWIFTEN_API SecurityLabelsCatalogParser : public GenericPayloadParser<SecurityLabelsCatalog> { + public: + SecurityLabelsCatalogParser(); + ~SecurityLabelsCatalogParser(); - 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); + 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, - LabelLevel = 3 - }; - int level_; - SecurityLabelParserFactory* labelParserFactory_; - SecurityLabelParser* labelParser_; - boost::shared_ptr<SecurityLabelsCatalog::Item> currentItem_; - }; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1, + ItemLevel = 2, + LabelLevel = 3 + }; + int level_; + SecurityLabelParserFactory* labelParserFactory_; + SecurityLabelParser* labelParser_; + std::shared_ptr<SecurityLabelsCatalog::Item> currentItem_; + }; } diff --git a/Swiften/Parser/PayloadParsers/SoftwareVersionParser.cpp b/Swiften/Parser/PayloadParsers/SoftwareVersionParser.cpp index b1c3e18..56b62c8 100644 --- a/Swiften/Parser/PayloadParsers/SoftwareVersionParser.cpp +++ b/Swiften/Parser/PayloadParsers/SoftwareVersionParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/SoftwareVersionParser.h> @@ -12,27 +12,27 @@ SoftwareVersionParser::SoftwareVersionParser() : level_(TopLevel) { } void SoftwareVersionParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++level_; + ++level_; } void SoftwareVersionParser::handleEndElement(const std::string& element, const std::string&) { - --level_; - if (level_ == PayloadLevel) { - if (element == "name") { - getPayloadInternal()->setName(currentText_); - } - else if (element == "version") { - getPayloadInternal()->setVersion(currentText_); - } - else if (element == "os") { - getPayloadInternal()->setOS(currentText_); - } - currentText_ = ""; - } + --level_; + if (level_ == PayloadLevel) { + if (element == "name") { + getPayloadInternal()->setName(currentText_); + } + else if (element == "version") { + getPayloadInternal()->setVersion(currentText_); + } + else if (element == "os") { + getPayloadInternal()->setOS(currentText_); + } + currentText_ = ""; + } } void SoftwareVersionParser::handleCharacterData(const std::string& data) { - currentText_ += data; + currentText_ += data; } } diff --git a/Swiften/Parser/PayloadParsers/SoftwareVersionParser.h b/Swiften/Parser/PayloadParsers/SoftwareVersionParser.h index 01d5ed8..29f700c 100644 --- a/Swiften/Parser/PayloadParsers/SoftwareVersionParser.h +++ b/Swiften/Parser/PayloadParsers/SoftwareVersionParser.h @@ -1,29 +1,30 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/SoftwareVersion.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class SoftwareVersionParser : public GenericPayloadParser<SoftwareVersion> { - public: - SoftwareVersionParser(); + class SWIFTEN_API SoftwareVersionParser : public GenericPayloadParser<SoftwareVersion> { + public: + SoftwareVersionParser(); - 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); + 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 - }; - int level_; - std::string currentText_; - }; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + int level_; + std::string currentText_; + }; } diff --git a/Swiften/Parser/PayloadParsers/StartSessionParser.h b/Swiften/Parser/PayloadParsers/StartSessionParser.h index ce78ae7..e0013af 100644 --- a/Swiften/Parser/PayloadParsers/StartSessionParser.h +++ b/Swiften/Parser/PayloadParsers/StartSessionParser.h @@ -1,21 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/StartSession.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class StartSessionParser : public GenericPayloadParser<StartSession> { - public: - StartSessionParser() {} + class SWIFTEN_API StartSessionParser : public GenericPayloadParser<StartSession> { + public: + StartSessionParser() {} - virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&) {} - virtual void handleEndElement(const std::string&, const std::string&) {} - virtual void handleCharacterData(const std::string&) {} - }; + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&) {} + virtual void handleEndElement(const std::string&, const std::string&) {} + virtual void handleCharacterData(const std::string&) {} + }; } diff --git a/Swiften/Parser/PayloadParsers/StatusParser.cpp b/Swiften/Parser/PayloadParsers/StatusParser.cpp index 1394d46..128a675 100644 --- a/Swiften/Parser/PayloadParsers/StatusParser.cpp +++ b/Swiften/Parser/PayloadParsers/StatusParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/StatusParser.h> @@ -12,18 +12,18 @@ StatusParser::StatusParser() : level_(0) { } void StatusParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++level_; + ++level_; } void StatusParser::handleEndElement(const std::string&, const std::string&) { - --level_; - if (level_ == 0) { - getPayloadInternal()->setText(text_); - } + --level_; + if (level_ == 0) { + getPayloadInternal()->setText(text_); + } } void StatusParser::handleCharacterData(const std::string& data) { - text_ += data; + text_ += data; } } diff --git a/Swiften/Parser/PayloadParsers/StatusParser.h b/Swiften/Parser/PayloadParsers/StatusParser.h index 9d7493e..cebf0cd 100644 --- a/Swiften/Parser/PayloadParsers/StatusParser.h +++ b/Swiften/Parser/PayloadParsers/StatusParser.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Status.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class StatusParser : public GenericPayloadParser<Status> { - public: - StatusParser(); + class SWIFTEN_API StatusParser : public GenericPayloadParser<Status> { + public: + StatusParser(); - 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); + 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: - int level_; - std::string text_; - }; + private: + int level_; + std::string text_; + }; } diff --git a/Swiften/Parser/PayloadParsers/StatusShowParser.cpp b/Swiften/Parser/PayloadParsers/StatusShowParser.cpp index f5814ec..761a411 100644 --- a/Swiften/Parser/PayloadParsers/StatusShowParser.cpp +++ b/Swiften/Parser/PayloadParsers/StatusShowParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/StatusShowParser.h> @@ -12,32 +12,32 @@ StatusShowParser::StatusShowParser() : level_(0) { } void StatusShowParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++level_; + ++level_; } void StatusShowParser::handleEndElement(const std::string&, const std::string&) { - --level_; - if (level_ == 0) { - if (text_ == "away") { - getPayloadInternal()->setType(StatusShow::Away); - } - else if (text_ == "chat") { - getPayloadInternal()->setType(StatusShow::FFC); - } - else if (text_ == "xa") { - getPayloadInternal()->setType(StatusShow::XA); - } - else if (text_ == "dnd") { - getPayloadInternal()->setType(StatusShow::DND); - } - else { - getPayloadInternal()->setType(StatusShow::Online); - } - } + --level_; + if (level_ == 0) { + if (text_ == "away") { + getPayloadInternal()->setType(StatusShow::Away); + } + else if (text_ == "chat") { + getPayloadInternal()->setType(StatusShow::FFC); + } + else if (text_ == "xa") { + getPayloadInternal()->setType(StatusShow::XA); + } + else if (text_ == "dnd") { + getPayloadInternal()->setType(StatusShow::DND); + } + else { + getPayloadInternal()->setType(StatusShow::Online); + } + } } void StatusShowParser::handleCharacterData(const std::string& data) { - text_ += data; + text_ += data; } } diff --git a/Swiften/Parser/PayloadParsers/StatusShowParser.h b/Swiften/Parser/PayloadParsers/StatusShowParser.h index 6e72c13..8cbb365 100644 --- a/Swiften/Parser/PayloadParsers/StatusShowParser.h +++ b/Swiften/Parser/PayloadParsers/StatusShowParser.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/StatusShow.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class StatusShowParser : public GenericPayloadParser<StatusShow> { - public: - StatusShowParser(); + class SWIFTEN_API StatusShowParser : public GenericPayloadParser<StatusShow> { + public: + StatusShowParser(); - 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); + 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: - int level_; - std::string text_; - }; + private: + int level_; + std::string text_; + }; } diff --git a/Swiften/Parser/PayloadParsers/StorageParser.cpp b/Swiften/Parser/PayloadParsers/StorageParser.cpp index 05e24e7..9628ea8 100644 --- a/Swiften/Parser/PayloadParsers/StorageParser.cpp +++ b/Swiften/Parser/PayloadParsers/StorageParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/StorageParser.h> @@ -14,53 +14,53 @@ StorageParser::StorageParser() : level(TopLevel) { } void StorageParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level == BookmarkLevel) { - if (element == "conference") { - assert(!room); - room = Storage::Room(); - room->autoJoin = attributes.getBoolAttribute("autojoin", false); - room->jid = JID(attributes.getAttribute("jid")); - room->name = attributes.getAttribute("name"); - } - else if (element == "url") { - assert(!url); - url = Storage::URL(); - url->name = attributes.getAttribute("name"); - url->url = attributes.getAttribute("url"); - } - } - else if (level == DetailLevel) { - currentText = ""; - } - ++level; + if (level == BookmarkLevel) { + if (element == "conference") { + assert(!room); + room = Storage::Room(); + room->autoJoin = attributes.getBoolAttribute("autojoin", false); + room->jid = JID(attributes.getAttribute("jid")); + room->name = attributes.getAttribute("name"); + } + else if (element == "url") { + assert(!url); + url = Storage::URL(); + url->name = attributes.getAttribute("name"); + url->url = attributes.getAttribute("url"); + } + } + else if (level == DetailLevel) { + currentText = ""; + } + ++level; } void StorageParser::handleEndElement(const std::string& element, const std::string&) { - --level; - if (level == BookmarkLevel) { - if (element == "conference") { - assert(room); - getPayloadInternal()->addRoom(*room); - room.reset(); - } - else if (element == "url") { - assert(url); - getPayloadInternal()->addURL(*url); - url.reset(); - } - } - else if (level == DetailLevel && room) { - if (element == "nick") { - room->nick = currentText; - } - else if (element == "password") { - room->password = currentText; - } - } + --level; + if (level == BookmarkLevel) { + if (element == "conference") { + assert(room); + getPayloadInternal()->addRoom(*room); + room.reset(); + } + else if (element == "url") { + assert(url); + getPayloadInternal()->addURL(*url); + url.reset(); + } + } + else if (level == DetailLevel && room) { + if (element == "nick") { + room->nick = currentText; + } + else if (element == "password") { + room->password = currentText; + } + } } void StorageParser::handleCharacterData(const std::string& data) { - currentText += data; + currentText += data; } } diff --git a/Swiften/Parser/PayloadParsers/StorageParser.h b/Swiften/Parser/PayloadParsers/StorageParser.h index 76dce90..92417c2 100644 --- a/Swiften/Parser/PayloadParsers/StorageParser.h +++ b/Swiften/Parser/PayloadParsers/StorageParser.h @@ -1,34 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Storage.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class StorageParser : public GenericPayloadParser<Storage> { - public: - StorageParser(); + class SWIFTEN_API StorageParser : public GenericPayloadParser<Storage> { + public: + StorageParser(); - 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); + 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, - BookmarkLevel = 1, - DetailLevel = 2 - }; - int level; - std::string currentText; - boost::optional<Storage::Room> room; - boost::optional<Storage::URL> url; - }; + private: + enum Level { + TopLevel = 0, + BookmarkLevel = 1, + DetailLevel = 2 + }; + int level; + std::string currentText; + boost::optional<Storage::Room> room; + boost::optional<Storage::URL> url; + }; } diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp index cc69348..ab5dbbe 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp +++ b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp @@ -4,10 +4,16 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "StreamInitiationFileInfoParser.h" +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h> -#include <boost/optional.hpp> #include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> #include <Swiften/Base/DateTime.h> #include <Swiften/Base/Log.h> @@ -15,55 +21,55 @@ namespace Swift { StreamInitiationFileInfoParser::StreamInitiationFileInfoParser() : level(0), parseDescription(false) { - + } void StreamInitiationFileInfoParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level == 0) { - getPayloadInternal()->setName(attributes.getAttributeValue("name").get_value_or("")); - getPayloadInternal()->setHash(attributes.getAttributeValue("hash").get_value_or("")); - getPayloadInternal()->setAlgo(attributes.getAttributeValue("algo").get_value_or("md5")); - try { - getPayloadInternal()->setSize(boost::lexical_cast<boost::uintmax_t>(attributes.getAttributeValue("size").get_value_or("0"))); - } catch (boost::bad_lexical_cast &) { - getPayloadInternal()->setSize(0); - } - getPayloadInternal()->setDate(stringToDateTime(attributes.getAttributeValue("date").get_value_or(""))); - } else if (level == 1) { - if (element == "desc") { - parseDescription = true; - } else { - parseDescription = false; - if (element == "range") { - boost::uintmax_t offset = 0; - try { - offset = boost::lexical_cast<boost::uintmax_t>(attributes.getAttributeValue("offset").get_value_or("0")); - } catch (boost::bad_lexical_cast &) { - offset = 0; - } - if (offset == 0) { - getPayloadInternal()->setSupportsRangeRequests(true); - } else { - getPayloadInternal()->setRangeOffset(offset); - } - } - } - } - ++level; + if (level == 0) { + getPayloadInternal()->setName(attributes.getAttributeValue("name").get_value_or("")); + getPayloadInternal()->setHash(attributes.getAttributeValue("hash").get_value_or("")); + getPayloadInternal()->setAlgo(attributes.getAttributeValue("algo").get_value_or("md5")); + try { + getPayloadInternal()->setSize(boost::lexical_cast<boost::uintmax_t>(attributes.getAttributeValue("size").get_value_or("0"))); + } catch (boost::bad_lexical_cast &) { + getPayloadInternal()->setSize(0); + } + getPayloadInternal()->setDate(stringToDateTime(attributes.getAttributeValue("date").get_value_or(""))); + } else if (level == 1) { + if (element == "desc") { + parseDescription = true; + } else { + parseDescription = false; + if (element == "range") { + boost::uintmax_t offset = 0; + try { + offset = boost::lexical_cast<boost::uintmax_t>(attributes.getAttributeValue("offset").get_value_or("0")); + } catch (boost::bad_lexical_cast &) { + offset = 0; + } + if (offset == 0) { + getPayloadInternal()->setSupportsRangeRequests(true); + } else { + getPayloadInternal()->setRangeOffset(offset); + } + } + } + } + ++level; } void StreamInitiationFileInfoParser::handleEndElement(const std::string& element, const std::string&) { - --level; - if (parseDescription && element == "desc") { - parseDescription = false; - getPayloadInternal()->setDescription(desc); - } + --level; + if (parseDescription && element == "desc") { + parseDescription = false; + getPayloadInternal()->setDescription(desc); + } } void StreamInitiationFileInfoParser::handleCharacterData(const std::string& data) { - if (parseDescription) { - desc += data; - } + if (parseDescription) { + desc += data; + } } } diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h index 6d3591d..a1e386c 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h +++ b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h @@ -4,25 +4,32 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamInitiationFileInfo.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { -class StreamInitiationFileInfoParser : public GenericPayloadParser<StreamInitiationFileInfo> { - public: - StreamInitiationFileInfoParser(); - - 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: - int level; - bool parseDescription; - std::string desc; +class SWIFTEN_API StreamInitiationFileInfoParser : public GenericPayloadParser<StreamInitiationFileInfo> { + public: + StreamInitiationFileInfoParser(); + + 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: + int level; + bool parseDescription; + std::string desc; }; } diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp index ff0a061..ad66b3f 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp +++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/StreamInitiationParser.h> @@ -9,112 +9,112 @@ #include <boost/lexical_cast.hpp> #include <boost/cast.hpp> +#include <cassert> + #include <Swiften/Parser/PayloadParsers/FormParserFactory.h> #include <Swiften/Parser/PayloadParsers/FormParser.h> -#include <Swiften/Base/foreach.h> - #define FILE_TRANSFER_NS "http://jabber.org/protocol/si/profile/file-transfer" #define FEATURE_NEG_NS "http://jabber.org/protocol/feature-neg" namespace Swift { -StreamInitiationParser::StreamInitiationParser() : level(TopLevel), formParser(0), inFile(false), inFeature(false) { - formParserFactory = new FormParserFactory(); +StreamInitiationParser::StreamInitiationParser() : level(TopLevel), formParser(nullptr), inFile(false), inFeature(false) { + formParserFactory = new FormParserFactory(); } StreamInitiationParser::~StreamInitiationParser() { - delete formParserFactory; + delete formParserFactory; } void StreamInitiationParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == TopLevel) { - getPayloadInternal()->setID(attributes.getAttribute("id")); - if (!attributes.getAttribute("profile").empty()) { - getPayloadInternal()->setIsFileTransfer(attributes.getAttribute("profile") == FILE_TRANSFER_NS); - } - } - else if (level == PayloadLevel) { - if (element == "file") { - inFile = true; - currentFile = StreamInitiationFileInfo(); - currentFile.setName(attributes.getAttribute("name")); - try { - currentFile.setSize(boost::lexical_cast<unsigned long long>(attributes.getAttribute("size"))); - } - catch (boost::bad_lexical_cast&) { - } - } - else if (element == "feature" && ns == FEATURE_NEG_NS) { - inFeature = true; - } - } - else if (level == FileOrFeatureLevel) { - if (inFile && element == "desc") { - currentText.clear(); - } - else if (inFeature && formParserFactory->canParse(element, ns, attributes)) { - assert(!formParser); - formParser = boost::polymorphic_downcast<FormParser*>(formParserFactory->createPayloadParser()); - } - } + if (level == TopLevel) { + getPayloadInternal()->setID(attributes.getAttribute("id")); + if (!attributes.getAttribute("profile").empty()) { + getPayloadInternal()->setIsFileTransfer(attributes.getAttribute("profile") == FILE_TRANSFER_NS); + } + } + else if (level == PayloadLevel) { + if (element == "file") { + inFile = true; + currentFile = StreamInitiationFileInfo(); + currentFile.setName(attributes.getAttribute("name")); + try { + currentFile.setSize(boost::lexical_cast<unsigned long long>(attributes.getAttribute("size"))); + } + catch (boost::bad_lexical_cast&) { + } + } + else if (element == "feature" && ns == FEATURE_NEG_NS) { + inFeature = true; + } + } + else if (level == FileOrFeatureLevel) { + if (inFile && element == "desc") { + currentText.clear(); + } + else if (inFeature && formParserFactory->canParse(element, ns, attributes)) { + assert(!formParser); + formParser = boost::polymorphic_downcast<FormParser*>(formParserFactory->createPayloadParser()); + } + } - if (formParser) { - formParser->handleStartElement(element, ns, attributes); - } - ++level; + if (formParser) { + formParser->handleStartElement(element, ns, attributes); + } + ++level; } void StreamInitiationParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (formParser) { - formParser->handleEndElement(element, ns); - } - if (level == TopLevel) { - } - else if (level == PayloadLevel) { - if (element == "file") { - getPayloadInternal()->setFileInfo(currentFile); - inFile = false; - } - else if (element == "feature" && ns == FEATURE_NEG_NS) { - inFeature = false; - } - } - else if (level == FileOrFeatureLevel) { - if (inFile && element == "desc") { - currentFile.setDescription(currentText); - } - else if (formParser) { - Form::ref form = formParser->getPayloadInternal(); - if (form) { - FormField::ref field = boost::dynamic_pointer_cast<FormField>(form->getField("stream-method")); - if (field) { - if (form->getType() == Form::FormType) { - foreach (const FormField::Option& option, field->getOptions()) { - getPayloadInternal()->addProvidedMethod(option.value); - } - } - else if (form->getType() == Form::SubmitType) { - if (!field->getValues().empty()) { - getPayloadInternal()->setRequestedMethod(field->getValues()[0]); - } - } - } - } - delete formParser; - formParser = NULL; - } - } + --level; + if (formParser) { + formParser->handleEndElement(element, ns); + } + if (level == TopLevel) { + } + else if (level == PayloadLevel) { + if (element == "file") { + getPayloadInternal()->setFileInfo(currentFile); + inFile = false; + } + else if (element == "feature" && ns == FEATURE_NEG_NS) { + inFeature = false; + } + } + else if (level == FileOrFeatureLevel) { + if (inFile && element == "desc") { + currentFile.setDescription(currentText); + } + else if (formParser) { + Form::ref form = formParser->getPayloadInternal(); + if (form) { + FormField::ref field = std::dynamic_pointer_cast<FormField>(form->getField("stream-method")); + if (field) { + if (form->getType() == Form::FormType) { + for (const auto& option : field->getOptions()) { + getPayloadInternal()->addProvidedMethod(option.value); + } + } + else if (form->getType() == Form::SubmitType) { + if (!field->getValues().empty()) { + getPayloadInternal()->setRequestedMethod(field->getValues()[0]); + } + } + } + } + delete formParser; + formParser = nullptr; + } + } } void StreamInitiationParser::handleCharacterData(const std::string& data) { - if (formParser) { - formParser->handleCharacterData(data); - } - else { - currentText += data; - } + if (formParser) { + formParser->handleCharacterData(data); + } + else { + currentText += data; + } } diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.h b/Swiften/Parser/PayloadParsers/StreamInitiationParser.h index f7350cd..42de8ba 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.h +++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.h @@ -1,42 +1,43 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/optional.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamInitiation.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class FormParserFactory; - class FormParser; + class FormParserFactory; + class FormParser; - class StreamInitiationParser : public GenericPayloadParser<StreamInitiation> { - public: - StreamInitiationParser(); - ~StreamInitiationParser(); + class SWIFTEN_API StreamInitiationParser : public GenericPayloadParser<StreamInitiation> { + public: + StreamInitiationParser(); + ~StreamInitiationParser(); - 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); + 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, - FileOrFeatureLevel = 2, - FormOrDescriptionLevel = 3 - }; - int level; - FormParserFactory* formParserFactory; - FormParser* formParser; - bool inFile; - bool inFeature; - StreamInitiationFileInfo currentFile; - std::string currentText; - }; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1, + FileOrFeatureLevel = 2, + FormOrDescriptionLevel = 3 + }; + int level; + FormParserFactory* formParserFactory; + FormParser* formParser; + bool inFile; + bool inFeature; + StreamInitiationFileInfo currentFile; + std::string currentText; + }; } diff --git a/Swiften/Parser/PayloadParsers/SubjectParser.cpp b/Swiften/Parser/PayloadParsers/SubjectParser.cpp index 276a05a..19a5488 100644 --- a/Swiften/Parser/PayloadParsers/SubjectParser.cpp +++ b/Swiften/Parser/PayloadParsers/SubjectParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/SubjectParser.h> @@ -12,18 +12,20 @@ SubjectParser::SubjectParser() : level_(0) { } void SubjectParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++level_; + ++level_; } void SubjectParser::handleEndElement(const std::string&, const std::string&) { - --level_; - if (level_ == 0) { - getPayloadInternal()->setText(text_); - } + --level_; + if (level_ == 0) { + getPayloadInternal()->setText(text_); + } } void SubjectParser::handleCharacterData(const std::string& data) { - text_ += data; + if (level_ == 1) { + text_ += data; + } } } diff --git a/Swiften/Parser/PayloadParsers/SubjectParser.h b/Swiften/Parser/PayloadParsers/SubjectParser.h index 1d7d2ce..a400283 100644 --- a/Swiften/Parser/PayloadParsers/SubjectParser.h +++ b/Swiften/Parser/PayloadParsers/SubjectParser.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Subject.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class SubjectParser : public GenericPayloadParser<Subject> { - public: - SubjectParser(); + class SWIFTEN_API SubjectParser : public GenericPayloadParser<Subject> { + public: + SubjectParser(); - 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); + 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: - int level_; - std::string text_; - }; + private: + int level_; + std::string text_; + }; } diff --git a/Swiften/Parser/PayloadParsers/ThreadParser.cpp b/Swiften/Parser/PayloadParsers/ThreadParser.cpp new file mode 100644 index 0000000..f416d32 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ThreadParser.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/ThreadParser.h> + +#include <boost/optional.hpp> + +namespace Swift { + +ThreadParser::ThreadParser() : level_(0) { +} + +ThreadParser::~ThreadParser() { +} + +void ThreadParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { + ++level_; + if (element == "thread") { + getPayloadInternal()->setParent(attributes.getAttributeValue("parent").get_value_or("")); + } +} + +void ThreadParser::handleEndElement(const std::string&, const std::string&) { + --level_; + if (level_ == 0) { + getPayloadInternal()->setText(text_); + } +} + +void ThreadParser::handleCharacterData(const std::string& data) { + if (level_ == 1) { + text_ += data; + } +} + +} diff --git a/Swiften/Parser/PayloadParsers/ThreadParser.h b/Swiften/Parser/PayloadParsers/ThreadParser.h new file mode 100644 index 0000000..371c535 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/ThreadParser.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Thread.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class SWIFTEN_API ThreadParser : public GenericPayloadParser<Thread> { + public: + ThreadParser(); + virtual ~ThreadParser(); + + 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: + int level_; + std::string text_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/BlockParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/BlockParserTest.cpp index ddd3a88..17a800e 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/BlockParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/BlockParserTest.cpp @@ -4,69 +4,74 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParsers/BlockParser.h> -#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> - +#include <Swiften/Elements/BlockListPayload.h> #include <Swiften/Elements/BlockPayload.h> #include <Swiften/Elements/UnblockPayload.h> -#include <Swiften/Elements/BlockListPayload.h> +#include <Swiften/Parser/PayloadParsers/BlockParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> using namespace Swift; class BlockParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(BlockParserTest); - CPPUNIT_TEST(testExample4); - CPPUNIT_TEST(testExample6); - CPPUNIT_TEST(testExample10); - CPPUNIT_TEST_SUITE_END(); - - public: - BlockParserTest() {} - - void testExample4() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<blocklist xmlns='urn:xmpp:blocking'>" - "<item jid='romeo@montague.net'/>" - "<item jid='iago@shakespeare.lit'/>" - "</blocklist>")); - - BlockListPayload* payload = dynamic_cast<BlockListPayload*>(parser.getPayload().get()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT(2 == payload->getItems().size()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), payload->getItems()[0]); - CPPUNIT_ASSERT_EQUAL(JID("iago@shakespeare.lit"), payload->getItems()[1]); - } - - void testExample6() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<block xmlns='urn:xmpp:blocking'>" - "<item jid='romeo@montague.net'/>" - "</block>")); - - BlockPayload* payload = dynamic_cast<BlockPayload*>(parser.getPayload().get()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT(1 == payload->getItems().size()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), payload->getItems()[0]); - } - - void testExample10() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<unblock xmlns='urn:xmpp:blocking'>" - "<item jid='romeo@montague.net'/>" - "</unblock>")); - - UnblockPayload* payload = dynamic_cast<UnblockPayload*>(parser.getPayload().get()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT(1 == payload->getItems().size()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), payload->getItems()[0]); - } + CPPUNIT_TEST_SUITE(BlockParserTest); + CPPUNIT_TEST(testExample4); + CPPUNIT_TEST(testExample6); + CPPUNIT_TEST(testExample10); + CPPUNIT_TEST_SUITE_END(); + + public: + BlockParserTest() {} + + void testExample4() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<blocklist xmlns='urn:xmpp:blocking'>" + "<item jid='romeo@montague.net'/>" + "<item jid='iago@shakespeare.lit'/>" + "</blocklist>")); + + BlockListPayload* payload = dynamic_cast<BlockListPayload*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(2 == payload->getItems().size()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), payload->getItems()[0]); + CPPUNIT_ASSERT_EQUAL(JID("iago@shakespeare.lit"), payload->getItems()[1]); + } + + void testExample6() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<block xmlns='urn:xmpp:blocking'>" + "<item jid='romeo@montague.net'/>" + "</block>")); + + BlockPayload* payload = dynamic_cast<BlockPayload*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(1 == payload->getItems().size()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), payload->getItems()[0]); + } + + void testExample10() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<unblock xmlns='urn:xmpp:blocking'>" + "<item jid='romeo@montague.net'/>" + "</unblock>")); + + UnblockPayload* payload = dynamic_cast<UnblockPayload*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(1 == payload->getItems().size()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), payload->getItems()[0]); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(BlockParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp index fe91088..002da16 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/BodyParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,21 +14,21 @@ using namespace Swift; class BodyParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(BodyParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(BodyParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); - public: - BodyParserTest() {} + public: + BodyParserTest() {} - void testParse() { - PayloadsParserTester parser; + void testParse() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<body>foo<baz>bar</baz>fum</body>")); + CPPUNIT_ASSERT(parser.parse("<body>foo<baz>bar</baz>fum</body>")); - Body* payload = dynamic_cast<Body*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("foobarfum"), payload->getText()); - } + Body* payload = dynamic_cast<Body*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("foobarfum"), payload->getText()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(BodyParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/CarbonsParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/CarbonsParserTest.cpp new file mode 100644 index 0000000..b5b9995 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/CarbonsParserTest.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Elements/CarbonsDisable.h> +#include <Swiften/Elements/CarbonsEnable.h> +#include <Swiften/Elements/CarbonsPrivate.h> +#include <Swiften/Elements/CarbonsReceived.h> +#include <Swiften/Elements/CarbonsSent.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Thread.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +class CarbonsParserTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(CarbonsParserTest); + CPPUNIT_TEST(testParseExample3); + CPPUNIT_TEST(testParseExample6); + CPPUNIT_TEST(testParseExample12); + CPPUNIT_TEST(testParseExample14); + CPPUNIT_TEST(testParseExample15); + CPPUNIT_TEST_SUITE_END(); + + public: + CarbonsParserTest() {} + + /* + * Test parsing of example 3 in XEP-0280. + */ + void testParseExample3() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<enable xmlns='urn:xmpp:carbons:2' />")); + + CarbonsEnable::ref enable = parser.getPayload<CarbonsEnable>(); + CPPUNIT_ASSERT(enable); + } + + /* + * Test parsing of example 6 in XEP-0280. + */ + void testParseExample6() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<disable xmlns='urn:xmpp:carbons:2' />")); + + CarbonsDisable::ref disable = parser.getPayload<CarbonsDisable>(); + CPPUNIT_ASSERT(disable); + } + + /* + * Test parsing of example 12 in XEP-0280. + */ + void testParseExample12() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<received xmlns='urn:xmpp:carbons:2'>" + "<forwarded xmlns='urn:xmpp:forward:0'>" + "<message xmlns='jabber:client'" + " from='juliet@capulet.example/balcony'" + " to='romeo@montague.example/garden'" + " type='chat'>" + "<body>What man art thou that, thus bescreen'd in night, so stumblest on my counsel?</body>" + "<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>" + "</message>" + "</forwarded>" + "</received>")); + + CarbonsReceived::ref received = parser.getPayload<CarbonsReceived>(); + CPPUNIT_ASSERT(received); + + std::shared_ptr<Forwarded> forwarded = received->getForwarded(); + CPPUNIT_ASSERT(forwarded); + + std::shared_ptr<Message> message = std::dynamic_pointer_cast<Message>(forwarded->getStanza()); + CPPUNIT_ASSERT(message); + CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.example/balcony"), message->getFrom()); + + std::shared_ptr<Thread> thread = message->getPayload<Thread>(); + CPPUNIT_ASSERT(thread); + CPPUNIT_ASSERT_EQUAL(std::string("0e3141cd80894871a68e6fe6b1ec56fa"), thread->getText()); + } + + /* + * Test parsing of example 14 in XEP-0280. + */ + void testParseExample14() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<sent xmlns='urn:xmpp:carbons:2'>" + "<forwarded xmlns='urn:xmpp:forward:0'>" + "<message xmlns='jabber:client'" + " to='juliet@capulet.example/balcony'" + " from='romeo@montague.example/home'" + " type='chat'>" + "<body>Neither, fair saint, if either thee dislike.</body>" + "<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>" + "</message>" + "</forwarded>" + "</sent>")); + + CarbonsSent::ref sent = parser.getPayload<CarbonsSent>(); + CPPUNIT_ASSERT(sent); + + std::shared_ptr<Forwarded> forwarded = sent->getForwarded(); + CPPUNIT_ASSERT(forwarded); + + std::shared_ptr<Message> message = std::dynamic_pointer_cast<Message>(forwarded->getStanza()); + CPPUNIT_ASSERT(message); + CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.example/balcony"), message->getTo()); + } + + /* + * Test parsing of example 15 in XEP-0280. + */ + void testParseExample15() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<private xmlns='urn:xmpp:carbons:2'/>")); + + CPPUNIT_ASSERT(parser.getPayload<CarbonsPrivate>()); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(CarbonsParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ClientStateParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ClientStateParserTest.cpp new file mode 100644 index 0000000..ca89040 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/ClientStateParserTest.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/ClientState.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(ClientStateParserTest, testParse_Active) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<active xmlns='urn:xmpp:csi:0'/>" + )); + + ClientState::ref payload = parser.getPayload<ClientState>(); + ASSERT_EQ(ClientState::ClientStateType::Active, payload->getClientState()); +} + +TEST(ClientStateParserTest, testParse_Inactive) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<inactive xmlns='urn:xmpp:csi:0'/>" + )); + + ClientState::ref payload = parser.getPayload<ClientState>(); + ASSERT_EQ(ClientState::ClientStateType::Inactive, payload->getClientState()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/CommandParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/CommandParserTest.cpp index 3e4971b..fa8d014 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/CommandParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/CommandParserTest.cpp @@ -1,86 +1,86 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> #include <Swiften/Elements/Command.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> using namespace Swift; class CommandParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(CommandParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_Result); - CPPUNIT_TEST(testParse_Form); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(CommandParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_Result); + CPPUNIT_TEST(testParse_Form); + CPPUNIT_TEST_SUITE_END(); - public: - void testParse() { - PayloadsParserTester parser; + public: + void testParse() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<command xmlns='http://jabber.org/protocol/commands' node='list' action='prev' sessionid='myid'/>" - )); + CPPUNIT_ASSERT(parser.parse( + "<command xmlns='http://jabber.org/protocol/commands' node='list' action='prev' sessionid='myid'/>" + )); - Command::ref payload = parser.getPayload<Command>(); - CPPUNIT_ASSERT_EQUAL(Command::Prev, payload->getAction()); - CPPUNIT_ASSERT_EQUAL(std::string("list"), payload->getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), payload->getSessionID()); - } + Command::ref payload = parser.getPayload<Command>(); + CPPUNIT_ASSERT_EQUAL(Command::Prev, payload->getAction()); + CPPUNIT_ASSERT_EQUAL(std::string("list"), payload->getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), payload->getSessionID()); + } - void testParse_Result() { - PayloadsParserTester parser; + void testParse_Result() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<command xmlns='http://jabber.org/protocol/commands' node='config' status='completed' sessionid='myid'>" - "<note type='warn'>Service 'httpd' has been configured.</note>" - "<note type='error'>I lied.</note>" - "<actions execute='next'>" - "<prev/>" - "<next/>" - "</actions>" - "</command>" - )); + CPPUNIT_ASSERT(parser.parse( + "<command xmlns='http://jabber.org/protocol/commands' node='config' status='completed' sessionid='myid'>" + "<note type='warn'>Service 'httpd' has been configured.</note>" + "<note type='error'>I lied.</note>" + "<actions execute='next'>" + "<prev/>" + "<next/>" + "</actions>" + "</command>" + )); - Command::ref payload = parser.getPayload<Command>(); - CPPUNIT_ASSERT_EQUAL(Command::Completed, payload->getStatus()); - std::vector<Command::Note> notes = payload->getNotes(); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(notes.size())); - CPPUNIT_ASSERT_EQUAL(Command::Note::Warn, notes[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("Service 'httpd' has been configured."), notes[0].note); - CPPUNIT_ASSERT_EQUAL(Command::Note::Error, notes[1].type); - CPPUNIT_ASSERT_EQUAL(std::string("I lied."), notes[1].note); - std::vector<Command::Action> actions = payload->getAvailableActions(); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(actions.size())); - CPPUNIT_ASSERT_EQUAL(Command::Prev, actions[0]); - CPPUNIT_ASSERT_EQUAL(Command::Next, actions[1]); - CPPUNIT_ASSERT_EQUAL(Command::Next, payload->getExecuteAction()); - } + Command::ref payload = parser.getPayload<Command>(); + CPPUNIT_ASSERT_EQUAL(Command::Completed, payload->getStatus()); + std::vector<Command::Note> notes = payload->getNotes(); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(notes.size())); + CPPUNIT_ASSERT_EQUAL(Command::Note::Warn, notes[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("Service 'httpd' has been configured."), notes[0].note); + CPPUNIT_ASSERT_EQUAL(Command::Note::Error, notes[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("I lied."), notes[1].note); + std::vector<Command::Action> actions = payload->getAvailableActions(); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(actions.size())); + CPPUNIT_ASSERT_EQUAL(Command::Prev, actions[0]); + CPPUNIT_ASSERT_EQUAL(Command::Next, actions[1]); + CPPUNIT_ASSERT_EQUAL(Command::Next, payload->getExecuteAction()); + } - void testParse_Form() { - PayloadsParserTester parser; + void testParse_Form() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<command xmlns='http://jabber.org/protocol/commands' node='config' status='completed'>" - "<x type=\"result\" xmlns=\"jabber:x:data\">" - "<title>Bot Configuration</title>" - "<instructions>Hello!</instructions>" - "<instructions>Fill out this form to configure your new bot!</instructions>" - "</x>" - "</command>" - )); + CPPUNIT_ASSERT(parser.parse( + "<command xmlns='http://jabber.org/protocol/commands' node='config' status='completed'>" + "<x type=\"result\" xmlns=\"jabber:x:data\">" + "<title>Bot Configuration</title>" + "<instructions>Hello!</instructions>" + "<instructions>Fill out this form to configure your new bot!</instructions>" + "</x>" + "</command>" + )); - Command::ref payload = parser.getPayload<Command>(); - Form::ref form = payload->getForm(); - CPPUNIT_ASSERT_EQUAL(std::string("Bot Configuration"), form->getTitle()); - CPPUNIT_ASSERT_EQUAL(std::string("Hello!\nFill out this form to configure your new bot!"), form->getInstructions()); - CPPUNIT_ASSERT_EQUAL(Form::ResultType, form->getType()); - } + Command::ref payload = parser.getPayload<Command>(); + Form::ref form = payload->getForm(); + CPPUNIT_ASSERT_EQUAL(std::string("Bot Configuration"), form->getTitle()); + CPPUNIT_ASSERT_EQUAL(std::string("Hello!\nFill out this form to configure your new bot!"), form->getInstructions()); + CPPUNIT_ASSERT_EQUAL(Form::ResultType, form->getType()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(CommandParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/DeliveryReceiptParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/DeliveryReceiptParserTest.cpp index 919c342..d93fd1f 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/DeliveryReceiptParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/DeliveryReceiptParserTest.cpp @@ -4,6 +4,12 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -15,29 +21,29 @@ using namespace Swift; class DeliveryReceiptParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DeliveryReceiptParserTest); - CPPUNIT_TEST(testParseXEP0184Example3); - CPPUNIT_TEST(testParseXEP0184Example4); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(DeliveryReceiptParserTest); + CPPUNIT_TEST(testParseXEP0184Example3); + CPPUNIT_TEST(testParseXEP0184Example4); + CPPUNIT_TEST_SUITE_END(); - public: - void testParseXEP0184Example3() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<request xmlns='urn:xmpp:receipts'/>")); + public: + void testParseXEP0184Example3() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<request xmlns='urn:xmpp:receipts'/>")); - DeliveryReceiptRequest::ref request = boost::dynamic_pointer_cast<DeliveryReceiptRequest>(parser.getPayload()); + DeliveryReceiptRequest::ref request = std::dynamic_pointer_cast<DeliveryReceiptRequest>(parser.getPayload()); - CPPUNIT_ASSERT(request); - } + CPPUNIT_ASSERT(request); + } - void testParseXEP0184Example4() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<received xmlns='urn:xmpp:receipts' id='richard2-4.1.247'/>")); + void testParseXEP0184Example4() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<received xmlns='urn:xmpp:receipts' id='richard2-4.1.247'/>")); - DeliveryReceipt::ref receipt = boost::dynamic_pointer_cast<DeliveryReceipt>(parser.getPayload()); + DeliveryReceipt::ref receipt = std::dynamic_pointer_cast<DeliveryReceipt>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(std::string("richard2-4.1.247"), receipt->getReceivedID()); - } + CPPUNIT_ASSERT_EQUAL(std::string("richard2-4.1.247"), receipt->getReceivedID()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(DeliveryReceiptParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp index d01abd1..6e866fc 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,91 +13,91 @@ using namespace Swift; class DiscoInfoParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DiscoInfoParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_Node); - CPPUNIT_TEST(testParse_Form); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(DiscoInfoParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_Node); + CPPUNIT_TEST(testParse_Form); + CPPUNIT_TEST_SUITE_END(); - public: - void testParse() { - PayloadsParserTester parser; + public: + void testParse() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<query xmlns=\"http://jabber.org/protocol/disco#info\">" - "<identity name=\"Swift\" category=\"client\" type=\"pc\" xml:lang=\"en\"/>" - "<identity name=\"Vlug\" category=\"client\" type=\"pc\" xml:lang=\"nl\"/>" - "<feature var=\"foo-feature\"/>" - "<feature var=\"bar-feature\"/>" - "<feature var=\"baz-feature\"/>" - "</query>")); + CPPUNIT_ASSERT(parser.parse( + "<query xmlns=\"http://jabber.org/protocol/disco#info\">" + "<identity name=\"Swift\" category=\"client\" type=\"pc\" xml:lang=\"en\"/>" + "<identity name=\"Vlug\" category=\"client\" type=\"pc\" xml:lang=\"nl\"/>" + "<feature var=\"foo-feature\"/>" + "<feature var=\"bar-feature\"/>" + "<feature var=\"baz-feature\"/>" + "</query>")); - DiscoInfo::ref payload = boost::dynamic_pointer_cast<DiscoInfo>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getIdentities().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Swift"), payload->getIdentities()[0].getName()); - CPPUNIT_ASSERT_EQUAL(std::string("pc"), payload->getIdentities()[0].getType()); - CPPUNIT_ASSERT_EQUAL(std::string("client"), payload->getIdentities()[0].getCategory()); - CPPUNIT_ASSERT_EQUAL(std::string("en"), payload->getIdentities()[0].getLanguage()); - CPPUNIT_ASSERT_EQUAL(std::string("Vlug"), payload->getIdentities()[1].getName()); - CPPUNIT_ASSERT_EQUAL(std::string("pc"), payload->getIdentities()[1].getType()); - CPPUNIT_ASSERT_EQUAL(std::string("client"), payload->getIdentities()[1].getCategory()); - CPPUNIT_ASSERT_EQUAL(std::string("nl"), payload->getIdentities()[1].getLanguage()); - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(payload->getFeatures().size())); - CPPUNIT_ASSERT_EQUAL(std::string("foo-feature"), payload->getFeatures()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("bar-feature"), payload->getFeatures()[1]); - CPPUNIT_ASSERT_EQUAL(std::string("baz-feature"), payload->getFeatures()[2]); - CPPUNIT_ASSERT(payload->getNode().empty()); - } + DiscoInfo::ref payload = std::dynamic_pointer_cast<DiscoInfo>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getIdentities().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Swift"), payload->getIdentities()[0].getName()); + CPPUNIT_ASSERT_EQUAL(std::string("pc"), payload->getIdentities()[0].getType()); + CPPUNIT_ASSERT_EQUAL(std::string("client"), payload->getIdentities()[0].getCategory()); + CPPUNIT_ASSERT_EQUAL(std::string("en"), payload->getIdentities()[0].getLanguage()); + CPPUNIT_ASSERT_EQUAL(std::string("Vlug"), payload->getIdentities()[1].getName()); + CPPUNIT_ASSERT_EQUAL(std::string("pc"), payload->getIdentities()[1].getType()); + CPPUNIT_ASSERT_EQUAL(std::string("client"), payload->getIdentities()[1].getCategory()); + CPPUNIT_ASSERT_EQUAL(std::string("nl"), payload->getIdentities()[1].getLanguage()); + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(payload->getFeatures().size())); + CPPUNIT_ASSERT_EQUAL(std::string("foo-feature"), payload->getFeatures()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("bar-feature"), payload->getFeatures()[1]); + CPPUNIT_ASSERT_EQUAL(std::string("baz-feature"), payload->getFeatures()[2]); + CPPUNIT_ASSERT(payload->getNode().empty()); + } - void testParse_Node() { - PayloadsParserTester parser; + void testParse_Node() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<query xmlns=\"http://jabber.org/protocol/disco#info\" node=\"blahblah\">" - "<identity name=\"Swift\" category=\"client\" type=\"pc\" xml:lang=\"en\"/>" - "<identity name=\"Vlug\" category=\"client\" type=\"pc\" xml:lang=\"nl\"/>" - "<feature var=\"foo-feature\"/>" - "<feature var=\"bar-feature\"/>" - "<feature var=\"baz-feature\"/>" - "</query>")); + CPPUNIT_ASSERT(parser.parse( + "<query xmlns=\"http://jabber.org/protocol/disco#info\" node=\"blahblah\">" + "<identity name=\"Swift\" category=\"client\" type=\"pc\" xml:lang=\"en\"/>" + "<identity name=\"Vlug\" category=\"client\" type=\"pc\" xml:lang=\"nl\"/>" + "<feature var=\"foo-feature\"/>" + "<feature var=\"bar-feature\"/>" + "<feature var=\"baz-feature\"/>" + "</query>")); - DiscoInfo::ref payload = boost::dynamic_pointer_cast<DiscoInfo>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getIdentities().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Swift"), payload->getIdentities()[0].getName()); - CPPUNIT_ASSERT_EQUAL(std::string("pc"), payload->getIdentities()[0].getType()); - CPPUNIT_ASSERT_EQUAL(std::string("client"), payload->getIdentities()[0].getCategory()); - CPPUNIT_ASSERT_EQUAL(std::string("en"), payload->getIdentities()[0].getLanguage()); - CPPUNIT_ASSERT_EQUAL(std::string("Vlug"), payload->getIdentities()[1].getName()); - CPPUNIT_ASSERT_EQUAL(std::string("pc"), payload->getIdentities()[1].getType()); - CPPUNIT_ASSERT_EQUAL(std::string("client"), payload->getIdentities()[1].getCategory()); - CPPUNIT_ASSERT_EQUAL(std::string("nl"), payload->getIdentities()[1].getLanguage()); - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(payload->getFeatures().size())); - CPPUNIT_ASSERT_EQUAL(std::string("foo-feature"), payload->getFeatures()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("bar-feature"), payload->getFeatures()[1]); - CPPUNIT_ASSERT_EQUAL(std::string("baz-feature"), payload->getFeatures()[2]); - CPPUNIT_ASSERT_EQUAL(std::string("blahblah"), payload->getNode()); - } + DiscoInfo::ref payload = std::dynamic_pointer_cast<DiscoInfo>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getIdentities().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Swift"), payload->getIdentities()[0].getName()); + CPPUNIT_ASSERT_EQUAL(std::string("pc"), payload->getIdentities()[0].getType()); + CPPUNIT_ASSERT_EQUAL(std::string("client"), payload->getIdentities()[0].getCategory()); + CPPUNIT_ASSERT_EQUAL(std::string("en"), payload->getIdentities()[0].getLanguage()); + CPPUNIT_ASSERT_EQUAL(std::string("Vlug"), payload->getIdentities()[1].getName()); + CPPUNIT_ASSERT_EQUAL(std::string("pc"), payload->getIdentities()[1].getType()); + CPPUNIT_ASSERT_EQUAL(std::string("client"), payload->getIdentities()[1].getCategory()); + CPPUNIT_ASSERT_EQUAL(std::string("nl"), payload->getIdentities()[1].getLanguage()); + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(payload->getFeatures().size())); + CPPUNIT_ASSERT_EQUAL(std::string("foo-feature"), payload->getFeatures()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("bar-feature"), payload->getFeatures()[1]); + CPPUNIT_ASSERT_EQUAL(std::string("baz-feature"), payload->getFeatures()[2]); + CPPUNIT_ASSERT_EQUAL(std::string("blahblah"), payload->getNode()); + } - void testParse_Form() { - PayloadsParserTester parser; + void testParse_Form() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<query xmlns=\"http://jabber.org/protocol/disco#info\">" - "<feature var=\"foo-feature\"/>" - "<x type=\"submit\" xmlns=\"jabber:x:data\">" - "<title>Bot Configuration</title>" - "<instructions>Hello!</instructions>" - "</x>" - "<feature var=\"bar-feature\"/>" - "</query>")); + CPPUNIT_ASSERT(parser.parse( + "<query xmlns=\"http://jabber.org/protocol/disco#info\">" + "<feature var=\"foo-feature\"/>" + "<x type=\"submit\" xmlns=\"jabber:x:data\">" + "<title>Bot Configuration</title>" + "<instructions>Hello!</instructions>" + "</x>" + "<feature var=\"bar-feature\"/>" + "</query>")); - DiscoInfo::ref payload = boost::dynamic_pointer_cast<DiscoInfo>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getExtensions().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Bot Configuration"), payload->getExtensions()[0]->getTitle()); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getFeatures().size())); - CPPUNIT_ASSERT_EQUAL(std::string("foo-feature"), payload->getFeatures()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("bar-feature"), payload->getFeatures()[1]); - } + DiscoInfo::ref payload = std::dynamic_pointer_cast<DiscoInfo>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getExtensions().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Bot Configuration"), payload->getExtensions()[0]->getTitle()); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getFeatures().size())); + CPPUNIT_ASSERT_EQUAL(std::string("foo-feature"), payload->getFeatures()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("bar-feature"), payload->getFeatures()[1]); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(DiscoInfoParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/DiscoItemsParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/DiscoItemsParserTest.cpp index ee234ad..977ef8e 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/DiscoItemsParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/DiscoItemsParserTest.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -13,30 +19,30 @@ using namespace Swift; class DiscoItemsParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DiscoItemsParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/commands'>" - "<item jid='responder@domain' node='list' name='List Service Configurations'/>" - "<item jid='responder@domain' node='config' name='Configure Service'/>" - "</query>")); - - boost::shared_ptr<DiscoItems> payload = boost::dynamic_pointer_cast<DiscoItems>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getItems().size())); - CPPUNIT_ASSERT_EQUAL(std::string("List Service Configurations"), payload->getItems()[0].getName()); - CPPUNIT_ASSERT_EQUAL(std::string("list"), payload->getItems()[0].getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("responder@domain"), payload->getItems()[0].getJID().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("Configure Service"), payload->getItems()[1].getName()); - CPPUNIT_ASSERT_EQUAL(std::string("config"), payload->getItems()[1].getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("responder@domain"), payload->getItems()[1].getJID().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("http://jabber.org/protocol/commands"), payload->getNode()); - } + CPPUNIT_TEST_SUITE(DiscoItemsParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/commands'>" + "<item jid='responder@domain' node='list' name='List Service Configurations'/>" + "<item jid='responder@domain' node='config' name='Configure Service'/>" + "</query>")); + + std::shared_ptr<DiscoItems> payload = std::dynamic_pointer_cast<DiscoItems>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getItems().size())); + CPPUNIT_ASSERT_EQUAL(std::string("List Service Configurations"), payload->getItems()[0].getName()); + CPPUNIT_ASSERT_EQUAL(std::string("list"), payload->getItems()[0].getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("responder@domain"), payload->getItems()[0].getJID().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("Configure Service"), payload->getItems()[1].getName()); + CPPUNIT_ASSERT_EQUAL(std::string("config"), payload->getItems()[1].getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("responder@domain"), payload->getItems()[1].getJID().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("http://jabber.org/protocol/commands"), payload->getNode()); + } }; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp index 005fc09..5402614 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp @@ -1,57 +1,57 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <Swiften/Elements/Delay.h> #include <Swiften/Parser/PayloadParsers/ErrorParser.h> #include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> -#include <Swiften/Elements/Delay.h> using namespace Swift; class ErrorParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ErrorParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParseWithPayload); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<error type=\"modify\">" - "<bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>" - "<text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">boo</text>" - "</error>")); - - ErrorPayload::ref payload = boost::dynamic_pointer_cast<ErrorPayload>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(ErrorPayload::BadRequest, payload->getCondition()); - CPPUNIT_ASSERT_EQUAL(ErrorPayload::Modify, payload->getType()); - CPPUNIT_ASSERT_EQUAL(std::string("boo"), payload->getText()); - CPPUNIT_ASSERT(!payload->getPayload()); - } - - void testParseWithPayload() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<error type=\"modify\">" - "<bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>" - "<delay xmlns='urn:xmpp:delay' from='juliet@capulet.com/balcony' stamp='2002-09-10T23:41:07Z'/>" - "<text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">boo</text>" - "</error>")); - - ErrorPayload::ref payload = boost::dynamic_pointer_cast<ErrorPayload>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(ErrorPayload::BadRequest, payload->getCondition()); - CPPUNIT_ASSERT_EQUAL(ErrorPayload::Modify, payload->getType()); - CPPUNIT_ASSERT_EQUAL(std::string("boo"), payload->getText()); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<Delay>(payload->getPayload())); - } + CPPUNIT_TEST_SUITE(ErrorParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParseWithPayload); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<error type=\"modify\">" + "<bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>" + "<text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">boo</text>" + "</error>")); + + ErrorPayload::ref payload = std::dynamic_pointer_cast<ErrorPayload>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(ErrorPayload::BadRequest, payload->getCondition()); + CPPUNIT_ASSERT_EQUAL(ErrorPayload::Modify, payload->getType()); + CPPUNIT_ASSERT_EQUAL(std::string("boo"), payload->getText()); + CPPUNIT_ASSERT(!payload->getPayload()); + } + + void testParseWithPayload() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<error type=\"modify\">" + "<bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>" + "<delay xmlns='urn:xmpp:delay' from='juliet@capulet.com/balcony' stamp='2002-09-10T23:41:07Z'/>" + "<text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">boo</text>" + "</error>")); + + ErrorPayload::ref payload = std::dynamic_pointer_cast<ErrorPayload>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(ErrorPayload::BadRequest, payload->getCondition()); + CPPUNIT_ASSERT_EQUAL(ErrorPayload::Modify, payload->getType()); + CPPUNIT_ASSERT_EQUAL(std::string("boo"), payload->getText()); + CPPUNIT_ASSERT(std::dynamic_pointer_cast<Delay>(payload->getPayload())); + } }; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp index bc8f1bc..610c4f3 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp @@ -1,184 +1,231 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> #include <Swiften/Elements/Form.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> using namespace Swift; class FormParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(FormParserTest); - CPPUNIT_TEST(testParse_FormInformation); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_FormItems); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse_FormInformation() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<x type=\"submit\" xmlns=\"jabber:x:data\">" - "<title>Bot Configuration</title>" - "<instructions>Hello!</instructions>" - "<instructions>Fill out this form to configure your new bot!</instructions>" - "</x>" - )); - - Form* payload = dynamic_cast<Form*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("Bot Configuration"), payload->getTitle()); - CPPUNIT_ASSERT_EQUAL(std::string("Hello!\nFill out this form to configure your new bot!"), payload->getInstructions()); - CPPUNIT_ASSERT_EQUAL(Form::SubmitType, payload->getType()); - } - - void testParse() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<x type=\"form\" xmlns=\"jabber:x:data\">" - "<field type=\"hidden\" var=\"FORM_TYPE\">" - "<value>jabber:bot</value>" - "</field>" - "<field type=\"fixed\"><value>Section 1: Bot Info</value></field>" - "<field label=\"The name of your bot\" type=\"text-single\" var=\"botname\"/>" - "<field label=\"Helpful description of your bot\" type=\"text-multi\" var=\"description\"><value>This is a bot.</value><value>A quite good one actually</value></field>" - "<field label=\"Public bot?\" type=\"boolean\" var=\"public\">" - "<required/>" - "<value>1</value>" - "</field>" - "<field label=\"Password for special access\" type=\"text-private\" var=\"password\"/>" - "<field label=\"What features will the bot support?\" type=\"list-multi\" var=\"features\">" - "<option label=\"Contests\"><value>contests</value></option>" - "<option label=\"News\"><value>news</value></option>" - "<option label=\"Polls\"><value>polls</value></option>" - "<option label=\"Reminders\"><value>reminders</value></option>" - "<option label=\"Search\"><value>search</value></option>" - "<value>news</value>" - "<value>search</value>" - "</field>" - "<field label=\"Maximum number of subscribers\" type=\"list-single\" var=\"maxsubs\">" - "<value>20</value>" - "<option label=\"10\"><value>10</value></option>" - "<option label=\"20\"><value>20</value></option>" - "<option label=\"30\"><value>30</value></option>" - "<option label=\"50\"><value>50</value></option>" - "<option label=\"100\"><value>100</value></option>" - "<option label=\"None\"><value>none</value></option>" - "</field>" - "<field label=\"People to invite\" type=\"jid-multi\" var=\"invitelist\">" - "<desc>Tell all your friends about your new bot!</desc>" - "<value>foo@bar.com</value>" - "<value>baz@fum.org</value>" - "</field>" - "<field var=\"untyped\">" - "<value>foo</value>" - "</field>" - "</x>")); - - Form* payload = dynamic_cast<Form*>(parser.getPayload().get()); - - CPPUNIT_ASSERT_EQUAL(10, static_cast<int>(payload->getFields().size())); - CPPUNIT_ASSERT_EQUAL(std::string("jabber:bot"), payload->getFields()[0]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("FORM_TYPE"), payload->getFields()[0]->getName()); - CPPUNIT_ASSERT(!payload->getFields()[0]->getRequired()); - - CPPUNIT_ASSERT_EQUAL(std::string("Section 1: Bot Info"), payload->getFields()[1]->getValues()[0]); - - CPPUNIT_ASSERT_EQUAL(std::string("The name of your bot"), payload->getFields()[2]->getLabel()); - - CPPUNIT_ASSERT_EQUAL(std::string("This is a bot.\nA quite good one actually"), payload->getFields()[3]->getTextMultiValue()); - - CPPUNIT_ASSERT_EQUAL(true, payload->getFields()[4]->getBoolValue()); - CPPUNIT_ASSERT(payload->getFields()[4]->getRequired()); - CPPUNIT_ASSERT_EQUAL(std::string("1"), payload->getFields()[4]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getFields()[6]->getValues().size())); - CPPUNIT_ASSERT_EQUAL(std::string("news"), payload->getFields()[6]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("search"), payload->getFields()[6]->getValues()[1]); - CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(payload->getFields()[6]->getOptions().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Contests"), payload->getFields()[6]->getOptions()[0].label); - CPPUNIT_ASSERT_EQUAL(std::string("contests"), payload->getFields()[6]->getOptions()[0].value); - CPPUNIT_ASSERT_EQUAL(std::string("News"), payload->getFields()[6]->getOptions()[1].label); - CPPUNIT_ASSERT_EQUAL(std::string("news"), payload->getFields()[6]->getOptions()[1].value); - - CPPUNIT_ASSERT_EQUAL(std::string("20"), payload->getFields()[7]->getValues()[0]); - - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), payload->getFields()[8]->getJIDMultiValue(0)); - CPPUNIT_ASSERT_EQUAL(JID("baz@fum.org"), payload->getFields()[8]->getJIDMultiValue(1)); - CPPUNIT_ASSERT_EQUAL(std::string("Tell all your friends about your new bot!"), payload->getFields()[8]->getDescription()); - - CPPUNIT_ASSERT_EQUAL(std::string("foo"), payload->getFields()[9]->getValues()[0]); - } - - void testParse_FormItems() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<x xmlns='jabber:x:data' type='result'>" - "<field type='hidden' var='FORM_TYPE'>" - "<value>jabber:iq:search</value>" - "</field>" - "<reported>" - "<field var='first' label='Given Name' type='text-single'/>" - "<field var='last' label='Family Name' type='text-single'/>" - "<field var='jid' label='Jabber ID' type='jid-single'/>" - "<field var='x-gender' label='Gender' type='list-single'/>" - "</reported>" - "<item>" - "<field var='first'><value>Benvolio</value></field>" - "<field var='last'><value>Montague</value></field>" - "<field var='jid'><value>benvolio@montague.net</value></field>" - "<field var='x-gender'><value>male</value></field>" - "</item>" - "<item>" - "<field var='first'><value>Romeo</value></field>" - "<field var='last'><value>Montague</value></field>" - "<field var='jid'><value>romeo@montague.net</value></field>" - "<field var='x-gender'><value>male</value></field>" - "</item>" - "</x>")); - - Form* dataForm = dynamic_cast<Form*>(parser.getPayload().get()); - CPPUNIT_ASSERT(dataForm); - - Form::FormItem reported = dataForm->getReportedFields(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), reported.size()); - - std::vector<Form::FormItem> items = dataForm->getItems(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items.size()); - - Form::FormItem item = items[0]; - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); - - CPPUNIT_ASSERT_EQUAL(std::string("Benvolio"), item[0]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); - boost::shared_ptr<FormField> jidField = item[2]; - CPPUNIT_ASSERT_EQUAL(JID("benvolio@montague.net"), jidField->getJIDSingleValue()); - CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); - - item = items[1]; - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); - - CPPUNIT_ASSERT_EQUAL(std::string("Romeo"), item[0]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); - jidField = item[2]; - CPPUNIT_ASSERT(jidField); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), jidField->getJIDSingleValue()); - CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); - } + CPPUNIT_TEST_SUITE(FormParserTest); + CPPUNIT_TEST(testParse_FormInformation); + CPPUNIT_TEST(testParse_FormLayout); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_FormItems); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse_FormInformation() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<x type=\"submit\" xmlns=\"jabber:x:data\">" + "<title>Bot Configuration</title>" + "<instructions>Hello!</instructions>" + "<instructions>Fill out this form to configure your new bot!</instructions>" + "</x>" + )); + + Form* payload = dynamic_cast<Form*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string("Bot Configuration"), payload->getTitle()); + CPPUNIT_ASSERT_EQUAL(std::string("Hello!\nFill out this form to configure your new bot!"), payload->getInstructions()); + CPPUNIT_ASSERT_EQUAL(Form::SubmitType, payload->getType()); + } + + void testParse_FormLayout() { + PayloadsParserTester parser; + + // P1 = page one, S1 = section one, F1 = field one, T1 = text one + CPPUNIT_ASSERT(parser.parse( + "<x type=\"form\" xmlns=\"jabber:x:data\">" + "<page label=\"P1\" xmlns=\"http://jabber.org/protocol/xdata-layout\">" + "<reportedref/>" + "<text>P1T1</text>" + "<fieldref var=\"P1F1\"/>" + "<section label=\"P1S1\">" + "<text>P1S1T1</text>" + "<fieldref var=\"P1S1F1\"/>" + "</section>" + "</page>" + "<page label=\"P2\" xmlns=\"http://jabber.org/protocol/xdata-layout\">" + "<section label=\"P2S1\">" + "<section label=\"P2S2\">" + "<section label=\"P2S3\"/>" + "</section>" + "</section>" + "</page>" + "<field label=\"field one\" type=\"text-single\" var=\"P1F1\"/>" + "<field label=\"field two\" type=\"text-single\" var=\"P1S1F1\"/>" + "</x>")); + + Form* payload = dynamic_cast<Form*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(payload->getFields().size())); + // PAGE ONE - parsing of element types + CPPUNIT_ASSERT_EQUAL(std::string("P1"), payload->getPages()[0]->getLabel()); + CPPUNIT_ASSERT(payload->getPages()[0]->getReportedRefs()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("P1T1"), payload->getPages()[0]->getTextElements()[0]->getTextString()); + CPPUNIT_ASSERT_EQUAL(std::string("P1F1"), payload->getPages()[0]->getFields()[0]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("P1S1"), payload->getPages()[0]->getChildSections()[0]->getLabel()); + CPPUNIT_ASSERT_EQUAL(std::string("P1S1T1"), payload->getPages()[0]->getChildSections()[0]->getTextElements()[0]->getTextString()); + CPPUNIT_ASSERT_EQUAL(std::string("P1S1F1"), payload->getPages()[0]->getChildSections()[0]->getFields()[0]->getName()); + // PAGE TWO - parsing of nested elements + CPPUNIT_ASSERT_EQUAL(std::string("P2"), payload->getPages()[1]->getLabel()); + CPPUNIT_ASSERT_EQUAL(std::string("P2S1"), payload->getPages()[1]->getChildSections()[0]->getLabel()); + CPPUNIT_ASSERT_EQUAL(std::string("P2S2"), payload->getPages()[1]->getChildSections()[0]->getChildSections()[0]->getLabel()); + CPPUNIT_ASSERT_EQUAL(std::string("P2S3"), payload->getPages()[1]->getChildSections()[0]->getChildSections()[0]->getChildSections()[0]->getLabel()); + } + + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<x type=\"form\" xmlns=\"jabber:x:data\">" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>jabber:bot</value>" + "</field>" + "<field type=\"fixed\"><value>Section 1: Bot Info</value></field>" + "<field label=\"The name of your bot\" type=\"text-single\" var=\"botname\"/>" + "<field label=\"Helpful description of your bot\" type=\"text-multi\" var=\"description\"><value>This is a bot.</value><value>A quite good one actually</value></field>" + "<field label=\"Public bot?\" type=\"boolean\" var=\"public\">" + "<required/>" + "<value>1</value>" + "</field>" + "<field label=\"Password for special access\" type=\"text-private\" var=\"password\"/>" + "<field label=\"What features will the bot support?\" type=\"list-multi\" var=\"features\">" + "<option label=\"Contests\"><value>contests</value></option>" + "<option label=\"News\"><value>news</value></option>" + "<option label=\"Polls\"><value>polls</value></option>" + "<option label=\"Reminders\"><value>reminders</value></option>" + "<option label=\"Search\"><value>search</value></option>" + "<value>news</value>" + "<value>search</value>" + "</field>" + "<field label=\"Maximum number of subscribers\" type=\"list-single\" var=\"maxsubs\">" + "<value>20</value>" + "<option label=\"10\"><value>10</value></option>" + "<option label=\"20\"><value>20</value></option>" + "<option label=\"30\"><value>30</value></option>" + "<option label=\"50\"><value>50</value></option>" + "<option label=\"100\"><value>100</value></option>" + "<option label=\"None\"><value>none</value></option>" + "</field>" + "<field label=\"People to invite\" type=\"jid-multi\" var=\"invitelist\">" + "<desc>Tell all your friends about your new bot!</desc>" + "<value>foo@bar.com</value>" + "<value>baz@fum.org</value>" + "</field>" + "<field var=\"untyped\">" + "<value>foo</value>" + "</field>" + "</x>")); + + Form* payload = dynamic_cast<Form*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + + CPPUNIT_ASSERT_EQUAL(10, static_cast<int>(payload->getFields().size())); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:bot"), payload->getFields()[0]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("FORM_TYPE"), payload->getFields()[0]->getName()); + CPPUNIT_ASSERT(!payload->getFields()[0]->getRequired()); + + CPPUNIT_ASSERT_EQUAL(std::string("Section 1: Bot Info"), payload->getFields()[1]->getValues()[0]); + + CPPUNIT_ASSERT_EQUAL(std::string("The name of your bot"), payload->getFields()[2]->getLabel()); + + CPPUNIT_ASSERT_EQUAL(std::string("This is a bot.\nA quite good one actually"), payload->getFields()[3]->getTextMultiValue()); + + CPPUNIT_ASSERT_EQUAL(true, payload->getFields()[4]->getBoolValue()); + CPPUNIT_ASSERT(payload->getFields()[4]->getRequired()); + CPPUNIT_ASSERT_EQUAL(std::string("1"), payload->getFields()[4]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getFields()[6]->getValues().size())); + CPPUNIT_ASSERT_EQUAL(std::string("news"), payload->getFields()[6]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("search"), payload->getFields()[6]->getValues()[1]); + CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(payload->getFields()[6]->getOptions().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Contests"), payload->getFields()[6]->getOptions()[0].label); + CPPUNIT_ASSERT_EQUAL(std::string("contests"), payload->getFields()[6]->getOptions()[0].value); + CPPUNIT_ASSERT_EQUAL(std::string("News"), payload->getFields()[6]->getOptions()[1].label); + CPPUNIT_ASSERT_EQUAL(std::string("news"), payload->getFields()[6]->getOptions()[1].value); + + CPPUNIT_ASSERT_EQUAL(std::string("20"), payload->getFields()[7]->getValues()[0]); + + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), payload->getFields()[8]->getJIDMultiValue(0)); + CPPUNIT_ASSERT_EQUAL(JID("baz@fum.org"), payload->getFields()[8]->getJIDMultiValue(1)); + CPPUNIT_ASSERT_EQUAL(std::string("Tell all your friends about your new bot!"), payload->getFields()[8]->getDescription()); + + CPPUNIT_ASSERT_EQUAL(std::string("foo"), payload->getFields()[9]->getValues()[0]); + } + + void testParse_FormItems() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<x xmlns='jabber:x:data' type='result'>" + "<field type='hidden' var='FORM_TYPE'>" + "<value>jabber:iq:search</value>" + "</field>" + "<reported>" + "<field var='first' label='Given Name' type='text-single'/>" + "<field var='last' label='Family Name' type='text-single'/>" + "<field var='jid' label='Jabber ID' type='jid-single'/>" + "<field var='x-gender' label='Gender' type='list-single'/>" + "</reported>" + "<item>" + "<field var='first'><value>Benvolio</value></field>" + "<field var='last'><value>Montague</value></field>" + "<field var='jid'><value>benvolio@montague.net</value></field>" + "<field var='x-gender'><value>male</value></field>" + "</item>" + "<item>" + "<field var='first'><value>Romeo</value></field>" + "<field var='last'><value>Montague</value></field>" + "<field var='jid'><value>romeo@montague.net</value></field>" + "<field var='x-gender'><value>male</value></field>" + "</item>" + "</x>")); + + Form* dataForm = dynamic_cast<Form*>(parser.getPayload().get()); + CPPUNIT_ASSERT(dataForm); + + Form::FormItem reported = dataForm->getReportedFields(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), reported.size()); + + std::vector<Form::FormItem> items = dataForm->getItems(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items.size()); + + Form::FormItem item = items[0]; + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); + + CPPUNIT_ASSERT_EQUAL(std::string("Benvolio"), item[0]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); + std::shared_ptr<FormField> jidField = item[2]; + CPPUNIT_ASSERT_EQUAL(JID("benvolio@montague.net"), jidField->getJIDSingleValue()); + CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); + + item = items[1]; + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); + + CPPUNIT_ASSERT_EQUAL(std::string("Romeo"), item[0]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); + jidField = item[2]; + CPPUNIT_ASSERT(jidField); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), jidField->getJIDSingleValue()); + CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(FormParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ForwardedParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ForwardedParserTest.cpp new file mode 100644 index 0000000..a807d4e --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/ForwardedParserTest.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Parser/PayloadParsers/ForwardedParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.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>")); + + std::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())); + + std::shared_ptr<IQ> iq = std::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>")); + + std::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())); + + std::shared_ptr<Message> message = std::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().get()); + 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>")); + + std::shared_ptr<Forwarded> payload = parser.getPayload<Forwarded>(); + CPPUNIT_ASSERT(!!payload); + CPPUNIT_ASSERT(!payload->getDelay()); + + std::shared_ptr<Message> message = std::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().get()); + 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>")); + + std::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())); + + std::shared_ptr<Presence> presence = std::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/IBBParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/IBBParserTest.cpp index 90d7b6b..782cb32 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/IBBParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/IBBParserTest.cpp @@ -1,40 +1,39 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> - #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Elements/IBB.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> using namespace Swift; class IBBParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IBBParserTest); - CPPUNIT_TEST(testParse_Data); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse_Data() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<data xmlns='http://jabber.org/protocol/ibb' seq='4'>\n" - "\t YWJjZGVmZ2loamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjEyMzQ1\n" - "\t Njc4OTAK\n" - "</data>" - )); - - IBB::ref ibb = parser.getPayload<IBB>(); - CPPUNIT_ASSERT(ibb->getAction() == IBB::Data); - CPPUNIT_ASSERT(createByteArray("abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\x0a") == ibb->getData()); - CPPUNIT_ASSERT_EQUAL(4, ibb->getSequenceNumber()); - } + CPPUNIT_TEST_SUITE(IBBParserTest); + CPPUNIT_TEST(testParse_Data); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse_Data() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<data xmlns='http://jabber.org/protocol/ibb' seq='4'>\n" + "\t YWJjZGVmZ2loamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjEyMzQ1\n" + "\t Njc4OTAK\n" + "</data>" + )); + + IBB::ref ibb = parser.getPayload<IBB>(); + CPPUNIT_ASSERT(ibb->getAction() == IBB::Data); + CPPUNIT_ASSERT(createByteArray("abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\x0a") == ibb->getData()); + CPPUNIT_ASSERT_EQUAL(4, ibb->getSequenceNumber()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(IBBParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/IdleParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/IdleParserTest.cpp index 74da474..462247a 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/IdleParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/IdleParserTest.cpp @@ -4,35 +4,41 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> -#include <Swiften/Elements/Presence.h> -#include <Swiften/Elements/Idle.h> #include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/Idle.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> using namespace Swift; class IdleParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IdleParserTest); - CPPUNIT_TEST(testParse_XepWhatever_Example1); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(IdleParserTest); + CPPUNIT_TEST(testParse_XepWhatever_Example1); + CPPUNIT_TEST_SUITE_END(); - public: - void testParse_XepWhatever_Example1() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<presence from='juliet@capulet.com/balcony'>\n" - "<show>away</show>\n" - "<idle xmlns='urn:xmpp:idle:1' since='1969-07-21T02:56:15Z'/>\n" - "</presence>\n" - )); + public: + void testParse_XepWhatever_Example1() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<presence from='juliet@capulet.com/balcony'>\n" + "<show>away</show>\n" + "<idle xmlns='urn:xmpp:idle:1' since='1969-07-21T02:56:15Z'/>\n" + "</presence>\n" + )); - Presence::ref presence = parser.getPayload<Presence>(); - CPPUNIT_ASSERT(presence); - Idle::ref idle = presence->getPayload<Idle>(); - CPPUNIT_ASSERT(idle); - CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == idle->getSince()); - } + Presence::ref presence = parser.getPayload<Presence>(); + CPPUNIT_ASSERT(presence); + Idle::ref idle = presence->getPayload<Idle>(); + CPPUNIT_ASSERT(idle); + CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == idle->getSince()); + } }; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/InBandRegistrationPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/InBandRegistrationPayloadParserTest.cpp new file mode 100644 index 0000000..6d08812 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/InBandRegistrationPayloadParserTest.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/InBandRegistrationPayload.h> +#include <Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +class InBandRegistrationPayloadParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(InBandRegistrationPayloadParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_Form); + CPPUNIT_TEST_SUITE_END(); + + public: + InBandRegistrationPayloadParserTest() {} + + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns=\"jabber:iq:register\">" + "<registered/>" + "</query>")); + + InBandRegistrationPayload* payload = dynamic_cast<InBandRegistrationPayload*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(payload->isRegistered()); + } + + void testParse_Form() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns=\"jabber:iq:register\">" + "<instructions>Use the enclosed form to register.</instructions>" + "<x type=\"form\" xmlns=\"jabber:x:data\">" + "<title>Contest Registration</title>" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>jabber:iq:register</value>" + "</field>" + "</x>" + "</query>")); + + InBandRegistrationPayload* payload = dynamic_cast<InBandRegistrationPayload*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + boost::optional<std::string> instruction = payload->getInstructions(); + CPPUNIT_ASSERT(instruction); + CPPUNIT_ASSERT_EQUAL(std::string("Use the enclosed form to register."), instruction.get()); + + Form::ref form = payload->getForm(); + CPPUNIT_ASSERT(form); + CPPUNIT_ASSERT_EQUAL(std::string("Contest Registration"), form->getTitle()); + CPPUNIT_ASSERT_EQUAL(Form::FormType, form->getType()); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:register"), form->getFormType()); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(InBandRegistrationPayloadParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp index 8c8601a..c502c8a 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp @@ -4,706 +4,614 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> -#include <Swiften/Elements/JinglePayload.h> +#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/JingleFileTransferDescription.h> +#include <Swiften/Elements/JingleFileTransferHash.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> +#include <Swiften/Elements/JinglePayload.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> -#include <Swiften/Elements/JingleFileTransferDescription.h> #include <Swiften/Elements/StreamInitiationFileInfo.h> -#include <Swiften/Elements/JingleFileTransferReceived.h> -#include <Swiften/Elements/JingleFileTransferHash.h> -#include <Swiften/Base/DateTime.h> - -#include <Swiften/Base/Log.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> +#include <Swiften/StringCodecs/Base64.h> using namespace Swift; class JingleParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(JingleParserTest); - CPPUNIT_TEST(testParse_Xep0166_Example3); - CPPUNIT_TEST(testParse_Xep0166_Example8); - - CPPUNIT_TEST(testParse_Xep0261_Example1); - CPPUNIT_TEST(testParse_Xep0261_Example3); - CPPUNIT_TEST(testParse_Xep0261_Example9); - CPPUNIT_TEST(testParse_Xep0261_Example13); - - CPPUNIT_TEST(testParse_Xep0234_Example1); - CPPUNIT_TEST(testParse_Xep0234_Example3); - CPPUNIT_TEST(testParse_Xep0234_Example5); - CPPUNIT_TEST(testParse_Xep0234_Example8); - CPPUNIT_TEST(testParse_Xep0234_Example10); - CPPUNIT_TEST(testParse_Xep0234_Example11); - CPPUNIT_TEST(testParse_Xep0234_Example12); - - CPPUNIT_TEST(testParse_Xep0260_Example1); - CPPUNIT_TEST(testParse_Xep0260_Example3); - CPPUNIT_TEST_SUITE_END(); - - public: - //http://xmpp.org/extensions/xep-0166.html#example-3 - void testParse_Xep0166_Example3() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-terminate'\n" - " sid='a73sjjvkla37jfea'>\n" - " <reason>\n" - " <success/>\n" - " </reason>\n" - "</jingle>\n" - )); - - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionTerminate, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - CPPUNIT_ASSERT_EQUAL(JinglePayload::Reason::Success, - jingle->getReason().get_value_or(JinglePayload::Reason(JinglePayload::Reason::UnknownType, "")).type); - } - - //http://xmpp.org/extensions/xep-0166.html#example-8 - void testParse_Xep0166_Example8() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-terminate'\n" - " sid='a73sjjvkla37jfea'>\n" - " <reason>\n" - " <success/>\n" - " <text>Sorry, gotta go!</text>\n" - " </reason>\n" - "</jingle>\n" - )); - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionTerminate, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - CPPUNIT_ASSERT_EQUAL(JinglePayload::Reason::Success, - jingle->getReason().get_value_or(JinglePayload::Reason(JinglePayload::Reason::UnknownType, "")).type); - CPPUNIT_ASSERT_EQUAL(std::string("Sorry, gotta go!"), - jingle->getReason().get_value_or(JinglePayload::Reason(JinglePayload::Reason::UnknownType, "")).text); - } - - // IBB Transport Method Examples - - // http://xmpp.org/extensions/xep-0261.html#example-1 - void testParse_Xep0261_Example1() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-initiate'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='a73sjjvkla37jfea'>\n" - " <content creator='initiator' name='ex'>\n" - " <description xmlns='urn:xmpp:example'/>\n" - " <transport xmlns='urn:xmpp:jingle:transports:ibb:1'\n" - " block-size='4096'\n" - " sid='ch3d9s71'/>\n" - " </content>\n" - "</jingle>\n" - )); - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - - std::vector<JingleContentPayload::ref> payloads = jingle->getContents(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payloads.size()); - JingleContentPayload::ref payload = payloads[0]; - CPPUNIT_ASSERT_EQUAL(JingleContentPayload::InitiatorCreator, payload->getCreator()); - CPPUNIT_ASSERT_EQUAL(std::string("ex"), payload->getName()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payload->getTransports().size()); - - JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); - CPPUNIT_ASSERT(transportPaylod); - CPPUNIT_ASSERT_EQUAL(4096U, *transportPaylod->getBlockSize()); - CPPUNIT_ASSERT_EQUAL(std::string("ch3d9s71"), transportPaylod->getSessionID()); - } - - // http://xmpp.org/extensions/xep-0261.html#example-1 - void testParse_Xep0261_Example3() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-accept'\n" - " initiator='romeo@montague.lit/orchard'\n" - " responder='juliet@capulet.lit/balcony'\n" - " sid='a73sjjvkla37jfea'>\n" - " <content creator='initiator' name='ex'>\n" - " <description xmlns='urn:xmpp:example'/>\n" - " <transport xmlns='urn:xmpp:jingle:transports:ibb:1'\n" - " block-size='2048'\n" - " sid='ch3d9s71'/>\n" - " </content>\n" - " </jingle>\n" - )); - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionAccept, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), jingle->getResponder()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - - std::vector<JingleContentPayload::ref> payloads = jingle->getContents(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payloads.size()); - JingleContentPayload::ref payload = payloads[0]; - CPPUNIT_ASSERT_EQUAL(JingleContentPayload::InitiatorCreator, payload->getCreator()); - CPPUNIT_ASSERT_EQUAL(std::string("ex"), payload->getName()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payload->getTransports().size()); - - JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); - CPPUNIT_ASSERT(transportPaylod); - CPPUNIT_ASSERT_EQUAL(2048U, *transportPaylod->getBlockSize()); - CPPUNIT_ASSERT_EQUAL(std::string("ch3d9s71"), transportPaylod->getSessionID()); - } - - // http://xmpp.org/extensions/xep-0261.html#example-9 - void testParse_Xep0261_Example9() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='transport-info'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='a73sjjvkla37jfea'>\n" - " <content creator='initiator' name='ex'>\n" - " <transport xmlns='urn:xmpp:jingle:transports:ibb:1'\n" - " block-size='2048'\n" - " sid='bt8a71h6'/>\n" - " </content>\n" - "</jingle>\n" - )); - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::TransportInfo, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - - std::vector<JingleContentPayload::ref> payloads = jingle->getContents(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payloads.size()); - JingleContentPayload::ref payload = payloads[0]; - CPPUNIT_ASSERT_EQUAL(JingleContentPayload::InitiatorCreator, payload->getCreator()); - CPPUNIT_ASSERT_EQUAL(std::string("ex"), payload->getName()); - - JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); - CPPUNIT_ASSERT(transportPaylod); - CPPUNIT_ASSERT_EQUAL(2048U, *transportPaylod->getBlockSize()); - CPPUNIT_ASSERT_EQUAL(std::string("bt8a71h6"), transportPaylod->getSessionID()); - } - - // http://xmpp.org/extensions/xep-0261.html#example-13 - void testParse_Xep0261_Example13() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-terminate'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='a73sjjvkla37jfea'>\n" - " <reason><success/></reason>\n" - " </jingle>\n" - )); - - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionTerminate, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - CPPUNIT_ASSERT_EQUAL(JinglePayload::Reason::Success, jingle->getReason().get_value_or(JinglePayload::Reason()).type); - - } - - // Jingle File Transfer Examples - - // http://xmpp.org/extensions/xep-0234.html#example-1 - void testParse_Xep0234_Example1() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-initiate'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='851ba2'>\n" - " <content creator='initiator' name='a-file-offer'>\n" - " <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" - " <offer>\n" - " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" - " date='1969-07-21T02:56:15Z'\n" - " hash='552da749930852c69ae5d2141d3766b1'\n" - " name='test.txt'\n" - " size='1022'>\n" - " <desc>This is a test. If this were a real file...</desc>\n" - " <range/>\n" - " </file>\n" - " </offer>\n" - " </description>\n" - " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" - " mode='tcp'\n" - " sid='vj3hs98y'>\n" - " <candidate cid='hft54dqy'\n" - " host='192.168.4.1'\n" - " jid='romeo@montague.lit/orchard'\n" - " port='5086'\n" - " priority='8257636'\n" - " type='direct'/>\n" - " <candidate cid='hutr46fe'\n" - " host='24.24.24.1'\n" - " jid='romeo@montague.lit/orchard'\n" - " port='5087'\n" - " priority='8258636'\n" - " type='direct'/>\n" - " </transport>\n" - " </content>\n" - " </jingle>\n" - )); - - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("851ba2"), jingle->getSessionID()); - - std::vector<JingleContentPayload::ref> contents = jingle->getContents(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), contents.size()); - - JingleFileTransferDescription::ref description = contents[0]->getDescription<JingleFileTransferDescription>(); - - - std::vector<StreamInitiationFileInfo> offers = description->getOffers(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), offers.size()); - CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), offers[0].getName()); - CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), offers[0].getHash()); - CPPUNIT_ASSERT(1022 == offers[0].getSize()); - CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), offers[0].getDescription()); - CPPUNIT_ASSERT_EQUAL(true, offers[0].getSupportsRangeRequests()); - CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == offers[0].getDate()); - CPPUNIT_ASSERT_EQUAL(std::string("md5"), offers[0].getAlgo()); - } - - // http://xmpp.org/extensions/xep-0234.html#example-3 - void testParse_Xep0234_Example3() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-accept'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='851ba2'>\n" - " <content creator='initiator' name='a-file-offer'>\n" - " <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" - " <offer>\n" - " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" - " name='test.txt'\n" - " size='1022'\n" - " hash='552da749930852c69ae5d2141d3766b1'\n" - " date='1969-07-21T02:56:15Z'>\n" - " <desc>This is a test. If this were a real file...</desc>\n" - " <range/>\n" - " </file>\n" - " </offer>\n" - " </description>\n" - " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" - " mode='tcp'\n" - " sid='vj3hs98y'>\n" - " <candidate cid='ht567dq'\n" - " host='192.169.1.10'\n" - " jid='juliet@capulet.lit/balcony'\n" - " port='6539'\n" - " priority='8257636'\n" - " type='direct'/>\n" - " <candidate cid='hr65dqyd'\n" - " host='134.102.201.180'\n" - " jid='juliet@capulet.lit/balcony'\n" - " port='16453'\n" - " priority='7929856'\n" - " type='assisted'/>\n" - " <candidate cid='grt654q2'\n" - " host='2001:638:708:30c9:219:d1ff:fea4:a17d'\n" - " jid='juliet@capulet.lit/balcony'\n" - " port='6539'\n" - " priority='8257606'\n" - " type='direct'/>\n" - " </transport>\n" - " </content>\n" - "</jingle>\n" - )); - - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionAccept, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("851ba2"), jingle->getSessionID()); - - std::vector<JingleContentPayload::ref> contents = jingle->getContents(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), contents.size()); - - JingleFileTransferDescription::ref description = contents[0]->getDescription<JingleFileTransferDescription>(); - - - std::vector<StreamInitiationFileInfo> offers = description->getOffers(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), offers.size()); - CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), offers[0].getName()); - CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), offers[0].getHash()); - CPPUNIT_ASSERT(1022 == offers[0].getSize()); - CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), offers[0].getDescription()); - CPPUNIT_ASSERT_EQUAL(true, offers[0].getSupportsRangeRequests()); - CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == offers[0].getDate()); - CPPUNIT_ASSERT_EQUAL(std::string("md5"), offers[0].getAlgo()); - } - - // http://xmpp.org/extensions/xep-0234.html#example-5 - void testParse_Xep0234_Example5() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='transport-info'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='a73sjjvkla37jfea'>\n" - " <content creator='initiator' name='ex'>\n" - " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" - " sid='vj3hs98y'>\n" - " <candidate-used cid='hr65dqyd'/>\n" - " </transport>\n" - " </content>\n" - "</jingle>\n" - )); - - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::TransportInfo, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - - std::vector<JingleContentPayload::ref> contents = jingle->getContents(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), contents.size()); - - JingleS5BTransportPayload::ref transport = contents[0]->getTransport<JingleS5BTransportPayload>(); - CPPUNIT_ASSERT(transport); - - CPPUNIT_ASSERT_EQUAL(std::string("vj3hs98y"), transport->getSessionID()); - CPPUNIT_ASSERT_EQUAL(std::string("hr65dqyd"), transport->getCandidateUsed()); - } - - // http://xmpp.org/extensions/xep-0234.html#example-8 - void testParse_Xep0234_Example8() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-info'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='a73sjjvkla37jfea'>\n" - " <checksum xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" - " <file>\n" - " <hashes xmlns='urn:xmpp:hashes:0'>\n" - " <hash algo='sha-1'>552da749930852c69ae5d2141d3766b1</hash>\n" - " </hashes>\n" - " </file>\n" - " </checksum>\n" - "</jingle>\n" - )); - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInfo, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - - JingleFileTransferHash::ref hash = jingle->getPayload<JingleFileTransferHash>(); - CPPUNIT_ASSERT(hash); - CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), hash->getHashes().find("sha-1")->second); - - } - - // http://xmpp.org/extensions/xep-0234.html#example-10 - void testParse_Xep0234_Example10() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-initiate'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='uj3b2'>\n" - " <content creator='initiator' name='a-file-request'>\n" - " <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" - " <request>\n" - " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" - " hash='552da749930852c69ae5d2141d3766b1'>\n" - " <range offset='270336'/>\n" - " </file>\n" - " </request>\n" - " </description>\n" - " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" - " mode='tcp'\n" - " sid='xig361fj'>\n" - " <candidate cid='ht567dq'\n" - " host='192.169.1.10'\n" - " jid='juliet@capulet.lit/balcony'\n" - " port='6539'\n" - " priority='8257636'\n" - " type='direct'/>\n" - " <candidate cid='hr65dqyd'\n" - " host='134.102.201.180'\n" - " jid='juliet@capulet.lit/balcony'\n" - " port='16453'\n" - " priority='7929856'\n" - " type='assisted'/>\n" - " <candidate cid='grt654q2'\n" - " host='2001:638:708:30c9:219:d1ff:fea4:a17d'\n" - " jid='juliet@capulet.lit/balcony'\n" - " port='6539'\n" - " priority='8257606'\n" - " type='direct'/>\n" - " </transport>\n" - " </content>\n" - "</jingle>\n" - )); - - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("uj3b2"), jingle->getSessionID()); - - JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>(); - CPPUNIT_ASSERT(content); - - StreamInitiationFileInfo file = content->getDescription<JingleFileTransferDescription>()->getRequests()[0]; - CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), file.getHash()); - CPPUNIT_ASSERT_EQUAL(static_cast<unsigned long long>(270336), file.getRangeOffset()); - CPPUNIT_ASSERT_EQUAL(true, file.getSupportsRangeRequests()); - } - - // http://xmpp.org/extensions/xep-0234.html#example-11 - void testParse_Xep0234_Example11() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-initiate'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='h2va419i'>\n" - " <content creator='initiator' name='a-file-offer'>\n" - " <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" - " <offer>\n" - " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" - " date='2011-06-01T15:58:15Z'\n" - " hash='a749930852c69ae5d2141d3766b1552d'\n" - " name='somefile.txt'\n" - " size='1234'/>\n" - " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" - " date='2011-06-01T15:58:15Z'\n" - " hash='930852c69ae5d2141d3766b1552da749'\n" - " name='anotherfile.txt'\n" - " size='2345'/>\n" - " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" - " date='2011-06-01T15:58:15Z'\n" - " hash='52c69ae5d2141d3766b1552da7499308'\n" - " name='yetanotherfile.txt'\n" - " size='3456'/>\n" - " </offer>\n" - " </description>\n" - " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" - " mode='tcp'\n" - " sid='vj3hs98y'>\n" - " <candidate cid='hft54dqy'\n" - " host='192.168.4.1'\n" - " jid='romeo@montague.lit/orchard'\n" - " port='5086'\n" - " priority='8257636'\n" - " type='direct'/>\n" - " <candidate cid='hutr46fe'\n" - " host='24.24.24.1'\n" - " jid='romeo@montague.lit/orchard'\n" - " port='5087'\n" - " priority='8258636'\n" - " type='direct'/>\n" - " </transport>\n" - " </content>\n" - "</jingle>\n" - )); - - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("h2va419i"), jingle->getSessionID()); - - JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>(); - CPPUNIT_ASSERT(content); - CPPUNIT_ASSERT_EQUAL(JingleContentPayload::InitiatorCreator, content->getCreator()); - CPPUNIT_ASSERT_EQUAL(std::string("a-file-offer"), content->getName()); - - std::vector<StreamInitiationFileInfo> offers = content->getDescription<JingleFileTransferDescription>()->getOffers(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), offers.size()); - } - - // http://xmpp.org/extensions/xep-0234.html#example-12 - void testParse_Xep0234_Example12() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-info'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='a73sjjvkla37jfea'>\n" - " <received xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" - " <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" - " hash='a749930852c69ae5d2141d3766b1552d'/>\n" - " </received>\n" - "</jingle>\n" - )); - - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInfo, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - - boost::shared_ptr<JingleFileTransferReceived> received = jingle->getPayload<JingleFileTransferReceived>(); - CPPUNIT_ASSERT(received); - CPPUNIT_ASSERT_EQUAL(std::string("a749930852c69ae5d2141d3766b1552d"), received->getFileInfo().getHash()); - } - - // http://xmpp.org/extensions/xep-0260.html#example-1 - void testParse_Xep0260_Example1() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-initiate'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='a73sjjvkla37jfea'>\n" - " <content creator='initiator' name='ex'>\n" - " <description xmlns='urn:xmpp:example'/>\n" - " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" - " mode='tcp'\n" - " sid='vj3hs98y'>\n" - " <candidate cid='hft54dqy'\n" - " host='192.168.4.1'\n" - " jid='romeo@montague.lit/orchard'\n" - " port='5086'\n" - " priority='8257636'\n" - " type='direct'/>\n" - " <candidate cid='hutr46fe'\n" - " host='24.24.24.1'\n" - " jid='romeo@montague.lit/orchard'\n" - " port='5087'\n" - " priority='8258636'\n" - " type='direct'/>\n" - " </transport>\n" - " </content>\n" - "</jingle>\n" - )); - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - - JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>(); - CPPUNIT_ASSERT(content); - - JingleS5BTransportPayload::ref s5bPayload = content->getTransport<JingleS5BTransportPayload>(); - CPPUNIT_ASSERT(s5bPayload); - - CPPUNIT_ASSERT_EQUAL(std::string("vj3hs98y"), s5bPayload->getSessionID()); - CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::TCPMode, s5bPayload->getMode()); - CPPUNIT_ASSERT_EQUAL(false, s5bPayload->hasCandidateError()); - CPPUNIT_ASSERT_EQUAL(false, s5bPayload->hasProxyError()); - CPPUNIT_ASSERT_EQUAL(std::string(), s5bPayload->getActivated()); - CPPUNIT_ASSERT_EQUAL(std::string(), s5bPayload->getCandidateUsed()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), s5bPayload->getCandidates().size()); - - JingleS5BTransportPayload::Candidate candidate; - candidate = s5bPayload->getCandidates()[0]; - CPPUNIT_ASSERT_EQUAL(std::string("hft54dqy"), candidate.cid); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), candidate.jid); - CPPUNIT_ASSERT(HostAddressPort(HostAddress("192.168.4.1"), 5086) == candidate.hostPort); - CPPUNIT_ASSERT_EQUAL(8257636, candidate.priority); - CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::DirectType, candidate.type); - - candidate = s5bPayload->getCandidates()[1]; - CPPUNIT_ASSERT_EQUAL(std::string("hutr46fe"), candidate.cid); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), candidate.jid); - CPPUNIT_ASSERT(HostAddressPort(HostAddress("24.24.24.1"), 5087) == candidate.hostPort); - CPPUNIT_ASSERT_EQUAL(8258636, candidate.priority); - CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::DirectType, candidate.type); - } - - // http://xmpp.org/extensions/xep-0260.html#example-3 - void testParse_Xep0260_Example3() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<jingle xmlns='urn:xmpp:jingle:1'\n" - " action='session-accept'\n" - " initiator='romeo@montague.lit/orchard'\n" - " sid='a73sjjvkla37jfea'>\n" - " <content creator='initiator' name='ex'>\n" - " <description xmlns='urn:xmpp:example'/>\n" - " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" - " mode='tcp'\n" - " sid='vj3hs98y'>\n" - " <candidate cid='ht567dq'\n" - " host='192.169.1.10'\n" - " jid='juliet@capulet.lit/balcony'\n" - " port='6539'\n" - " priority='8257636'\n" - " type='direct'/>\n" - " <candidate cid='hr65dqyd'\n" - " host='134.102.201.180'\n" - " jid='juliet@capulet.lit/balcony'\n" - " port='16453'\n" - " priority='7929856'\n" - " type='assisted'/>\n" - " <candidate cid='grt654q2'\n" - " host='2001:638:708:30c9:219:d1ff:fea4:a17d'\n" - " jid='juliet@capulet.lit/balcony'\n" - " port='6539'\n" - " priority='8257606'\n" - " type='direct'/>\n" - " </transport>\n" - " </content>\n" - "</jingle>\n" - )); - - JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); - CPPUNIT_ASSERT(jingle); - CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionAccept, jingle->getAction()); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); - CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); - - JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>(); - CPPUNIT_ASSERT(content); - - JingleS5BTransportPayload::ref s5bPayload = content->getTransport<JingleS5BTransportPayload>(); - CPPUNIT_ASSERT(s5bPayload); - - CPPUNIT_ASSERT_EQUAL(std::string("vj3hs98y"), s5bPayload->getSessionID()); - CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::TCPMode, s5bPayload->getMode()); - CPPUNIT_ASSERT_EQUAL(false, s5bPayload->hasCandidateError()); - CPPUNIT_ASSERT_EQUAL(false, s5bPayload->hasProxyError()); - CPPUNIT_ASSERT_EQUAL(std::string(), s5bPayload->getActivated()); - CPPUNIT_ASSERT_EQUAL(std::string(), s5bPayload->getCandidateUsed()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), s5bPayload->getCandidates().size()); - - JingleS5BTransportPayload::Candidate candidate; - candidate = s5bPayload->getCandidates()[0]; - CPPUNIT_ASSERT_EQUAL(std::string("ht567dq"), candidate.cid); - CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), candidate.jid); - CPPUNIT_ASSERT(HostAddressPort(HostAddress("192.169.1.10"), 6539) == candidate.hostPort); - CPPUNIT_ASSERT_EQUAL(8257636, candidate.priority); - CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::DirectType, candidate.type); - - candidate = s5bPayload->getCandidates()[1]; - CPPUNIT_ASSERT_EQUAL(std::string("hr65dqyd"), candidate.cid); - CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), candidate.jid); - CPPUNIT_ASSERT(HostAddressPort(HostAddress("134.102.201.180"), 16453) == candidate.hostPort); - CPPUNIT_ASSERT_EQUAL(7929856, candidate.priority); - CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::AssistedType, candidate.type); - - candidate = s5bPayload->getCandidates()[2]; - CPPUNIT_ASSERT_EQUAL(std::string("grt654q2"), candidate.cid); - CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), candidate.jid); - CPPUNIT_ASSERT(HostAddressPort(HostAddress("2001:638:708:30c9:219:d1ff:fea4:a17d"), 6539) == candidate.hostPort); - CPPUNIT_ASSERT_EQUAL(8257606, candidate.priority); - CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::DirectType, candidate.type); - } + CPPUNIT_TEST_SUITE(JingleParserTest); + CPPUNIT_TEST(testParse_Xep0166_Example3); + CPPUNIT_TEST(testParse_Xep0166_Example8); + + CPPUNIT_TEST(testParse_Xep0261_Example1); + CPPUNIT_TEST(testParse_Xep0261_Example3); + CPPUNIT_TEST(testParse_Xep0261_Example9); + CPPUNIT_TEST(testParse_Xep0261_Example13); + + CPPUNIT_TEST(testParse_Xep0234_Example1); + CPPUNIT_TEST(testParse_Xep0234_Example3); + CPPUNIT_TEST(testParse_Xep0234_Example5); + CPPUNIT_TEST(testParse_Xep0234_Example8); + CPPUNIT_TEST(testParse_Xep0234_Example10); + + CPPUNIT_TEST(testParse_Xep0260_Example1); + CPPUNIT_TEST(testParse_Xep0260_Example3); + CPPUNIT_TEST_SUITE_END(); + + public: + //http://xmpp.org/extensions/xep-0166.html#example-3 + void testParse_Xep0166_Example3() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-terminate'\n" + " sid='a73sjjvkla37jfea'>\n" + " <reason>\n" + " <success/>\n" + " </reason>\n" + "</jingle>\n" + )); + + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionTerminate, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); + CPPUNIT_ASSERT_EQUAL(JinglePayload::Reason::Success, + jingle->getReason().get_value_or(JinglePayload::Reason(JinglePayload::Reason::UnknownType, "")).type); + } + + //http://xmpp.org/extensions/xep-0166.html#example-8 + void testParse_Xep0166_Example8() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-terminate'\n" + " sid='a73sjjvkla37jfea'>\n" + " <reason>\n" + " <success/>\n" + " <text>Sorry, gotta go!</text>\n" + " </reason>\n" + "</jingle>\n" + )); + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionTerminate, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); + CPPUNIT_ASSERT_EQUAL(JinglePayload::Reason::Success, + jingle->getReason().get_value_or(JinglePayload::Reason(JinglePayload::Reason::UnknownType, "")).type); + CPPUNIT_ASSERT_EQUAL(std::string("Sorry, gotta go!"), + jingle->getReason().get_value_or(JinglePayload::Reason(JinglePayload::Reason::UnknownType, "")).text); + } + + // IBB Transport Method Examples + + // http://xmpp.org/extensions/xep-0261.html#example-1 + void testParse_Xep0261_Example1() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-initiate'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='a73sjjvkla37jfea'>\n" + " <content creator='initiator' name='ex'>\n" + " <description xmlns='urn:xmpp:example'/>\n" + " <transport xmlns='urn:xmpp:jingle:transports:ibb:1'\n" + " block-size='4096'\n" + " sid='ch3d9s71'/>\n" + " </content>\n" + "</jingle>\n" + )); + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); + + std::vector<JingleContentPayload::ref> payloads = jingle->getContents(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payloads.size()); + JingleContentPayload::ref payload = payloads[0]; + CPPUNIT_ASSERT_EQUAL(JingleContentPayload::InitiatorCreator, payload->getCreator()); + CPPUNIT_ASSERT_EQUAL(std::string("ex"), payload->getName()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payload->getTransports().size()); + + JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); + CPPUNIT_ASSERT(transportPaylod); + CPPUNIT_ASSERT_EQUAL(4096U, *transportPaylod->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(std::string("ch3d9s71"), transportPaylod->getSessionID()); + } + + // http://xmpp.org/extensions/xep-0261.html#example-1 + void testParse_Xep0261_Example3() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-accept'\n" + " initiator='romeo@montague.lit/orchard'\n" + " responder='juliet@capulet.lit/balcony'\n" + " sid='a73sjjvkla37jfea'>\n" + " <content creator='initiator' name='ex'>\n" + " <description xmlns='urn:xmpp:example'/>\n" + " <transport xmlns='urn:xmpp:jingle:transports:ibb:1'\n" + " block-size='2048'\n" + " sid='ch3d9s71'/>\n" + " </content>\n" + " </jingle>\n" + )); + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionAccept, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), jingle->getResponder()); + CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); + + std::vector<JingleContentPayload::ref> payloads = jingle->getContents(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payloads.size()); + JingleContentPayload::ref payload = payloads[0]; + CPPUNIT_ASSERT_EQUAL(JingleContentPayload::InitiatorCreator, payload->getCreator()); + CPPUNIT_ASSERT_EQUAL(std::string("ex"), payload->getName()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payload->getTransports().size()); + + JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); + CPPUNIT_ASSERT(transportPaylod); + CPPUNIT_ASSERT_EQUAL(2048U, *transportPaylod->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(std::string("ch3d9s71"), transportPaylod->getSessionID()); + } + + // http://xmpp.org/extensions/xep-0261.html#example-9 + void testParse_Xep0261_Example9() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='transport-info'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='a73sjjvkla37jfea'>\n" + " <content creator='initiator' name='ex'>\n" + " <transport xmlns='urn:xmpp:jingle:transports:ibb:1'\n" + " block-size='2048'\n" + " sid='bt8a71h6'/>\n" + " </content>\n" + "</jingle>\n" + )); + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::TransportInfo, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); + + std::vector<JingleContentPayload::ref> payloads = jingle->getContents(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), payloads.size()); + JingleContentPayload::ref payload = payloads[0]; + CPPUNIT_ASSERT_EQUAL(JingleContentPayload::InitiatorCreator, payload->getCreator()); + CPPUNIT_ASSERT_EQUAL(std::string("ex"), payload->getName()); + + JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); + CPPUNIT_ASSERT(transportPaylod); + CPPUNIT_ASSERT_EQUAL(2048U, *transportPaylod->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(std::string("bt8a71h6"), transportPaylod->getSessionID()); + } + + // http://xmpp.org/extensions/xep-0261.html#example-13 + void testParse_Xep0261_Example13() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-terminate'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='a73sjjvkla37jfea'>\n" + " <reason><success/></reason>\n" + " </jingle>\n" + )); + + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionTerminate, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); + CPPUNIT_ASSERT_EQUAL(JinglePayload::Reason::Success, jingle->getReason().get_value_or(JinglePayload::Reason()).type); + + } + + // Jingle File Transfer Examples + + // http://xmpp.org/extensions/xep-0234.html#example-1 + void testParse_Xep0234_Example1() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-initiate'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='851ba2'>\n" + "<content creator='initiator' name='a-file-offer'>\n" + "<description xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n" + "<file>\n" + "<date>1969-07-21T02:56:15Z</date>\n" + "<desc>This is a test. If this were a real file...</desc>\n" + "<media-type>text/plain</media-type>\n" + "<name>test.txt</name>\n" + "<range/>\n" + "<size>1022</size>\n" + "<hash xmlns='urn:xmpp:hashes:1' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n" + "</file>\n" + "</description>\n" + "<transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" + " mode='tcp'\n" + " sid='vj3hs98y'>\n" + "<candidate cid='hft54dqy'\n" + " host='192.168.4.1'\n" + " jid='romeo@montague.lit/orchard'\n" + " port='5086'\n" + " priority='8257636'\n" + " type='direct'/>\n" + "<candidate cid='hutr46fe'\n" + " host='24.24.24.1'\n" + " jid='romeo@montague.lit/orchard'\n" + " port='5087'\n" + " priority='8258636'\n" + " type='direct'/>\n" + "</transport>\n" + "</content>\n" + "</jingle>\n" + )); + + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(std::string("851ba2"), jingle->getSessionID()); + + std::vector<JingleContentPayload::ref> contents = jingle->getContents(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), contents.size()); + + JingleFileTransferDescription::ref description = contents[0]->getDescription<JingleFileTransferDescription>(); + + CPPUNIT_ASSERT(description); + JingleFileTransferFileInfo fileInfo = description->getFileInfo(); + CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), fileInfo.getName()); + CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), fileInfo.getHashes().begin()->first); + CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(fileInfo.getHashes().begin()->second)); + CPPUNIT_ASSERT(1022 == fileInfo.getSize()); + CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), fileInfo.getDescription()); + CPPUNIT_ASSERT_EQUAL(true, fileInfo.getSupportsRangeRequests()); + CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == fileInfo.getDate()); + } + + // http://xmpp.org/extensions/xep-0234.html#example-3 + void testParse_Xep0234_Example3() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-accept'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='851ba2'>\n" + "<content creator='initiator' name='a-file-offer'>\n" + "<description xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n" + "<file>\n" + "<date>1969-07-21T02:56:15Z</date>\n" + "<desc>This is a test. If this were a real file...</desc>\n" + "<media-type>text/plain</media-type>\n" + "<name>test.txt</name>\n" + "<range/>\n" + "<size>1022</size>\n" + "<hash xmlns='urn:xmpp:hashes:1' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n" + "</file>\n" + "</description>\n" + " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" + " mode='tcp'\n" + " sid='vj3hs98y'>\n" + " <candidate cid='ht567dq'\n" + " host='192.169.1.10'\n" + " jid='juliet@capulet.lit/balcony'\n" + " port='6539'\n" + " priority='8257636'\n" + " type='direct'/>\n" + " <candidate cid='hr65dqyd'\n" + " host='134.102.201.180'\n" + " jid='juliet@capulet.lit/balcony'\n" + " port='16453'\n" + " priority='7929856'\n" + " type='assisted'/>\n" + " <candidate cid='grt654q2'\n" + " host='2001:638:708:30c9:219:d1ff:fea4:a17d'\n" + " jid='juliet@capulet.lit/balcony'\n" + " port='6539'\n" + " priority='8257606'\n" + " type='direct'/>\n" + " </transport>\n" + " </content>\n" + "</jingle>\n" + )); + + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionAccept, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(std::string("851ba2"), jingle->getSessionID()); + + std::vector<JingleContentPayload::ref> contents = jingle->getContents(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), contents.size()); + + JingleFileTransferDescription::ref description = contents[0]->getDescription<JingleFileTransferDescription>(); + + CPPUNIT_ASSERT(description); + + JingleFileTransferFileInfo fileInfo = description->getFileInfo(); + CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), fileInfo.getName()); + CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), fileInfo.getHashes().begin()->first); + CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(fileInfo.getHashes().begin()->second)); + CPPUNIT_ASSERT(1022 == fileInfo.getSize()); + CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), fileInfo.getDescription()); + CPPUNIT_ASSERT_EQUAL(true, fileInfo.getSupportsRangeRequests()); + CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == fileInfo.getDate()); + } + + // http://xmpp.org/extensions/xep-0234.html#example-5 + void testParse_Xep0234_Example5() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='transport-info'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='a73sjjvkla37jfea'>\n" + " <content creator='initiator' name='ex'>\n" + " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" + " sid='vj3hs98y'>\n" + " <candidate-used cid='hr65dqyd'/>\n" + " </transport>\n" + " </content>\n" + "</jingle>\n" + )); + + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::TransportInfo, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); + + std::vector<JingleContentPayload::ref> contents = jingle->getContents(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), contents.size()); + + JingleS5BTransportPayload::ref transport = contents[0]->getTransport<JingleS5BTransportPayload>(); + CPPUNIT_ASSERT(transport); + + CPPUNIT_ASSERT_EQUAL(std::string("vj3hs98y"), transport->getSessionID()); + CPPUNIT_ASSERT_EQUAL(std::string("hr65dqyd"), transport->getCandidateUsed()); + } + + // http://xmpp.org/extensions/xep-0234.html#example-8 + void testParse_Xep0234_Example8() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-info'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='a73sjjvkla37jfea'>\n" + " <checksum xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n" + " <file>\n" + " <hash xmlns='urn:xmpp:hashes:0' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n" + " </file>\n" + " </checksum>\n" + "</jingle>\n" + )); + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInfo, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); + + JingleFileTransferHash::ref hash = jingle->getPayload<JingleFileTransferHash>(); + CPPUNIT_ASSERT(hash); + CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(hash->getFileInfo().getHash("sha-1").get())); + } + + // http://xmpp.org/extensions/xep-0234.html#example-10 + void testParse_Xep0234_Example10() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-initiate'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='uj3b2'>\n" + " <content creator='initiator' name='a-file-request'>\n" + " <description xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n" + " <file>\n" + " <hash xmlns='urn:xmpp:hashes:1' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n" + " <range offset='270336'/>\n" + " </file>\n" + " </description>\n" + " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" + " mode='tcp'\n" + " sid='xig361fj'>\n" + " <candidate cid='ht567dq'\n" + " host='192.169.1.10'\n" + " jid='juliet@capulet.lit/balcony'\n" + " port='6539'\n" + " priority='8257636'\n" + " type='direct'/>\n" + " <candidate cid='hr65dqyd'\n" + " host='134.102.201.180'\n" + " jid='juliet@capulet.lit/balcony'\n" + " port='16453'\n" + " priority='7929856'\n" + " type='assisted'/>\n" + " <candidate cid='grt654q2'\n" + " host='2001:638:708:30c9:219:d1ff:fea4:a17d'\n" + " jid='juliet@capulet.lit/balcony'\n" + " port='6539'\n" + " priority='8257606'\n" + " type='direct'/>\n" + " </transport>\n" + " </content>\n" + "</jingle>\n" + )); + + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(std::string("uj3b2"), jingle->getSessionID()); + + JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>(); + CPPUNIT_ASSERT(content); + + JingleFileTransferFileInfo file = content->getDescription<JingleFileTransferDescription>()->getFileInfo(); + CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), file.getHashes().begin()->first); + CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(file.getHashes().begin()->second)); + CPPUNIT_ASSERT_EQUAL(static_cast<boost::uintmax_t>(270336), file.getRangeOffset()); + CPPUNIT_ASSERT_EQUAL(true, file.getSupportsRangeRequests()); + } + + // http://xmpp.org/extensions/xep-0260.html#example-1 + void testParse_Xep0260_Example1() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-initiate'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='a73sjjvkla37jfea'>\n" + " <content creator='initiator' name='ex'>\n" + " <description xmlns='urn:xmpp:example'/>\n" + " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" + " mode='tcp'\n" + " sid='vj3hs98y'>\n" + " <candidate cid='hft54dqy'\n" + " host='192.168.4.1'\n" + " jid='romeo@montague.lit/orchard'\n" + " port='5086'\n" + " priority='8257636'\n" + " type='direct'/>\n" + " <candidate cid='hutr46fe'\n" + " host='24.24.24.1'\n" + " jid='romeo@montague.lit/orchard'\n" + " port='5087'\n" + " priority='8258636'\n" + " type='direct'/>\n" + " </transport>\n" + " </content>\n" + "</jingle>\n" + )); + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); + + JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>(); + CPPUNIT_ASSERT(content); + + JingleS5BTransportPayload::ref s5bPayload = content->getTransport<JingleS5BTransportPayload>(); + CPPUNIT_ASSERT(s5bPayload); + + CPPUNIT_ASSERT_EQUAL(std::string("vj3hs98y"), s5bPayload->getSessionID()); + CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::TCPMode, s5bPayload->getMode()); + CPPUNIT_ASSERT_EQUAL(false, s5bPayload->hasCandidateError()); + CPPUNIT_ASSERT_EQUAL(false, s5bPayload->hasProxyError()); + CPPUNIT_ASSERT_EQUAL(std::string(), s5bPayload->getActivated()); + CPPUNIT_ASSERT_EQUAL(std::string(), s5bPayload->getCandidateUsed()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), s5bPayload->getCandidates().size()); + + JingleS5BTransportPayload::Candidate candidate; + candidate = s5bPayload->getCandidates()[0]; + CPPUNIT_ASSERT_EQUAL(std::string("hft54dqy"), candidate.cid); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), candidate.jid); + CPPUNIT_ASSERT(HostAddressPort(HostAddress::fromString("192.168.4.1").get(), 5086) == candidate.hostPort); + CPPUNIT_ASSERT_EQUAL(8257636, candidate.priority); + CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::DirectType, candidate.type); + + candidate = s5bPayload->getCandidates()[1]; + CPPUNIT_ASSERT_EQUAL(std::string("hutr46fe"), candidate.cid); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), candidate.jid); + CPPUNIT_ASSERT(HostAddressPort(HostAddress::fromString("24.24.24.1").get(), 5087) == candidate.hostPort); + CPPUNIT_ASSERT_EQUAL(8258636, candidate.priority); + CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::DirectType, candidate.type); + } + + // http://xmpp.org/extensions/xep-0260.html#example-3 + void testParse_Xep0260_Example3() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<jingle xmlns='urn:xmpp:jingle:1'\n" + " action='session-accept'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='a73sjjvkla37jfea'>\n" + " <content creator='initiator' name='ex'>\n" + " <description xmlns='urn:xmpp:example'/>\n" + " <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" + " dstaddr='1a12fb7bc625e55f3ed5b29a53dbe0e4aa7d80ba'\n" + " mode='tcp'\n" + " sid='vj3hs98y'>\n" + " <candidate cid='ht567dq'\n" + " host='192.169.1.10'\n" + " jid='juliet@capulet.lit/balcony'\n" + " port='6539'\n" + " priority='8257636'\n" + " type='direct'/>\n" + " <candidate cid='hr65dqyd'\n" + " host='134.102.201.180'\n" + " jid='juliet@capulet.lit/balcony'\n" + " port='16453'\n" + " priority='7929856'\n" + " type='assisted'/>\n" + " <candidate cid='grt654q2'\n" + " host='2001:638:708:30c9:219:d1ff:fea4:a17d'\n" + " jid='juliet@capulet.lit/balcony'\n" + " port='6539'\n" + " priority='8257606'\n" + " type='direct'/>\n" + " </transport>\n" + " </content>\n" + "</jingle>\n" + )); + + JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); + CPPUNIT_ASSERT(jingle); + CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionAccept, jingle->getAction()); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); + CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); + + JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>(); + CPPUNIT_ASSERT(content); + + JingleS5BTransportPayload::ref s5bPayload = content->getTransport<JingleS5BTransportPayload>(); + CPPUNIT_ASSERT(s5bPayload); + + CPPUNIT_ASSERT_EQUAL(std::string("vj3hs98y"), s5bPayload->getSessionID()); + CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::TCPMode, s5bPayload->getMode()); + CPPUNIT_ASSERT_EQUAL(std::string("1a12fb7bc625e55f3ed5b29a53dbe0e4aa7d80ba"), s5bPayload->getDstAddr()); + CPPUNIT_ASSERT_EQUAL(false, s5bPayload->hasCandidateError()); + CPPUNIT_ASSERT_EQUAL(false, s5bPayload->hasProxyError()); + CPPUNIT_ASSERT_EQUAL(std::string(), s5bPayload->getActivated()); + CPPUNIT_ASSERT_EQUAL(std::string(), s5bPayload->getCandidateUsed()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), s5bPayload->getCandidates().size()); + + JingleS5BTransportPayload::Candidate candidate; + candidate = s5bPayload->getCandidates()[0]; + CPPUNIT_ASSERT_EQUAL(std::string("ht567dq"), candidate.cid); + CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), candidate.jid); + CPPUNIT_ASSERT(HostAddressPort(HostAddress::fromString("192.169.1.10").get(), 6539) == candidate.hostPort); + CPPUNIT_ASSERT_EQUAL(8257636, candidate.priority); + CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::DirectType, candidate.type); + + candidate = s5bPayload->getCandidates()[1]; + CPPUNIT_ASSERT_EQUAL(std::string("hr65dqyd"), candidate.cid); + CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), candidate.jid); + CPPUNIT_ASSERT(HostAddressPort(HostAddress::fromString("134.102.201.180").get(), 16453) == candidate.hostPort); + CPPUNIT_ASSERT_EQUAL(7929856, candidate.priority); + CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::AssistedType, candidate.type); + + candidate = s5bPayload->getCandidates()[2]; + CPPUNIT_ASSERT_EQUAL(std::string("grt654q2"), candidate.cid); + CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.lit/balcony"), candidate.jid); + CPPUNIT_ASSERT(HostAddressPort(HostAddress::fromString("2001:638:708:30c9:219:d1ff:fea4:a17d").get(), 6539) == candidate.hostPort); + CPPUNIT_ASSERT_EQUAL(8257606, candidate.priority); + CPPUNIT_ASSERT_EQUAL(JingleS5BTransportPayload::Candidate::DirectType, candidate.type); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(JingleParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MAMFinParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MAMFinParserTest.cpp new file mode 100644 index 0000000..6a8e2ed --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MAMFinParserTest.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Elements/MAMFin.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +class MAMFinParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(MAMFinParserTest); + CPPUNIT_TEST(testParse_XEP0313_Exmaple1); + CPPUNIT_TEST(testParse_XEP0313_Exmaple9); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse_XEP0313_Exmaple1() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<fin xmlns='urn:xmpp:mam:0' queryid='f27' />")); + + std::shared_ptr<MAMFin> payload = parser.getPayload<MAMFin>(); + CPPUNIT_ASSERT(!!payload); + CPPUNIT_ASSERT_EQUAL(false, payload->isComplete()); + CPPUNIT_ASSERT_EQUAL(true, payload->isStable()); + + boost::optional<std::string> queryID = payload->getQueryID(); + CPPUNIT_ASSERT(queryID); + CPPUNIT_ASSERT_EQUAL(std::string("f27"), queryID.get()); + } + + void testParse_XEP0313_Exmaple9() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<fin xmlns='urn:xmpp:mam:0' complete='true'>" + "<set xmlns='http://jabber.org/protocol/rsm'>" + "<first index='0'>23452-4534-1</first>" + "<last>390-2342-22</last>" + "<count>16</count>" + "</set>" + "</fin>")); + + std::shared_ptr<MAMFin> payload = parser.getPayload<MAMFin>(); + CPPUNIT_ASSERT(!!payload); + CPPUNIT_ASSERT_EQUAL(true, payload->isComplete()); + CPPUNIT_ASSERT_EQUAL(true, payload->isStable()); + + CPPUNIT_ASSERT(!!payload->getResultSet()); + std::shared_ptr<ResultSet> resultSet = payload->getResultSet(); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MAMFinParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MAMQueryParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MAMQueryParserTest.cpp new file mode 100644 index 0000000..8750c2e --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MAMQueryParserTest.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file 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(testParse_XEP0313_Example3); + CPPUNIT_TEST(testParse_XEP0313_Example4); + CPPUNIT_TEST(testParseEmpty); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<query queryid=\"id0\" xmlns=\"urn:xmpp:mam:0\" node=\"node1\">" + "<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>")); + + + std::shared_ptr<MAMQuery> payload = parser.getPayload<MAMQuery>(); + CPPUNIT_ASSERT(!!payload); + CPPUNIT_ASSERT(payload->getQueryID()); + CPPUNIT_ASSERT_EQUAL(std::string("id0"), *payload->getQueryID()); + CPPUNIT_ASSERT_EQUAL(std::string("node1"), *payload->getNode()); + + CPPUNIT_ASSERT(payload->getForm()); + std::shared_ptr<FormField> fieldType = payload->getForm()->getField("FORM_TYPE"); + CPPUNIT_ASSERT(fieldType); + CPPUNIT_ASSERT_EQUAL(std::string("urn:xmpp:mam:0"), fieldType->getTextSingleValue()); + std::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()); + std::shared_ptr<ResultSet> resultSet = payload->getResultSet(); + CPPUNIT_ASSERT(resultSet->getMaxItems()); + CPPUNIT_ASSERT_EQUAL(*resultSet->getMaxItems(), 10); + } + + void testParse_XEP0313_Example3() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<query xmlns='urn:xmpp:mam:0'>" + "<x xmlns='jabber:x:data'>" + "<field var='FORM_TYPE'>" + "<value>urn:xmpp:mam:0</value>" + "</field>" + "<field var='with'>" + "<value>juliet@capulet.lit</value>" + "</field>" + "</x>" + "</query>")); + + std::shared_ptr<MAMQuery> payload = parser.getPayload<MAMQuery>(); + CPPUNIT_ASSERT(!!payload && !!payload->getForm() && !!payload->getForm()->getField("FORM_TYPE") && !!payload->getForm()->getField("with")); + CPPUNIT_ASSERT_EQUAL(std::string("urn:xmpp:mam:0"), payload->getForm()->getField("FORM_TYPE")->getTextSingleValue()); + CPPUNIT_ASSERT_EQUAL(std::string("juliet@capulet.lit"), payload->getForm()->getField("with")->getTextSingleValue()); + } + + void testParse_XEP0313_Example4() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<query xmlns='urn:xmpp:mam:0'>" + "<x xmlns='jabber:x:data'>" + "<field var='FORM_TYPE'>" + "<value>urn:xmpp:mam:0</value>" + "</field>" + "<field var='start'>" + "<value>2010-06-07T00:00:00Z</value>" + "</field>" + "<field var='end'>" + "<value>2010-07-07T13:23:54Z</value>" + "</field>" + "</x>" + "</query>")); + std::shared_ptr<MAMQuery> payload = parser.getPayload<MAMQuery>(); + CPPUNIT_ASSERT(!!payload && !!payload->getForm() && !!payload->getForm()->getField("FORM_TYPE") && !!payload->getForm()->getField("start") && !!payload->getForm()->getField("start")); + CPPUNIT_ASSERT_EQUAL(std::string("urn:xmpp:mam:0"), payload->getForm()->getField("FORM_TYPE")->getTextSingleValue()); + CPPUNIT_ASSERT_EQUAL(std::string("2010-06-07T00:00:00Z"), payload->getForm()->getField("start")->getTextSingleValue()); + CPPUNIT_ASSERT_EQUAL(std::string("2010-07-07T13:23:54Z"), payload->getForm()->getField("end")->getTextSingleValue()); + } + + void testParseEmpty() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<query queryid=\"id0\" xmlns=\"urn:xmpp:mam:0\">" + "</query>")); + + std::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..15912b1 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MAMResultParserTest.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#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/Message.h> +#include <Swiften/Parser/PayloadParsers/MAMResultParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.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>")); + + std::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()); + + std::shared_ptr<Forwarded> forwarded = payload->getPayload(); + CPPUNIT_ASSERT(forwarded->getDelay()); + CPPUNIT_ASSERT_EQUAL(std::string("2010-07-10T23:08:25Z"), dateTimeToString(forwarded->getDelay()->getStamp())); + + std::shared_ptr<Message> message = std::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().get()); + 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/MIXCreateParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXCreateParserTest.cpp new file mode 100644 index 0000000..f48bbc7 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXCreateParserTest.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXCreate.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXCreateParserTest, XEP0369_Example68) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<create xmlns=\"urn:xmpp:mix:0\"/>" + )); + + auto payload = parser.getPayload<MIXCreate>(); + ASSERT_TRUE(payload); + + ASSERT_FALSE(payload->getData()); + ASSERT_FALSE(payload->getChannel()); +} + +TEST(MIXCreateParserTest, XEP0369_Example66) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<create channel=\"coven\" xmlns=\"urn:xmpp:mix:0\"/>" + )); + + auto payload = parser.getPayload<MIXCreate>(); + ASSERT_TRUE(payload); + + ASSERT_FALSE(payload->getData()); + + ASSERT_TRUE(payload->getChannel()); + ASSERT_EQ(std::string("coven"), *payload->getChannel()); +} + +TEST(MIXCreateParserTest, XEP0369_Example67) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<create channel=\"coven\" xmlns=\"urn:xmpp:mix:0\">" + "<x xmlns=\"jabber:x:data\" type=\"result\">" + "<field var=\"FORM_TYPE\" type=\"hidden\">" + "<value>urn:xmpp:mix:0</value>" + "</field>" + "<field var=\"Owner\">" + "<value>hecate@shakespeare.lit</value>" + "<value>greymalkin@shakespeare.lit</value>" + "</field>" + "<field var=\"Messages Node Subscription\">" + "<value>allowed</value>" + "</field>" + "<field var=\"JID Visibility\">" + "<value>jid-mandatory-visible</value>" + "</field>" + "<field var=\"No Private Messages\">" + "<value>true</value>" + "</field>" + "</x>" + "</create>" + )); + + auto payload = parser.getPayload<MIXCreate>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getData()); + ASSERT_EQ(Form::Type::ResultType, payload->getData()->getType()); + std::shared_ptr<FormField> fieldType = payload->getData()->getField("FORM_TYPE"); + ASSERT_TRUE(fieldType); + + std::shared_ptr<FormField> fieldJIDVisibility = payload->getData()->getField("JID Visibility"); + ASSERT_TRUE(fieldJIDVisibility); + ASSERT_EQ(std::string("jid-mandatory-visible"), fieldJIDVisibility->getTextSingleValue()); + + std::shared_ptr<FormField> fieldprivateMessages = payload->getData()->getField("No Private Messages"); + ASSERT_TRUE(fieldprivateMessages); + ASSERT_EQ(std::string("true"), fieldprivateMessages->getTextSingleValue()); + + std::shared_ptr<FormField> nodeSubs = payload->getData()->getField("Messages Node Subscription"); + ASSERT_TRUE(nodeSubs); + ASSERT_EQ(std::string("allowed"), nodeSubs->getTextSingleValue()); + + ASSERT_TRUE(payload->getChannel()); + ASSERT_EQ(std::string("coven"), *payload->getChannel()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MIXDestroyParser.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXDestroyParser.cpp new file mode 100644 index 0000000..80eb144 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXDestroyParser.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXDestroy.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXDestroyParserTest, XEP0369_Example70) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<destroy channel=\"coven\" xmlns=\"urn:xmpp:mix:0\"/>" + )); + + auto payload = parser.getPayload<MIXDestroy>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getChannel()); + ASSERT_EQ(std::string("coven"), *payload->getChannel()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MIXDestroyParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXDestroyParserTest.cpp new file mode 100644 index 0000000..5fa321e --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXDestroyParserTest.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXDestroy.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXDestroyParserTest, XEP0369_Example70) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<destroy channel=\"coven\" xmlns=\"urn:xmpp:mix:0\"/>" + )); + + auto payload = parser.getPayload<MIXDestroy>(); + ASSERT_TRUE(payload); + + ASSERT_EQ(std::string("coven"), payload->getChannel()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MIXJoinParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXJoinParserTest.cpp new file mode 100644 index 0000000..0ad4589 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXJoinParserTest.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXJoin.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXJoinParserTest, XEP0369_Example22) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<join xmlns=\"urn:xmpp:mix:0\" channel=\"coven@mix.shakespeare.example\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:presence\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:participants\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:config\"/>" + "</join>" + )); + + MIXJoin::ref payload = parser.getPayload<MIXJoin>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getChannel()); + ASSERT_EQ(JID("coven@mix.shakespeare.example"), *payload->getChannel()); + ASSERT_FALSE(payload->getJID()); + ASSERT_FALSE(payload->getForm()); + + ASSERT_EQ(static_cast<size_t>(4), payload->getSubscriptions().size()); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:messages"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:presence"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:participants"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:config"))); +} + +TEST(MIXJoinParserTest, XEP0369_Example23) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<join xmlns=\"urn:xmpp:mix:0\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:presence\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:participants\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:config\"/>" + "</join>" + )); + + MIXJoin::ref payload = parser.getPayload<MIXJoin>(); + ASSERT_TRUE(payload); + + ASSERT_FALSE(payload->getChannel()); + ASSERT_FALSE(payload->getJID()); + ASSERT_FALSE(payload->getForm()); + + ASSERT_EQ(static_cast<size_t>(4), payload->getSubscriptions().size()); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:messages"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:presence"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:participants"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:config"))); +} + +TEST(MIXJoinParserTest, XEP0369_Example24) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<join xmlns=\"urn:xmpp:mix:0\" jid=\"123456#coven@mix.shakespeare.example\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:presence\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:participants\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:config\"/>" + "</join>" + )); + + MIXJoin::ref payload = parser.getPayload<MIXJoin>(); + ASSERT_TRUE(payload); + + ASSERT_FALSE(payload->getChannel()); + ASSERT_TRUE(payload->getJID()); + ASSERT_EQ(JID("123456#coven@mix.shakespeare.example"), *payload->getJID()); + ASSERT_FALSE(payload->getForm()); + + ASSERT_EQ(static_cast<size_t>(4), payload->getSubscriptions().size()); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:messages"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:presence"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:participants"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:config"))); +} + +TEST(MIXJoinParserTest, XEP0369_Example29) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<join xmlns=\"urn:xmpp:mix:0\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:presence\"/>" + "<x xmlns=\"jabber:x:data\" type=\"submit\">" + "<field var=\"FORM_TYPE\" type=\"hidden\">" + "<value>urn:xmpp:mix:0</value>" + "</field>" + "<field var=\"JID Visibility\">" + "<value>never</value>" + "</field>" + "</x>" + "</join>")); + + MIXJoin::ref payload = parser.getPayload<MIXJoin>(); + ASSERT_TRUE(payload); + + ASSERT_FALSE(payload->getChannel()); + ASSERT_FALSE(payload->getJID()); + + ASSERT_EQ(static_cast<size_t>(2), payload->getSubscriptions().size()); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:messages"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:presence"))); + + ASSERT_TRUE(payload->getForm()); + ASSERT_EQ(Form::Type::SubmitType, payload->getForm()->getType()); + std::shared_ptr<FormField> fieldType = payload->getForm()->getField("FORM_TYPE"); + ASSERT_TRUE(fieldType); + + std::shared_ptr<FormField> fieldJIDVisibility = payload->getForm()->getField("JID Visibility"); + ASSERT_TRUE(fieldJIDVisibility); + ASSERT_EQ(std::string("never"), fieldJIDVisibility->getTextSingleValue()); +} + +TEST(MIXJoinParserTest, XEP0369_Example30) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<join xmlns=\"urn:xmpp:mix:0\" jid=\"hag66@shakespeare.example\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:presence\"/>" + "<x xmlns=\"jabber:x:data\" type=\"result\">" + "<field var=\"FORM_TYPE\" type=\"hidden\">" + "<value>urn:xmpp:mix:0</value>" + "</field>" + "<field var=\"JID Visibility\">" + "<value>never</value>" + "</field>" + "<field var=\"Private Messages\">" + "<value>allow</value>" + "</field>" + "<field var=\"vCard\">" + "<value>block</value>" + "</field>" + "</x>" + "</join>")); + + MIXJoin::ref payload = parser.getPayload<MIXJoin>(); + ASSERT_TRUE(payload); + + ASSERT_FALSE(payload->getChannel()); + ASSERT_TRUE(payload->getJID()); + ASSERT_EQ(JID("hag66@shakespeare.example"), *payload->getJID()); + + ASSERT_EQ(static_cast<size_t>(2), payload->getSubscriptions().size()); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:messages"))); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:presence"))); + + ASSERT_TRUE(payload->getForm()); + ASSERT_EQ(Form::Type::ResultType, payload->getForm()->getType()); + std::shared_ptr<FormField> fieldType = payload->getForm()->getField("FORM_TYPE"); + ASSERT_TRUE(fieldType); + + std::shared_ptr<FormField> fieldJIDVisibility = payload->getForm()->getField("JID Visibility"); + ASSERT_TRUE(fieldJIDVisibility); + ASSERT_EQ(std::string("never"), fieldJIDVisibility->getTextSingleValue()); + + std::shared_ptr<FormField> fieldprivateMessages = payload->getForm()->getField("Private Messages"); + ASSERT_TRUE(fieldprivateMessages); + ASSERT_EQ(std::string("allow"), fieldprivateMessages->getTextSingleValue()); + + std::shared_ptr<FormField> vCard = payload->getForm()->getField("vCard"); + ASSERT_TRUE(vCard); + ASSERT_EQ(std::string("block"), vCard->getTextSingleValue()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MIXLeaveParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXLeaveParserTest.cpp new file mode 100644 index 0000000..0a2839e --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXLeaveParserTest.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXLeave.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXLeaveParserTest, XEP0369_Example33) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse("<leave xmlns=\"urn:xmpp:mix:0\" channel=\"coven@mix.shakespeare.example\"/>")); + + auto payload = parser.getPayload<MIXLeave>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getChannel()); + ASSERT_EQ(JID("coven@mix.shakespeare.example"), *payload->getChannel()); +} + +TEST(MIXLeaveParserTest, XEP0369_Example34) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse("<leave xmlns=\"urn:xmpp:mix:0\"/>")); + + auto payload = parser.getPayload<MIXLeave>(); + ASSERT_TRUE(payload); + ASSERT_FALSE(payload->getChannel()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MIXParticipantParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXParticipantParserTest.cpp new file mode 100644 index 0000000..57d4b35 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXParticipantParserTest.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXParticipant.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXParticipantParserTest, XEP0369_Example1_ParticipantWithNick) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<participant xmlns='urn:xmpp:mix:0'> <nick>thirdwitch</nick> </participant>" + )); + + MIXParticipant::ref payload = parser.getPayload<MIXParticipant>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getNick()); + std::string nick = *payload->getNick(); + ASSERT_EQ("thirdwitch", nick); + + ASSERT_FALSE(payload->getJID()); +} + +TEST(MIXParticipantParserTest, XEP0369_Example2_ParticipantWithJID) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<participant xmlns='urn:xmpp:mix:0'> <jid>hecate@mix.shakespeare.example</jid> </participant>" + )); + + MIXParticipant::ref payload = parser.getPayload<MIXParticipant>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getJID()); + JID jid = *payload->getJID(); + ASSERT_EQ("hecate@mix.shakespeare.example", jid.toString()); + + ASSERT_FALSE(payload->getNick()); +} + +TEST(MIXParticipantParserTest, XEP0369_Example27_ParticipantEmpty) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<participant xmlns='urn:xmpp:mix:0'/>" + )); + + MIXParticipant::ref payload = parser.getPayload<MIXParticipant>(); + ASSERT_TRUE(payload); + ASSERT_FALSE(payload->getNick()); + ASSERT_FALSE(payload->getJID()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MIXPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXPayloadParserTest.cpp new file mode 100644 index 0000000..920aca7 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXPayloadParserTest.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXPayload.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXPayloadParserTest, WithNick) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<mix xmlns=\"urn:xmpp:mix:0\"> <nick>thirdwitch</nick> </mix>" + )); + + auto payload = parser.getPayload<MIXPayload>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getNick()); + std::string nick = *payload->getNick(); + ASSERT_EQ("thirdwitch", nick); + + ASSERT_FALSE(payload->getJID()); + ASSERT_FALSE(payload->getSubmissionID()); +} + +TEST(MIXPayloadParserTest, WithJID) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<mix xmlns=\"urn:xmpp:mix:0\"> <jid>hecate@mix.shakespeare.example</jid> </mix>" + )); + + auto payload = parser.getPayload<MIXPayload>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getJID()); + JID jid = *payload->getJID(); + ASSERT_EQ("hecate@mix.shakespeare.example", jid.toString()); + + ASSERT_FALSE(payload->getNick()); + ASSERT_FALSE(payload->getSubmissionID()); +} + +TEST(MIXPayloadParserTest, WithAll) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<mix xmlns=\"urn:xmpp:mix:0\">" + "<nick>thirdwitch</nick>" + "<jid>hecate@mix.shakespeare.example</jid>" + "<submission-id>92vax143g</submission-id>" + "</mix>" + )); + + auto payload = parser.getPayload<MIXPayload>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getNick()); + std::string nick = *payload->getNick(); + ASSERT_EQ("thirdwitch", nick); + + ASSERT_TRUE(payload->getJID()); + JID jid = *payload->getJID(); + ASSERT_EQ("hecate@mix.shakespeare.example", jid.toString()); + + ASSERT_TRUE(payload->getSubmissionID()); + std::string subID = *payload->getSubmissionID(); + ASSERT_EQ("92vax143g", subID); +} + +TEST(MIXPayloadParserTest, Empty) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<mix xmlns=\"urn:xmpp:mix:0\"/>" + )); + + auto payload = parser.getPayload<MIXPayload>(); + ASSERT_TRUE(payload); + ASSERT_FALSE(payload->getNick()); + ASSERT_FALSE(payload->getJID()); + ASSERT_FALSE(payload->getSubmissionID()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MIXRegisterNickParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXRegisterNickParserTest.cpp new file mode 100644 index 0000000..d0539fd --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXRegisterNickParserTest.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXRegisterNick.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXRegisterNickParserTest, WithNick) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<register xmlns=\"urn:xmpp:mix:0\"> <nick>thirdwitch</nick> </register>" + )); + + auto payload = parser.getPayload<MIXRegisterNick>(); + ASSERT_TRUE(payload); + ASSERT_EQ("thirdwitch", payload->getNick()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MIXSetNickParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXSetNickParserTest.cpp new file mode 100644 index 0000000..84f8a5e --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXSetNickParserTest.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXSetNick.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXSetNickParserTest, WithNick) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<setnick xmlns=\"urn:xmpp:mix:0\"> <nick>thirdwitch</nick> </setnick>" + )); + + auto payload = parser.getPayload<MIXSetNick>(); + ASSERT_TRUE(payload); + ASSERT_EQ("thirdwitch", payload->getNick()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MIXUpdateSubscriptionParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXUpdateSubscriptionParserTest.cpp new file mode 100644 index 0000000..985a34b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXUpdateSubscriptionParserTest.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXUpdateSubscription.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXUpdateSubscriptionParserTest, XEP0369_Example28) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<update-subscription xmlns=\"urn:xmpp:mix:0\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "</update-subscription>" + )); + + auto payload = parser.getPayload<MIXUpdateSubscription>(); + ASSERT_TRUE(payload); + + ASSERT_FALSE(payload->getJID()); + + auto items = payload->getSubscriptions(); + ASSERT_EQ(static_cast<size_t>(1), items.size()); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:messages"))); +} + +TEST(MIXUpdateSubscriptionParserTest, XEP0369_Example28_WithJID) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<update-subscription xmlns=\"urn:xmpp:mix:0\" jid=\"hag66@shakespeare.example\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "</update-subscription>" + )); + + auto payload = parser.getPayload<MIXUpdateSubscription>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getJID()); + ASSERT_EQ(JID("hag66@shakespeare.example"), *payload->getJID()); + + auto items = payload->getSubscriptions(); + ASSERT_EQ(static_cast<size_t>(1), items.size()); + ASSERT_TRUE(payload->hasSubscription(std::string("urn:xmpp:mix:nodes:messages"))); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MIXUserPreferenceParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MIXUserPreferenceParserTest.cpp new file mode 100644 index 0000000..7115f2a --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/MIXUserPreferenceParserTest.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/MIXUserPreference.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(MIXUserPreferenceParserTest, XEP0369_Example31) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<user-preference xmlns='urn:xmpp:mix:0'/>" + )); + + auto payload = parser.getPayload<MIXUserPreference>(); + ASSERT_TRUE(payload); + + ASSERT_FALSE(payload->getData()); +} + +TEST(MIXUserPreferenceParserTest, XEP0369_Example32) { + PayloadsParserTester parser; + ASSERT_TRUE(parser.parse( + "<user-preference xmlns='urn:xmpp:mix:0'>" + "<x xmlns='jabber:x:data' type='result'>" + "<field var='FORM_TYPE' type='hidden'>" + "<value>urn:xmpp:mix:0</value>" + "</field>" + "<field var='JID Visibility'>" + "<value>never</value>" + "</field>" + "<field var='Private Messages'>" + "<value>allow</value>" + "</field>" + "<field var='vCard'>" + "<value>block</value>" + "</field>" + "</x>" + "</user-preference>" + )); + + auto payload = parser.getPayload<MIXUserPreference>(); + ASSERT_TRUE(payload); + + ASSERT_TRUE(payload->getData()); + ASSERT_EQ(Form::Type::ResultType, payload->getData()->getType()); + std::shared_ptr<FormField> fieldType = payload->getData()->getField("FORM_TYPE"); + ASSERT_TRUE(fieldType); + + std::shared_ptr<FormField> fieldJIDVisibility = payload->getData()->getField("JID Visibility"); + ASSERT_TRUE(fieldJIDVisibility); + ASSERT_EQ(std::string("never"), fieldJIDVisibility->getTextSingleValue()); + + std::shared_ptr<FormField> fieldprivateMessages = payload->getData()->getField("Private Messages"); + ASSERT_TRUE(fieldprivateMessages); + ASSERT_EQ(std::string("allow"), fieldprivateMessages->getTextSingleValue()); + + std::shared_ptr<FormField> vCard = payload->getData()->getField("vCard"); + ASSERT_TRUE(vCard); + ASSERT_EQ(std::string("block"), vCard->getTextSingleValue()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp index 0648f58..d403872 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,25 +14,25 @@ using namespace Swift; class MUCAdminPayloadParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(MUCAdminPayloadParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(MUCAdminPayloadParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); - public: - MUCAdminPayloadParserTest() {} + public: + MUCAdminPayloadParserTest() {} - void testParse() { - PayloadsParserTester parser; + void testParse() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<query xmlns=\"http://jabber.org/protocol/muc#admin\"><item affiliation=\"owner\" role=\"visitor\"><actor jid=\"kev@tester.lit\"/><reason>malice</reason></item></query>")); + CPPUNIT_ASSERT(parser.parse("<query xmlns=\"http://jabber.org/protocol/muc#admin\"><item affiliation=\"owner\" role=\"visitor\"><actor jid=\"kev@tester.lit\"/><reason>malice</reason></item></query>")); - MUCAdminPayload::ref payload = boost::dynamic_pointer_cast<MUCAdminPayload>(parser.getPayload()); - MUCItem item = payload->getItems()[0]; - CPPUNIT_ASSERT_EQUAL(MUCOccupant::Owner, item.affiliation.get()); - CPPUNIT_ASSERT_EQUAL(MUCOccupant::Visitor, item.role.get()); - CPPUNIT_ASSERT_EQUAL(JID("kev@tester.lit"), item.actor.get()); - CPPUNIT_ASSERT_EQUAL(std::string("malice"), item.reason.get()); - } + MUCAdminPayload::ref payload = std::dynamic_pointer_cast<MUCAdminPayload>(parser.getPayload()); + MUCItem item = payload->getItems()[0]; + CPPUNIT_ASSERT_EQUAL(MUCOccupant::Owner, item.affiliation.get()); + CPPUNIT_ASSERT_EQUAL(MUCOccupant::Visitor, item.role.get()); + CPPUNIT_ASSERT_EQUAL(JID("kev@tester.lit"), item.actor.get()); + CPPUNIT_ASSERT_EQUAL(std::string("malice"), item.reason.get()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(MUCAdminPayloadParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp index 40d7358..f0cf68d 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp @@ -1,93 +1,92 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h> #include <Swiften/Elements/MUCDestroyPayload.h> +#include <Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h> #include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> using namespace Swift; class MUCUserPayloadParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(MUCUserPayloadParserTest); - CPPUNIT_TEST(testParseEmpty); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParseDestroy); - CPPUNIT_TEST(testParseInvite); - CPPUNIT_TEST_SUITE_END(); - - public: - MUCUserPayloadParserTest() {} - - void testParse() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"><status code='110'/><item affiliation=\"owner\" role=\"visitor\"><actor jid=\"kev@tester.lit\"/><reason>malice</reason></item><status code='210'/></x>")); - - bool found110 = false; - bool found210 = false; - - MUCUserPayload::ref payload = boost::dynamic_pointer_cast<MUCUserPayload>(parser.getPayload()); - - foreach (MUCUserPayload::StatusCode status, payload->getStatusCodes()) { - if (status.code == 110) found110 = true; - if (status.code == 210) found210 = true; - } - - MUCItem item = payload->getItems()[0]; - CPPUNIT_ASSERT_EQUAL(MUCOccupant::Owner, item.affiliation.get()); - CPPUNIT_ASSERT_EQUAL(MUCOccupant::Visitor, item.role.get()); - CPPUNIT_ASSERT_EQUAL(JID("kev@tester.lit"), item.actor.get()); - CPPUNIT_ASSERT_EQUAL(std::string("malice"), item.reason.get()); - CPPUNIT_ASSERT(found110); - CPPUNIT_ASSERT(found210); - } - - void testParseEmpty() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"/>")); - - MUCUserPayload::ref payload = boost::dynamic_pointer_cast<MUCUserPayload>(parser.getPayload()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT(payload->getItems().empty()); - } - - void testParseDestroy() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"><destroy jid='alice@wonderland.lit'><reason>bert</reason></destroy></x>")); - - MUCUserPayload::ref payload = boost::dynamic_pointer_cast<MUCUserPayload>(parser.getPayload()); - CPPUNIT_ASSERT(payload); - MUCDestroyPayload::ref destroy = boost::dynamic_pointer_cast<MUCDestroyPayload>(payload->getPayload()); - CPPUNIT_ASSERT(destroy); - CPPUNIT_ASSERT_EQUAL(std::string("bert"), destroy->getReason()); - CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit"), destroy->getNewVenue()); - } - - void testParseInvite() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"><invite from='crone1@shakespeare.lit/desktop' to='alice@wonderland.lit/xxx'> <reason>Hey Hecate, this is the place for all good witches!</reason> </invite> <password>cauldronburn</password></x>")); - - MUCUserPayload::ref payload = boost::dynamic_pointer_cast<MUCUserPayload>(parser.getPayload()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT(payload->getInvite()); - CPPUNIT_ASSERT(payload->getPassword()); - CPPUNIT_ASSERT_EQUAL(std::string("cauldronburn"), *payload->getPassword()); - MUCUserPayload::Invite invite = *payload->getInvite(); - CPPUNIT_ASSERT_EQUAL(std::string("Hey Hecate, this is the place for all good witches!"), invite.reason); - CPPUNIT_ASSERT_EQUAL(JID("crone1@shakespeare.lit/desktop"), invite.from); - CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/xxx"), invite.to); - } + CPPUNIT_TEST_SUITE(MUCUserPayloadParserTest); + CPPUNIT_TEST(testParseEmpty); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParseDestroy); + CPPUNIT_TEST(testParseInvite); + CPPUNIT_TEST_SUITE_END(); + + public: + MUCUserPayloadParserTest() {} + + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"><status code='110'/><item affiliation=\"owner\" role=\"visitor\"><actor jid=\"kev@tester.lit\"/><reason>malice</reason></item><status code='210'/></x>")); + + bool found110 = false; + bool found210 = false; + + MUCUserPayload::ref payload = std::dynamic_pointer_cast<MUCUserPayload>(parser.getPayload()); + + for (const auto& status : payload->getStatusCodes()) { + if (status.code == 110) found110 = true; + if (status.code == 210) found210 = true; + } + + MUCItem item = payload->getItems()[0]; + CPPUNIT_ASSERT_EQUAL(MUCOccupant::Owner, item.affiliation.get()); + CPPUNIT_ASSERT_EQUAL(MUCOccupant::Visitor, item.role.get()); + CPPUNIT_ASSERT_EQUAL(JID("kev@tester.lit"), item.actor.get()); + CPPUNIT_ASSERT_EQUAL(std::string("malice"), item.reason.get()); + CPPUNIT_ASSERT(found110); + CPPUNIT_ASSERT(found210); + } + + void testParseEmpty() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"/>")); + + MUCUserPayload::ref payload = std::dynamic_pointer_cast<MUCUserPayload>(parser.getPayload()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(payload->getItems().empty()); + } + + void testParseDestroy() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"><destroy jid='alice@wonderland.lit'><reason>bert</reason></destroy></x>")); + + MUCUserPayload::ref payload = std::dynamic_pointer_cast<MUCUserPayload>(parser.getPayload()); + CPPUNIT_ASSERT(payload); + MUCDestroyPayload::ref destroy = std::dynamic_pointer_cast<MUCDestroyPayload>(payload->getPayload()); + CPPUNIT_ASSERT(destroy); + CPPUNIT_ASSERT_EQUAL(std::string("bert"), destroy->getReason()); + CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit"), destroy->getNewVenue()); + } + + void testParseInvite() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"><invite from='crone1@shakespeare.lit/desktop' to='alice@wonderland.lit/xxx'> <reason>Hey Hecate, this is the place for all good witches!</reason> </invite> <password>cauldronburn</password></x>")); + + MUCUserPayload::ref payload = std::dynamic_pointer_cast<MUCUserPayload>(parser.getPayload()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(payload->getInvite()); + CPPUNIT_ASSERT(payload->getPassword()); + CPPUNIT_ASSERT_EQUAL(std::string("cauldronburn"), *payload->getPassword()); + MUCUserPayload::Invite invite = *payload->getInvite(); + CPPUNIT_ASSERT_EQUAL(std::string("Hey Hecate, this is the place for all good witches!"), invite.reason); + CPPUNIT_ASSERT_EQUAL(JID("crone1@shakespeare.lit/desktop"), invite.from); + CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/xxx"), invite.to); + } }; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h b/Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h index b0f68ab..a85a692 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h +++ b/Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h @@ -1,14 +1,14 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/UnitTest/ParserTester.h> #include <Swiften/Parser/PayloadParser.h> +#include <Swiften/Parser/UnitTest/ParserTester.h> namespace Swift { - typedef ParserTester<PayloadParser> PayloadParserTester; + typedef ParserTester<PayloadParser> PayloadParserTester; } diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h b/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h index b328670..8f9e0e1 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h +++ b/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h @@ -1,66 +1,64 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <cassert> + +#include <Swiften/Elements/Payload.h> +#include <Swiften/Parser/PayloadParser.h> #include <Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h> +#include <Swiften/Parser/PlatformXMLParserFactory.h> #include <Swiften/Parser/XMLParser.h> #include <Swiften/Parser/XMLParserClient.h> -#include <Swiften/Parser/PlatformXMLParserFactory.h> -#include <Swiften/Elements/Payload.h> -#include <Swiften/Parser/PayloadParser.h> namespace Swift { - class PayloadsParserTester : public XMLParserClient { - public: - PayloadsParserTester() : level(0) { - xmlParser = PlatformXMLParserFactory().createXMLParser(this); - } - - ~PayloadsParserTester() { - delete xmlParser; - } + class PayloadsParserTester : public XMLParserClient { + public: + PayloadsParserTester() : level(0) { + xmlParser = PlatformXMLParserFactory().createXMLParser(this, false); + } - bool parse(const std::string& data) { - return xmlParser->parse(data); - } + bool parse(const std::string& data) { + return xmlParser->parse(data); + } - virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (level == 0) { - assert(!payloadParser.get()); - PayloadParserFactory* payloadParserFactory = factories.getPayloadParserFactory(element, ns, attributes); - assert(payloadParserFactory); - payloadParser.reset(payloadParserFactory->createPayloadParser()); - } - payloadParser->handleStartElement(element, ns, attributes); - level++; - } + virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + if (level == 0) { + assert(!payloadParser.get()); + PayloadParserFactory* payloadParserFactory = factories.getPayloadParserFactory(element, ns, attributes); + assert(payloadParserFactory); + payloadParser.reset(payloadParserFactory->createPayloadParser()); + } + payloadParser->handleStartElement(element, ns, attributes); + level++; + } - virtual void handleEndElement(const std::string& element, const std::string& ns) { - level--; - payloadParser->handleEndElement(element, ns); - } + virtual void handleEndElement(const std::string& element, const std::string& ns) { + level--; + payloadParser->handleEndElement(element, ns); + } - virtual void handleCharacterData(const std::string& data) { - payloadParser->handleCharacterData(data); - } + virtual void handleCharacterData(const std::string& data) { + payloadParser->handleCharacterData(data); + } - boost::shared_ptr<Payload> getPayload() const { - return payloadParser->getPayload(); - } + std::shared_ptr<Payload> getPayload() const { + return payloadParser->getPayload(); + } - template<typename T> - boost::shared_ptr<T> getPayload() const { - return boost::dynamic_pointer_cast<T>(payloadParser->getPayload()); - } + template<typename T> + std::shared_ptr<T> getPayload() const { + return std::dynamic_pointer_cast<T>(payloadParser->getPayload()); + } - private: - XMLParser* xmlParser; - FullPayloadParserFactoryCollection factories; - boost::shared_ptr<PayloadParser> payloadParser; - int level; - }; + private: + std::unique_ptr<XMLParser> xmlParser; + FullPayloadParserFactoryCollection factories; + std::shared_ptr<PayloadParser> payloadParser; + int level; + }; } diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp index 0974aec..2c89f0f 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,29 +13,29 @@ using namespace Swift; class PriorityParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PriorityParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_Invalid); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(PriorityParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_Invalid); + CPPUNIT_TEST_SUITE_END(); - public: - void testParse() { - PayloadsParserTester parser; + public: + void testParse() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<priority>-120</priority>")); + CPPUNIT_ASSERT(parser.parse("<priority>-120</priority>")); - boost::shared_ptr<Priority> payload = boost::dynamic_pointer_cast<Priority>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(-120, payload->getPriority()); - } + std::shared_ptr<Priority> payload = std::dynamic_pointer_cast<Priority>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(-120, payload->getPriority()); + } - void testParse_Invalid() { - PayloadsParserTester parser; + void testParse_Invalid() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<priority>invalid</priority>")); + CPPUNIT_ASSERT(parser.parse("<priority>invalid</priority>")); - boost::shared_ptr<Priority> payload = boost::dynamic_pointer_cast<Priority>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(0, payload->getPriority()); - } + std::shared_ptr<Priority> payload = std::dynamic_pointer_cast<Priority>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(0, payload->getPriority()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(PriorityParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp index ef6ed9a..06f3ae5 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -9,87 +9,87 @@ #include <Swiften/Elements/Storage.h> #include <Swiften/Parser/PayloadParsers/PrivateStorageParser.h> -#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> #include <Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> using namespace Swift; class PrivateStorageParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PrivateStorageParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_NoPayload); - CPPUNIT_TEST(testParse_MultiplePayloads); - CPPUNIT_TEST_SUITE_END(); - - public: - PrivateStorageParserTest() {} - - void testParse() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<query xmlns='jabber:iq:private'>" - "<storage xmlns='storage:bookmarks'>" - "<conference name='Swift' jid='swift@rooms.swift.im'>" - "<nick>Alice</nick>" - "</conference>" - "</storage>" - "</query>")); - - boost::shared_ptr<PrivateStorage> payload = boost::dynamic_pointer_cast<PrivateStorage>(parser.getPayload()); - CPPUNIT_ASSERT(payload); - boost::shared_ptr<Storage> storage = boost::dynamic_pointer_cast<Storage>(payload->getPayload()); - CPPUNIT_ASSERT(storage); - CPPUNIT_ASSERT_EQUAL(std::string("Alice"), storage->getRooms()[0].nick); - CPPUNIT_ASSERT_EQUAL(JID("swift@rooms.swift.im"), storage->getRooms()[0].jid); - } - - void testParse_NoPayload() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:private'/>")); - - boost::shared_ptr<PrivateStorage> payload = boost::dynamic_pointer_cast<PrivateStorage>(parser.getPayload()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT(!payload->getPayload()); - } - - void testParse_MultiplePayloads() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<query xmlns='jabber:iq:private'>" - "<storage xmlns='storage:bookmarks'>" - "<conference name='Swift' jid='swift@rooms.swift.im'>" - "<nick>Alice</nick>" - "</conference>" - "</storage>" - "<storage xmlns='storage:bookmarks'>" - "<conference name='Swift' jid='swift@rooms.swift.im'>" - "<nick>Rabbit</nick>" - "</conference>" - "</storage>" - "</query>")); - - boost::shared_ptr<PrivateStorage> payload = boost::dynamic_pointer_cast<PrivateStorage>(parser.getPayload()); - CPPUNIT_ASSERT(payload); - boost::shared_ptr<Storage> storage = boost::dynamic_pointer_cast<Storage>(payload->getPayload()); - CPPUNIT_ASSERT(storage); - CPPUNIT_ASSERT_EQUAL(std::string("Rabbit"), storage->getRooms()[0].nick); - } - - void testParse_UnsupportedPayload() { - PayloadParserFactoryCollection factories; - PrivateStorageParser testling(&factories); - PayloadParserTester parser(&testling); - - CPPUNIT_ASSERT(parser.parse( - "<query xmlns='jabber:iq:private'>" - "<foo>Bar</foo>" - "</query>")); - - CPPUNIT_ASSERT(!boost::dynamic_pointer_cast<PrivateStorage>(testling.getPayload())->getPayload()); - } + CPPUNIT_TEST_SUITE(PrivateStorageParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_NoPayload); + CPPUNIT_TEST(testParse_MultiplePayloads); + CPPUNIT_TEST_SUITE_END(); + + public: + PrivateStorageParserTest() {} + + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns='jabber:iq:private'>" + "<storage xmlns='storage:bookmarks'>" + "<conference name='Swift' jid='swift@rooms.swift.im'>" + "<nick>Alice</nick>" + "</conference>" + "</storage>" + "</query>")); + + std::shared_ptr<PrivateStorage> payload = std::dynamic_pointer_cast<PrivateStorage>(parser.getPayload()); + CPPUNIT_ASSERT(payload); + std::shared_ptr<Storage> storage = std::dynamic_pointer_cast<Storage>(payload->getPayload()); + CPPUNIT_ASSERT(storage); + CPPUNIT_ASSERT_EQUAL(std::string("Alice"), storage->getRooms()[0].nick); + CPPUNIT_ASSERT_EQUAL(JID("swift@rooms.swift.im"), storage->getRooms()[0].jid); + } + + void testParse_NoPayload() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:private'/>")); + + std::shared_ptr<PrivateStorage> payload = std::dynamic_pointer_cast<PrivateStorage>(parser.getPayload()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(!payload->getPayload()); + } + + void testParse_MultiplePayloads() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns='jabber:iq:private'>" + "<storage xmlns='storage:bookmarks'>" + "<conference name='Swift' jid='swift@rooms.swift.im'>" + "<nick>Alice</nick>" + "</conference>" + "</storage>" + "<storage xmlns='storage:bookmarks'>" + "<conference name='Swift' jid='swift@rooms.swift.im'>" + "<nick>Rabbit</nick>" + "</conference>" + "</storage>" + "</query>")); + + std::shared_ptr<PrivateStorage> payload = std::dynamic_pointer_cast<PrivateStorage>(parser.getPayload()); + CPPUNIT_ASSERT(payload); + std::shared_ptr<Storage> storage = std::dynamic_pointer_cast<Storage>(payload->getPayload()); + CPPUNIT_ASSERT(storage); + CPPUNIT_ASSERT_EQUAL(std::string("Rabbit"), storage->getRooms()[0].nick); + } + + void testParse_UnsupportedPayload() { + PayloadParserFactoryCollection factories; + PrivateStorageParser testling(&factories); + PayloadParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns='jabber:iq:private'>" + "<foo>Bar</foo>" + "</query>")); + + CPPUNIT_ASSERT(!std::dynamic_pointer_cast<PrivateStorage>(testling.getPayload())->getPayload()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(PrivateStorageParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PubSubRetractParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/PubSubRetractParserTest.cpp new file mode 100644 index 0000000..91bc123 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/PubSubRetractParserTest.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Elements/ContainerPayload.h> +#include <Swiften/Parser/PayloadParsers/PubSubRetractParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +class PubSubRetractParserTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(PubSubRetractParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParseNotify); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<pubsub xmlns='http://jabber.org/protocol/pubsub'>" + "<retract node='princely_musings' xmlns='http://jabber.org/protocol/pubsub'>" + "<item id='ae890ac52d0df67ed7cfdf51b644e901' xmlns='http://jabber.org/protocol/pubsub'/>" + "</retract>" + "</pubsub>")); + + auto payload = parser.getPayload<ContainerPayload<PubSubPayload>>(); + std::shared_ptr<PubSubRetract> retract = std::dynamic_pointer_cast<PubSubRetract>(payload->getPayload()); + CPPUNIT_ASSERT(retract); + CPPUNIT_ASSERT_EQUAL(std::string("princely_musings"), retract->getNode()); + CPPUNIT_ASSERT_EQUAL(false, retract->isNotify().is_initialized()); + } + + void testParseNotify() { + { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<pubsub xmlns='http://jabber.org/protocol/pubsub'>" + "<retract node='princely_musings' notify='true' xmlns='http://jabber.org/protocol/pubsub'>" + "<item id='ae890ac52d0df67ed7cfdf51b644e901' xmlns='http://jabber.org/protocol/pubsub'/>" + "</retract>" + "</pubsub>")); + + auto payload = parser.getPayload<ContainerPayload<PubSubPayload>>(); + std::shared_ptr<PubSubRetract> retract = std::dynamic_pointer_cast<PubSubRetract>(payload->getPayload()); + CPPUNIT_ASSERT(retract); + CPPUNIT_ASSERT_EQUAL(std::string("princely_musings"), retract->getNode()); + CPPUNIT_ASSERT_EQUAL(true, retract->isNotify().get()); + } + + { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<pubsub xmlns='http://jabber.org/protocol/pubsub'>" + "<retract node='princely_musings' notify='0' xmlns='http://jabber.org/protocol/pubsub'>" + "<item id='ae890ac52d0df67ed7cfdf51b644e901' xmlns='http://jabber.org/protocol/pubsub'/>" + "</retract>" + "</pubsub>")); + + auto payload = parser.getPayload<ContainerPayload<PubSubPayload>>(); + auto retract = std::dynamic_pointer_cast<PubSubRetract>(payload->getPayload()); + CPPUNIT_ASSERT(retract); + CPPUNIT_ASSERT_EQUAL(std::string("princely_musings"), retract->getNode()); + CPPUNIT_ASSERT_EQUAL(false, retract->isNotify().get()); + } + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(PubSubRetractParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp index 4862584..2deca6e 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,27 +14,27 @@ using namespace Swift; class RawXMLPayloadParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(RawXMLPayloadParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST_SUITE_END(); - - public: - RawXMLPayloadParserTest() {} - - void testParse() { - RawXMLPayloadParser testling; - PayloadParserTester parser(&testling); - - std::string xml = - "<foo foo-attr=\"foo-val\" xmlns=\"ns:foo\">" - "<bar bar-attr=\"bar-val\" xmlns=\"ns:bar\"/>" - "<baz baz-attr=\"baz-val\" xmlns=\"ns:baz\"/>" - "</foo>"; - CPPUNIT_ASSERT(parser.parse(xml)); - - RawXMLPayload* payload = dynamic_cast<RawXMLPayload*>(testling.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(xml, payload->getRawXML()); - } + CPPUNIT_TEST_SUITE(RawXMLPayloadParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + RawXMLPayloadParserTest() {} + + void testParse() { + RawXMLPayloadParser testling; + PayloadParserTester parser(&testling); + + std::string xml = + "<foo foo-attr=\"foo-val\" xmlns=\"ns:foo\">" + "<bar bar-attr=\"bar-val\" xmlns=\"ns:bar\"/>" + "<baz baz-attr=\"baz-val\" xmlns=\"ns:baz\"/>" + "</foo>"; + CPPUNIT_ASSERT(parser.parse(xml)); + + RawXMLPayload* payload = dynamic_cast<RawXMLPayload*>(testling.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(xml, payload->getRawXML()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(RawXMLPayloadParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ReferencePayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ReferencePayloadParserTest.cpp new file mode 100644 index 0000000..ca7b280 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/ReferencePayloadParserTest.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Elements/Body.h> +#include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Parser/PayloadParsers/ReferencePayloadParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +using namespace Swift; + +TEST(ReferencePayloadParserTest, testParse) { + PayloadsParserTester parser; + + ASSERT_TRUE(parser.parse( + "<reference xmlns='urn:xmpp:reference:0' " + "type='data' " + "uri='https://www.example.com/mindBlowingImage.jpeg' " + "begin='11' " + "end='22' " + "anchor='xmpp:data@localhost.example.test'>" + "</reference>")); + + auto payload = std::dynamic_pointer_cast<ReferencePayload>(parser.getPayload()); + ASSERT_EQ(static_cast<int>(ReferencePayload::Type::Data), static_cast<int>(payload->getType())); + ASSERT_EQ(std::string("https://www.example.com/mindBlowingImage.jpeg"), *payload->getUri()); + ASSERT_EQ(std::string("11"), *payload->getBegin()); + ASSERT_EQ(std::string("22"), *payload->getEnd()); + ASSERT_EQ(std::string("xmpp:data@localhost.example.test"), *payload->getAnchor()); +} + +TEST(ReferencePayloadParserTest, testParseNoType) { + PayloadsParserTester parser; + + ASSERT_TRUE(parser.parse( + "<reference xmlns='urn:xmpp:reference:0' " + "uri='https://www.example.com/mindBlowingImage.jpeg' " + "begin='11' " + "end='22' " + "anchor='xmpp:data@localhost.example.test'>" + "</reference>")); + + auto payload = std::dynamic_pointer_cast<ReferencePayload>(parser.getPayload()); + ASSERT_EQ(static_cast<int>(ReferencePayload::Type::Unknown), static_cast<int>(payload->getType())); + ASSERT_EQ(std::string("https://www.example.com/mindBlowingImage.jpeg"), *payload->getUri()); + ASSERT_EQ(std::string("11"), *payload->getBegin()); + ASSERT_EQ(std::string("22"), *payload->getEnd()); + ASSERT_EQ(std::string("xmpp:data@localhost.example.test"), *payload->getAnchor()); +} + +TEST(ReferencePayloadParserTest, testParseEmbeddedPayloads) { + PayloadsParserTester parser; + + ASSERT_TRUE(parser.parse( + "<reference xmlns='urn:xmpp:reference:0' type='data'> " + "<error type=\"modify\">" + "<bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>" + "<delay xmlns='urn:xmpp:delay' from='juliet@capulet.com/balcony' stamp='2002-09-10T23:41:07Z'/>" + "<text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">boo</text>" + "</error>" + "</reference>")); + + auto payload = std::dynamic_pointer_cast<ReferencePayload>(parser.getPayload()); + ASSERT_EQ(static_cast<int>(ReferencePayload::Type::Data), static_cast<int>(payload->getType())); + ASSERT_FALSE(payload->getUri()); + ASSERT_FALSE(payload->getBegin()); + ASSERT_FALSE(payload->getEnd()); + ASSERT_FALSE(payload->getAnchor()); + auto childPayloadList = payload->getPayloads(); + auto errorPayload = std::dynamic_pointer_cast<ErrorPayload>(childPayloadList[0]); + ASSERT_TRUE(errorPayload); + ASSERT_EQ("boo", errorPayload->getText()); + auto delayPayload = std::dynamic_pointer_cast<Delay>(errorPayload->getPayload()); + ASSERT_TRUE(delayPayload); +} + +TEST(ReferencePayloadParserTest, testParseEmbeddedPayloadWithText) { + PayloadsParserTester parser; + + ASSERT_TRUE(parser.parse( + "<reference xmlns='urn:xmpp:reference:0' type='data'> " + "<body>Example Text</body>" + "</reference>")); + + auto payload = std::dynamic_pointer_cast<ReferencePayload>(parser.getPayload()); + auto childPayloadList = payload->getPayloads(); + auto bodyPayload = std::dynamic_pointer_cast<Body>(childPayloadList[0]); + ASSERT_EQ("Example Text", bodyPayload->getText()); +} + +TEST(ReferencePayloadParserTest, testParseRecursive) { + PayloadsParserTester parser; + + ASSERT_TRUE(parser.parse( + "<reference xmlns='urn:xmpp:reference:0' type='data'> " + "<reference xmlns='urn:xmpp:reference:0' type='data' uri='https://download.montague.lit/4a771ac1-f0b2-4a4a-9700-f2a26fa2bb67/summit.jpg' /> " + "<reference xmlns='urn:xmpp:reference:0' type='data' uri='xmpp:romeo@montague.lit/resource?jingle;id=9559976B-3FBF-4E7E-B457-2DAA225972BB' /> " + "<reference xmlns='urn:xmpp:reference:0' type='data'> " + "<reference xmlns='urn:xmpp:reference:0' type='data' uri='https://www.example.com/mindBlowingImage.jpeg' /> " + "</reference>" + "</reference>")); + + auto payload = std::dynamic_pointer_cast<ReferencePayload>(parser.getPayload()); + ASSERT_EQ(static_cast<int>(ReferencePayload::Type::Data), static_cast<int>(payload->getType())); + auto childPayloadList = payload->getPayloads(); + auto childPayloadA = std::dynamic_pointer_cast<ReferencePayload>(childPayloadList[0]); + auto childPayloadB = std::dynamic_pointer_cast<ReferencePayload>(childPayloadList[1]); + auto childPayloadC = std::dynamic_pointer_cast<ReferencePayload>(childPayloadList[2]); + ASSERT_TRUE(childPayloadA); + ASSERT_TRUE(childPayloadB); + ASSERT_TRUE(childPayloadC); + ASSERT_EQ(static_cast<int>(ReferencePayload::Type::Data), static_cast<int>(childPayloadA->getType())); + ASSERT_EQ(static_cast<int>(ReferencePayload::Type::Data), static_cast<int>(childPayloadB->getType())); + ASSERT_EQ(static_cast<int>(ReferencePayload::Type::Data), static_cast<int>(childPayloadC->getType())); + ASSERT_EQ(std::string("https://download.montague.lit/4a771ac1-f0b2-4a4a-9700-f2a26fa2bb67/summit.jpg"), *childPayloadA->getUri()); + ASSERT_EQ(std::string("xmpp:romeo@montague.lit/resource?jingle;id=9559976B-3FBF-4E7E-B457-2DAA225972BB"), *childPayloadB->getUri()); + ASSERT_FALSE(childPayloadC->getUri()); + ASSERT_FALSE(childPayloadC->getBegin()); + ASSERT_FALSE(childPayloadC->getEnd()); + ASSERT_FALSE(childPayloadC->getAnchor()); + auto grandChildPayloadList = childPayloadC->getPayloads(); + auto grandChildPayload = std::dynamic_pointer_cast<ReferencePayload>(grandChildPayloadList[0]); + ASSERT_TRUE(grandChildPayload); + ASSERT_EQ(static_cast<int>(ReferencePayload::Type::Data), static_cast<int>(grandChildPayload->getType())); + ASSERT_EQ(std::string("https://www.example.com/mindBlowingImage.jpeg"), *grandChildPayload->getUri()); + ASSERT_FALSE(grandChildPayload->getBegin()); + ASSERT_FALSE(grandChildPayload->getEnd()); + ASSERT_FALSE(grandChildPayload->getAnchor()); +} diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ReplaceTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ReplaceTest.cpp index c3f410f..6d77d4a 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/ReplaceTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/ReplaceTest.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -13,24 +19,24 @@ using namespace Swift; class ReplaceParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ReplaceParserTest); - CPPUNIT_TEST(testParseTrivial); - CPPUNIT_TEST(testParseChild); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(ReplaceParserTest); + CPPUNIT_TEST(testParseTrivial); + CPPUNIT_TEST(testParseChild); + CPPUNIT_TEST_SUITE_END(); - public: - void testParseTrivial() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<replace id='bad1' xmlns='http://swift.im/protocol/replace'/>")); - Replace::ref payload = boost::dynamic_pointer_cast <Replace>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(std::string("bad1"), payload->getID()); - } - void testParseChild() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<replace id='bad1' xmlns='http://swift.im/protocol/replace' ><child xmlns='blah' id=\"hi\"/></replace>")); - Replace::ref payload = boost::dynamic_pointer_cast <Replace>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(std::string("bad1"), payload->getID()); - } + public: + void testParseTrivial() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<replace id='bad1' xmlns='http://swift.im/protocol/replace'/>")); + Replace::ref payload = std::dynamic_pointer_cast <Replace>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(std::string("bad1"), payload->getID()); + } + void testParseChild() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<replace id='bad1' xmlns='http://swift.im/protocol/replace' ><child xmlns='blah' id=\"hi\"/></replace>")); + Replace::ref payload = std::dynamic_pointer_cast <Replace>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(std::string("bad1"), payload->getID()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(ReplaceParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp index 663a81c..5c786c5 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/ResourceBindParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,31 +14,31 @@ using namespace Swift; class ResourceBindParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ResourceBindParserTest); - CPPUNIT_TEST(testParse_JID); - CPPUNIT_TEST(testParse_Resource); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(ResourceBindParserTest); + CPPUNIT_TEST(testParse_JID); + CPPUNIT_TEST(testParse_Resource); + CPPUNIT_TEST_SUITE_END(); - public: - ResourceBindParserTest() {} + public: + ResourceBindParserTest() {} - void testParse_JID() { - PayloadsParserTester parser; + void testParse_JID() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>somenode@example.com/someresource</jid></bind>")); + CPPUNIT_ASSERT(parser.parse("<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>somenode@example.com/someresource</jid></bind>")); - ResourceBind* payload = dynamic_cast<ResourceBind*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(JID("somenode@example.com/someresource"), payload->getJID()); - } + ResourceBind* payload = dynamic_cast<ResourceBind*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(JID("somenode@example.com/someresource"), payload->getJID()); + } - void testParse_Resource() { - PayloadsParserTester parser; + void testParse_Resource() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>someresource</resource></bind>")); + CPPUNIT_ASSERT(parser.parse("<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>someresource</resource></bind>")); - ResourceBind* payload = dynamic_cast<ResourceBind*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("someresource"), payload->getResource()); - } + ResourceBind* payload = dynamic_cast<ResourceBind*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("someresource"), payload->getResource()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(ResourceBindParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/ResultSetParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/ResultSetParserTest.cpp new file mode 100644 index 0000000..da5d978 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/ResultSetParserTest.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file 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>" + "<index>0</index>" + "<first index=\"123\">stpeter@jabber.org</first>" + "<last>peterpan@neverland.lit</last>" + "<before>decaf-badba-dbad1</before>" + "<after>09af3-cc343-b409f</after>" + "</set>")); + + std::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->getIndex()); + CPPUNIT_ASSERT_EQUAL(0, *payload->getIndex()); + 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->getBefore()); + CPPUNIT_ASSERT_EQUAL(std::string("decaf-badba-dbad1"), *payload->getBefore()); + 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>")); + + std::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/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp index 1a18d6d..a94a6fe 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/RosterItemExchangeParserTest.cpp @@ -14,39 +14,39 @@ 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].getJID()); - CPPUNIT_ASSERT_EQUAL(std::string("Foo @ Bar"), items[0].getName()); - CPPUNIT_ASSERT_EQUAL(RosterItemExchangePayload::Item::Add, items[0].getAction()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items[0].getGroups().size()); - CPPUNIT_ASSERT_EQUAL(std::string("Group 1"), items[0].getGroups()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("Group 2"), items[0].getGroups()[1]); - - CPPUNIT_ASSERT_EQUAL(JID("baz@blo.com"), items[1].getJID()); - CPPUNIT_ASSERT_EQUAL(std::string("Baz"), items[1].getName()); - CPPUNIT_ASSERT_EQUAL(RosterItemExchangePayload::Item::Modify, items[1].getAction()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), items[1].getGroups().size()); - } + 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].getJID()); + CPPUNIT_ASSERT_EQUAL(std::string("Foo @ Bar"), items[0].getName()); + CPPUNIT_ASSERT_EQUAL(RosterItemExchangePayload::Item::Add, items[0].getAction()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items[0].getGroups().size()); + CPPUNIT_ASSERT_EQUAL(std::string("Group 1"), items[0].getGroups()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Group 2"), items[0].getGroups()[1]); + + CPPUNIT_ASSERT_EQUAL(JID("baz@blo.com"), items[1].getJID()); + CPPUNIT_ASSERT_EQUAL(std::string("Baz"), items[1].getName()); + CPPUNIT_ASSERT_EQUAL(RosterItemExchangePayload::Item::Modify, items[1].getAction()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), items[1].getGroups().size()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(RosterItemExchangeParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp index 6cb5dbc..261dad2 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/RosterParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,88 +14,88 @@ using namespace Swift; class RosterParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(RosterParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_ItemWithUnknownContent); - CPPUNIT_TEST(testParse_WithVersion); - CPPUNIT_TEST(testParse_WithEmptyVersion); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<query xmlns='jabber:iq:roster'>" - " <item jid='foo@bar.com' name='Foo @ Bar' subscription='from' ask='subscribe'>" - " <group>Group 1</group>" - " <group>Group 2</group>" - " </item>" - " <item jid='baz@blo.com' name='Baz'/>" - "</query>")); - - RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get()); - - CPPUNIT_ASSERT(!payload->getVersion()); - const RosterPayload::RosterItemPayloads& items = payload->getItems(); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items.size()); - - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), items[0].getJID()); - CPPUNIT_ASSERT_EQUAL(std::string("Foo @ Bar"), items[0].getName()); - CPPUNIT_ASSERT_EQUAL(RosterItemPayload::From, items[0].getSubscription()); - CPPUNIT_ASSERT(items[0].getSubscriptionRequested()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items[0].getGroups().size()); - CPPUNIT_ASSERT_EQUAL(std::string("Group 1"), items[0].getGroups()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("Group 2"), items[0].getGroups()[1]); - - CPPUNIT_ASSERT_EQUAL(JID("baz@blo.com"), items[1].getJID()); - CPPUNIT_ASSERT_EQUAL(std::string("Baz"), items[1].getName()); - CPPUNIT_ASSERT_EQUAL(RosterItemPayload::None, items[1].getSubscription()); - CPPUNIT_ASSERT(!items[1].getSubscriptionRequested()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), items[1].getGroups().size()); - } - - void testParse_ItemWithUnknownContent() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<query xmlns='jabber:iq:roster'>" - " <item jid='foo@bar.com' name='Foo @ Bar' subscription='from' ask='subscribe'>" - " <group>Group 1</group>" - " <foo xmlns=\"http://example.com\"><bar>Baz</bar></foo>" - " <group>Group 2</group>" - " <baz><fum>foo</fum></baz>" - " </item>" - "</query>")); - - RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get()); - const RosterPayload::RosterItemPayloads& items = payload->getItems(); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), items.size()); - CPPUNIT_ASSERT_EQUAL(std::string("Group 1"), items[0].getGroups()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("Group 2"), items[0].getGroups()[1]); - CPPUNIT_ASSERT_EQUAL(std::string( - "<foo xmlns=\"http://example.com\"><bar xmlns=\"http://example.com\">Baz</bar></foo>" - "<baz xmlns=\"jabber:iq:roster\"><fum xmlns=\"jabber:iq:roster\">foo</fum></baz>" - ), items[0].getUnknownContent()); - } - - void testParse_WithVersion() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:roster' ver='ver10'/>")); - - RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get()); - CPPUNIT_ASSERT(payload->getVersion()); - CPPUNIT_ASSERT_EQUAL(std::string("ver10"), *payload->getVersion()); - } - - void testParse_WithEmptyVersion() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:roster' ver=''/>")); - - RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get()); - CPPUNIT_ASSERT(payload->getVersion()); - CPPUNIT_ASSERT_EQUAL(std::string(""), *payload->getVersion()); - } + CPPUNIT_TEST_SUITE(RosterParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_ItemWithUnknownContent); + CPPUNIT_TEST(testParse_WithVersion); + CPPUNIT_TEST(testParse_WithEmptyVersion); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<query xmlns='jabber:iq:roster'>" + " <item jid='foo@bar.com' name='Foo @ Bar' subscription='from' ask='subscribe'>" + " <group>Group 1</group>" + " <group>Group 2</group>" + " </item>" + " <item jid='baz@blo.com' name='Baz'/>" + "</query>")); + + RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get()); + + CPPUNIT_ASSERT(!payload->getVersion()); + const RosterPayload::RosterItemPayloads& items = payload->getItems(); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items.size()); + + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), items[0].getJID()); + CPPUNIT_ASSERT_EQUAL(std::string("Foo @ Bar"), items[0].getName()); + CPPUNIT_ASSERT_EQUAL(RosterItemPayload::From, items[0].getSubscription()); + CPPUNIT_ASSERT(items[0].getSubscriptionRequested()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items[0].getGroups().size()); + CPPUNIT_ASSERT_EQUAL(std::string("Group 1"), items[0].getGroups()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Group 2"), items[0].getGroups()[1]); + + CPPUNIT_ASSERT_EQUAL(JID("baz@blo.com"), items[1].getJID()); + CPPUNIT_ASSERT_EQUAL(std::string("Baz"), items[1].getName()); + CPPUNIT_ASSERT_EQUAL(RosterItemPayload::None, items[1].getSubscription()); + CPPUNIT_ASSERT(!items[1].getSubscriptionRequested()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), items[1].getGroups().size()); + } + + void testParse_ItemWithUnknownContent() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse( + "<query xmlns='jabber:iq:roster'>" + " <item jid='foo@bar.com' name='Foo @ Bar' subscription='from' ask='subscribe'>" + " <group>Group 1</group>" + " <foo xmlns=\"http://example.com\"><bar>Baz</bar></foo>" + " <group>Group 2</group>" + " <baz><fum>foo</fum></baz>" + " </item>" + "</query>")); + + RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get()); + const RosterPayload::RosterItemPayloads& items = payload->getItems(); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), items.size()); + CPPUNIT_ASSERT_EQUAL(std::string("Group 1"), items[0].getGroups()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Group 2"), items[0].getGroups()[1]); + CPPUNIT_ASSERT_EQUAL(std::string( + "<foo xmlns=\"http://example.com\"><bar xmlns=\"http://example.com\">Baz</bar></foo>" + "<baz xmlns=\"jabber:iq:roster\"><fum xmlns=\"jabber:iq:roster\">foo</fum></baz>" + ), items[0].getUnknownContent()); + } + + void testParse_WithVersion() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:roster' ver='ver10'/>")); + + RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload->getVersion()); + CPPUNIT_ASSERT_EQUAL(std::string("ver10"), *payload->getVersion()); + } + + void testParse_WithEmptyVersion() { + PayloadsParserTester parser; + CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:roster' ver=''/>")); + + RosterPayload* payload = dynamic_cast<RosterPayload*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload->getVersion()); + CPPUNIT_ASSERT_EQUAL(std::string(""), *payload->getVersion()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(RosterParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp index 59ea3ff..5fe4168 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp @@ -1,181 +1,181 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> #include <Swiften/Elements/SearchPayload.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> using namespace Swift; class SearchPayloadParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SearchPayloadParserTest); - CPPUNIT_TEST(testParse_FormRequestResponse); - CPPUNIT_TEST(testParse_Results); - CPPUNIT_TEST(testParse_FormRequestResponse_XDATA); - CPPUNIT_TEST(testParse_Results_XDATA); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse_FormRequestResponse() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<query xmlns=\"jabber:iq:search\">" - "<instructions>Foo</instructions>" - "<first/>" - "<last/>" - "</query>" - )); - - SearchPayload::ref payload = parser.getPayload<SearchPayload>(); - CPPUNIT_ASSERT_EQUAL(std::string("Foo"), *payload->getInstructions()); - CPPUNIT_ASSERT(payload->getFirst()); - CPPUNIT_ASSERT(payload->getLast()); - CPPUNIT_ASSERT(!payload->getNick()); - } - - void testParse_Results() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<query xmlns=\"jabber:iq:search\">" - "<item jid=\"juliet@capulet.com\">" - "<first>Juliet</first>" - "<last>Capulet</last>" - "<nick>JuliC</nick>" - "<email>juliet@shakespeare.lit</email>" - "</item>" - "<item jid=\"tybalt@shakespeare.lit\">" - "<first>Tybalt</first>" - "<last>Capulet</last>" - "<nick>ty</nick>" - "<email>tybalt@shakespeare.lit</email>" - "</item>" - "</query>" - )); - - SearchPayload::ref payload = parser.getPayload<SearchPayload>(); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getItems().size())); - CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.com"), payload->getItems()[0].jid); - CPPUNIT_ASSERT_EQUAL(std::string("Juliet"), payload->getItems()[0].first); - CPPUNIT_ASSERT_EQUAL(std::string("Capulet"), payload->getItems()[0].last); - CPPUNIT_ASSERT_EQUAL(std::string("JuliC"), payload->getItems()[0].nick); - CPPUNIT_ASSERT_EQUAL(std::string("juliet@shakespeare.lit"), payload->getItems()[0].email); - CPPUNIT_ASSERT_EQUAL(JID("tybalt@shakespeare.lit"), payload->getItems()[1].jid); - } - - void testParse_FormRequestResponse_XDATA() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<query xmlns='jabber:iq:search'>" - "<instructions>" - "Use the enclosed form to search. If your Jabber client does not" - " support Data Forms, visit http://shakespeare.lit/" - "</instructions>" - "<x xmlns='jabber:x:data' type='form'>" - "<title>User Directory Search</title>" - "<instructions>" - "Please provide the following information" - " to search for Shakespearean characters." - "</instructions>" - "<field type='hidden'" - " var='FORM_TYPE'>" - "<value>jabber:iq:search</value>" - "</field>" - "<field type='text-single'" - " label='Given Name'" - " var='first'/>" - "<field type='text-single'" - " label='Family Name'" - " var='last'/>" - "<field type='list-single'" - " label='Gender'" - " var='x-gender'>" - "<option label='Male'><value>male</value></option>" - "<option label='Female'><value>female</value></option>" - "</field>" - "</x>" - "</query>" - )); - - SearchPayload::ref payload = parser.getPayload<SearchPayload>(); - CPPUNIT_ASSERT_EQUAL(std::string("Use the enclosed form to search. If your Jabber client does not" - " support Data Forms, visit http://shakespeare.lit/"), *payload->getInstructions()); - CPPUNIT_ASSERT(payload->getForm()); - CPPUNIT_ASSERT_EQUAL(std::string("Please provide the following information" - " to search for Shakespearean characters."), payload->getForm()->getInstructions()); - } - - void testParse_Results_XDATA() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:search'>" - " <x xmlns='jabber:x:data' type='result'>" - " <field type='hidden' var='FORM_TYPE'>" - " <value>jabber:iq:search</value>" - " </field>" - " <reported>" - " <field var='first' label='Given Name' type='text-single'/>" - " <field var='last' label='Family Name' type='text-single'/>" - " <field var='jid' label='Jabber ID' type='jid-single'/>" - " <field var='x-gender' label='Gender' type='list-single'/>" - " </reported>" - " <item>" - " <field var='first'><value>Benvolio</value></field>" - " <field var='last'><value>Montague</value></field>" - " <field var='jid'><value>benvolio@montague.net</value></field>" - " <field var='x-gender'><value>male</value></field>" - " </item>" - " <item>" - " <field var='first'><value>Romeo</value></field>" - " <field var='last'><value>Montague</value></field>" - " <field var='jid'><value>romeo@montague.net</value></field>" - " <field var='x-gender'><value>male</value></field>" - " </item>" - " </x>" - "</query>")); - SearchPayload::ref payload = parser.getPayload<SearchPayload>(); - CPPUNIT_ASSERT(payload); - - Form::ref dataForm = payload->getForm(); - CPPUNIT_ASSERT(dataForm); - - Form::FormItem reported = dataForm->getReportedFields(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), reported.size()); - - std::vector<Form::FormItem> items = dataForm->getItems(); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items.size()); - - Form::FormItem item = items[0]; - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); - - CPPUNIT_ASSERT_EQUAL(std::string("Benvolio"), item[0]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("benvolio@montague.net"), item[2]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); - - item = items[1]; - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); - - CPPUNIT_ASSERT_EQUAL(std::string("Romeo"), item[0]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("romeo@montague.net"), item[2]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); - } + CPPUNIT_TEST_SUITE(SearchPayloadParserTest); + CPPUNIT_TEST(testParse_FormRequestResponse); + CPPUNIT_TEST(testParse_Results); + CPPUNIT_TEST(testParse_FormRequestResponse_XDATA); + CPPUNIT_TEST(testParse_Results_XDATA); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse_FormRequestResponse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns=\"jabber:iq:search\">" + "<instructions>Foo</instructions>" + "<first/>" + "<last/>" + "</query>" + )); + + SearchPayload::ref payload = parser.getPayload<SearchPayload>(); + CPPUNIT_ASSERT_EQUAL(std::string("Foo"), *payload->getInstructions()); + CPPUNIT_ASSERT(payload->getFirst()); + CPPUNIT_ASSERT(payload->getLast()); + CPPUNIT_ASSERT(!payload->getNick()); + } + + void testParse_Results() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns=\"jabber:iq:search\">" + "<item jid=\"juliet@capulet.com\">" + "<first>Juliet</first>" + "<last>Capulet</last>" + "<nick>JuliC</nick>" + "<email>juliet@shakespeare.lit</email>" + "</item>" + "<item jid=\"tybalt@shakespeare.lit\">" + "<first>Tybalt</first>" + "<last>Capulet</last>" + "<nick>ty</nick>" + "<email>tybalt@shakespeare.lit</email>" + "</item>" + "</query>" + )); + + SearchPayload::ref payload = parser.getPayload<SearchPayload>(); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getItems().size())); + CPPUNIT_ASSERT_EQUAL(JID("juliet@capulet.com"), payload->getItems()[0].jid); + CPPUNIT_ASSERT_EQUAL(std::string("Juliet"), payload->getItems()[0].first); + CPPUNIT_ASSERT_EQUAL(std::string("Capulet"), payload->getItems()[0].last); + CPPUNIT_ASSERT_EQUAL(std::string("JuliC"), payload->getItems()[0].nick); + CPPUNIT_ASSERT_EQUAL(std::string("juliet@shakespeare.lit"), payload->getItems()[0].email); + CPPUNIT_ASSERT_EQUAL(JID("tybalt@shakespeare.lit"), payload->getItems()[1].jid); + } + + void testParse_FormRequestResponse_XDATA() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns='jabber:iq:search'>" + "<instructions>" + "Use the enclosed form to search. If your Jabber client does not" + " support Data Forms, visit http://shakespeare.lit/" + "</instructions>" + "<x xmlns='jabber:x:data' type='form'>" + "<title>User Directory Search</title>" + "<instructions>" + "Please provide the following information" + " to search for Shakespearean characters." + "</instructions>" + "<field type='hidden'" + " var='FORM_TYPE'>" + "<value>jabber:iq:search</value>" + "</field>" + "<field type='text-single'" + " label='Given Name'" + " var='first'/>" + "<field type='text-single'" + " label='Family Name'" + " var='last'/>" + "<field type='list-single'" + " label='Gender'" + " var='x-gender'>" + "<option label='Male'><value>male</value></option>" + "<option label='Female'><value>female</value></option>" + "</field>" + "</x>" + "</query>" + )); + + SearchPayload::ref payload = parser.getPayload<SearchPayload>(); + CPPUNIT_ASSERT_EQUAL(std::string("Use the enclosed form to search. If your Jabber client does not" + " support Data Forms, visit http://shakespeare.lit/"), *payload->getInstructions()); + CPPUNIT_ASSERT(payload->getForm()); + CPPUNIT_ASSERT_EQUAL(std::string("Please provide the following information" + " to search for Shakespearean characters."), payload->getForm()->getInstructions()); + } + + void testParse_Results_XDATA() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<query xmlns='jabber:iq:search'>" + " <x xmlns='jabber:x:data' type='result'>" + " <field type='hidden' var='FORM_TYPE'>" + " <value>jabber:iq:search</value>" + " </field>" + " <reported>" + " <field var='first' label='Given Name' type='text-single'/>" + " <field var='last' label='Family Name' type='text-single'/>" + " <field var='jid' label='Jabber ID' type='jid-single'/>" + " <field var='x-gender' label='Gender' type='list-single'/>" + " </reported>" + " <item>" + " <field var='first'><value>Benvolio</value></field>" + " <field var='last'><value>Montague</value></field>" + " <field var='jid'><value>benvolio@montague.net</value></field>" + " <field var='x-gender'><value>male</value></field>" + " </item>" + " <item>" + " <field var='first'><value>Romeo</value></field>" + " <field var='last'><value>Montague</value></field>" + " <field var='jid'><value>romeo@montague.net</value></field>" + " <field var='x-gender'><value>male</value></field>" + " </item>" + " </x>" + "</query>")); + SearchPayload::ref payload = parser.getPayload<SearchPayload>(); + CPPUNIT_ASSERT(payload); + + Form::ref dataForm = payload->getForm(); + CPPUNIT_ASSERT(dataForm); + + Form::FormItem reported = dataForm->getReportedFields(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), reported.size()); + + std::vector<Form::FormItem> items = dataForm->getItems(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), items.size()); + + Form::FormItem item = items[0]; + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); + + CPPUNIT_ASSERT_EQUAL(std::string("Benvolio"), item[0]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("benvolio@montague.net"), item[2]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); + + item = items[1]; + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); + + CPPUNIT_ASSERT_EQUAL(std::string("Romeo"), item[0]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("first"), item[0]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("romeo@montague.net"), item[2]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("jid"), item[2]->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(SearchPayloadParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp index 5083a07..c27b716 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,38 +14,38 @@ using namespace Swift; class SecurityLabelParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SecurityLabelParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST_SUITE_END(); - - public: - SecurityLabelParserTest() {} - - void testParse() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" - "<displaymarking fgcolor=\"black\" bgcolor=\"red\">SECRET</displaymarking>" - "<label>" - "<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>" - "</label>" - "<equivalentlabel>" - "<icismlabel xmlns=\"http://example.gov/IC-ISM/0\" classification=\"S\" ownerProducer=\"USA\" disseminationControls=\"FOUO\"/>" - "</equivalentlabel>" - "<equivalentlabel>" - "<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MRUCAgD9DA9BcXVhIChvYnNvbGV0ZSk=</esssecuritylabel>" - "</equivalentlabel>" - "</securitylabel>")); - - SecurityLabel* payload = dynamic_cast<SecurityLabel*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("SECRET"), payload->getDisplayMarking()); - CPPUNIT_ASSERT_EQUAL(std::string("black"), payload->getForegroundColor()); - CPPUNIT_ASSERT_EQUAL(std::string("red"), payload->getBackgroundColor()); - CPPUNIT_ASSERT_EQUAL(std::string("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"), payload->getLabel()); - CPPUNIT_ASSERT_EQUAL(std::string("<icismlabel classification=\"S\" disseminationControls=\"FOUO\" ownerProducer=\"USA\" xmlns=\"http://example.gov/IC-ISM/0\"/>"), payload->getEquivalentLabels()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MRUCAgD9DA9BcXVhIChvYnNvbGV0ZSk=</esssecuritylabel>"), payload->getEquivalentLabels()[1]); - } + CPPUNIT_TEST_SUITE(SecurityLabelParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + SecurityLabelParserTest() {} + + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" + "<displaymarking fgcolor=\"black\" bgcolor=\"red\">SECRET</displaymarking>" + "<label>" + "<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>" + "</label>" + "<equivalentlabel>" + "<icismlabel xmlns=\"http://example.gov/IC-ISM/0\" classification=\"S\" ownerProducer=\"USA\" disseminationControls=\"FOUO\"/>" + "</equivalentlabel>" + "<equivalentlabel>" + "<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MRUCAgD9DA9BcXVhIChvYnNvbGV0ZSk=</esssecuritylabel>" + "</equivalentlabel>" + "</securitylabel>")); + + SecurityLabel* payload = dynamic_cast<SecurityLabel*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("SECRET"), payload->getDisplayMarking()); + CPPUNIT_ASSERT_EQUAL(std::string("black"), payload->getForegroundColor()); + CPPUNIT_ASSERT_EQUAL(std::string("red"), payload->getBackgroundColor()); + CPPUNIT_ASSERT_EQUAL(std::string("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"), payload->getLabel()); + CPPUNIT_ASSERT_EQUAL(std::string("<icismlabel classification=\"S\" disseminationControls=\"FOUO\" ownerProducer=\"USA\" xmlns=\"http://example.gov/IC-ISM/0\"/>"), payload->getEquivalentLabels()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MRUCAgD9DA9BcXVhIChvYnNvbGV0ZSk=</esssecuritylabel>"), payload->getEquivalentLabels()[1]); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(SecurityLabelParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp index 395daf5..ee7668c 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,50 +14,107 @@ using namespace Swift; class SecurityLabelsCatalogParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SecurityLabelsCatalogParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST_SUITE_END(); - - public: - SecurityLabelsCatalogParserTest() {} - - void testParse() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<catalog desc=\"an example set of labels\" name=\"Default\" to=\"example.com\" xmlns=\"urn:xmpp:sec-label:catalog:2\">" - "<item selector='Classified|SECRET'>" - "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" - "<displaymarking bgcolor=\"red\" fgcolor=\"black\">SECRET</displaymarking>" - "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel></label>" - "</securitylabel>" - "</item>" - "<item selector='Classified|CONFIDENTIAL' default='true'>" - "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" - "<displaymarking bgcolor=\"navy\" fgcolor=\"black\">CONFIDENTIAL</displaymarking>" - "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel></label>" - "</securitylabel>" - "</item>" - "<item selector='Unclassified|UNCLASSIFIED'/>" - "</catalog>")); - - SecurityLabelsCatalog* payload = dynamic_cast<SecurityLabelsCatalog*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("Default"), payload->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("an example set of labels"), payload->getDescription()); - CPPUNIT_ASSERT_EQUAL(JID("example.com"), payload->getTo()); - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(payload->getItems().size())); - CPPUNIT_ASSERT_EQUAL(std::string("SECRET"), payload->getItems()[0].getLabel()->getDisplayMarking()); - CPPUNIT_ASSERT_EQUAL(std::string("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"), payload->getItems()[0].getLabel()->getLabel()); - CPPUNIT_ASSERT_EQUAL(false, payload->getItems()[0].getIsDefault()); - CPPUNIT_ASSERT_EQUAL(std::string("Classified|SECRET"), payload->getItems()[0].getSelector()); - CPPUNIT_ASSERT_EQUAL(std::string("CONFIDENTIAL"), payload->getItems()[1].getLabel()->getDisplayMarking()); - CPPUNIT_ASSERT_EQUAL(std::string("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel>"), payload->getItems()[1].getLabel()->getLabel()); - CPPUNIT_ASSERT_EQUAL(true, payload->getItems()[1].getIsDefault()); - CPPUNIT_ASSERT_EQUAL(std::string("Classified|CONFIDENTIAL"), payload->getItems()[1].getSelector()); - CPPUNIT_ASSERT_EQUAL(false, payload->getItems()[2].getIsDefault()); - CPPUNIT_ASSERT_EQUAL(std::string("Unclassified|UNCLASSIFIED"), payload->getItems()[2].getSelector()); - CPPUNIT_ASSERT(!payload->getItems()[2].getLabel()); - } + CPPUNIT_TEST_SUITE(SecurityLabelsCatalogParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParseInvalidInput); + CPPUNIT_TEST_SUITE_END(); + + public: + SecurityLabelsCatalogParserTest() {} + + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<catalog desc=\"an example set of labels\" name=\"Default\" to=\"example.com\" xmlns=\"urn:xmpp:sec-label:catalog:2\">" + "<item selector='Classified|SECRET'>" + "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" + "<displaymarking bgcolor=\"red\" fgcolor=\"black\">SECRET</displaymarking>" + "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel></label>" + "</securitylabel>" + "</item>" + "<item selector='Classified|CONFIDENTIAL' default='true'>" + "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" + "<displaymarking bgcolor=\"navy\" fgcolor=\"black\">CONFIDENTIAL</displaymarking>" + "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel></label>" + "</securitylabel>" + "</item>" + "<item selector='Unclassified|UNCLASSIFIED'/>" + "</catalog>")); + + SecurityLabelsCatalog* payload = dynamic_cast<SecurityLabelsCatalog*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Default"), payload->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("an example set of labels"), payload->getDescription()); + CPPUNIT_ASSERT_EQUAL(JID("example.com"), payload->getTo()); + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(payload->getItems().size())); + + CPPUNIT_ASSERT_EQUAL(std::string("SECRET"), payload->getItems()[0].getLabel()->getDisplayMarking()); + CPPUNIT_ASSERT_EQUAL(std::string("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"), payload->getItems()[0].getLabel()->getLabel()); + CPPUNIT_ASSERT_EQUAL(false, payload->getItems()[0].getIsDefault()); + CPPUNIT_ASSERT_EQUAL(std::string("Classified|SECRET"), payload->getItems()[0].getSelector()); + CPPUNIT_ASSERT_EQUAL(std::string("CONFIDENTIAL"), payload->getItems()[1].getLabel()->getDisplayMarking()); + CPPUNIT_ASSERT_EQUAL(std::string("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel>"), payload->getItems()[1].getLabel()->getLabel()); + CPPUNIT_ASSERT_EQUAL(true, payload->getItems()[1].getIsDefault()); + CPPUNIT_ASSERT_EQUAL(std::string("Classified|CONFIDENTIAL"), payload->getItems()[1].getSelector()); + CPPUNIT_ASSERT_EQUAL(false, payload->getItems()[2].getIsDefault()); + CPPUNIT_ASSERT_EQUAL(std::string("Unclassified|UNCLASSIFIED"), payload->getItems()[2].getSelector()); + CPPUNIT_ASSERT(!payload->getItems()[2].getLabel()); + } + + void testParseInvalidInput() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<catalog desc=\"an example set of labels\" name=\"Default\" to=\"example.com\" xmlns=\"urn:xmpp:sec-label:catalog:2\">" + "<item selector='Classified|INVALID-SECRET' xmlns=\"\">" + "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" + "<displaymarking bgcolor=\"red\" fgcolor=\"black\">INVALID-SECRET</displaymarking>" + "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel></label>" + "</securitylabel>" + "</item>" + "<item selector='Classified|INVALID-TOPSECRET' xmlns=\"urn:xmpp:sec-label:catalog:invalid:2\">" + "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" + "<displaymarking bgcolor=\"red\" fgcolor=\"black\">INVALID-TOPSECRET</displaymarking>" + "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel></label>" + "</securitylabel>" + "</item>" + "<item selector='Classified|CONFIDENTIAL' default='true' xmlns=\"urn:xmpp:sec-label:catalog:2\">" + "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" + "<displaymarking bgcolor=\"navy\" fgcolor=\"black\">CONFIDENTIAL</displaymarking>" + "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel></label>" + "</securitylabel>" + "</item>" + "<item selector='Classified|INVALID-LABEL'>" + "<securitylabel xmlns=\"\">" + "<displaymarking bgcolor=\"yellow\" fgcolor=\"black\">INVALID</displaymarking>" + "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel></label>" + "</securitylabel>" + "</item>" + "<item selector='Unclassified|UNCLASSIFIED'/>" + "</catalog>")); + + SecurityLabelsCatalog* payload = dynamic_cast<SecurityLabelsCatalog*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Default"), payload->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("an example set of labels"), payload->getDescription()); + CPPUNIT_ASSERT_EQUAL(JID("example.com"), payload->getTo()); + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(payload->getItems().size())); + + CPPUNIT_ASSERT(payload->getItems()[0].getLabel()); + if (payload->getItems()[0].getLabel()) { + CPPUNIT_ASSERT_EQUAL(std::string("CONFIDENTIAL"), payload->getItems()[0].getLabel()->getDisplayMarking()); + CPPUNIT_ASSERT_EQUAL(std::string("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel>"), payload->getItems()[0].getLabel()->getLabel()); + CPPUNIT_ASSERT_EQUAL(true, payload->getItems()[0].getIsDefault()); + CPPUNIT_ASSERT_EQUAL(std::string("Classified|CONFIDENTIAL"), payload->getItems()[0].getSelector()); + } + //The label is invalid, but the rest of the item entry should be there. + CPPUNIT_ASSERT(!payload->getItems()[1].getLabel()); + CPPUNIT_ASSERT_EQUAL(false, payload->getItems()[1].getIsDefault()); + CPPUNIT_ASSERT_EQUAL(std::string("Classified|INVALID-LABEL"), payload->getItems()[1].getSelector()); + CPPUNIT_ASSERT_EQUAL(false, payload->getItems()[2].getIsDefault()); + CPPUNIT_ASSERT_EQUAL(std::string("Unclassified|UNCLASSIFIED"), payload->getItems()[2].getSelector()); + CPPUNIT_ASSERT(!payload->getItems()[2].getLabel()); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(SecurityLabelsCatalogParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp index d22d207..7471856 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,28 +14,28 @@ using namespace Swift; class SoftwareVersionParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SoftwareVersionParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST_SUITE_END(); - - public: - SoftwareVersionParserTest() {} - - void testParse() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<query xmlns=\"jabber:iq:version\">" - "<name>myclient</name>" - "<version>1.0</version>" - "<os>Mac OS X</os>" - "</query>")); - - SoftwareVersion* payload = dynamic_cast<SoftwareVersion*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("myclient"), payload->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("1.0"), payload->getVersion()); - CPPUNIT_ASSERT_EQUAL(std::string("Mac OS X"), payload->getOS()); - } + CPPUNIT_TEST_SUITE(SoftwareVersionParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + SoftwareVersionParserTest() {} + + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<query xmlns=\"jabber:iq:version\">" + "<name>myclient</name>" + "<version>1.0</version>" + "<os>Mac OS X</os>" + "</query>")); + + SoftwareVersion* payload = dynamic_cast<SoftwareVersion*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("myclient"), payload->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("1.0"), payload->getVersion()); + CPPUNIT_ASSERT_EQUAL(std::string("Mac OS X"), payload->getOS()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(SoftwareVersionParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/StatusParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/StatusParserTest.cpp index 358ff88..6b93637 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/StatusParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/StatusParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,21 +14,21 @@ using namespace Swift; class StatusParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StatusParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(StatusParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); - public: - StatusParserTest() {} + public: + StatusParserTest() {} - void testParse() { - PayloadsParserTester parser; + void testParse() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse("<status>foo<baz>bar</baz>fum</status>")); + CPPUNIT_ASSERT(parser.parse("<status>foo<baz>bar</baz>fum</status>")); - Status* payload = dynamic_cast<Status*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("foobarfum"), payload->getText()); - } + Status* payload = dynamic_cast<Status*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("foobarfum"), payload->getText()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StatusParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp index 924a87f..94f14c6 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,61 +14,61 @@ using namespace Swift; class StatusShowParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StatusShowParserTest); - CPPUNIT_TEST(testParse_Invalid); - CPPUNIT_TEST(testParse_Away); - CPPUNIT_TEST(testParse_FFC); - CPPUNIT_TEST(testParse_XA); - CPPUNIT_TEST(testParse_DND); - CPPUNIT_TEST_SUITE_END(); - - public: - StatusShowParserTest() {} - - void testParse_Invalid() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<show>invalid</show>")); - - StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get()); - CPPUNIT_ASSERT(StatusShow::Online == payload->getType()); - } - - void testParse_Away() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<show>away</show>")); - - StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get()); - CPPUNIT_ASSERT(StatusShow::Away == payload->getType()); - } - - void testParse_FFC() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<show>chat</show>")); - - StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get()); - CPPUNIT_ASSERT(StatusShow::FFC == payload->getType()); - } - - void testParse_XA() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<show>xa</show>")); - - StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get()); - CPPUNIT_ASSERT(StatusShow::XA == payload->getType()); - } - - void testParse_DND() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse("<show>dnd</show>")); - - StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get()); - CPPUNIT_ASSERT(StatusShow::DND == payload->getType()); - } + CPPUNIT_TEST_SUITE(StatusShowParserTest); + CPPUNIT_TEST(testParse_Invalid); + CPPUNIT_TEST(testParse_Away); + CPPUNIT_TEST(testParse_FFC); + CPPUNIT_TEST(testParse_XA); + CPPUNIT_TEST(testParse_DND); + CPPUNIT_TEST_SUITE_END(); + + public: + StatusShowParserTest() {} + + void testParse_Invalid() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<show>invalid</show>")); + + StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get()); + CPPUNIT_ASSERT(StatusShow::Online == payload->getType()); + } + + void testParse_Away() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<show>away</show>")); + + StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get()); + CPPUNIT_ASSERT(StatusShow::Away == payload->getType()); + } + + void testParse_FFC() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<show>chat</show>")); + + StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get()); + CPPUNIT_ASSERT(StatusShow::FFC == payload->getType()); + } + + void testParse_XA() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<show>xa</show>")); + + StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get()); + CPPUNIT_ASSERT(StatusShow::XA == payload->getType()); + } + + void testParse_DND() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<show>dnd</show>")); + + StatusShow* payload = dynamic_cast<StatusShow*>(parser.getPayload().get()); + CPPUNIT_ASSERT(StatusShow::DND == payload->getType()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StatusShowParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp index 5ceec27..4430668 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,74 +13,74 @@ using namespace Swift; class StorageParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StorageParserTest); - CPPUNIT_TEST(testParse_Room); - CPPUNIT_TEST(testParse_MultipleRooms); - CPPUNIT_TEST(testParse_URL); - CPPUNIT_TEST_SUITE_END(); - - public: - StorageParserTest() {} - - void testParse_Room() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<storage xmlns='storage:bookmarks'>" - "<conference " - "name='Council of Oberon' " - "autojoin='true' jid='council@conference.underhill.org'>" - "<nick>Puck</nick>" - "<password>MyPass</password>" - "</conference>" - "</storage>")); - - Storage* payload = dynamic_cast<Storage*>(parser.getPayload().get()); - std::vector<Storage::Room> rooms = payload->getRooms(); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(rooms.size())); - CPPUNIT_ASSERT_EQUAL(std::string("Council of Oberon"), rooms[0].name); - CPPUNIT_ASSERT_EQUAL(JID("council@conference.underhill.org"), rooms[0].jid); - CPPUNIT_ASSERT(rooms[0].autoJoin); - CPPUNIT_ASSERT_EQUAL(std::string("Puck"), rooms[0].nick); - CPPUNIT_ASSERT_EQUAL(std::string("MyPass"), *rooms[0].password); - } - - void testParse_MultipleRooms() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<storage xmlns='storage:bookmarks'>" - "<conference " - "name='Council of Oberon' " - "jid='council@conference.underhill.org' />" - "<conference " - "name='Tea & jam party' " - "jid='teaparty@wonderland.lit' />" - "</storage>")); - - Storage* payload = dynamic_cast<Storage*>(parser.getPayload().get()); - std::vector<Storage::Room> rooms = payload->getRooms(); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(rooms.size())); - CPPUNIT_ASSERT_EQUAL(std::string("Council of Oberon"), rooms[0].name); - CPPUNIT_ASSERT_EQUAL(JID("council@conference.underhill.org"), rooms[0].jid); - CPPUNIT_ASSERT_EQUAL(std::string("Tea & jam party"), rooms[1].name); - CPPUNIT_ASSERT_EQUAL(JID("teaparty@wonderland.lit"), rooms[1].jid); - } - - void testParse_URL() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<storage xmlns='storage:bookmarks'>" - "<url name='Complete Works of Shakespeare' url='http://the-tech.mit.edu/Shakespeare/'/>" - "</storage>")); - - Storage* payload = dynamic_cast<Storage*>(parser.getPayload().get()); - std::vector<Storage::URL> urls = payload->getURLs(); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(urls.size())); - CPPUNIT_ASSERT_EQUAL(std::string("Complete Works of Shakespeare"), urls[0].name); - CPPUNIT_ASSERT_EQUAL(std::string("http://the-tech.mit.edu/Shakespeare/"), urls[0].url); - } + CPPUNIT_TEST_SUITE(StorageParserTest); + CPPUNIT_TEST(testParse_Room); + CPPUNIT_TEST(testParse_MultipleRooms); + CPPUNIT_TEST(testParse_URL); + CPPUNIT_TEST_SUITE_END(); + + public: + StorageParserTest() {} + + void testParse_Room() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<storage xmlns='storage:bookmarks'>" + "<conference " + "name='Council of Oberon' " + "autojoin='true' jid='council@conference.underhill.org'>" + "<nick>Puck</nick>" + "<password>MyPass</password>" + "</conference>" + "</storage>")); + + Storage* payload = dynamic_cast<Storage*>(parser.getPayload().get()); + std::vector<Storage::Room> rooms = payload->getRooms(); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(rooms.size())); + CPPUNIT_ASSERT_EQUAL(std::string("Council of Oberon"), rooms[0].name); + CPPUNIT_ASSERT_EQUAL(JID("council@conference.underhill.org"), rooms[0].jid); + CPPUNIT_ASSERT(rooms[0].autoJoin); + CPPUNIT_ASSERT_EQUAL(std::string("Puck"), rooms[0].nick); + CPPUNIT_ASSERT_EQUAL(std::string("MyPass"), *rooms[0].password); + } + + void testParse_MultipleRooms() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<storage xmlns='storage:bookmarks'>" + "<conference " + "name='Council of Oberon' " + "jid='council@conference.underhill.org' />" + "<conference " + "name='Tea & jam party' " + "jid='teaparty@wonderland.lit' />" + "</storage>")); + + Storage* payload = dynamic_cast<Storage*>(parser.getPayload().get()); + std::vector<Storage::Room> rooms = payload->getRooms(); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(rooms.size())); + CPPUNIT_ASSERT_EQUAL(std::string("Council of Oberon"), rooms[0].name); + CPPUNIT_ASSERT_EQUAL(JID("council@conference.underhill.org"), rooms[0].jid); + CPPUNIT_ASSERT_EQUAL(std::string("Tea & jam party"), rooms[1].name); + CPPUNIT_ASSERT_EQUAL(JID("teaparty@wonderland.lit"), rooms[1].jid); + } + + void testParse_URL() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<storage xmlns='storage:bookmarks'>" + "<url name='Complete Works of Shakespeare' url='http://the-tech.mit.edu/Shakespeare/'/>" + "</storage>")); + + Storage* payload = dynamic_cast<Storage*>(parser.getPayload().get()); + std::vector<Storage::URL> urls = payload->getURLs(); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(urls.size())); + CPPUNIT_ASSERT_EQUAL(std::string("Complete Works of Shakespeare"), urls[0].name); + CPPUNIT_ASSERT_EQUAL(std::string("http://the-tech.mit.edu/Shakespeare/"), urls[0].url); + } }; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/StreamInitiationParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/StreamInitiationParserTest.cpp index 63a6c9b..9b0679d 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/StreamInitiationParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/StreamInitiationParserTest.cpp @@ -1,75 +1,75 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> #include <Swiften/Elements/StreamInitiation.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> using namespace Swift; class StreamInitiationParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StreamInitiationParserTest); - CPPUNIT_TEST(testParse_Request); - CPPUNIT_TEST(testParse_Response); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(StreamInitiationParserTest); + CPPUNIT_TEST(testParse_Request); + CPPUNIT_TEST(testParse_Response); + CPPUNIT_TEST_SUITE_END(); - public: - void testParse_Request() { - PayloadsParserTester parser; + public: + void testParse_Request() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<si xmlns='http://jabber.org/protocol/si' id='a0' mime-type='text/plain' profile='http://jabber.org/protocol/si/profile/file-transfer'>" - "<file xmlns='http://jabber.org/protocol/si/profile/file-transfer' name='test.txt' size='1022'>" - "<desc>This is info about the file.</desc>" - "</file>" - "<feature xmlns='http://jabber.org/protocol/feature-neg'>" - "<x xmlns='jabber:x:data' type='form'>" - "<field var='stream-method' type='list-single'>" - "<option><value>http://jabber.org/protocol/bytestreams</value></option>" - "<option><value>jabber:iq:oob</value></option>" - "<option><value>http://jabber.org/protocol/ibb</value></option>" - "</field>" - "</x>" - "</feature>" - "</si>" - )); + CPPUNIT_ASSERT(parser.parse( + "<si xmlns='http://jabber.org/protocol/si' id='a0' mime-type='text/plain' profile='http://jabber.org/protocol/si/profile/file-transfer'>" + "<file xmlns='http://jabber.org/protocol/si/profile/file-transfer' name='test.txt' size='1022'>" + "<desc>This is info about the file.</desc>" + "</file>" + "<feature xmlns='http://jabber.org/protocol/feature-neg'>" + "<x xmlns='jabber:x:data' type='form'>" + "<field var='stream-method' type='list-single'>" + "<option><value>http://jabber.org/protocol/bytestreams</value></option>" + "<option><value>jabber:iq:oob</value></option>" + "<option><value>http://jabber.org/protocol/ibb</value></option>" + "</field>" + "</x>" + "</feature>" + "</si>" + )); - StreamInitiation::ref si = parser.getPayload<StreamInitiation>(); - CPPUNIT_ASSERT(si->getIsFileTransfer()); - CPPUNIT_ASSERT(si->getFileInfo()); - CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), si->getFileInfo()->getName()); - CPPUNIT_ASSERT(1022 == si->getFileInfo()->getSize()); - CPPUNIT_ASSERT_EQUAL(std::string("This is info about the file."), si->getFileInfo()->getDescription()); - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(si->getProvidedMethods().size())); - CPPUNIT_ASSERT_EQUAL(std::string("http://jabber.org/protocol/bytestreams"), si->getProvidedMethods()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:oob"), si->getProvidedMethods()[1]); - CPPUNIT_ASSERT_EQUAL(std::string("http://jabber.org/protocol/ibb"), si->getProvidedMethods()[2]); - } + StreamInitiation::ref si = parser.getPayload<StreamInitiation>(); + CPPUNIT_ASSERT(si->getIsFileTransfer()); + CPPUNIT_ASSERT(si->getFileInfo()); + CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), si->getFileInfo()->getName()); + CPPUNIT_ASSERT(1022 == si->getFileInfo()->getSize()); + CPPUNIT_ASSERT_EQUAL(std::string("This is info about the file."), si->getFileInfo()->getDescription()); + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(si->getProvidedMethods().size())); + CPPUNIT_ASSERT_EQUAL(std::string("http://jabber.org/protocol/bytestreams"), si->getProvidedMethods()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:oob"), si->getProvidedMethods()[1]); + CPPUNIT_ASSERT_EQUAL(std::string("http://jabber.org/protocol/ibb"), si->getProvidedMethods()[2]); + } - void testParse_Response() { - PayloadsParserTester parser; + void testParse_Response() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<si xmlns='http://jabber.org/protocol/si'>" - "<feature xmlns='http://jabber.org/protocol/feature-neg'>" - "<x xmlns='jabber:x:data' type='submit'>" - "<field var='stream-method'>" - "<value>http://jabber.org/protocol/bytestreams</value>" - "</field>" - "</x>" - "</feature>" - "</si>" - )); + CPPUNIT_ASSERT(parser.parse( + "<si xmlns='http://jabber.org/protocol/si'>" + "<feature xmlns='http://jabber.org/protocol/feature-neg'>" + "<x xmlns='jabber:x:data' type='submit'>" + "<field var='stream-method'>" + "<value>http://jabber.org/protocol/bytestreams</value>" + "</field>" + "</x>" + "</feature>" + "</si>" + )); - StreamInitiation::ref si = parser.getPayload<StreamInitiation>(); - CPPUNIT_ASSERT(si->getIsFileTransfer()); - CPPUNIT_ASSERT_EQUAL(std::string("http://jabber.org/protocol/bytestreams"), si->getRequestedMethod()); - } + StreamInitiation::ref si = parser.getPayload<StreamInitiation>(); + CPPUNIT_ASSERT(si->getIsFileTransfer()); + CPPUNIT_ASSERT_EQUAL(std::string("http://jabber.org/protocol/bytestreams"), si->getRequestedMethod()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StreamInitiationParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/UserLocationParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/UserLocationParserTest.cpp new file mode 100644 index 0000000..98a147f --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/UserLocationParserTest.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/UserLocation.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> +#include <Swiften/Parser/PayloadParsers/UserLocationParser.h> + +using namespace Swift; + +class UserLocationParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(UserLocationParserTest); + CPPUNIT_TEST(testParse_with_all_variables); + CPPUNIT_TEST(testParse_with_Some_variables); + CPPUNIT_TEST_SUITE_END(); + + public: + UserLocationParserTest() {} + + void testParse_with_all_variables() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<geoloc xmlns=\"http://jabber.org/protocol/geoloc\">" + "<area>Barbaric</area><alt>5.75</alt><locality>Near</locality>" + "<lat>1.67</lat><accuracy>0.95</accuracy><description>Nice</description>" + "<countrycode>+91</countrycode><timestamp>2015-06-11T20:55:50Z</timestamp><floor>3</floor>" + "<building>First</building><room>E315</room><country>USA</country>" + "<region>NewSode</region><uri>URIs</uri><lon>6.7578</lon><error>5.66</error>" + "<postalcode>67</postalcode><bearing>12.89</bearing><text>Hello</text>" + "<datum>Datee</datum><street>Highway</street><speed>56.77</speed></geoloc>")); + + UserLocation* payload = dynamic_cast<UserLocation*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string("Barbaric"), payload->getArea().get()); + CPPUNIT_ASSERT_EQUAL(5.75, payload->getAltitude().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Near"), payload->getLocality().get()); + CPPUNIT_ASSERT_EQUAL(1.670, payload->getLatitude().get()); + CPPUNIT_ASSERT_EQUAL(0.95, payload->getAccuracy().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Nice"), payload->getDescription().get()); + CPPUNIT_ASSERT_EQUAL(std::string("+91"), payload->getCountryCode().get()); + CPPUNIT_ASSERT_EQUAL(std::string("2015-06-11T20:55:50Z"), dateTimeToString(payload->getTimestamp().get())); + CPPUNIT_ASSERT_EQUAL(std::string("3"), payload->getFloor().get()); + CPPUNIT_ASSERT_EQUAL(std::string("First"), payload->getBuilding().get()); + CPPUNIT_ASSERT_EQUAL(std::string("E315"), payload->getRoom().get()); + CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getCountry().get()); + CPPUNIT_ASSERT_EQUAL(std::string("NewSode"), payload->getRegion().get()); + CPPUNIT_ASSERT_EQUAL(std::string("URIs"), payload->getURI().get()); + CPPUNIT_ASSERT_EQUAL(6.7578, payload->getLongitude().get()); + CPPUNIT_ASSERT_EQUAL(5.66, payload->getError().get()); + CPPUNIT_ASSERT_EQUAL(std::string("67"), payload->getPostalCode().get()); + CPPUNIT_ASSERT_EQUAL(12.89, payload->getBearing().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Hello"), payload->getText().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Datee"), payload->getDatum().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Highway"), payload->getStreet().get()); + CPPUNIT_ASSERT_EQUAL(56.77, payload->getSpeed().get()); + } + + void testParse_with_Some_variables() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<geoloc xmlns=\"http://jabber.org/protocol/geoloc\">" + "<area>Barbaric</area><alt>5.75</alt><locality>Near</locality>" + "<accuracy>0.95</accuracy><description>Nice</description>" + "<countrycode>+91</countrycode><timestamp>2015-06-11T20:55:50Z</timestamp><floor>3</floor>" + "<region>NewSode</region><uri>URIs</uri><lon>6.7578</lon><error>5.66</error>" + "<postalcode>67</postalcode><bearing>12.89</bearing><text>Hello</text></geoloc>")); + + UserLocation* payload = dynamic_cast<UserLocation*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string("Barbaric"), payload->getArea().get()); + CPPUNIT_ASSERT_EQUAL(5.75, payload->getAltitude().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Near"), payload->getLocality().get()); + CPPUNIT_ASSERT(!payload->getLatitude()); + CPPUNIT_ASSERT_EQUAL(0.95, payload->getAccuracy().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Nice"), payload->getDescription().get()); + CPPUNIT_ASSERT_EQUAL(std::string("+91"), payload->getCountryCode().get()); + CPPUNIT_ASSERT_EQUAL(std::string("2015-06-11T20:55:50Z"), dateTimeToString(payload->getTimestamp().get())); + CPPUNIT_ASSERT_EQUAL(std::string("3"), payload->getFloor().get()); + CPPUNIT_ASSERT(!payload->getBuilding()); + CPPUNIT_ASSERT(!payload->getRoom()); + CPPUNIT_ASSERT(!payload->getCountry()); + CPPUNIT_ASSERT_EQUAL(std::string("NewSode"), payload->getRegion().get()); + CPPUNIT_ASSERT_EQUAL(std::string("URIs"), payload->getURI().get()); + CPPUNIT_ASSERT_EQUAL(6.7578, payload->getLongitude().get()); + CPPUNIT_ASSERT_EQUAL(5.66, payload->getError().get()); + CPPUNIT_ASSERT_EQUAL(std::string("67"), payload->getPostalCode().get()); + CPPUNIT_ASSERT_EQUAL(12.89, payload->getBearing().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Hello"), payload->getText().get()); + CPPUNIT_ASSERT(!payload->getDatum()); + CPPUNIT_ASSERT(!payload->getStreet()); + CPPUNIT_ASSERT(!payload->getSpeed()); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(UserLocationParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/UserTuneParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/UserTuneParserTest.cpp new file mode 100644 index 0000000..3783231 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/UserTuneParserTest.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/UserTune.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> +#include <Swiften/Parser/PayloadParsers/UserTuneParser.h> + +using namespace Swift; + +class UserTuneParserTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(UserTuneParserTest); + CPPUNIT_TEST(testParse_with_all_variables); + CPPUNIT_TEST(testParse_with_Some_variables); + CPPUNIT_TEST_SUITE_END(); + + public: + UserTuneParserTest() {} + + void testParse_with_all_variables() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<tune xmlns=\"http://jabber.org/protocol/tune\">" + "<rating>5</rating><title>Minion</title><track>Yellow</track><artist>Ice</artist><URI>Fire</URI><source>Origin</source><length>226</length></tune>")); + + UserTune* payload = dynamic_cast<UserTune*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(5), payload->getRating().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Minion"), payload->getTitle().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Yellow"), payload->getTrack().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Ice"), payload->getArtist().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Fire"), payload->getURI().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Origin"), payload->getSource().get()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(226), payload->getLength().get()); + } + + void testParse_with_Some_variables() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<tune xmlns=\"http://jabber.org/protocol/tune\">" + "<title>Minion</title><track>Yellow</track><source>Origin</source><length>226</length></tune>")); + + UserTune* payload = dynamic_cast<UserTune*>(parser.getPayload().get()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT(!payload->getRating()); + CPPUNIT_ASSERT_EQUAL(std::string("Minion"), payload->getTitle().get()); + CPPUNIT_ASSERT_EQUAL(std::string("Yellow"), payload->getTrack().get()); + CPPUNIT_ASSERT(!payload->getArtist()); + CPPUNIT_ASSERT(!payload->getURI()); + CPPUNIT_ASSERT_EQUAL(std::string("Origin"), payload->getSource().get()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(226), payload->getLength().get()); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(UserTuneParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp index 6436e90..bc29921 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp @@ -1,207 +1,207 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> -#include <QA/Checker/IO.h> - #include <boost/date_time/posix_time/posix_time.hpp> +#include <QA/Checker/IO.h> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParsers/VCardParser.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> +#include <Swiften/Parser/PayloadParsers/VCardParser.h> using namespace Swift; class VCardParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(VCardParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_Photo); - CPPUNIT_TEST(testParse_NewlinedPhoto); - CPPUNIT_TEST(testParse_Nickname); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<vCard xmlns=\"vcard-temp\">" - "<VERSION>2.0</VERSION>" - "<FN>Alice In Wonderland</FN>" - "<N>" - "<FAMILY>Wonderland</FAMILY>" - "<GIVEN>Alice</GIVEN>" - "<MIDDLE>In</MIDDLE>" - "<PREFIX>Mrs</PREFIX>" - "<SUFFIX>PhD</SUFFIX>" - "</N>" - "<EMAIL>" - "<USERID>alice@wonderland.lit</USERID>" - "<HOME/>" - "<INTERNET/>" - "<PREF/>" - "</EMAIL>" - "<EMAIL>" - "<USERID>alice@teaparty.lit</USERID>" - "<WORK/>" - "<X400/>" - "</EMAIL>" - "<TEL>" - "<NUMBER>555-6273</NUMBER>" - "<HOME/>" - "<VOICE/>" - "</TEL>" - "<ADR>" - "<LOCALITY>Any Town</LOCALITY>" - "<STREET>Fake Street 123</STREET>" - "<PCODE>12345</PCODE>" - "<CTRY>USA</CTRY>" - "<HOME/>" - "</ADR>" - "<LABEL>" - "<LINE>Fake Street 123</LINE>" - "<LINE>12345 Any Town</LINE>" - "<LINE>USA</LINE>" - "<HOME/>" - "</LABEL>" - "<NICKNAME>DreamGirl</NICKNAME>" - "<BDAY>1865-05-04</BDAY>" - "<JID>alice@teaparty.lit</JID>" - "<JID>alice@wonderland.lit</JID>" - "<DESC>I once fell down a rabbit hole.</DESC>" - "<ORG>" - "<ORGNAME>Alice In Wonderland Inc.</ORGNAME>" - "</ORG>" - "<TITLE>Some Title</TITLE>" - "<ROLE>Main Character</ROLE>" - "<URL>http://wonderland.lit/~alice</URL>" - "<URL>http://teaparty.lit/~alice2</URL>" - "<MAILER>mutt</MAILER>" - "</vCard>")); - - boost::shared_ptr<VCard> payload = boost::dynamic_pointer_cast<VCard>(parser.getPayload()); - CPPUNIT_ASSERT_EQUAL(std::string("2.0"), payload->getVersion()); - CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland"), payload->getFullName()); - CPPUNIT_ASSERT_EQUAL(std::string("Alice"), payload->getGivenName()); - CPPUNIT_ASSERT_EQUAL(std::string("In"), payload->getMiddleName()); - CPPUNIT_ASSERT_EQUAL(std::string("Wonderland"), payload->getFamilyName()); - CPPUNIT_ASSERT_EQUAL(std::string("Mrs"), payload->getPrefix()); - CPPUNIT_ASSERT_EQUAL(std::string("PhD"), payload->getSuffix()); - CPPUNIT_ASSERT_EQUAL(std::string("DreamGirl"), payload->getNickname()); - CPPUNIT_ASSERT_EQUAL(boost::posix_time::ptime(boost::gregorian::date(1865, 5, 4)), payload->getBirthday()); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getEMailAddresses().size())); - CPPUNIT_ASSERT_EQUAL(std::string("alice@wonderland.lit"), payload->getEMailAddresses()[0].address); - CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isHome); - CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isInternet); - CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isPreferred); - CPPUNIT_ASSERT(!payload->getEMailAddresses()[0].isWork); - CPPUNIT_ASSERT(!payload->getEMailAddresses()[0].isX400); - CPPUNIT_ASSERT_EQUAL(std::string("alice@teaparty.lit"), payload->getEMailAddresses()[1].address); - CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isHome); - CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isInternet); - CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isPreferred); - CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isWork); - CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isX400); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getTelephones().size())); - CPPUNIT_ASSERT_EQUAL(std::string("555-6273"), payload->getTelephones()[0].number); - CPPUNIT_ASSERT(payload->getTelephones()[0].isHome); - CPPUNIT_ASSERT(payload->getTelephones()[0].isVoice); - CPPUNIT_ASSERT(!payload->getTelephones()[0].isPreferred); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getAddresses().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Any Town"), payload->getAddresses()[0].locality); - CPPUNIT_ASSERT_EQUAL(std::string("Fake Street 123"), payload->getAddresses()[0].street); - CPPUNIT_ASSERT_EQUAL(std::string("12345"), payload->getAddresses()[0].postalCode); - CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getAddresses()[0].country); - CPPUNIT_ASSERT(payload->getAddresses()[0].isHome); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getAddressLabels().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Fake Street 123"), payload->getAddressLabels()[0].lines[0]); - CPPUNIT_ASSERT_EQUAL(std::string("12345 Any Town"), payload->getAddressLabels()[0].lines[1]); - CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getAddressLabels()[0].lines[2]); - CPPUNIT_ASSERT(payload->getAddressLabels()[0].isHome); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getJIDs().size())); - CPPUNIT_ASSERT_EQUAL(JID("alice@teaparty.lit"), payload->getJIDs()[0]); - CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit"), payload->getJIDs()[1]); - - CPPUNIT_ASSERT_EQUAL(std::string("I once fell down a rabbit hole."), payload->getDescription()); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getOrganizations().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland Inc."), payload->getOrganizations()[0].name); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(payload->getOrganizations()[0].units.size())); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getTitles().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Some Title"), payload->getTitles()[0]); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getRoles().size())); - CPPUNIT_ASSERT_EQUAL(std::string("Main Character"), payload->getRoles()[0]); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getURLs().size())); - CPPUNIT_ASSERT_EQUAL(std::string("http://wonderland.lit/~alice"), payload->getURLs()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("http://teaparty.lit/~alice2"), payload->getURLs()[1]); - - CPPUNIT_ASSERT_EQUAL(std::string("<MAILER xmlns=\"vcard-temp\">mutt</MAILER>"), payload->getUnknownContent()); - } - - void testParse_Photo() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<vCard xmlns='vcard-temp'>" - "<PHOTO>" - "<TYPE>image/jpeg</TYPE>" - "<BINVAL>" - "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ej" - "EyMzQ1Njc4OTA=" - "</BINVAL>" - "</PHOTO>" - "</vCard>")); - - VCard* payload = dynamic_cast<VCard*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("image/jpeg"), payload->getPhotoType()); - CPPUNIT_ASSERT_EQUAL(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"), payload->getPhoto()); - } - - void testParse_NewlinedPhoto() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<vCard xmlns='vcard-temp'>" - "<PHOTO>" - "<TYPE>image/jpeg</TYPE>" - "<BINVAL>" - "dTsETKSAskgu2/BqVO+ogcu3DJy4QATGJqpsa6znWwNGiLnVElVVB6PtS+mTiHUXsrOlKvRjtvzV\n" - "VDknNaRF58Elmu5EC6VoCllBEEB/lFf0emYn2gkp0X1khNi75dl+rOj95Ar6XuwLh+ZoSStqwOWj\n" - "pIpxmZmVw7E69qr0FY0oI3zcaxXwzHw7Lx9Qf4sH7ufQvIN88ga+hwp8MiXevh3Ac8pN00kgINlq\n" - "9AY/bYJL418Y/6wWsJbgmrJ/N78wSMpC7VVszLBZVv8uFnupubyi8Ophd/1wIWWzPPwAbBhepWVb\n" - "1oPiFEBT5MNKCMTPEi0npXtedVz0HQbbPNIVwmo=" - "</BINVAL>" - "</PHOTO>" - "</vCard>")); - - VCard* payload = dynamic_cast<VCard*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("image/jpeg"), payload->getPhotoType()); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x75\x3B\x04\x4C\xA4\x80\xB2\x48\x2E\xDB\xF0\x6A\x54\xEF\xA8\x81\xCB\xB7\x0C\x9C\xB8\x40\x04\xC6\x26\xAA\x6C\x6B\xAC\xE7\x5B\x03\x46\x88\xB9\xD5\x12\x55\x55\x07\xA3\xED\x4B\xE9\x93\x88\x75\x17\xB2\xB3\xA5\x2A\xF4\x63\xB6\xFC\xD5\x54\x39\x27\x35\xA4\x45\xE7\xC1\x25\x9A\xEE\x44\x0B\xA5\x68\x0A\x59\x41\x10\x40\x7F\x94\x57\xF4\x7A\x66\x27\xDA\x09\x29\xD1\x7D\x64\x84\xD8\xBB\xE5\xD9\x7E\xAC\xE8\xFD\xE4\x0A\xFA\x5E\xEC\x0B\x87\xE6\x68\x49\x2B\x6A\xC0\xE5\xA3\xA4\x8A\x71\x99\x99\x95\xC3\xB1\x3A\xF6\xAA\xF4\x15\x8D\x28\x23\x7C\xDC\x6B\x15\xF0\xCC\x7C\x3B\x2F\x1F\x50\x7F\x8B\x07\xEE\xE7\xD0\xBC\x83\x7C\xF2\x06\xBE\x87\x0A\x7C\x32\x25\xDE\xBE\x1D\xC0\x73\xCA\x4D\xD3\x49\x20\x20\xD9\x6A\xF4\x06\x3F\x6D\x82\x4B\xE3\x5F\x18\xFF\xAC\x16\xB0\x96\xE0\x9A\xB2\x7F\x37\xBF\x30\x48\xCA\x42\xED\x55\x6C\xCC\xB0\x59\x56\xFF\x2E\x16\x7B\xA9\xB9\xBC\xA2\xF0\xEA\x61\x77\xFD\x70\x21\x65\xB3\x3C\xFC\x00\x6C\x18\x5E\xA5\x65\x5B\xD6\x83\xE2\x14\x40\x53\xE4\xC3\x4A\x08\xC4\xCF\x12\x2D\x27\xA5\x7B\x5E\x75\x5C\xF4\x1D\x06\xDB\x3C\xD2\x15\xC2\x6A", 257), payload->getPhoto()); - } - - - - void testParse_Nickname() { - PayloadsParserTester parser; - - CPPUNIT_ASSERT(parser.parse( - "<vCard xmlns='vcard-temp'>" - "<NICKNAME>mynick</NICKNAME>" - "</vCard>")); - - VCard* payload = dynamic_cast<VCard*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("mynick"), payload->getNickname()); - } + CPPUNIT_TEST_SUITE(VCardParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_Photo); + CPPUNIT_TEST(testParse_NewlinedPhoto); + CPPUNIT_TEST(testParse_Nickname); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<vCard xmlns=\"vcard-temp\">" + "<VERSION>2.0</VERSION>" + "<FN>Alice In Wonderland</FN>" + "<N>" + "<FAMILY>Wonderland</FAMILY>" + "<GIVEN>Alice</GIVEN>" + "<MIDDLE>In</MIDDLE>" + "<PREFIX>Mrs</PREFIX>" + "<SUFFIX>PhD</SUFFIX>" + "</N>" + "<EMAIL>" + "<USERID>alice@wonderland.lit</USERID>" + "<HOME/>" + "<INTERNET/>" + "<PREF/>" + "</EMAIL>" + "<EMAIL>" + "<USERID>alice@teaparty.lit</USERID>" + "<WORK/>" + "<X400/>" + "</EMAIL>" + "<TEL>" + "<NUMBER>555-6273</NUMBER>" + "<HOME/>" + "<VOICE/>" + "</TEL>" + "<ADR>" + "<LOCALITY>Any Town</LOCALITY>" + "<STREET>Fake Street 123</STREET>" + "<PCODE>12345</PCODE>" + "<CTRY>USA</CTRY>" + "<HOME/>" + "</ADR>" + "<LABEL>" + "<LINE>Fake Street 123</LINE>" + "<LINE>12345 Any Town</LINE>" + "<LINE>USA</LINE>" + "<HOME/>" + "</LABEL>" + "<NICKNAME>DreamGirl</NICKNAME>" + "<BDAY>1865-05-04</BDAY>" + "<JID>alice@teaparty.lit</JID>" + "<JID>alice@wonderland.lit</JID>" + "<DESC>I once fell down a rabbit hole.</DESC>" + "<ORG>" + "<ORGNAME>Alice In Wonderland Inc.</ORGNAME>" + "</ORG>" + "<TITLE>Some Title</TITLE>" + "<ROLE>Main Character</ROLE>" + "<URL>http://wonderland.lit/~alice</URL>" + "<URL>http://teaparty.lit/~alice2</URL>" + "<MAILER>mutt</MAILER>" + "</vCard>")); + + std::shared_ptr<VCard> payload = std::dynamic_pointer_cast<VCard>(parser.getPayload()); + CPPUNIT_ASSERT_EQUAL(std::string("2.0"), payload->getVersion()); + CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland"), payload->getFullName()); + CPPUNIT_ASSERT_EQUAL(std::string("Alice"), payload->getGivenName()); + CPPUNIT_ASSERT_EQUAL(std::string("In"), payload->getMiddleName()); + CPPUNIT_ASSERT_EQUAL(std::string("Wonderland"), payload->getFamilyName()); + CPPUNIT_ASSERT_EQUAL(std::string("Mrs"), payload->getPrefix()); + CPPUNIT_ASSERT_EQUAL(std::string("PhD"), payload->getSuffix()); + CPPUNIT_ASSERT_EQUAL(std::string("DreamGirl"), payload->getNickname()); + CPPUNIT_ASSERT_EQUAL(boost::posix_time::ptime(boost::gregorian::date(1865, 5, 4)), payload->getBirthday()); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getEMailAddresses().size())); + CPPUNIT_ASSERT_EQUAL(std::string("alice@wonderland.lit"), payload->getEMailAddresses()[0].address); + CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isHome); + CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isInternet); + CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isPreferred); + CPPUNIT_ASSERT(!payload->getEMailAddresses()[0].isWork); + CPPUNIT_ASSERT(!payload->getEMailAddresses()[0].isX400); + CPPUNIT_ASSERT_EQUAL(std::string("alice@teaparty.lit"), payload->getEMailAddresses()[1].address); + CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isHome); + CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isInternet); + CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isPreferred); + CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isWork); + CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isX400); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getTelephones().size())); + CPPUNIT_ASSERT_EQUAL(std::string("555-6273"), payload->getTelephones()[0].number); + CPPUNIT_ASSERT(payload->getTelephones()[0].isHome); + CPPUNIT_ASSERT(payload->getTelephones()[0].isVoice); + CPPUNIT_ASSERT(!payload->getTelephones()[0].isPreferred); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getAddresses().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Any Town"), payload->getAddresses()[0].locality); + CPPUNIT_ASSERT_EQUAL(std::string("Fake Street 123"), payload->getAddresses()[0].street); + CPPUNIT_ASSERT_EQUAL(std::string("12345"), payload->getAddresses()[0].postalCode); + CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getAddresses()[0].country); + CPPUNIT_ASSERT(payload->getAddresses()[0].isHome); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getAddressLabels().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Fake Street 123"), payload->getAddressLabels()[0].lines[0]); + CPPUNIT_ASSERT_EQUAL(std::string("12345 Any Town"), payload->getAddressLabels()[0].lines[1]); + CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getAddressLabels()[0].lines[2]); + CPPUNIT_ASSERT(payload->getAddressLabels()[0].isHome); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getJIDs().size())); + CPPUNIT_ASSERT_EQUAL(JID("alice@teaparty.lit"), payload->getJIDs()[0]); + CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit"), payload->getJIDs()[1]); + + CPPUNIT_ASSERT_EQUAL(std::string("I once fell down a rabbit hole."), payload->getDescription()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getOrganizations().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland Inc."), payload->getOrganizations()[0].name); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(payload->getOrganizations()[0].units.size())); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getTitles().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Some Title"), payload->getTitles()[0]); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getRoles().size())); + CPPUNIT_ASSERT_EQUAL(std::string("Main Character"), payload->getRoles()[0]); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getURLs().size())); + CPPUNIT_ASSERT_EQUAL(std::string("http://wonderland.lit/~alice"), payload->getURLs()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("http://teaparty.lit/~alice2"), payload->getURLs()[1]); + + CPPUNIT_ASSERT_EQUAL(std::string("<MAILER xmlns=\"vcard-temp\">mutt</MAILER>"), payload->getUnknownContent()); + } + + void testParse_Photo() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<vCard xmlns='vcard-temp'>" + "<PHOTO>" + "<TYPE>image/jpeg</TYPE>" + "<BINVAL>" + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ej" + "EyMzQ1Njc4OTA=" + "</BINVAL>" + "</PHOTO>" + "</vCard>")); + + VCard* payload = dynamic_cast<VCard*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("image/jpeg"), payload->getPhotoType()); + CPPUNIT_ASSERT_EQUAL(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"), payload->getPhoto()); + } + + void testParse_NewlinedPhoto() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<vCard xmlns='vcard-temp'>" + "<PHOTO>" + "<TYPE>image/jpeg</TYPE>" + "<BINVAL>" + "dTsETKSAskgu2/BqVO+ogcu3DJy4QATGJqpsa6znWwNGiLnVElVVB6PtS+mTiHUXsrOlKvRjtvzV\n" + "VDknNaRF58Elmu5EC6VoCllBEEB/lFf0emYn2gkp0X1khNi75dl+rOj95Ar6XuwLh+ZoSStqwOWj\n" + "pIpxmZmVw7E69qr0FY0oI3zcaxXwzHw7Lx9Qf4sH7ufQvIN88ga+hwp8MiXevh3Ac8pN00kgINlq\n" + "9AY/bYJL418Y/6wWsJbgmrJ/N78wSMpC7VVszLBZVv8uFnupubyi8Ophd/1wIWWzPPwAbBhepWVb\n" + "1oPiFEBT5MNKCMTPEi0npXtedVz0HQbbPNIVwmo=" + "</BINVAL>" + "</PHOTO>" + "</vCard>")); + + VCard* payload = dynamic_cast<VCard*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("image/jpeg"), payload->getPhotoType()); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x75\x3B\x04\x4C\xA4\x80\xB2\x48\x2E\xDB\xF0\x6A\x54\xEF\xA8\x81\xCB\xB7\x0C\x9C\xB8\x40\x04\xC6\x26\xAA\x6C\x6B\xAC\xE7\x5B\x03\x46\x88\xB9\xD5\x12\x55\x55\x07\xA3\xED\x4B\xE9\x93\x88\x75\x17\xB2\xB3\xA5\x2A\xF4\x63\xB6\xFC\xD5\x54\x39\x27\x35\xA4\x45\xE7\xC1\x25\x9A\xEE\x44\x0B\xA5\x68\x0A\x59\x41\x10\x40\x7F\x94\x57\xF4\x7A\x66\x27\xDA\x09\x29\xD1\x7D\x64\x84\xD8\xBB\xE5\xD9\x7E\xAC\xE8\xFD\xE4\x0A\xFA\x5E\xEC\x0B\x87\xE6\x68\x49\x2B\x6A\xC0\xE5\xA3\xA4\x8A\x71\x99\x99\x95\xC3\xB1\x3A\xF6\xAA\xF4\x15\x8D\x28\x23\x7C\xDC\x6B\x15\xF0\xCC\x7C\x3B\x2F\x1F\x50\x7F\x8B\x07\xEE\xE7\xD0\xBC\x83\x7C\xF2\x06\xBE\x87\x0A\x7C\x32\x25\xDE\xBE\x1D\xC0\x73\xCA\x4D\xD3\x49\x20\x20\xD9\x6A\xF4\x06\x3F\x6D\x82\x4B\xE3\x5F\x18\xFF\xAC\x16\xB0\x96\xE0\x9A\xB2\x7F\x37\xBF\x30\x48\xCA\x42\xED\x55\x6C\xCC\xB0\x59\x56\xFF\x2E\x16\x7B\xA9\xB9\xBC\xA2\xF0\xEA\x61\x77\xFD\x70\x21\x65\xB3\x3C\xFC\x00\x6C\x18\x5E\xA5\x65\x5B\xD6\x83\xE2\x14\x40\x53\xE4\xC3\x4A\x08\xC4\xCF\x12\x2D\x27\xA5\x7B\x5E\x75\x5C\xF4\x1D\x06\xDB\x3C\xD2\x15\xC2\x6A", 257), payload->getPhoto()); + } + + + + void testParse_Nickname() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse( + "<vCard xmlns='vcard-temp'>" + "<NICKNAME>mynick</NICKNAME>" + "</vCard>")); + + VCard* payload = dynamic_cast<VCard*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("mynick"), payload->getNickname()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp index fe69242..11e8ded 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp @@ -1,37 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParsers/VCardUpdateParser.h> #include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> +#include <Swiften/Parser/PayloadParsers/VCardUpdateParser.h> using namespace Swift; class VCardUpdateParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(VCardUpdateParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(VCardUpdateParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); - public: - VCardUpdateParserTest() {} + public: + VCardUpdateParserTest() {} - void testParse() { - PayloadsParserTester parser; + void testParse() { + PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "<x xmlns='vcard-temp:x:update'>" - "<photo>sha1-hash-of-image</photo>" - "</x>")); + CPPUNIT_ASSERT(parser.parse( + "<x xmlns='vcard-temp:x:update'>" + "<photo>sha1-hash-of-image</photo>" + "</x>")); - VCardUpdate* payload = dynamic_cast<VCardUpdate*>(parser.getPayload().get()); - CPPUNIT_ASSERT_EQUAL(std::string("sha1-hash-of-image"), payload->getPhotoHash()); - } + VCardUpdate* payload = dynamic_cast<VCardUpdate*>(parser.getPayload().get()); + CPPUNIT_ASSERT_EQUAL(std::string("sha1-hash-of-image"), payload->getPhotoHash()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardUpdateParserTest); diff --git a/Swiften/Parser/PayloadParsers/UserLocationParser.cpp b/Swiften/Parser/PayloadParsers/UserLocationParser.cpp index d3aac69..09d0e9a 100644 --- a/Swiften/Parser/PayloadParsers/UserLocationParser.cpp +++ b/Swiften/Parser/PayloadParsers/UserLocationParser.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -19,88 +19,88 @@ UserLocationParser::~UserLocationParser() { } void UserLocationParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - if (level == 1) { - currentText = ""; - } - ++level; + if (level == 1) { + currentText = ""; + } + ++level; } void UserLocationParser::handleEndElement(const std::string& element, const std::string&) { - --level; - if (level == 1) { - try { - if (element == "accuracy") { - getPayloadInternal()->setAccuracy(boost::lexical_cast<float>(currentText)); - } - else if (element == "alt") { - getPayloadInternal()->setAltitude(boost::lexical_cast<float>(currentText)); - } - else if (element == "area") { - getPayloadInternal()->setArea(currentText); - } - else if (element == "bearing") { - getPayloadInternal()->setBearing(boost::lexical_cast<float>(currentText)); - } - else if (element == "building") { - getPayloadInternal()->setBuilding(currentText); - } - else if (element == "country") { - getPayloadInternal()->setCountry(currentText); - } - else if (element == "countrycode") { - getPayloadInternal()->setCountryCode(currentText); - } - else if (element == "datum") { - getPayloadInternal()->setDatum(currentText); - } - else if (element == "description") { - getPayloadInternal()->setDescription(currentText); - } - else if (element == "error") { - getPayloadInternal()->setError(boost::lexical_cast<float>(currentText)); - } - else if (element == "floor") { - getPayloadInternal()->setFloor(currentText); - } - else if (element == "lat") { - getPayloadInternal()->setLatitude(boost::lexical_cast<float>(currentText)); - } - else if (element == "locality") { - getPayloadInternal()->setLocality(currentText); - } - else if (element == "lon") { - getPayloadInternal()->setLongitude(boost::lexical_cast<float>(currentText)); - } - else if (element == "postalcode") { - getPayloadInternal()->setPostalCode(currentText); - } - else if (element == "region") { - getPayloadInternal()->setRegion(currentText); - } - else if (element == "room") { - getPayloadInternal()->setRoom(currentText); - } - else if (element == "speed") { - getPayloadInternal()->setSpeed(boost::lexical_cast<float>(currentText)); - } - else if (element == "street") { - getPayloadInternal()->setStreet(currentText); - } - else if (element == "text") { - getPayloadInternal()->setText(currentText); - } - else if (element == "timestamp") { - getPayloadInternal()->setTimestamp(stringToDateTime(currentText)); - } - else if (element == "uri") { - getPayloadInternal()->setURI(currentText); - } - } - catch (const boost::bad_lexical_cast&) { - } - } + --level; + if (level == 1) { + try { + if (element == "accuracy") { + getPayloadInternal()->setAccuracy(boost::lexical_cast<double>(currentText)); + } + else if (element == "alt") { + getPayloadInternal()->setAltitude(boost::lexical_cast<double>(currentText)); + } + else if (element == "area") { + getPayloadInternal()->setArea(currentText); + } + else if (element == "bearing") { + getPayloadInternal()->setBearing(boost::lexical_cast<double>(currentText)); + } + else if (element == "building") { + getPayloadInternal()->setBuilding(currentText); + } + else if (element == "country") { + getPayloadInternal()->setCountry(currentText); + } + else if (element == "countrycode") { + getPayloadInternal()->setCountryCode(currentText); + } + else if (element == "datum") { + getPayloadInternal()->setDatum(currentText); + } + else if (element == "description") { + getPayloadInternal()->setDescription(currentText); + } + else if (element == "error") { + getPayloadInternal()->setError(boost::lexical_cast<double>(currentText)); + } + else if (element == "floor") { + getPayloadInternal()->setFloor(currentText); + } + else if (element == "lat") { + getPayloadInternal()->setLatitude(boost::lexical_cast<double>(currentText)); + } + else if (element == "locality") { + getPayloadInternal()->setLocality(currentText); + } + else if (element == "lon") { + getPayloadInternal()->setLongitude(boost::lexical_cast<double>(currentText)); + } + else if (element == "postalcode") { + getPayloadInternal()->setPostalCode(currentText); + } + else if (element == "region") { + getPayloadInternal()->setRegion(currentText); + } + else if (element == "room") { + getPayloadInternal()->setRoom(currentText); + } + else if (element == "speed") { + getPayloadInternal()->setSpeed(boost::lexical_cast<double>(currentText)); + } + else if (element == "street") { + getPayloadInternal()->setStreet(currentText); + } + else if (element == "text") { + getPayloadInternal()->setText(currentText); + } + else if (element == "timestamp") { + getPayloadInternal()->setTimestamp(stringToDateTime(currentText)); + } + else if (element == "uri") { + getPayloadInternal()->setURI(currentText); + } + } + catch (const boost::bad_lexical_cast&) { + } + } } void UserLocationParser::handleCharacterData(const std::string& data) { - currentText += data; + currentText += data; } diff --git a/Swiften/Parser/PayloadParsers/UserLocationParser.h b/Swiften/Parser/PayloadParsers/UserLocationParser.h index eb6e668..39df9de 100644 --- a/Swiften/Parser/PayloadParsers/UserLocationParser.h +++ b/Swiften/Parser/PayloadParsers/UserLocationParser.h @@ -1,31 +1,30 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> -#include <Swiften/Parser/GenericPayloadParser.h> #include <Swiften/Elements/UserLocation.h> +#include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class SWIFTEN_API UserLocationParser : public GenericPayloadParser<UserLocation> { - public: - UserLocationParser(); - virtual ~UserLocationParser(); + class SWIFTEN_API UserLocationParser : public GenericPayloadParser<UserLocation> { + public: + UserLocationParser(); + virtual ~UserLocationParser() override; - 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; + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; - private: - int level; - std::string currentText; - }; + private: + int level; + std::string currentText; + }; } diff --git a/Swiften/Parser/PayloadParsers/UserTuneParser.cpp b/Swiften/Parser/PayloadParsers/UserTuneParser.cpp new file mode 100644 index 0000000..f030f8f --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UserTuneParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/UserTuneParser.h> + +#include <boost/lexical_cast.hpp> + +using namespace Swift; + +UserTuneParser::UserTuneParser() : level(0) { +} + +UserTuneParser::~UserTuneParser() { +} + +void UserTuneParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { + if (level == 1) { + currentText = ""; + } + ++level; +} + +void UserTuneParser::handleEndElement(const std::string& element, const std::string&) { + --level; + if (level == 1) { + try { + if (element == "artist") { + getPayloadInternal()->setArtist(currentText); + } + else if (element == "length") { + getPayloadInternal()->setLength(boost::lexical_cast<unsigned int>(currentText)); + } + else if (element == "rating") { + getPayloadInternal()->setRating(boost::lexical_cast<unsigned int>(currentText)); + } + else if (element == "source") { + getPayloadInternal()->setSource(currentText); + } + else if (element == "title") { + getPayloadInternal()->setTitle(currentText); + } + else if (element == "track") { + getPayloadInternal()->setTrack(currentText); + } + else if (element == "URI") { + getPayloadInternal()->setURI(currentText); + } + } + catch (const boost::bad_lexical_cast&) { + } + } +} + +void UserTuneParser::handleCharacterData(const std::string& data) { + currentText += data; +} diff --git a/Swiften/Parser/PayloadParsers/UserTuneParser.h b/Swiften/Parser/PayloadParsers/UserTuneParser.h new file mode 100644 index 0000000..8c7e8c5 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UserTuneParser.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/UserTune.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class SWIFTEN_API UserTuneParser : public GenericPayloadParser<UserTune> { + public: + UserTuneParser(); + virtual ~UserTuneParser() override; + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) override; + virtual void handleEndElement(const std::string& element, const std::string&) override; + virtual void handleCharacterData(const std::string& data) override; + + private: + int level; + std::string currentText; + }; +} diff --git a/Swiften/Parser/PayloadParsers/VCardParser.cpp b/Swiften/Parser/PayloadParsers/VCardParser.cpp index 0028411..f8779d1 100644 --- a/Swiften/Parser/PayloadParsers/VCardParser.cpp +++ b/Swiften/Parser/PayloadParsers/VCardParser.cpp @@ -1,288 +1,290 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/VCardParser.h> -#include <Swiften/Base/foreach.h> + +#include <cassert> + #include <Swiften/Base/DateTime.h> -#include <Swiften/StringCodecs/Base64.h> #include <Swiften/Parser/SerializingParser.h> +#include <Swiften/StringCodecs/Base64.h> namespace Swift { -VCardParser::VCardParser() : unknownContentParser_(NULL) { +VCardParser::VCardParser() : unknownContentParser_(nullptr) { } void VCardParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - elementStack_.push_back(element); - std::string elementHierarchy = getElementHierarchy(); - if (elementHierarchy == "/vCard/EMAIL") { - currentEMailAddress_ = VCard::EMailAddress(); - } - if (elementHierarchy == "/vCard/TEL") { - currentTelephone_ = VCard::Telephone(); - } - if (elementHierarchy == "/vCard/ADR") { - currentAddress_ = VCard::Address(); - } - if (elementHierarchy == "/vCard/LABEL") { - currentAddressLabel_ = VCard::AddressLabel(); - } - if (elementHierarchy == "/vCard/ORG") { - currentOrganization_ = VCard::Organization(); - } - if (elementStack_.size() == 2) { - assert(!unknownContentParser_); - unknownContentParser_ = new SerializingParser(); - unknownContentParser_->handleStartElement(element, ns, attributes); - } - else if (unknownContentParser_) { - unknownContentParser_->handleStartElement(element, ns, attributes); - } + elementStack_.push_back(element); + std::string elementHierarchy = getElementHierarchy(); + if (elementHierarchy == "/vCard/EMAIL") { + currentEMailAddress_ = VCard::EMailAddress(); + } + if (elementHierarchy == "/vCard/TEL") { + currentTelephone_ = VCard::Telephone(); + } + if (elementHierarchy == "/vCard/ADR") { + currentAddress_ = VCard::Address(); + } + if (elementHierarchy == "/vCard/LABEL") { + currentAddressLabel_ = VCard::AddressLabel(); + } + if (elementHierarchy == "/vCard/ORG") { + currentOrganization_ = VCard::Organization(); + } + if (elementStack_.size() == 2) { + assert(!unknownContentParser_); + unknownContentParser_ = new SerializingParser(); + unknownContentParser_->handleStartElement(element, ns, attributes); + } + else if (unknownContentParser_) { + unknownContentParser_->handleStartElement(element, ns, attributes); + } - currentText_ = ""; + currentText_ = ""; } void VCardParser::handleEndElement(const std::string& element, const std::string& ns) { - if (unknownContentParser_) { - unknownContentParser_->handleEndElement(element, ns); - } + if (unknownContentParser_) { + unknownContentParser_->handleEndElement(element, ns); + } - std::string elementHierarchy = getElementHierarchy(); - if (elementHierarchy == "/vCard/VERSION") { - getPayloadInternal()->setVersion(currentText_); - } - else if (elementHierarchy == "/vCard/FN") { - getPayloadInternal()->setFullName(currentText_); - } - else if (elementHierarchy == "/vCard/N/FAMILY") { - getPayloadInternal()->setFamilyName(currentText_); - } - else if (elementHierarchy == "/vCard/N/GIVEN") { - getPayloadInternal()->setGivenName(currentText_); - } - else if (elementHierarchy == "/vCard/N/MIDDLE") { - getPayloadInternal()->setMiddleName(currentText_); - } - else if (elementHierarchy == "/vCard/N/PREFIX") { - getPayloadInternal()->setPrefix(currentText_); - } - else if (elementHierarchy == "/vCard/N/SUFFIX") { - getPayloadInternal()->setSuffix(currentText_); - } - else if (elementHierarchy == "/vCard/N") { - } - else if (elementHierarchy == "/vCard/NICKNAME") { - getPayloadInternal()->setNickname(currentText_); - } - else if (elementHierarchy == "/vCard/PHOTO/TYPE") { - getPayloadInternal()->setPhotoType(currentText_); - } - else if (elementHierarchy == "/vCard/PHOTO/BINVAL") { - currentText_.erase(std::remove(currentText_.begin(), currentText_.end(), '\n'), currentText_.end()); - currentText_.erase(std::remove(currentText_.begin(), currentText_.end(), '\r'), currentText_.end()); - getPayloadInternal()->setPhoto(Base64::decode(currentText_)); - } - else if (elementHierarchy == "/vCard/PHOTO") { - } - else if (elementHierarchy == "/vCard/EMAIL/USERID") { - currentEMailAddress_.address = currentText_; - } - else if (elementHierarchy == "/vCard/EMAIL/HOME") { - currentEMailAddress_.isHome = true; - } - else if (elementHierarchy == "/vCard/EMAIL/WORK") { - currentEMailAddress_.isWork = true; - } - else if (elementHierarchy == "/vCard/EMAIL/INTERNET") { - currentEMailAddress_.isInternet = true; - } - else if (elementHierarchy == "/vCard/EMAIL/X400") { - currentEMailAddress_.isX400 = true; - } - else if (elementHierarchy == "/vCard/EMAIL/PREF") { - currentEMailAddress_.isPreferred = true; - } - else if (elementHierarchy == "/vCard/EMAIL" && !currentEMailAddress_.address.empty()) { - getPayloadInternal()->addEMailAddress(currentEMailAddress_); - } - else if (elementHierarchy == "/vCard/BDAY" && !currentText_.empty()) { - getPayloadInternal()->setBirthday(stringToDateTime(currentText_)); - } - else if (elementHierarchy == "/vCard/TEL/NUMBER") { - currentTelephone_.number = currentText_; - } - else if (elementHierarchy == "/vCard/TEL/HOME") { - currentTelephone_.isHome = true; - } - else if (elementHierarchy == "/vCard/TEL/WORK") { - currentTelephone_.isWork = true; - } - else if (elementHierarchy == "/vCard/TEL/VOICE") { - currentTelephone_.isVoice = true; - } - else if (elementHierarchy == "/vCard/TEL/FAX") { - currentTelephone_.isFax = true; - } - else if (elementHierarchy == "/vCard/TEL/PAGER") { - currentTelephone_.isPager = true; - } - else if (elementHierarchy == "/vCard/TEL/MSG") { - currentTelephone_.isMSG = true; - } - else if (elementHierarchy == "/vCard/TEL/CELL") { - currentTelephone_.isCell = true; - } - else if (elementHierarchy == "/vCard/TEL/VIDEO") { - currentTelephone_.isVideo = true; - } - else if (elementHierarchy == "/vCard/TEL/BBS") { - currentTelephone_.isBBS = true; - } - else if (elementHierarchy == "/vCard/TEL/MODEM") { - currentTelephone_.isModem = true; - } - else if (elementHierarchy == "/vCard/TEL/ISDN") { - currentTelephone_.isISDN = true; - } - else if (elementHierarchy == "/vCard/TEL/PCS") { - currentTelephone_.isPCS = true; - } - else if (elementHierarchy == "/vCard/TEL/PREF") { - currentTelephone_.isPreferred = true; - } - else if (elementHierarchy == "/vCard/TEL" && !currentTelephone_.number.empty()) { - getPayloadInternal()->addTelephone(currentTelephone_); - } - else if (elementHierarchy == "/vCard/ADR/HOME") { - currentAddress_.isHome = true; - } - else if (elementHierarchy == "/vCard/ADR/WORK") { - currentAddress_.isWork = true; - } - else if (elementHierarchy == "/vCard/ADR/POSTAL") { - currentAddress_.isPostal = true; - } - else if (elementHierarchy == "/vCard/ADR/PARCEL") { - currentAddress_.isParcel = true; - } - else if (elementHierarchy == "/vCard/ADR/DOM") { - currentAddress_.deliveryType = VCard::DomesticDelivery; - } - else if (elementHierarchy == "/vCard/ADR/INTL") { - currentAddress_.deliveryType = VCard::InternationalDelivery; - } - else if (elementHierarchy == "/vCard/ADR/PREF") { - currentAddress_.isPreferred = true; - } - else if (elementHierarchy == "/vCard/ADR/POBOX") { - currentAddress_.poBox = currentText_; - } - else if (elementHierarchy == "/vCard/ADR/EXTADD") { - currentAddress_.addressExtension = currentText_; - } - else if (elementHierarchy == "/vCard/ADR/STREET") { - currentAddress_.street = currentText_; - } - else if (elementHierarchy == "/vCard/ADR/LOCALITY") { - currentAddress_.locality = currentText_; - } - else if (elementHierarchy == "/vCard/ADR/REGION") { - currentAddress_.region = currentText_; - } - else if (elementHierarchy == "/vCard/ADR/PCODE") { - currentAddress_.postalCode = currentText_; - } - else if (elementHierarchy == "/vCard/ADR/CTRY") { - currentAddress_.country = currentText_; - } - else if (elementHierarchy == "/vCard/ADR") { - if (!currentAddress_.poBox.empty() || !currentAddress_.addressExtension.empty() || - !currentAddress_.street.empty() || !currentAddress_.locality.empty() || - !currentAddress_.region.empty() || !currentAddress_.region.empty() || - !currentAddress_.postalCode.empty() || !currentAddress_.country.empty()) { - getPayloadInternal()->addAddress(currentAddress_); - } - } - else if (elementHierarchy == "/vCard/LABEL/HOME") { - currentAddressLabel_.isHome = true; - } - else if (elementHierarchy == "/vCard/LABEL/WORK") { - currentAddressLabel_.isWork = true; - } - else if (elementHierarchy == "/vCard/LABEL/POSTAL") { - currentAddressLabel_.isPostal = true; - } - else if (elementHierarchy == "/vCard/LABEL/PARCEL") { - currentAddressLabel_.isParcel = true; - } - else if (elementHierarchy == "/vCard/LABEL/DOM") { - currentAddressLabel_.deliveryType = VCard::DomesticDelivery; - } - else if (elementHierarchy == "/vCard/LABEL/INTL") { - currentAddressLabel_.deliveryType = VCard::InternationalDelivery; - } - else if (elementHierarchy == "/vCard/LABEL/PREF") { - currentAddressLabel_.isPreferred = true; - } - else if (elementHierarchy == "/vCard/LABEL/LINE") { - currentAddressLabel_.lines.push_back(currentText_); - } - else if (elementHierarchy == "/vCard/LABEL") { - getPayloadInternal()->addAddressLabel(currentAddressLabel_); - } - else if (elementHierarchy == "/vCard/JID" && !currentText_.empty()) { - getPayloadInternal()->addJID(JID(currentText_)); - } - else if (elementHierarchy == "/vCard/DESC") { - getPayloadInternal()->setDescription(currentText_); - } - else if (elementHierarchy == "/vCard/ORG/ORGNAME") { - currentOrganization_.name = currentText_; - } - else if (elementHierarchy == "/vCard/ORG/ORGUNIT" && !currentText_.empty()) { - currentOrganization_.units.push_back(currentText_); - } - else if (elementHierarchy == "/vCard/ORG") { - if (!currentOrganization_.name.empty() || !currentOrganization_.units.empty()) { - getPayloadInternal()->addOrganization(currentOrganization_); - } - } - else if (elementHierarchy == "/vCard/TITLE" && !currentText_.empty()) { - getPayloadInternal()->addTitle(currentText_); - } - else if (elementHierarchy == "/vCard/ROLE" && !currentText_.empty()) { - getPayloadInternal()->addRole(currentText_); - } - else if (elementHierarchy == "/vCard/URL" && !currentText_.empty()) { - getPayloadInternal()->addURL(currentText_); - } - else if (elementStack_.size() == 2 && unknownContentParser_) { - getPayloadInternal()->addUnknownContent(unknownContentParser_->getResult()); - } + std::string elementHierarchy = getElementHierarchy(); + if (elementHierarchy == "/vCard/VERSION") { + getPayloadInternal()->setVersion(currentText_); + } + else if (elementHierarchy == "/vCard/FN") { + getPayloadInternal()->setFullName(currentText_); + } + else if (elementHierarchy == "/vCard/N/FAMILY") { + getPayloadInternal()->setFamilyName(currentText_); + } + else if (elementHierarchy == "/vCard/N/GIVEN") { + getPayloadInternal()->setGivenName(currentText_); + } + else if (elementHierarchy == "/vCard/N/MIDDLE") { + getPayloadInternal()->setMiddleName(currentText_); + } + else if (elementHierarchy == "/vCard/N/PREFIX") { + getPayloadInternal()->setPrefix(currentText_); + } + else if (elementHierarchy == "/vCard/N/SUFFIX") { + getPayloadInternal()->setSuffix(currentText_); + } + else if (elementHierarchy == "/vCard/N") { + } + else if (elementHierarchy == "/vCard/NICKNAME") { + getPayloadInternal()->setNickname(currentText_); + } + else if (elementHierarchy == "/vCard/PHOTO/TYPE") { + getPayloadInternal()->setPhotoType(currentText_); + } + else if (elementHierarchy == "/vCard/PHOTO/BINVAL") { + currentText_.erase(std::remove(currentText_.begin(), currentText_.end(), '\n'), currentText_.end()); + currentText_.erase(std::remove(currentText_.begin(), currentText_.end(), '\r'), currentText_.end()); + getPayloadInternal()->setPhoto(Base64::decode(currentText_)); + } + else if (elementHierarchy == "/vCard/PHOTO") { + } + else if (elementHierarchy == "/vCard/EMAIL/USERID") { + currentEMailAddress_.address = currentText_; + } + else if (elementHierarchy == "/vCard/EMAIL/HOME") { + currentEMailAddress_.isHome = true; + } + else if (elementHierarchy == "/vCard/EMAIL/WORK") { + currentEMailAddress_.isWork = true; + } + else if (elementHierarchy == "/vCard/EMAIL/INTERNET") { + currentEMailAddress_.isInternet = true; + } + else if (elementHierarchy == "/vCard/EMAIL/X400") { + currentEMailAddress_.isX400 = true; + } + else if (elementHierarchy == "/vCard/EMAIL/PREF") { + currentEMailAddress_.isPreferred = true; + } + else if (elementHierarchy == "/vCard/EMAIL" && !currentEMailAddress_.address.empty()) { + getPayloadInternal()->addEMailAddress(currentEMailAddress_); + } + else if (elementHierarchy == "/vCard/BDAY" && !currentText_.empty()) { + getPayloadInternal()->setBirthday(stringToDateTime(currentText_)); + } + else if (elementHierarchy == "/vCard/TEL/NUMBER") { + currentTelephone_.number = currentText_; + } + else if (elementHierarchy == "/vCard/TEL/HOME") { + currentTelephone_.isHome = true; + } + else if (elementHierarchy == "/vCard/TEL/WORK") { + currentTelephone_.isWork = true; + } + else if (elementHierarchy == "/vCard/TEL/VOICE") { + currentTelephone_.isVoice = true; + } + else if (elementHierarchy == "/vCard/TEL/FAX") { + currentTelephone_.isFax = true; + } + else if (elementHierarchy == "/vCard/TEL/PAGER") { + currentTelephone_.isPager = true; + } + else if (elementHierarchy == "/vCard/TEL/MSG") { + currentTelephone_.isMSG = true; + } + else if (elementHierarchy == "/vCard/TEL/CELL") { + currentTelephone_.isCell = true; + } + else if (elementHierarchy == "/vCard/TEL/VIDEO") { + currentTelephone_.isVideo = true; + } + else if (elementHierarchy == "/vCard/TEL/BBS") { + currentTelephone_.isBBS = true; + } + else if (elementHierarchy == "/vCard/TEL/MODEM") { + currentTelephone_.isModem = true; + } + else if (elementHierarchy == "/vCard/TEL/ISDN") { + currentTelephone_.isISDN = true; + } + else if (elementHierarchy == "/vCard/TEL/PCS") { + currentTelephone_.isPCS = true; + } + else if (elementHierarchy == "/vCard/TEL/PREF") { + currentTelephone_.isPreferred = true; + } + else if (elementHierarchy == "/vCard/TEL" && !currentTelephone_.number.empty()) { + getPayloadInternal()->addTelephone(currentTelephone_); + } + else if (elementHierarchy == "/vCard/ADR/HOME") { + currentAddress_.isHome = true; + } + else if (elementHierarchy == "/vCard/ADR/WORK") { + currentAddress_.isWork = true; + } + else if (elementHierarchy == "/vCard/ADR/POSTAL") { + currentAddress_.isPostal = true; + } + else if (elementHierarchy == "/vCard/ADR/PARCEL") { + currentAddress_.isParcel = true; + } + else if (elementHierarchy == "/vCard/ADR/DOM") { + currentAddress_.deliveryType = VCard::DomesticDelivery; + } + else if (elementHierarchy == "/vCard/ADR/INTL") { + currentAddress_.deliveryType = VCard::InternationalDelivery; + } + else if (elementHierarchy == "/vCard/ADR/PREF") { + currentAddress_.isPreferred = true; + } + else if (elementHierarchy == "/vCard/ADR/POBOX") { + currentAddress_.poBox = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/EXTADD") { + currentAddress_.addressExtension = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/STREET") { + currentAddress_.street = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/LOCALITY") { + currentAddress_.locality = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/REGION") { + currentAddress_.region = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/PCODE") { + currentAddress_.postalCode = currentText_; + } + else if (elementHierarchy == "/vCard/ADR/CTRY") { + currentAddress_.country = currentText_; + } + else if (elementHierarchy == "/vCard/ADR") { + if (!currentAddress_.poBox.empty() || !currentAddress_.addressExtension.empty() || + !currentAddress_.street.empty() || !currentAddress_.locality.empty() || + !currentAddress_.region.empty() || !currentAddress_.region.empty() || + !currentAddress_.postalCode.empty() || !currentAddress_.country.empty()) { + getPayloadInternal()->addAddress(currentAddress_); + } + } + else if (elementHierarchy == "/vCard/LABEL/HOME") { + currentAddressLabel_.isHome = true; + } + else if (elementHierarchy == "/vCard/LABEL/WORK") { + currentAddressLabel_.isWork = true; + } + else if (elementHierarchy == "/vCard/LABEL/POSTAL") { + currentAddressLabel_.isPostal = true; + } + else if (elementHierarchy == "/vCard/LABEL/PARCEL") { + currentAddressLabel_.isParcel = true; + } + else if (elementHierarchy == "/vCard/LABEL/DOM") { + currentAddressLabel_.deliveryType = VCard::DomesticDelivery; + } + else if (elementHierarchy == "/vCard/LABEL/INTL") { + currentAddressLabel_.deliveryType = VCard::InternationalDelivery; + } + else if (elementHierarchy == "/vCard/LABEL/PREF") { + currentAddressLabel_.isPreferred = true; + } + else if (elementHierarchy == "/vCard/LABEL/LINE") { + currentAddressLabel_.lines.push_back(currentText_); + } + else if (elementHierarchy == "/vCard/LABEL") { + getPayloadInternal()->addAddressLabel(currentAddressLabel_); + } + else if (elementHierarchy == "/vCard/JID" && !currentText_.empty()) { + getPayloadInternal()->addJID(JID(currentText_)); + } + else if (elementHierarchy == "/vCard/DESC") { + getPayloadInternal()->setDescription(currentText_); + } + else if (elementHierarchy == "/vCard/ORG/ORGNAME") { + currentOrganization_.name = currentText_; + } + else if (elementHierarchy == "/vCard/ORG/ORGUNIT" && !currentText_.empty()) { + currentOrganization_.units.push_back(currentText_); + } + else if (elementHierarchy == "/vCard/ORG") { + if (!currentOrganization_.name.empty() || !currentOrganization_.units.empty()) { + getPayloadInternal()->addOrganization(currentOrganization_); + } + } + else if (elementHierarchy == "/vCard/TITLE" && !currentText_.empty()) { + getPayloadInternal()->addTitle(currentText_); + } + else if (elementHierarchy == "/vCard/ROLE" && !currentText_.empty()) { + getPayloadInternal()->addRole(currentText_); + } + else if (elementHierarchy == "/vCard/URL" && !currentText_.empty()) { + getPayloadInternal()->addURL(currentText_); + } + else if (elementStack_.size() == 2 && unknownContentParser_) { + getPayloadInternal()->addUnknownContent(unknownContentParser_->getResult()); + } - if (elementStack_.size() == 2 && unknownContentParser_) { - delete unknownContentParser_; - unknownContentParser_ = NULL; - } - elementStack_.pop_back(); + if (elementStack_.size() == 2 && unknownContentParser_) { + delete unknownContentParser_; + unknownContentParser_ = nullptr; + } + elementStack_.pop_back(); } void VCardParser::handleCharacterData(const std::string& text) { - if (unknownContentParser_) { - unknownContentParser_->handleCharacterData(text); - } - currentText_ += text; + if (unknownContentParser_) { + unknownContentParser_->handleCharacterData(text); + } + currentText_ += text; } std::string VCardParser::getElementHierarchy() const { - std::string result; - foreach(const std::string& element, elementStack_) { - result += "/" + element; - } - return result; + std::string result; + for (const auto& element : elementStack_) { + result += "/" + element; + } + return result; } } diff --git a/Swiften/Parser/PayloadParsers/VCardParser.h b/Swiften/Parser/PayloadParsers/VCardParser.h index f10d639..5a47cbf 100644 --- a/Swiften/Parser/PayloadParsers/VCardParser.h +++ b/Swiften/Parser/PayloadParsers/VCardParser.h @@ -1,38 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/VCard.h> #include <Swiften/Parser/GenericPayloadParser.h> -#include <Swiften/Base/API.h> - namespace Swift { - class SerializingParser; - - class SWIFTEN_API VCardParser : public GenericPayloadParser<VCard> { - public: - VCardParser(); - - 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: - std::string getElementHierarchy() const; - - private: - std::vector<std::string> elementStack_; - VCard::EMailAddress currentEMailAddress_; - VCard::Telephone currentTelephone_; - VCard::Address currentAddress_; - VCard::AddressLabel currentAddressLabel_; - VCard::Organization currentOrganization_; - SerializingParser* unknownContentParser_; - std::string currentText_; - }; + class SerializingParser; + + class SWIFTEN_API VCardParser : public GenericPayloadParser<VCard> { + public: + VCardParser(); + + 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: + std::string getElementHierarchy() const; + + private: + std::vector<std::string> elementStack_; + VCard::EMailAddress currentEMailAddress_; + VCard::Telephone currentTelephone_; + VCard::Address currentAddress_; + VCard::AddressLabel currentAddressLabel_; + VCard::Organization currentOrganization_; + SerializingParser* unknownContentParser_; + std::string currentText_; + }; } diff --git a/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp b/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp index d4703da..64559ae 100644 --- a/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp +++ b/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PayloadParsers/VCardUpdateParser.h> @@ -12,21 +12,21 @@ VCardUpdateParser::VCardUpdateParser() : level_(TopLevel) { } void VCardUpdateParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - if (level_ == PayloadLevel) { - currentText_ = ""; - } - ++level_; + if (level_ == PayloadLevel) { + currentText_ = ""; + } + ++level_; } void VCardUpdateParser::handleEndElement(const std::string& element, const std::string&) { - --level_; - if (level_ == PayloadLevel && element == "photo") { - getPayloadInternal()->setPhotoHash(currentText_); - } + --level_; + if (level_ == PayloadLevel && element == "photo") { + getPayloadInternal()->setPhotoHash(currentText_); + } } void VCardUpdateParser::handleCharacterData(const std::string& text) { - currentText_ += text; + currentText_ += text; } } diff --git a/Swiften/Parser/PayloadParsers/VCardUpdateParser.h b/Swiften/Parser/PayloadParsers/VCardUpdateParser.h index 4954f0a..91837fb 100644 --- a/Swiften/Parser/PayloadParsers/VCardUpdateParser.h +++ b/Swiften/Parser/PayloadParsers/VCardUpdateParser.h @@ -1,31 +1,30 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/VCardUpdate.h> #include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class SerializingParser; + class SWIFTEN_API VCardUpdateParser : public GenericPayloadParser<VCardUpdate> { + public: + VCardUpdateParser(); - class VCardUpdateParser : public GenericPayloadParser<VCardUpdate> { - public: - VCardUpdateParser(); + 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); - 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 - }; - int level_; - std::string currentText_; - }; + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1 + }; + int level_; + std::string currentText_; + }; } diff --git a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp index a480813..d3a7211 100644 --- a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp +++ b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp @@ -4,312 +4,321 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Parser/PayloadParsers/WhiteboardParser.h> -#include <Swiften/Elements/Whiteboard/WhiteboardLineElement.h> -#include <Swiften/Elements/Whiteboard/WhiteboardRectElement.h> -#include <Swiften/Elements/Whiteboard/WhiteboardTextElement.h> -#include <Swiften/Elements/Whiteboard/WhiteboardPolygonElement.h> + +#include <memory> + +#include <boost/lexical_cast.hpp> +#include <boost/optional.hpp> + +#include <Swiften/Elements/Whiteboard/WhiteboardColor.h> +#include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h> #include <Swiften/Elements/Whiteboard/WhiteboardFreehandPathElement.h> -#include <Swiften/Elements/Whiteboard/WhiteboardColor.h> #include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> +#include <Swiften/Elements/Whiteboard/WhiteboardLineElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardPolygonElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardRectElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardTextElement.h> #include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h> -#include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> -#include <boost/optional.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/lexical_cast.hpp> namespace Swift { - WhiteboardParser::WhiteboardParser() : actualIsText(false), level_(0) { - } + WhiteboardParser::WhiteboardParser() : actualIsText(false), level_(0) { + } - void WhiteboardParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { - if (level_ == 0) { - getPayloadInternal()->setType(stringToType(attributes.getAttributeValue("type").get_value_or(""))); - } else if (level_ == 1) { - std::string type = attributes.getAttributeValue("type").get_value_or(""); - if (type == "insert") { - WhiteboardInsertOperation::ref insertOp = boost::make_shared<WhiteboardInsertOperation>(); - operation = insertOp; - } else if (type == "update") { - WhiteboardUpdateOperation::ref updateOp = boost::make_shared<WhiteboardUpdateOperation>(); - std::string move = attributes.getAttributeValue("newpos").get_value_or("0"); - updateOp->setNewPos(boost::lexical_cast<int>(attributes.getAttributeValue("newpos").get_value_or("0"))); - operation = updateOp; - } else if (type == "delete") { - WhiteboardDeleteOperation::ref deleteOp = boost::make_shared<WhiteboardDeleteOperation>(); - deleteOp->setElementID(attributes.getAttributeValue("elementid").get_value_or("")); - operation = deleteOp; - } - if (operation) { - try { - operation->setID(attributes.getAttributeValue("id").get_value_or("")); - operation->setParentID(attributes.getAttributeValue("parentid").get_value_or("")); - operation->setPos(boost::lexical_cast<int>(attributes.getAttributeValue("pos").get_value_or("0"))); - } catch (boost::bad_lexical_cast&) { - } - } + void WhiteboardParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { + if (level_ == 0) { + getPayloadInternal()->setType(stringToType(attributes.getAttributeValue("type").get_value_or(""))); + } else if (level_ == 1) { + std::string type = attributes.getAttributeValue("type").get_value_or(""); + if (type == "insert") { + WhiteboardInsertOperation::ref insertOp = std::make_shared<WhiteboardInsertOperation>(); + operation = insertOp; + } else if (type == "update") { + WhiteboardUpdateOperation::ref updateOp = std::make_shared<WhiteboardUpdateOperation>(); + std::string move = attributes.getAttributeValue("newpos").get_value_or("0"); + updateOp->setNewPos(boost::lexical_cast<int>(attributes.getAttributeValue("newpos").get_value_or("0"))); + operation = updateOp; + } else if (type == "delete") { + WhiteboardDeleteOperation::ref deleteOp = std::make_shared<WhiteboardDeleteOperation>(); + deleteOp->setElementID(attributes.getAttributeValue("elementid").get_value_or("")); + operation = deleteOp; + } + if (operation) { + try { + operation->setID(attributes.getAttributeValue("id").get_value_or("")); + operation->setParentID(attributes.getAttributeValue("parentid").get_value_or("")); + operation->setPos(boost::lexical_cast<int>(attributes.getAttributeValue("pos").get_value_or("0"))); + } catch (boost::bad_lexical_cast&) { + } + } - } else if (level_ == 2) { - if (element == "line") { - int x1 = 0; - int y1 = 0; - int x2 = 0; - int y2 = 0; - try { - x1 = boost::lexical_cast<int>(attributes.getAttributeValue("x1").get_value_or("0")); - y1 = boost::lexical_cast<int>(attributes.getAttributeValue("y1").get_value_or("0")); - x2 = boost::lexical_cast<int>(attributes.getAttributeValue("x2").get_value_or("0")); - y2 = boost::lexical_cast<int>(attributes.getAttributeValue("y2").get_value_or("0")); - } catch (boost::bad_lexical_cast&) { - } - WhiteboardLineElement::ref whiteboardElement = boost::make_shared<WhiteboardLineElement>(x1, y1, x2, y2); + } else if (level_ == 2) { + if (element == "line") { + int x1 = 0; + int y1 = 0; + int x2 = 0; + int y2 = 0; + try { + x1 = boost::lexical_cast<int>(attributes.getAttributeValue("x1").get_value_or("0")); + y1 = boost::lexical_cast<int>(attributes.getAttributeValue("y1").get_value_or("0")); + x2 = boost::lexical_cast<int>(attributes.getAttributeValue("x2").get_value_or("0")); + y2 = boost::lexical_cast<int>(attributes.getAttributeValue("y2").get_value_or("0")); + } catch (boost::bad_lexical_cast&) { + } + WhiteboardLineElement::ref whiteboardElement = std::make_shared<WhiteboardLineElement>(x1, y1, x2, y2); - WhiteboardColor color(attributes.getAttributeValue("stroke").get_value_or("#000000")); - color.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); - whiteboardElement->setColor(color); + WhiteboardColor color(attributes.getAttributeValue("stroke").get_value_or("#000000")); + color.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); + whiteboardElement->setColor(color); - int penWidth = 1; - try { - penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1")); - } catch (boost::bad_lexical_cast&) { - } - whiteboardElement->setPenWidth(penWidth); - whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); - getPayloadInternal()->setElement(whiteboardElement); - wbElement = whiteboardElement; - } else if (element == "path") { - WhiteboardFreehandPathElement::ref whiteboardElement = boost::make_shared<WhiteboardFreehandPathElement>(); - std::string pathData = attributes.getAttributeValue("d").get_value_or(""); - std::vector<std::pair<int, int> > points; - if (pathData[0] == 'M') { - size_t pos = 1; - size_t npos; - int x, y; - if (pathData[pos] == ' ') { - pos++; - } - try { - npos = pathData.find(' ', pos); - x = boost::lexical_cast<int>(pathData.substr(pos, npos-pos)); - pos = npos+1; - npos = pathData.find('L', pos); - y = boost::lexical_cast<int>(pathData.substr(pos, npos-pos)); - pos = npos+1; - if (pathData[pos] == ' ') { - pos++; - } - points.push_back(std::pair<int, int>(x, y)); - while (pos < pathData.size()) { - npos = pathData.find(' ', pos); - x = boost::lexical_cast<int>(pathData.substr(pos, npos-pos)); - pos = npos+1; - npos = pathData.find(' ', pos); - y = boost::lexical_cast<int>(pathData.substr(pos, npos-pos)); - pos = npos+1; - points.push_back(std::pair<int, int>(x, y)); - } - } catch (boost::bad_lexical_cast&) { - } - } - whiteboardElement->setPoints(points); + int penWidth = 1; + try { + penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1")); + } catch (boost::bad_lexical_cast&) { + } + whiteboardElement->setPenWidth(penWidth); + whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); + getPayloadInternal()->setElement(whiteboardElement); + wbElement = whiteboardElement; + } else if (element == "path") { + WhiteboardFreehandPathElement::ref whiteboardElement = std::make_shared<WhiteboardFreehandPathElement>(); + std::string pathData = attributes.getAttributeValue("d").get_value_or(""); + std::vector<std::pair<int, int> > points; + if (pathData[0] == 'M') { + size_t pos = 1; + size_t npos; + int x, y; + if (pathData[pos] == ' ') { + pos++; + } + try { + npos = pathData.find(' ', pos); + x = boost::lexical_cast<int>(pathData.substr(pos, npos-pos)); + pos = npos+1; + npos = pathData.find('L', pos); + y = boost::lexical_cast<int>(pathData.substr(pos, npos-pos)); + pos = npos+1; + if (pathData[pos] == ' ') { + pos++; + } + points.push_back(std::pair<int, int>(x, y)); + while (pos < pathData.size()) { + npos = pathData.find(' ', pos); + x = boost::lexical_cast<int>(pathData.substr(pos, npos-pos)); + pos = npos+1; + npos = pathData.find(' ', pos); + y = boost::lexical_cast<int>(pathData.substr(pos, npos-pos)); + pos = npos+1; + points.push_back(std::pair<int, int>(x, y)); + } + } catch (boost::bad_lexical_cast&) { + } + } + whiteboardElement->setPoints(points); - int penWidth = 1; - try { - penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1")); - } catch (boost::bad_lexical_cast&) { - } - whiteboardElement->setPenWidth(penWidth); + int penWidth = 1; + try { + penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1")); + } catch (boost::bad_lexical_cast&) { + } + whiteboardElement->setPenWidth(penWidth); - WhiteboardColor color(attributes.getAttributeValue("stroke").get_value_or("#000000")); - color.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); - whiteboardElement->setColor(color); - whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); - getPayloadInternal()->setElement(whiteboardElement); - wbElement = whiteboardElement; - } else if (element == "rect") { - int x = 0; - int y = 0; - int width = 0; - int height = 0; - try { - x = boost::lexical_cast<int>(attributes.getAttributeValue("x").get_value_or("0")); - y = boost::lexical_cast<int>(attributes.getAttributeValue("y").get_value_or("0")); - width = boost::lexical_cast<int>(attributes.getAttributeValue("width").get_value_or("0")); - height = boost::lexical_cast<int>(attributes.getAttributeValue("height").get_value_or("0")); - } catch (boost::bad_lexical_cast&) { - } + WhiteboardColor color(attributes.getAttributeValue("stroke").get_value_or("#000000")); + color.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); + whiteboardElement->setColor(color); + whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); + getPayloadInternal()->setElement(whiteboardElement); + wbElement = whiteboardElement; + } else if (element == "rect") { + int x = 0; + int y = 0; + int width = 0; + int height = 0; + try { + x = boost::lexical_cast<int>(attributes.getAttributeValue("x").get_value_or("0")); + y = boost::lexical_cast<int>(attributes.getAttributeValue("y").get_value_or("0")); + width = boost::lexical_cast<int>(attributes.getAttributeValue("width").get_value_or("0")); + height = boost::lexical_cast<int>(attributes.getAttributeValue("height").get_value_or("0")); + } catch (boost::bad_lexical_cast&) { + } - WhiteboardRectElement::ref whiteboardElement = boost::make_shared<WhiteboardRectElement>(x, y, width, height); + WhiteboardRectElement::ref whiteboardElement = std::make_shared<WhiteboardRectElement>(x, y, width, height); - int penWidth = 1; - try { - penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1")); - } catch (boost::bad_lexical_cast&) { - } - whiteboardElement->setPenWidth(penWidth); + int penWidth = 1; + try { + penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1")); + } catch (boost::bad_lexical_cast&) { + } + whiteboardElement->setPenWidth(penWidth); - WhiteboardColor penColor(attributes.getAttributeValue("stroke").get_value_or("#000000")); - WhiteboardColor brushColor(attributes.getAttributeValue("fill").get_value_or("#000000")); - penColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); - brushColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("fill-opacity").get_value_or("1"))); - whiteboardElement->setPenColor(penColor); - whiteboardElement->setBrushColor(brushColor); - whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); - getPayloadInternal()->setElement(whiteboardElement); - wbElement = whiteboardElement; - } else if (element == "polygon") { - WhiteboardPolygonElement::ref whiteboardElement = boost::make_shared<WhiteboardPolygonElement>(); + WhiteboardColor penColor(attributes.getAttributeValue("stroke").get_value_or("#000000")); + WhiteboardColor brushColor(attributes.getAttributeValue("fill").get_value_or("#000000")); + penColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); + brushColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("fill-opacity").get_value_or("1"))); + whiteboardElement->setPenColor(penColor); + whiteboardElement->setBrushColor(brushColor); + whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); + getPayloadInternal()->setElement(whiteboardElement); + wbElement = whiteboardElement; + } else if (element == "polygon") { + WhiteboardPolygonElement::ref whiteboardElement = std::make_shared<WhiteboardPolygonElement>(); - std::string pointsData = attributes.getAttributeValue("points").get_value_or(""); - std::vector<std::pair<int, int> > points; - size_t pos = 0; - size_t npos; - int x, y; - try { - while (pos < pointsData.size()) { - npos = pointsData.find(',', pos); - x = boost::lexical_cast<int>(pointsData.substr(pos, npos-pos)); - pos = npos+1; - npos = pointsData.find(' ', pos); - y = boost::lexical_cast<int>(pointsData.substr(pos, npos-pos)); - pos = npos+1; - points.push_back(std::pair<int, int>(x, y)); - } - } catch (boost::bad_lexical_cast&) { - } + std::string pointsData = attributes.getAttributeValue("points").get_value_or(""); + std::vector<std::pair<int, int> > points; + size_t pos = 0; + size_t npos; + int x, y; + try { + while (pos < pointsData.size()) { + npos = pointsData.find(',', pos); + x = boost::lexical_cast<int>(pointsData.substr(pos, npos-pos)); + pos = npos+1; + npos = pointsData.find(' ', pos); + y = boost::lexical_cast<int>(pointsData.substr(pos, npos-pos)); + pos = npos+1; + points.push_back(std::pair<int, int>(x, y)); + } + } catch (boost::bad_lexical_cast&) { + } - whiteboardElement->setPoints(points); + whiteboardElement->setPoints(points); - int penWidth = 1; - try { - penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1")); - } catch (boost::bad_lexical_cast&) { - } - whiteboardElement->setPenWidth(penWidth); + int penWidth = 1; + try { + penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1")); + } catch (boost::bad_lexical_cast&) { + } + whiteboardElement->setPenWidth(penWidth); - WhiteboardColor penColor(attributes.getAttributeValue("stroke").get_value_or("#000000")); - WhiteboardColor brushColor(attributes.getAttributeValue("fill").get_value_or("#000000")); - penColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); - brushColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("fill-opacity").get_value_or("1"))); - whiteboardElement->setPenColor(penColor); - whiteboardElement->setBrushColor(brushColor); - whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); - getPayloadInternal()->setElement(whiteboardElement); - wbElement = whiteboardElement; - } else if (element == "text") { - int x = 0; - int y = 0; - try { - x = boost::lexical_cast<int>(attributes.getAttributeValue("x").get_value_or("0")); - y = boost::lexical_cast<int>(attributes.getAttributeValue("y").get_value_or("0")); - } catch (boost::bad_lexical_cast&) { - } + WhiteboardColor penColor(attributes.getAttributeValue("stroke").get_value_or("#000000")); + WhiteboardColor brushColor(attributes.getAttributeValue("fill").get_value_or("#000000")); + penColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); + brushColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("fill-opacity").get_value_or("1"))); + whiteboardElement->setPenColor(penColor); + whiteboardElement->setBrushColor(brushColor); + whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); + getPayloadInternal()->setElement(whiteboardElement); + wbElement = whiteboardElement; + } else if (element == "text") { + int x = 0; + int y = 0; + try { + x = boost::lexical_cast<int>(attributes.getAttributeValue("x").get_value_or("0")); + y = boost::lexical_cast<int>(attributes.getAttributeValue("y").get_value_or("0")); + } catch (boost::bad_lexical_cast&) { + } - WhiteboardTextElement::ref whiteboardElement = boost::make_shared<WhiteboardTextElement>(x, y); + WhiteboardTextElement::ref whiteboardElement = std::make_shared<WhiteboardTextElement>(x, y); - actualIsText = true; - WhiteboardColor color(attributes.getAttributeValue("fill").get_value_or("#000000")); - color.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); - whiteboardElement->setColor(color); + actualIsText = true; + WhiteboardColor color(attributes.getAttributeValue("fill").get_value_or("#000000")); + color.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); + whiteboardElement->setColor(color); - int fontSize = 1; - try { - fontSize = boost::lexical_cast<int>(attributes.getAttributeValue("font-size").get_value_or("12")); - } catch (boost::bad_lexical_cast&) { - } - whiteboardElement->setSize(fontSize); - whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); - getPayloadInternal()->setElement(whiteboardElement); - wbElement = whiteboardElement; - } else if (element == "ellipse") { - int cx = 0; - int cy = 0; - int rx = 0; - int ry = 0; - try { - cx = boost::lexical_cast<int>(attributes.getAttributeValue("cx").get_value_or("0")); - cy = boost::lexical_cast<int>(attributes.getAttributeValue("cy").get_value_or("0")); - rx = boost::lexical_cast<int>(attributes.getAttributeValue("rx").get_value_or("0")); - ry = boost::lexical_cast<int>(attributes.getAttributeValue("ry").get_value_or("0")); - } catch (boost::bad_lexical_cast&) { - } + int fontSize = 1; + try { + fontSize = boost::lexical_cast<int>(attributes.getAttributeValue("font-size").get_value_or("12")); + } catch (boost::bad_lexical_cast&) { + } + whiteboardElement->setSize(fontSize); + whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); + getPayloadInternal()->setElement(whiteboardElement); + wbElement = whiteboardElement; + } else if (element == "ellipse") { + int cx = 0; + int cy = 0; + int rx = 0; + int ry = 0; + try { + cx = boost::lexical_cast<int>(attributes.getAttributeValue("cx").get_value_or("0")); + cy = boost::lexical_cast<int>(attributes.getAttributeValue("cy").get_value_or("0")); + rx = boost::lexical_cast<int>(attributes.getAttributeValue("rx").get_value_or("0")); + ry = boost::lexical_cast<int>(attributes.getAttributeValue("ry").get_value_or("0")); + } catch (boost::bad_lexical_cast&) { + } - WhiteboardEllipseElement::ref whiteboardElement = boost::make_shared<WhiteboardEllipseElement>(cx, cy, rx, ry); + WhiteboardEllipseElement::ref whiteboardElement = std::make_shared<WhiteboardEllipseElement>(cx, cy, rx, ry); - int penWidth = 1; - try { - penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1")); - } catch (boost::bad_lexical_cast&) { - } - whiteboardElement->setPenWidth(penWidth); + int penWidth = 1; + try { + penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1")); + } catch (boost::bad_lexical_cast&) { + } + whiteboardElement->setPenWidth(penWidth); - WhiteboardColor penColor(attributes.getAttributeValue("stroke").get_value_or("#000000")); - WhiteboardColor brushColor(attributes.getAttributeValue("fill").get_value_or("#000000")); - penColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); - brushColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("fill-opacity").get_value_or("1"))); - whiteboardElement->setPenColor(penColor); - whiteboardElement->setBrushColor(brushColor); - whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); - getPayloadInternal()->setElement(whiteboardElement); - wbElement = whiteboardElement; - } - } - ++level_; - } + WhiteboardColor penColor(attributes.getAttributeValue("stroke").get_value_or("#000000")); + WhiteboardColor brushColor(attributes.getAttributeValue("fill").get_value_or("#000000")); + penColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); + brushColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("fill-opacity").get_value_or("1"))); + whiteboardElement->setPenColor(penColor); + whiteboardElement->setBrushColor(brushColor); + whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or("")); + getPayloadInternal()->setElement(whiteboardElement); + wbElement = whiteboardElement; + } + } + ++level_; + } - void WhiteboardParser::handleEndElement(const std::string& element, const std::string&) { - --level_; - if (level_ == 0) { - getPayloadInternal()->setData(data_); - } else if (level_ == 1) { - WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(operation); - if (insertOp) { - insertOp->setElement(wbElement); - } + void WhiteboardParser::handleEndElement(const std::string& element, const std::string&) { + --level_; + if (level_ == 0) { + getPayloadInternal()->setData(data_); + } else if (level_ == 1) { + WhiteboardInsertOperation::ref insertOp = std::dynamic_pointer_cast<WhiteboardInsertOperation>(operation); + if (insertOp) { + insertOp->setElement(wbElement); + } - WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast<WhiteboardUpdateOperation>(operation); - if (updateOp) { - updateOp->setElement(wbElement); - } - getPayloadInternal()->setOperation(operation); - } else if (level_ == 2) { - if (element == "text") { - actualIsText = false; - } - } - } + WhiteboardUpdateOperation::ref updateOp = std::dynamic_pointer_cast<WhiteboardUpdateOperation>(operation); + if (updateOp) { + updateOp->setElement(wbElement); + } + getPayloadInternal()->setOperation(operation); + } else if (level_ == 2) { + if (element == "text") { + actualIsText = false; + } + } + } - void WhiteboardParser::handleCharacterData(const std::string& data) { - if (level_ == 3 && actualIsText) { - WhiteboardTextElement::ref element = boost::dynamic_pointer_cast<WhiteboardTextElement>(getPayloadInternal()->getElement()); - element->setText(data); - } - } + void WhiteboardParser::handleCharacterData(const std::string& data) { + if (level_ == 3 && actualIsText) { + WhiteboardTextElement::ref element = std::dynamic_pointer_cast<WhiteboardTextElement>(getPayloadInternal()->getElement()); + element->setText(data); + } + } - WhiteboardPayload::Type WhiteboardParser::stringToType(const std::string& type) const { - if (type == "data") { - return WhiteboardPayload::Data; - } else if (type == "session-request") { - return WhiteboardPayload::SessionRequest; - } else if (type == "session-accept") { - return WhiteboardPayload::SessionAccept; - } else if (type == "session-terminate") { - return WhiteboardPayload::SessionTerminate; - } else { - return WhiteboardPayload::UnknownType; - } - } + WhiteboardPayload::Type WhiteboardParser::stringToType(const std::string& type) const { + if (type == "data") { + return WhiteboardPayload::Data; + } else if (type == "session-request") { + return WhiteboardPayload::SessionRequest; + } else if (type == "session-accept") { + return WhiteboardPayload::SessionAccept; + } else if (type == "session-terminate") { + return WhiteboardPayload::SessionTerminate; + } else { + return WhiteboardPayload::UnknownType; + } + } - int WhiteboardParser::opacityToAlpha(std::string opacity) const { - int value = 255; - if (opacity.find('.') != std::string::npos) { - opacity = opacity.substr(opacity.find('.')+1, 2); - try { - value = boost::lexical_cast<int>(opacity)*255/100; - } catch (boost::bad_lexical_cast&) { - } - } - return value; - } + int WhiteboardParser::opacityToAlpha(std::string opacity) const { + int value = 255; + if (opacity.find('.') != std::string::npos) { + opacity = opacity.substr(opacity.find('.')+1, 2); + try { + value = boost::lexical_cast<int>(opacity)*255/100; + } catch (boost::bad_lexical_cast&) { + } + } + return value; + } } diff --git a/Swiften/Parser/PayloadParsers/WhiteboardParser.h b/Swiften/Parser/PayloadParsers/WhiteboardParser.h index 0368c7c..2f22624 100644 --- a/Swiften/Parser/PayloadParsers/WhiteboardParser.h +++ b/Swiften/Parser/PayloadParsers/WhiteboardParser.h @@ -4,31 +4,38 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Elements/WhiteboardPayload.h> -#include <Swiften/Parser/GenericPayloadParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Whiteboard/WhiteboardElement.h> #include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> +#include <Swiften/Elements/WhiteboardPayload.h> +#include <Swiften/Parser/GenericPayloadParser.h> namespace Swift { - class WhiteboardParser : public Swift::GenericPayloadParser<WhiteboardPayload> { - public: - WhiteboardParser(); + class SWIFTEN_API WhiteboardParser : public Swift::GenericPayloadParser<WhiteboardPayload> { + public: + WhiteboardParser(); - 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); + 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: - WhiteboardPayload::Type stringToType(const std::string& type) const; - int opacityToAlpha(std::string opacity) const; + private: + WhiteboardPayload::Type stringToType(const std::string& type) const; + int opacityToAlpha(std::string opacity) const; - private: - bool actualIsText; - int level_; - std::string data_; - WhiteboardElement::ref wbElement; - WhiteboardOperation::ref operation; - }; + private: + bool actualIsText; + int level_; + std::string data_; + WhiteboardElement::ref wbElement; + WhiteboardOperation::ref operation; + }; } diff --git a/Swiften/Parser/PlatformXMLParserFactory.cpp b/Swiften/Parser/PlatformXMLParserFactory.cpp index 18acdc2..a424aca 100644 --- a/Swiften/Parser/PlatformXMLParserFactory.cpp +++ b/Swiften/Parser/PlatformXMLParserFactory.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/PlatformXMLParserFactory.h> @@ -20,11 +20,11 @@ namespace Swift { PlatformXMLParserFactory::PlatformXMLParserFactory() { } -XMLParser* PlatformXMLParserFactory::createXMLParser(XMLParserClient* client) { +std::unique_ptr<XMLParser> PlatformXMLParserFactory::createXMLParser(XMLParserClient* client, bool allowComments) { #ifdef HAVE_LIBXML - return new LibXMLParser(client); + return std::make_unique<LibXMLParser>(client, allowComments); #else - return new ExpatParser(client); + return std::make_unique<ExpatParser>(client, allowComments); #endif } diff --git a/Swiften/Parser/PlatformXMLParserFactory.h b/Swiften/Parser/PlatformXMLParserFactory.h index 70355d0..d72a513 100644 --- a/Swiften/Parser/PlatformXMLParserFactory.h +++ b/Swiften/Parser/PlatformXMLParserFactory.h @@ -1,19 +1,19 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/XMLParserFactory.h> #include <Swiften/Base/API.h> +#include <Swiften/Parser/XMLParserFactory.h> namespace Swift { - class SWIFTEN_API PlatformXMLParserFactory : public XMLParserFactory { - public: - PlatformXMLParserFactory(); + class SWIFTEN_API PlatformXMLParserFactory : public XMLParserFactory { + public: + PlatformXMLParserFactory(); - virtual XMLParser* createXMLParser(XMLParserClient*); - }; + virtual std::unique_ptr<XMLParser> createXMLParser(XMLParserClient*, bool allowComments = false); + }; } diff --git a/Swiften/Parser/PresenceParser.cpp b/Swiften/Parser/PresenceParser.cpp index 39305c0..f73e9d8 100644 --- a/Swiften/Parser/PresenceParser.cpp +++ b/Swiften/Parser/PresenceParser.cpp @@ -1,52 +1,53 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <iostream> +#include <Swiften/Parser/PresenceParser.h> + #include <boost/optional.hpp> -#include <Swiften/Parser/PresenceParser.h> +#include <Swiften/Base/Log.h> namespace Swift { -PresenceParser::PresenceParser(PayloadParserFactoryCollection* factories) : - GenericStanzaParser<Presence>(factories) { +PresenceParser::PresenceParser(PayloadParserFactoryCollection* factories) : + GenericStanzaParser<Presence>(factories) { } void PresenceParser::handleStanzaAttributes(const AttributeMap& attributes) { - boost::optional<std::string> type = attributes.getAttributeValue("type"); - if (type) { - if (*type == "unavailable") { - getStanzaGeneric()->setType(Presence::Unavailable); - } - else if (*type == "probe") { - getStanzaGeneric()->setType(Presence::Probe); - } - else if (*type == "subscribe") { - getStanzaGeneric()->setType(Presence::Subscribe); - } - else if (*type == "subscribed") { - getStanzaGeneric()->setType(Presence::Subscribed); - } - else if (*type == "unsubscribe") { - getStanzaGeneric()->setType(Presence::Unsubscribe); - } - else if (*type == "unsubscribed") { - getStanzaGeneric()->setType(Presence::Unsubscribed); - } - else if (*type == "error") { - getStanzaGeneric()->setType(Presence::Error); - } - else { - std::cerr << "Unknown Presence type: " << *type << std::endl; - getStanzaGeneric()->setType(Presence::Available); - } - } - else { - getStanzaGeneric()->setType(Presence::Available); - } + boost::optional<std::string> type = attributes.getAttributeValue("type"); + if (type) { + if (*type == "unavailable") { + getStanzaGeneric()->setType(Presence::Unavailable); + } + else if (*type == "probe") { + getStanzaGeneric()->setType(Presence::Probe); + } + else if (*type == "subscribe") { + getStanzaGeneric()->setType(Presence::Subscribe); + } + else if (*type == "subscribed") { + getStanzaGeneric()->setType(Presence::Subscribed); + } + else if (*type == "unsubscribe") { + getStanzaGeneric()->setType(Presence::Unsubscribe); + } + else if (*type == "unsubscribed") { + getStanzaGeneric()->setType(Presence::Unsubscribed); + } + else if (*type == "error") { + getStanzaGeneric()->setType(Presence::Error); + } + else { + SWIFT_LOG(error) << "Unknown Presence type: " << *type; + getStanzaGeneric()->setType(Presence::Available); + } + } + else { + getStanzaGeneric()->setType(Presence::Available); + } } } diff --git a/Swiften/Parser/PresenceParser.h b/Swiften/Parser/PresenceParser.h index eb07af8..76753f8 100644 --- a/Swiften/Parser/PresenceParser.h +++ b/Swiften/Parser/PresenceParser.h @@ -1,21 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Parser/GenericStanzaParser.h> #include <Swiften/Elements/Presence.h> +#include <Swiften/Parser/GenericStanzaParser.h> namespace Swift { - class SWIFTEN_API PresenceParser : public GenericStanzaParser<Presence> { - public: - PresenceParser(PayloadParserFactoryCollection* factories); + class SWIFTEN_API PresenceParser : public GenericStanzaParser<Presence> { + public: + PresenceParser(PayloadParserFactoryCollection* factories); - private: - virtual void handleStanzaAttributes(const AttributeMap&); - }; + private: + virtual void handleStanzaAttributes(const AttributeMap&); + }; } diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 0a6972e..4ac5aa4 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -6,101 +6,126 @@ myenv.MergeFlags(swiften_env.get("LIBXML_FLAGS", "")) myenv.MergeFlags(swiften_env.get("EXPAT_FLAGS", "")) sources = [ - "AttributeMap.cpp", - "AuthRequestParser.cpp", - "AuthChallengeParser.cpp", - "AuthSuccessParser.cpp", - "AuthResponseParser.cpp", - "CompressParser.cpp", - "ElementParser.cpp", - "IQParser.cpp", - "MessageParser.cpp", - "PayloadParser.cpp", - "StanzaAckParser.cpp", - "BOSHBodyExtractor.cpp", - "ComponentHandshakeParser.cpp", - "PayloadParserFactory.cpp", - "PayloadParserFactoryCollection.cpp", - "PayloadParsers/BodyParser.cpp", - "PayloadParsers/SubjectParser.cpp", - "PayloadParsers/ChatStateParser.cpp", - "PayloadParsers/CapsInfoParser.cpp", - "PayloadParsers/DiscoInfoParser.cpp", - "PayloadParsers/DiscoItemsParser.cpp", - "PayloadParsers/ErrorParser.cpp", - "PayloadParsers/FormParser.cpp", - "PayloadParsers/IBBParser.cpp", - "PayloadParsers/JingleParser.cpp", - "PayloadParsers/JingleReasonParser.cpp", - "PayloadParsers/JingleContentPayloadParser.cpp", - "PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp", - "PayloadParsers/JingleS5BTransportMethodPayloadParser.cpp", - "PayloadParsers/JingleFileTransferDescriptionParser.cpp", - "PayloadParsers/JingleFileTransferReceivedParser.cpp", - "PayloadParsers/JingleFileTransferHashParser.cpp", - "PayloadParsers/StreamInitiationFileInfoParser.cpp", - "PayloadParsers/CommandParser.cpp", - "PayloadParsers/InBandRegistrationPayloadParser.cpp", - "PayloadParsers/SearchPayloadParser.cpp", - "PayloadParsers/FullPayloadParserFactoryCollection.cpp", - "PayloadParsers/PriorityParser.cpp", - "PayloadParsers/PrivateStorageParser.cpp", - "PayloadParsers/RawXMLPayloadParser.cpp", - "PayloadParsers/ResourceBindParser.cpp", - "PayloadParsers/RosterItemExchangeParser.cpp", - "PayloadParsers/RosterParser.cpp", - "PayloadParsers/SecurityLabelParser.cpp", - "PayloadParsers/SecurityLabelsCatalogParser.cpp", - "PayloadParsers/SoftwareVersionParser.cpp", - "PayloadParsers/StorageParser.cpp", - "PayloadParsers/StatusParser.cpp", - "PayloadParsers/StatusShowParser.cpp", - "PayloadParsers/StreamInitiationParser.cpp", - "PayloadParsers/BytestreamsParser.cpp", - "PayloadParsers/VCardParser.cpp", - "PayloadParsers/VCardUpdateParser.cpp", - "PayloadParsers/DelayParser.cpp", - "PayloadParsers/MUCUserPayloadParser.cpp", - "PayloadParsers/MUCAdminPayloadParser.cpp", - "PayloadParsers/MUCOwnerPayloadParser.cpp", - "PayloadParsers/MUCDestroyPayloadParser.cpp", - "PayloadParsers/MUCInvitationPayloadParser.cpp", - "PayloadParsers/MUCItemParser.cpp", - "PayloadParsers/NicknameParser.cpp", - "PayloadParsers/ReplaceParser.cpp", - "PayloadParsers/LastParser.cpp", - "PayloadParsers/IdleParser.cpp", - "PayloadParsers/S5BProxyRequestParser.cpp", - "PayloadParsers/DeliveryReceiptParser.cpp", - "PayloadParsers/DeliveryReceiptRequestParser.cpp", - "PayloadParsers/UserLocationParser.cpp", - "PayloadParsers/WhiteboardParser.cpp", - "PayloadParsers/PubSubErrorParserFactory.cpp", - "PlatformXMLParserFactory.cpp", - "PresenceParser.cpp", - "SerializingParser.cpp", - "StanzaParser.cpp", - "StreamErrorParser.cpp", - "StreamFeaturesParser.cpp", - "StreamManagementEnabledParser.cpp", - "StreamResumeParser.cpp", - "StreamResumedParser.cpp", - "Tree/ParserElement.cpp", - "Tree/NullParserElement.cpp", - "Tree/TreeReparser.cpp", - "XMLParser.cpp", - "XMLParserClient.cpp", - "XMLParserFactory.cpp", - "XMPPParser.cpp", - "XMPPParserClient.cpp", - ] + "AttributeMap.cpp", + "AuthRequestParser.cpp", + "AuthChallengeParser.cpp", + "AuthSuccessParser.cpp", + "AuthResponseParser.cpp", + "CompressParser.cpp", + "ElementParser.cpp", + "IQParser.cpp", + "MessageParser.cpp", + "PayloadParser.cpp", + "StanzaAckParser.cpp", + "BOSHBodyExtractor.cpp", + "ComponentHandshakeParser.cpp", + "PayloadParserFactory.cpp", + "PayloadParserFactoryCollection.cpp", + "PayloadParsers/BodyParser.cpp", + "PayloadParsers/SubjectParser.cpp", + "PayloadParsers/ThreadParser.cpp", + "PayloadParsers/CarbonsEnableParser.cpp", + "PayloadParsers/CarbonsDisableParser.cpp", + "PayloadParsers/CarbonsPrivateParser.cpp", + "PayloadParsers/CarbonsReceivedParser.cpp", + "PayloadParsers/CarbonsSentParser.cpp", + "PayloadParsers/ChatStateParser.cpp", + "PayloadParsers/ClientStateParser.cpp", + "PayloadParsers/CapsInfoParser.cpp", + "PayloadParsers/DiscoInfoParser.cpp", + "PayloadParsers/DiscoItemsParser.cpp", + "PayloadParsers/ErrorParser.cpp", + "PayloadParsers/FormParser.cpp", + "PayloadParsers/IBBParser.cpp", + "PayloadParsers/JingleParser.cpp", + "PayloadParsers/JingleReasonParser.cpp", + "PayloadParsers/JingleContentPayloadParser.cpp", + "PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp", + "PayloadParsers/JingleS5BTransportMethodPayloadParser.cpp", + "PayloadParsers/JingleFileTransferDescriptionParser.cpp", + "PayloadParsers/JingleFileTransferHashParser.cpp", + "PayloadParsers/JingleFileTransferFileInfoParser.cpp", + "PayloadParsers/StreamInitiationFileInfoParser.cpp", + "PayloadParsers/CommandParser.cpp", + "PayloadParsers/InBandRegistrationPayloadParser.cpp", + "PayloadParsers/SearchPayloadParser.cpp", + "PayloadParsers/FullPayloadParserFactoryCollection.cpp", + "PayloadParsers/PriorityParser.cpp", + "PayloadParsers/PrivateStorageParser.cpp", + "PayloadParsers/RawXMLPayloadParser.cpp", + "PayloadParsers/ReferencePayloadParser.cpp", + "PayloadParsers/ResourceBindParser.cpp", + "PayloadParsers/RosterItemExchangeParser.cpp", + "PayloadParsers/RosterParser.cpp", + "PayloadParsers/SecurityLabelParser.cpp", + "PayloadParsers/SecurityLabelsCatalogParser.cpp", + "PayloadParsers/SoftwareVersionParser.cpp", + "PayloadParsers/StorageParser.cpp", + "PayloadParsers/StatusParser.cpp", + "PayloadParsers/StatusShowParser.cpp", + "PayloadParsers/StreamInitiationParser.cpp", + "PayloadParsers/BytestreamsParser.cpp", + "PayloadParsers/VCardParser.cpp", + "PayloadParsers/VCardUpdateParser.cpp", + "PayloadParsers/DelayParser.cpp", + "PayloadParsers/MIXParticipantParser.cpp", + "PayloadParsers/MIXSetNickParser.cpp", + "PayloadParsers/MIXRegisterNickParser.cpp", + "PayloadParsers/MIXDestroyParser.cpp", + "PayloadParsers/MIXCreateParser.cpp", + "PayloadParsers/MIXPayloadParser.cpp", + "PayloadParsers/MIXLeaveParser.cpp", + "PayloadParsers/MIXJoinParser.cpp", + "PayloadParsers/MIXUserPreferenceParser.cpp", + "PayloadParsers/MIXUpdateSubscriptionParser.cpp", + "PayloadParsers/MUCUserPayloadParser.cpp", + "PayloadParsers/MUCAdminPayloadParser.cpp", + "PayloadParsers/MUCOwnerPayloadParser.cpp", + "PayloadParsers/MUCDestroyPayloadParser.cpp", + "PayloadParsers/MUCInvitationPayloadParser.cpp", + "PayloadParsers/MUCItemParser.cpp", + "PayloadParsers/NicknameParser.cpp", + "PayloadParsers/ReplaceParser.cpp", + "PayloadParsers/LastParser.cpp", + "PayloadParsers/IdleParser.cpp", + "PayloadParsers/S5BProxyRequestParser.cpp", + "PayloadParsers/DeliveryReceiptParser.cpp", + "PayloadParsers/DeliveryReceiptRequestParser.cpp", + "PayloadParsers/UserLocationParser.cpp", + "PayloadParsers/UserTuneParser.cpp", + "PayloadParsers/WhiteboardParser.cpp", + "PayloadParsers/PubSubErrorParserFactory.cpp", + "PayloadParsers/ResultSetParser.cpp", + "PayloadParsers/ForwardedParser.cpp", + "PayloadParsers/MAMFinParser.cpp", + "PayloadParsers/MAMResultParser.cpp", + "PayloadParsers/MAMQueryParser.cpp", + "PayloadParsers/IsodeIQDelegationParser.cpp", + "PlatformXMLParserFactory.cpp", + "PresenceParser.cpp", + "SerializingParser.cpp", + "StanzaParser.cpp", + "StreamErrorParser.cpp", + "StreamFeaturesParser.cpp", + "StreamManagementEnabledParser.cpp", + "StreamResumeParser.cpp", + "StreamResumedParser.cpp", + "Tree/ParserElement.cpp", + "Tree/NullParserElement.cpp", + "Tree/TreeReparser.cpp", + "XMLParser.cpp", + "XMLParserClient.cpp", + "XMLParserFactory.cpp", + "XMPPParser.cpp", + "XMPPParserClient.cpp", + ] if myenv.get("HAVE_EXPAT", 0) : - myenv.Append(CPPDEFINES = "HAVE_EXPAT") - sources += ["ExpatParser.cpp"] + myenv.Append(CPPDEFINES = "HAVE_EXPAT") + sources += ["ExpatParser.cpp"] if myenv.get("HAVE_LIBXML", 0) : - myenv.Append(CPPDEFINES = "HAVE_LIBXML") - sources += ["LibXMLParser.cpp"] + myenv.Append(CPPDEFINES = "HAVE_LIBXML") + sources += ["LibXMLParser.cpp"] objects = myenv.SwiftenObject(sources) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Parser/SerializingParser.cpp b/Swiften/Parser/SerializingParser.cpp index cd044cc..85b0dd4 100644 --- a/Swiften/Parser/SerializingParser.cpp +++ b/Swiften/Parser/SerializingParser.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/SerializingParser.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <cassert> +#include <memory> #include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Base/foreach.h> namespace Swift { @@ -17,34 +17,34 @@ SerializingParser::SerializingParser() { } void SerializingParser::handleStartElement(const std::string& tag, const std::string& ns, const AttributeMap& attributes) { - boost::shared_ptr<XMLElement> element = boost::make_shared<XMLElement>(tag, ns); - // FIXME: Ignoring attribute namespace - foreach (const AttributeMap::Entry& e, attributes.getEntries()) { - element->setAttribute(e.getAttribute().getName(), e.getValue()); - } - - if (elementStack_.empty()) { - rootElement_ = element; - } - else { - (*(elementStack_.end() - 1))->addNode(element); - } - elementStack_.push_back(element); + std::shared_ptr<XMLElement> element = std::make_shared<XMLElement>(tag, ns); + // FIXME: Ignoring attribute namespace + for (const auto& e : attributes.getEntries()) { + element->setAttribute(e.getAttribute().getName(), e.getValue()); + } + + if (elementStack_.empty()) { + rootElement_ = element; + } + else { + (*(elementStack_.end() - 1))->addNode(element); + } + elementStack_.push_back(element); } void SerializingParser::handleEndElement(const std::string&, const std::string&) { - assert(!elementStack_.empty()); - elementStack_.pop_back(); + assert(!elementStack_.empty()); + elementStack_.pop_back(); } void SerializingParser::handleCharacterData(const std::string& data) { - if (!elementStack_.empty()) { - (*(elementStack_.end()-1))->addNode(boost::make_shared<XMLTextNode>(data)); - } + if (!elementStack_.empty()) { + (*(elementStack_.end()-1))->addNode(std::make_shared<XMLTextNode>(data)); + } } std::string SerializingParser::getResult() const { - return (rootElement_ ? rootElement_->serialize() : ""); + return (rootElement_ ? rootElement_->serialize() : ""); } } diff --git a/Swiften/Parser/SerializingParser.h b/Swiften/Parser/SerializingParser.h index 7706961..bc2d872 100644 --- a/Swiften/Parser/SerializingParser.h +++ b/Swiften/Parser/SerializingParser.h @@ -1,29 +1,30 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + #include <Swiften/Base/API.h> #include <Swiften/Parser/AttributeMap.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class SWIFTEN_API SerializingParser { - public: - SerializingParser(); + class SWIFTEN_API SerializingParser { + public: + SerializingParser(); - void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); - void handleEndElement(const std::string& element, const std::string& ns); - void handleCharacterData(const std::string& data); + void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); + void handleEndElement(const std::string& element, const std::string& ns); + void handleCharacterData(const std::string& data); - std::string getResult() const; + std::string getResult() const; - private: - std::vector< boost::shared_ptr<XMLElement> > elementStack_; - boost::shared_ptr<XMLElement> rootElement_; - }; + private: + std::vector< std::shared_ptr<XMLElement> > elementStack_; + std::shared_ptr<XMLElement> rootElement_; + }; } diff --git a/Swiften/Parser/StanzaAckParser.cpp b/Swiften/Parser/StanzaAckParser.cpp index 1730493..42ab181 100644 --- a/Swiften/Parser/StanzaAckParser.cpp +++ b/Swiften/Parser/StanzaAckParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/StanzaAckParser.h> @@ -14,19 +14,19 @@ StanzaAckParser::StanzaAckParser() : GenericElementParser<StanzaAck>(), depth(0) } void StanzaAckParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { - if (depth == 0) { - std::string handledStanzasString = attributes.getAttribute("h"); - try { - getElementGeneric()->setHandledStanzasCount(boost::lexical_cast<int>(handledStanzasString)); - } - catch (const boost::bad_lexical_cast &) { - } - } - ++depth; + if (depth == 0) { + std::string handledStanzasString = attributes.getAttribute("h"); + try { + getElementGeneric()->setHandledStanzasCount(boost::lexical_cast<unsigned int>(handledStanzasString)); + } + catch (const boost::bad_lexical_cast &) { + } + } + ++depth; } void StanzaAckParser::handleEndElement(const std::string&, const std::string&) { - --depth; + --depth; } } diff --git a/Swiften/Parser/StanzaAckParser.h b/Swiften/Parser/StanzaAckParser.h index c453039..7e5a75f 100644 --- a/Swiften/Parser/StanzaAckParser.h +++ b/Swiften/Parser/StanzaAckParser.h @@ -1,24 +1,24 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Parser/GenericElementParser.h> #include <Swiften/Elements/StanzaAck.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class SWIFTEN_API StanzaAckParser : public GenericElementParser<StanzaAck> { - public: - StanzaAckParser(); + class SWIFTEN_API StanzaAckParser : public GenericElementParser<StanzaAck> { + public: + StanzaAckParser(); - virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); - virtual void handleEndElement(const std::string&, const std::string& ns); + virtual void handleStartElement(const std::string&, const std::string& ns, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string& ns); - private: - int depth; - }; + private: + int depth; + }; } diff --git a/Swiften/Parser/StanzaAckRequestParser.h b/Swiften/Parser/StanzaAckRequestParser.h index 9a2ccd1..9766e98 100644 --- a/Swiften/Parser/StanzaAckRequestParser.h +++ b/Swiften/Parser/StanzaAckRequestParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StanzaAckRequest.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class StanzaAckRequestParser : public GenericElementParser<StanzaAckRequest> { - public: - StanzaAckRequestParser() : GenericElementParser<StanzaAckRequest>() {} - }; + class SWIFTEN_API StanzaAckRequestParser : public GenericElementParser<StanzaAckRequest> { + public: + StanzaAckRequestParser() : GenericElementParser<StanzaAckRequest>() {} + }; } diff --git a/Swiften/Parser/StanzaParser.cpp b/Swiften/Parser/StanzaParser.cpp index 271fbf0..8be4103 100644 --- a/Swiften/Parser/StanzaParser.cpp +++ b/Swiften/Parser/StanzaParser.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/StanzaParser.h> -#include <iostream> -#include <boost/optional.hpp> #include <cassert> +#include <boost/optional.hpp> + #include <Swiften/Parser/PayloadParser.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParserFactoryCollection.h> @@ -17,69 +17,69 @@ namespace Swift { -StanzaParser::StanzaParser(PayloadParserFactoryCollection* factories) : - currentDepth_(0), factories_(factories) { +StanzaParser::StanzaParser(PayloadParserFactoryCollection* factories) : + currentDepth_(0), factories_(factories) { } StanzaParser::~StanzaParser() { } void StanzaParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (inStanza()) { - if (!inPayload()) { - assert(!currentPayloadParser_); - PayloadParserFactory* payloadParserFactory = factories_->getPayloadParserFactory(element, ns, attributes); - if (payloadParserFactory) { - currentPayloadParser_.reset(payloadParserFactory->createPayloadParser()); - } - else { - currentPayloadParser_.reset(new UnknownPayloadParser()); - } - } - assert(currentPayloadParser_); - currentPayloadParser_->handleStartElement(element, ns, attributes); - } - else { - boost::optional<std::string> from = attributes.getAttributeValue("from"); - if (from) { - getStanza()->setFrom(JID(*from)); - } - boost::optional<std::string> to = attributes.getAttributeValue("to"); - if (to) { - getStanza()->setTo(JID(*to)); - } - boost::optional<std::string> id = attributes.getAttributeValue("id"); - if (id) { - getStanza()->setID(*id); - } - handleStanzaAttributes(attributes); - } - ++currentDepth_; + if (inStanza()) { + if (!inPayload()) { + assert(!currentPayloadParser_); + PayloadParserFactory* payloadParserFactory = factories_->getPayloadParserFactory(element, ns, attributes); + if (payloadParserFactory) { + currentPayloadParser_.reset(payloadParserFactory->createPayloadParser()); + } + else { + currentPayloadParser_.reset(new UnknownPayloadParser()); + } + } + assert(currentPayloadParser_); + currentPayloadParser_->handleStartElement(element, ns, attributes); + } + else { + boost::optional<std::string> from = attributes.getAttributeValue("from"); + if (from) { + getStanza()->setFrom(JID(*from)); + } + boost::optional<std::string> to = attributes.getAttributeValue("to"); + if (to) { + getStanza()->setTo(JID(*to)); + } + boost::optional<std::string> id = attributes.getAttributeValue("id"); + if (id) { + getStanza()->setID(*id); + } + handleStanzaAttributes(attributes); + } + ++currentDepth_; } void StanzaParser::handleEndElement(const std::string& element, const std::string& ns) { - assert(inStanza()); - if (inPayload()) { - assert(currentPayloadParser_); - currentPayloadParser_->handleEndElement(element, ns); - --currentDepth_; - if (!inPayload()) { - boost::shared_ptr<Payload> payload(currentPayloadParser_->getPayload()); - if (payload) { - getStanza()->addPayload(payload); - } - currentPayloadParser_.reset(); - } - } - else { - --currentDepth_; - } + assert(inStanza()); + if (inPayload()) { + assert(currentPayloadParser_); + currentPayloadParser_->handleEndElement(element, ns); + --currentDepth_; + if (!inPayload()) { + std::shared_ptr<Payload> payload(currentPayloadParser_->getPayload()); + if (payload) { + getStanza()->addPayload(payload); + } + currentPayloadParser_.reset(); + } + } + else { + --currentDepth_; + } } void StanzaParser::handleCharacterData(const std::string& data) { - if (currentPayloadParser_) { - currentPayloadParser_->handleCharacterData(data); - } + if (currentPayloadParser_) { + currentPayloadParser_->handleCharacterData(data); + } } } diff --git a/Swiften/Parser/StanzaParser.h b/Swiften/Parser/StanzaParser.h index 0af6b43..7b83e99 100644 --- a/Swiften/Parser/StanzaParser.h +++ b/Swiften/Parser/StanzaParser.h @@ -1,53 +1,54 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> +#include <string> + #include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> -#include <string> #include <Swiften/Elements/Stanza.h> -#include <Swiften/Parser/ElementParser.h> #include <Swiften/Parser/AttributeMap.h> +#include <Swiften/Parser/ElementParser.h> namespace Swift { - class PayloadParser; - class PayloadParserFactoryCollection; + class PayloadParser; + class PayloadParserFactoryCollection; - class SWIFTEN_API StanzaParser : public ElementParser, public boost::noncopyable { - public: - StanzaParser(PayloadParserFactoryCollection* factories); - ~StanzaParser(); + class SWIFTEN_API StanzaParser : public ElementParser, public boost::noncopyable { + public: + StanzaParser(PayloadParserFactoryCollection* factories); + ~StanzaParser(); - void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); - void handleEndElement(const std::string& element, const std::string& ns); - void handleCharacterData(const std::string& data); + void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); + void handleEndElement(const std::string& element, const std::string& ns); + void handleCharacterData(const std::string& data); - virtual boost::shared_ptr<Element> getElement() const = 0; - virtual void handleStanzaAttributes(const AttributeMap&) {} + virtual std::shared_ptr<ToplevelElement> getElement() const = 0; + virtual void handleStanzaAttributes(const AttributeMap&) {} - virtual boost::shared_ptr<Stanza> getStanza() const { - return boost::dynamic_pointer_cast<Stanza>(getElement()); - } + virtual std::shared_ptr<Stanza> getStanza() const { + return std::dynamic_pointer_cast<Stanza>(getElement()); + } - private: - bool inPayload() const { - return currentDepth_ > 1; - } + private: + bool inPayload() const { + return currentDepth_ > 1; + } - bool inStanza() const { - return currentDepth_ > 0; - } + bool inStanza() const { + return currentDepth_ > 0; + } - private: - int currentDepth_; - PayloadParserFactoryCollection* factories_; - boost::shared_ptr<PayloadParser> currentPayloadParser_; - }; + private: + int currentDepth_; + PayloadParserFactoryCollection* factories_; + std::shared_ptr<PayloadParser> currentPayloadParser_; + }; } diff --git a/Swiften/Parser/StartTLSFailureParser.h b/Swiften/Parser/StartTLSFailureParser.h index 41ecafb..2f13e71 100644 --- a/Swiften/Parser/StartTLSFailureParser.h +++ b/Swiften/Parser/StartTLSFailureParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StartTLSFailure.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class StartTLSFailureParser : public GenericElementParser<StartTLSFailure> { - public: - StartTLSFailureParser() : GenericElementParser<StartTLSFailure>() {} - }; + class SWIFTEN_API StartTLSFailureParser : public GenericElementParser<StartTLSFailure> { + public: + StartTLSFailureParser() : GenericElementParser<StartTLSFailure>() {} + }; } diff --git a/Swiften/Parser/StartTLSParser.h b/Swiften/Parser/StartTLSParser.h index 9bc7576..f769d4d 100644 --- a/Swiften/Parser/StartTLSParser.h +++ b/Swiften/Parser/StartTLSParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StartTLSRequest.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class StartTLSParser : public GenericElementParser<StartTLSRequest> { - public: - StartTLSParser() : GenericElementParser<StartTLSRequest>() {} - }; + class SWIFTEN_API StartTLSParser : public GenericElementParser<StartTLSRequest> { + public: + StartTLSParser() : GenericElementParser<StartTLSRequest>() {} + }; } diff --git a/Swiften/Parser/StreamErrorParser.cpp b/Swiften/Parser/StreamErrorParser.cpp index f4530f9..e89af58 100644 --- a/Swiften/Parser/StreamErrorParser.cpp +++ b/Swiften/Parser/StreamErrorParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/StreamErrorParser.h> @@ -12,98 +12,98 @@ StreamErrorParser::StreamErrorParser() : level(TopLevel) { } void StreamErrorParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { - ++level; + ++level; } void StreamErrorParser::handleEndElement(const std::string& element, const std::string& ns) { - --level; - if (level == ElementLevel && ns == "urn:ietf:params:xml:ns:xmpp-streams") { - if (element == "text") { - getElementGeneric()->setText(currentText); - } - else if (element == "bad-format") { - getElementGeneric()->setType(StreamError::BadFormat); - } - else if(element == "bad-namespace-prefix") { - getElementGeneric()->setType(StreamError::BadNamespacePrefix); - } - else if(element == "conflict") { - getElementGeneric()->setType(StreamError::Conflict); - } - else if(element == "connection-timeout") { - getElementGeneric()->setType(StreamError::ConnectionTimeout); - } - else if(element == "host-gone") { - getElementGeneric()->setType(StreamError::HostGone); - } - else if(element == "host-unknown") { - getElementGeneric()->setType(StreamError::HostUnknown); - } - else if(element == "improper-addressing") { - getElementGeneric()->setType(StreamError::ImproperAddressing); - } - else if(element == "internal-server-error") { - getElementGeneric()->setType(StreamError::InternalServerError); - } - else if(element == "invalid-from") { - getElementGeneric()->setType(StreamError::InvalidFrom); - } - else if(element == "invalid-id") { - getElementGeneric()->setType(StreamError::InvalidID); - } - else if(element == "invalid-namespace") { - getElementGeneric()->setType(StreamError::InvalidNamespace); - } - else if(element == "invalid-xml") { - getElementGeneric()->setType(StreamError::InvalidXML); - } - else if(element == "not-authorized") { - getElementGeneric()->setType(StreamError::NotAuthorized); - } - else if(element == "not-well-formed") { - getElementGeneric()->setType(StreamError::NotWellFormed); - } - else if(element == "policy-violation") { - getElementGeneric()->setType(StreamError::PolicyViolation); - } - else if(element == "remote-connection-failed") { - getElementGeneric()->setType(StreamError::RemoteConnectionFailed); - } - else if(element == "reset") { - getElementGeneric()->setType(StreamError::Reset); - } - else if(element == "resource-constraint") { - getElementGeneric()->setType(StreamError::ResourceConstraint); - } - else if(element == "restricted-xml") { - getElementGeneric()->setType(StreamError::RestrictedXML); - } - else if(element == "see-other-host") { - getElementGeneric()->setType(StreamError::SeeOtherHost); - } - else if(element == "system-shutdown") { - getElementGeneric()->setType(StreamError::SystemShutdown); - } - else if(element == "undefined-condition") { - getElementGeneric()->setType(StreamError::UndefinedCondition); - } - else if(element == "unsupported-encoding") { - getElementGeneric()->setType(StreamError::UnsupportedEncoding); - } - else if(element == "unsupported-stanza-type") { - getElementGeneric()->setType(StreamError::UnsupportedStanzaType); - } - else if(element == "unsupported-version") { - getElementGeneric()->setType(StreamError::UnsupportedVersion); - } - else { - getElementGeneric()->setType(StreamError::UndefinedCondition); - } - } + --level; + if (level == ElementLevel && ns == "urn:ietf:params:xml:ns:xmpp-streams") { + if (element == "text") { + getElementGeneric()->setText(currentText); + } + else if (element == "bad-format") { + getElementGeneric()->setType(StreamError::BadFormat); + } + else if(element == "bad-namespace-prefix") { + getElementGeneric()->setType(StreamError::BadNamespacePrefix); + } + else if(element == "conflict") { + getElementGeneric()->setType(StreamError::Conflict); + } + else if(element == "connection-timeout") { + getElementGeneric()->setType(StreamError::ConnectionTimeout); + } + else if(element == "host-gone") { + getElementGeneric()->setType(StreamError::HostGone); + } + else if(element == "host-unknown") { + getElementGeneric()->setType(StreamError::HostUnknown); + } + else if(element == "improper-addressing") { + getElementGeneric()->setType(StreamError::ImproperAddressing); + } + else if(element == "internal-server-error") { + getElementGeneric()->setType(StreamError::InternalServerError); + } + else if(element == "invalid-from") { + getElementGeneric()->setType(StreamError::InvalidFrom); + } + else if(element == "invalid-namespace") { + getElementGeneric()->setType(StreamError::InvalidNamespace); + } + else if(element == "invalid-xml") { + getElementGeneric()->setType(StreamError::InvalidXML); + } + else if(element == "not-authorized") { + getElementGeneric()->setType(StreamError::NotAuthorized); + } + else if(element == "not-well-formed") { + getElementGeneric()->setType(StreamError::NotWellFormed); + } + else if(element == "policy-violation") { + getElementGeneric()->setType(StreamError::PolicyViolation); + } + else if(element == "remote-connection-failed") { + getElementGeneric()->setType(StreamError::RemoteConnectionFailed); + } + else if(element == "reset") { + getElementGeneric()->setType(StreamError::Reset); + } + else if(element == "resource-constraint") { + getElementGeneric()->setType(StreamError::ResourceConstraint); + } + else if(element == "restricted-xml") { + getElementGeneric()->setType(StreamError::RestrictedXML); + } + else if(element == "see-other-host") { + getElementGeneric()->setType(StreamError::SeeOtherHost); + } + else if(element == "system-shutdown") { + getElementGeneric()->setType(StreamError::SystemShutdown); + } + else if(element == "undefined-condition") { + getElementGeneric()->setType(StreamError::UndefinedCondition); + } + else if(element == "unsupported-encoding") { + getElementGeneric()->setType(StreamError::UnsupportedEncoding); + } + else if(element == "unsupported-feature") { + getElementGeneric()->setType(StreamError::UnsupportedFeature); + } + else if(element == "unsupported-stanza-type") { + getElementGeneric()->setType(StreamError::UnsupportedStanzaType); + } + else if(element == "unsupported-version") { + getElementGeneric()->setType(StreamError::UnsupportedVersion); + } + else { + getElementGeneric()->setType(StreamError::UndefinedCondition); + } + } } void StreamErrorParser::handleCharacterData(const std::string& data) { - currentText += data; + currentText += data; } } diff --git a/Swiften/Parser/StreamErrorParser.h b/Swiften/Parser/StreamErrorParser.h index 61c8c12..27efc86 100644 --- a/Swiften/Parser/StreamErrorParser.h +++ b/Swiften/Parser/StreamErrorParser.h @@ -1,29 +1,30 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamError.h> #include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class StreamErrorParser : public GenericElementParser<StreamError> { - public: - StreamErrorParser(); + class SWIFTEN_API StreamErrorParser : public GenericElementParser<StreamError> { + public: + StreamErrorParser(); - 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); + 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, - ElementLevel = 1 - }; - int level; - std::string currentText; - }; + private: + enum Level { + TopLevel = 0, + ElementLevel = 1 + }; + int level; + std::string currentText; + }; } diff --git a/Swiften/Parser/StreamFeaturesParser.cpp b/Swiften/Parser/StreamFeaturesParser.cpp index 6a527ce..ce99a1e 100644 --- a/Swiften/Parser/StreamFeaturesParser.cpp +++ b/Swiften/Parser/StreamFeaturesParser.cpp @@ -1,73 +1,82 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/StreamFeaturesParser.h> namespace Swift { -StreamFeaturesParser::StreamFeaturesParser() : GenericElementParser<StreamFeatures>(), currentDepth_(0), inMechanisms_(false), inMechanism_(false), inCompression_(false), inCompressionMethod_(false) { +StreamFeaturesParser::StreamFeaturesParser() : GenericElementParser<StreamFeatures>(), currentDepth_(0), inMechanisms_(false), inMechanism_(false), inAuthenticationHostname_(false), inCompression_(false), inCompressionMethod_(false) { } void StreamFeaturesParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap&) { - if (currentDepth_ == 1) { - if (element == "starttls" && ns == "urn:ietf:params:xml:ns:xmpp-tls") { - getElementGeneric()->setHasStartTLS(); - } - else if (element == "session" && ns == "urn:ietf:params:xml:ns:xmpp-session") { - getElementGeneric()->setHasSession(); - } - else if (element == "bind" && ns == "urn:ietf:params:xml:ns:xmpp-bind") { - getElementGeneric()->setHasResourceBind(); - } - else if (element == "sm" && ns == "urn:xmpp:sm:2") { - getElementGeneric()->setHasStreamManagement(); - } - else if (element == "mechanisms" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") { - inMechanisms_ = true; - } - else if (element == "compression" && ns == "http://jabber.org/features/compress") { - inCompression_ = true; - } - else if (element == "ver" && ns == "urn:xmpp:features:rosterver") { - getElementGeneric()->setHasRosterVersioning(); - } - } - else if (currentDepth_ == 2) { - if (inCompression_ && element == "method") { - inCompressionMethod_ = true; - currentText_ = ""; - } - else if (inMechanisms_ && element == "mechanism") { - inMechanism_ = true; - currentText_ = ""; - } - } - ++currentDepth_; + if (currentDepth_ == 1) { + if (element == "starttls" && ns == "urn:ietf:params:xml:ns:xmpp-tls") { + getElementGeneric()->setHasStartTLS(); + } + else if (element == "session" && ns == "urn:ietf:params:xml:ns:xmpp-session") { + getElementGeneric()->setHasSession(); + } + else if (element == "bind" && ns == "urn:ietf:params:xml:ns:xmpp-bind") { + getElementGeneric()->setHasResourceBind(); + } + else if (element == "sm" && ns == "urn:xmpp:sm:2") { + getElementGeneric()->setHasStreamManagement(); + } + else if (element == "mechanisms" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") { + inMechanisms_ = true; + } + else if (element == "compression" && ns == "http://jabber.org/features/compress") { + inCompression_ = true; + } + else if (element == "ver" && ns == "urn:xmpp:features:rosterver") { + getElementGeneric()->setHasRosterVersioning(); + } + } + else if (currentDepth_ == 2) { + if (inCompression_ && element == "method") { + inCompressionMethod_ = true; + currentText_ = ""; + } + else if (inMechanisms_ && element == "mechanism") { + inMechanism_ = true; + currentText_ = ""; + } + else if (inMechanisms_ && element == "hostname" && ns == "urn:xmpp:domain-based-name:1") { + inAuthenticationHostname_ = true; + currentText_ = ""; + } + + } + ++currentDepth_; } void StreamFeaturesParser::handleEndElement(const std::string&, const std::string&) { - --currentDepth_; - if (currentDepth_ == 1) { - inCompression_ = false; - inMechanisms_ = false; - } - else if (currentDepth_ == 2) { - if (inCompressionMethod_) { - getElementGeneric()->addCompressionMethod(currentText_); - inCompressionMethod_ = false; - } - else if (inMechanism_) { - getElementGeneric()->addAuthenticationMechanism(currentText_); - inMechanism_ = false; - } - } + --currentDepth_; + if (currentDepth_ == 1) { + inCompression_ = false; + inMechanisms_ = false; + } + else if (currentDepth_ == 2) { + if (inCompressionMethod_) { + getElementGeneric()->addCompressionMethod(currentText_); + inCompressionMethod_ = false; + } + else if (inMechanism_) { + getElementGeneric()->addAuthenticationMechanism(currentText_); + inMechanism_ = false; + } + else if (inAuthenticationHostname_) { + getElementGeneric()->setAuthenticationHostname(currentText_); + inAuthenticationHostname_ = false; + } + } } void StreamFeaturesParser::handleCharacterData(const std::string& data) { - currentText_ += data; + currentText_ += data; } } diff --git a/Swiften/Parser/StreamFeaturesParser.h b/Swiften/Parser/StreamFeaturesParser.h index 4bbb31c..5af8de8 100644 --- a/Swiften/Parser/StreamFeaturesParser.h +++ b/Swiften/Parser/StreamFeaturesParser.h @@ -1,32 +1,34 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + #include <Swiften/Base/API.h> -#include <Swiften/Parser/GenericElementParser.h> #include <Swiften/Elements/StreamFeatures.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class SWIFTEN_API StreamFeaturesParser : public GenericElementParser<StreamFeatures> { - public: - StreamFeaturesParser(); + class SWIFTEN_API StreamFeaturesParser : public GenericElementParser<StreamFeatures> { + public: + StreamFeaturesParser(); - private: - void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); - void handleEndElement(const std::string& element, const std::string& ns); - void handleCharacterData(const std::string& data); + private: + void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); + void handleEndElement(const std::string& element, const std::string& ns); + void handleCharacterData(const std::string& data); - private: - int currentDepth_; - std::string currentText_; - bool inMechanisms_; - bool inMechanism_; - bool inCompression_; - bool inCompressionMethod_; - }; + private: + int currentDepth_; + std::string currentText_; + bool inMechanisms_; + bool inMechanism_; + bool inAuthenticationHostname_; + bool inCompression_; + bool inCompressionMethod_; + }; } diff --git a/Swiften/Parser/StreamManagementEnabledParser.cpp b/Swiften/Parser/StreamManagementEnabledParser.cpp index 906e071..9e87d65 100644 --- a/Swiften/Parser/StreamManagementEnabledParser.cpp +++ b/Swiften/Parser/StreamManagementEnabledParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/StreamManagementEnabledParser.h> @@ -15,15 +15,15 @@ StreamManagementEnabledParser::~StreamManagementEnabledParser() { } void StreamManagementEnabledParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { - if (level == TopLevel) { - if (attributes.getBoolAttribute("resume", false)) { - getElementGeneric()->setResumeSupported(); - } - getElementGeneric()->setResumeID(attributes.getAttribute("id")); - } - ++level; + if (level == TopLevel) { + if (attributes.getBoolAttribute("resume", false)) { + getElementGeneric()->setResumeSupported(); + } + getElementGeneric()->setResumeID(attributes.getAttribute("id")); + } + ++level; } void StreamManagementEnabledParser::handleEndElement(const std::string&, const std::string&) { - --level; + --level; } diff --git a/Swiften/Parser/StreamManagementEnabledParser.h b/Swiften/Parser/StreamManagementEnabledParser.h index dfe232c..0f75071 100644 --- a/Swiften/Parser/StreamManagementEnabledParser.h +++ b/Swiften/Parser/StreamManagementEnabledParser.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2010-2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> -#include <Swiften/Elements/StreamManagementEnabled.h> #include <Swiften/Base/API.h> +#include <Swiften/Elements/StreamManagementEnabled.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class SWIFTEN_API StreamManagementEnabledParser : public GenericElementParser<StreamManagementEnabled> { - public: - StreamManagementEnabledParser(); - ~StreamManagementEnabledParser(); + class SWIFTEN_API StreamManagementEnabledParser : public GenericElementParser<StreamManagementEnabled> { + public: + StreamManagementEnabledParser(); + ~StreamManagementEnabledParser(); - virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); - virtual void handleEndElement(const std::string&, const std::string&); + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string&); - private: - enum Level { - TopLevel = 0 - }; - int level; - }; + private: + enum Level { + TopLevel = 0 + }; + int level; + }; } diff --git a/Swiften/Parser/StreamManagementFailedParser.h b/Swiften/Parser/StreamManagementFailedParser.h index 6c111d0..c87beee 100644 --- a/Swiften/Parser/StreamManagementFailedParser.h +++ b/Swiften/Parser/StreamManagementFailedParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamManagementFailed.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class StreamManagementFailedParser : public GenericElementParser<StreamManagementFailed> { - public: - StreamManagementFailedParser() : GenericElementParser<StreamManagementFailed>() {} - }; + class SWIFTEN_API StreamManagementFailedParser : public GenericElementParser<StreamManagementFailed> { + public: + StreamManagementFailedParser() : GenericElementParser<StreamManagementFailed>() {} + }; } diff --git a/Swiften/Parser/StreamResumeParser.cpp b/Swiften/Parser/StreamResumeParser.cpp index cb1a61d..a6ca444 100644 --- a/Swiften/Parser/StreamResumeParser.cpp +++ b/Swiften/Parser/StreamResumeParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/StreamResumeParser.h> @@ -17,20 +17,20 @@ StreamResumeParser::~StreamResumeParser() { } void StreamResumeParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { - if (level == TopLevel) { - boost::optional<std::string> handledStanzasCount = attributes.getAttributeValue("h"); - if (handledStanzasCount) { - try { - getElementGeneric()->setHandledStanzasCount(boost::lexical_cast<unsigned int>(*handledStanzasCount)); - } - catch (const boost::bad_lexical_cast &) { - } - } - getElementGeneric()->setResumeID(attributes.getAttribute("previd")); - } - ++level; + if (level == TopLevel) { + boost::optional<std::string> handledStanzasCount = attributes.getAttributeValue("h"); + if (handledStanzasCount) { + try { + getElementGeneric()->setHandledStanzasCount(boost::lexical_cast<unsigned int>(*handledStanzasCount)); + } + catch (const boost::bad_lexical_cast &) { + } + } + getElementGeneric()->setResumeID(attributes.getAttribute("previd")); + } + ++level; } void StreamResumeParser::handleEndElement(const std::string&, const std::string&) { - --level; + --level; } diff --git a/Swiften/Parser/StreamResumeParser.h b/Swiften/Parser/StreamResumeParser.h index 0ccd24c..d3d2498 100644 --- a/Swiften/Parser/StreamResumeParser.h +++ b/Swiften/Parser/StreamResumeParser.h @@ -1,27 +1,28 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamResume.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class StreamResumeParser : public GenericElementParser<StreamResume> { - public: - StreamResumeParser(); - ~StreamResumeParser(); + class SWIFTEN_API StreamResumeParser : public GenericElementParser<StreamResume> { + public: + StreamResumeParser(); + ~StreamResumeParser(); - virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); - virtual void handleEndElement(const std::string&, const std::string&); + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string&); - private: - enum Level { - TopLevel = 0 - }; - int level; - }; + private: + enum Level { + TopLevel = 0 + }; + int level; + }; } diff --git a/Swiften/Parser/StreamResumedParser.cpp b/Swiften/Parser/StreamResumedParser.cpp index 4b39c04..f69bad1 100644 --- a/Swiften/Parser/StreamResumedParser.cpp +++ b/Swiften/Parser/StreamResumedParser.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/StreamResumedParser.h> @@ -17,20 +17,20 @@ StreamResumedParser::~StreamResumedParser() { } void StreamResumedParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { - if (level == TopLevel) { - boost::optional<std::string> handledStanzasCount = attributes.getAttributeValue("h"); - if (handledStanzasCount) { - try { - getElementGeneric()->setHandledStanzasCount(boost::lexical_cast<unsigned int>(*handledStanzasCount)); - } - catch (const boost::bad_lexical_cast &) { - } - } - getElementGeneric()->setResumeID(attributes.getAttribute("previd")); - } - ++level; + if (level == TopLevel) { + boost::optional<std::string> handledStanzasCount = attributes.getAttributeValue("h"); + if (handledStanzasCount) { + try { + getElementGeneric()->setHandledStanzasCount(boost::lexical_cast<unsigned int>(*handledStanzasCount)); + } + catch (const boost::bad_lexical_cast &) { + } + } + getElementGeneric()->setResumeID(attributes.getAttribute("previd")); + } + ++level; } void StreamResumedParser::handleEndElement(const std::string&, const std::string&) { - --level; + --level; } diff --git a/Swiften/Parser/StreamResumedParser.h b/Swiften/Parser/StreamResumedParser.h index f2377aa..ca89597 100644 --- a/Swiften/Parser/StreamResumedParser.h +++ b/Swiften/Parser/StreamResumedParser.h @@ -1,27 +1,28 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamResumed.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class StreamResumedParser : public GenericElementParser<StreamResumed> { - public: - StreamResumedParser(); - ~StreamResumedParser(); + class SWIFTEN_API StreamResumedParser : public GenericElementParser<StreamResumed> { + public: + StreamResumedParser(); + ~StreamResumedParser(); - virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); - virtual void handleEndElement(const std::string&, const std::string&); + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&); + virtual void handleEndElement(const std::string&, const std::string&); - private: - enum Level { - TopLevel = 0 - }; - int level; - }; + private: + enum Level { + TopLevel = 0 + }; + int level; + }; } diff --git a/Swiften/Parser/TLSProceedParser.h b/Swiften/Parser/TLSProceedParser.h index d36f088..da6cfd1 100644 --- a/Swiften/Parser/TLSProceedParser.h +++ b/Swiften/Parser/TLSProceedParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/TLSProceed.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class TLSProceedParser : public GenericElementParser<TLSProceed> { - public: - TLSProceedParser() : GenericElementParser<TLSProceed>() {} - }; + class SWIFTEN_API TLSProceedParser : public GenericElementParser<TLSProceed> { + public: + TLSProceedParser() : GenericElementParser<TLSProceed>() {} + }; } diff --git a/Swiften/Parser/Tree/NullParserElement.cpp b/Swiften/Parser/Tree/NullParserElement.cpp index 7dda9c3..7b52926 100644 --- a/Swiften/Parser/Tree/NullParserElement.cpp +++ b/Swiften/Parser/Tree/NullParserElement.cpp @@ -1,13 +1,13 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/Tree/NullParserElement.h> namespace Swift { -boost::shared_ptr<NullParserElement> NullParserElement::element = boost::make_shared<NullParserElement>(); +std::shared_ptr<NullParserElement> NullParserElement::element = std::make_shared<NullParserElement>(); } diff --git a/Swiften/Parser/Tree/NullParserElement.h b/Swiften/Parser/Tree/NullParserElement.h index 8dd9bc1..320e098 100644 --- a/Swiften/Parser/Tree/NullParserElement.h +++ b/Swiften/Parser/Tree/NullParserElement.h @@ -1,21 +1,23 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + +#include <Swiften/Base/API.h> #include <Swiften/Parser/Tree/ParserElement.h> namespace Swift { - class NullParserElement : public ParserElement { - public: - NullParserElement() : ParserElement("", "", AttributeMap()) {} + class SWIFTEN_API NullParserElement : public ParserElement { + public: + NullParserElement() : ParserElement("", "", AttributeMap()) {} - virtual operator bool() { return false; } + virtual operator bool() { return false; } - static boost::shared_ptr<NullParserElement> element; - }; + static std::shared_ptr<NullParserElement> element; + }; } diff --git a/Swiften/Parser/Tree/ParserElement.cpp b/Swiften/Parser/Tree/ParserElement.cpp index e5f8bc8..988bc13 100644 --- a/Swiften/Parser/Tree/ParserElement.cpp +++ b/Swiften/Parser/Tree/ParserElement.cpp @@ -1,18 +1,13 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/Tree/ParserElement.h> -#include <Swiften/Parser/Tree/NullParserElement.h> - -#include <iostream> -#include <boost/lambda/lambda.hpp> -#include <boost/lambda/bind.hpp> -namespace lambda = boost::lambda; +#include <Swiften/Parser/Tree/NullParserElement.h> namespace Swift { @@ -23,26 +18,27 @@ ParserElement::~ParserElement() { } ParserElement::ref ParserElement::addChild(const std::string& name, const std::string& xmlns, const AttributeMap& attributes) { - ParserElement::ref child = boost::make_shared<ParserElement>(name, xmlns, attributes); - children_.push_back(child); - return child; + ParserElement::ref child = std::make_shared<ParserElement>(name, xmlns, attributes); + children_.push_back(child); + return child; } void ParserElement::appendCharacterData(const std::string& data) { - text_ += data; + text_ += data; } std::vector<ParserElement::ref> ParserElement::getChildren(const std::string& name, const std::string& xmlns) const { - std::vector<ParserElement::ref> result; - std::remove_copy_if(children_.begin(), children_.end(), std::back_inserter(result), - lambda::bind(&ParserElement::getName, *lambda::_1) != name || lambda::bind(&ParserElement::getNamespace, *lambda::_1) != xmlns); - return result; + std::vector<ParserElement::ref> result; + std::remove_copy_if(children_.begin(), children_.end(), std::back_inserter(result), [&](const ParserElement::ref& element) { + return (element->getName() != name) || (element->getNamespace() != xmlns); + }); + return result; } ParserElement::ref ParserElement::getChild(const std::string& name, const std::string& xmlns) const { - std::vector<ParserElement::ref> results = getChildren(name, xmlns); - ParserElement::ref result = results.empty() ? NullParserElement::element : results[0]; - return result; + std::vector<ParserElement::ref> results = getChildren(name, xmlns); + ParserElement::ref result = results.empty() ? NullParserElement::element : results[0]; + return result; } } diff --git a/Swiften/Parser/Tree/ParserElement.h b/Swiften/Parser/Tree/ParserElement.h index 6be0631..38f2dee 100644 --- a/Swiften/Parser/Tree/ParserElement.h +++ b/Swiften/Parser/Tree/ParserElement.h @@ -1,49 +1,50 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <string> #include <vector> + +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Parser/AttributeMap.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> namespace Swift { - class SWIFTEN_API ParserElement { - public: - typedef boost::shared_ptr<ParserElement> ref; - - ParserElement(const std::string& name, const std::string& xmlns, const AttributeMap& attributes); - virtual ~ParserElement(); - - const std::string& getText() const { return text_; } - const std::string& getName() const { return name_; } - const std::string& getNamespace() const { return xmlns_; } - const AttributeMap& getAttributes() const { return attributes_; } - - ParserElement::ref addChild(const std::string& name, const std::string& xmlns, const AttributeMap& attributes); - void appendCharacterData(const std::string& data); - - std::vector<ParserElement::ref> getChildren(const std::string& name, const std::string& xmlns) const; - const std::vector<ParserElement::ref>& getAllChildren() const {return children_;} - ParserElement::ref getChild(const std::string& name, const std::string& xmlns) const; - - virtual operator bool() { - return true; - } - - private: - std::vector<ParserElement::ref> children_; - std::string name_; - std::string xmlns_; - AttributeMap attributes_; - std::string text_; - }; + class SWIFTEN_API ParserElement { + public: + typedef std::shared_ptr<ParserElement> ref; + + ParserElement(const std::string& name, const std::string& xmlns, const AttributeMap& attributes); + virtual ~ParserElement(); + + const std::string& getText() const { return text_; } + const std::string& getName() const { return name_; } + const std::string& getNamespace() const { return xmlns_; } + const AttributeMap& getAttributes() const { return attributes_; } + + ParserElement::ref addChild(const std::string& name, const std::string& xmlns, const AttributeMap& attributes); + void appendCharacterData(const std::string& data); + + std::vector<ParserElement::ref> getChildren(const std::string& name, const std::string& xmlns) const; + const std::vector<ParserElement::ref>& getAllChildren() const {return children_;} + ParserElement::ref getChild(const std::string& name, const std::string& xmlns) const; + + virtual operator bool() { + return true; + } + + private: + std::vector<ParserElement::ref> children_; + std::string name_; + std::string xmlns_; + AttributeMap attributes_; + std::string text_; + }; } diff --git a/Swiften/Parser/Tree/TreeReparser.cpp b/Swiften/Parser/Tree/TreeReparser.cpp index 9d09831..6993d73 100644 --- a/Swiften/Parser/Tree/TreeReparser.cpp +++ b/Swiften/Parser/Tree/TreeReparser.cpp @@ -1,48 +1,48 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/Tree/TreeReparser.h> -#include <boost/lexical_cast.hpp> -#include <utility> #include <deque> +#include <utility> + +#include <boost/lexical_cast.hpp> -#include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Parser/PayloadParserFactory.h> -#include <Swiften/Parser/PayloadParser.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Elements/MUCOccupant.h> +#include <Swiften/Parser/PayloadParser.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> namespace Swift { typedef std::pair<ParserElement::ref, bool> ElementState; -boost::shared_ptr<Payload> TreeReparser::parseTree(ParserElement::ref root, PayloadParserFactoryCollection* collection) { - PayloadParser* parser = collection->getPayloadParserFactory(root->getName(), root->getNamespace(), root->getAttributes())->createPayloadParser(); - std::deque<ElementState > stack; - stack.push_back(ElementState(root, true)); - while (!stack.empty()) { - ElementState current = stack.back(); - stack.pop_back(); - if (current.second) { - stack.push_back(ElementState(current.first, false)); - parser->handleStartElement(current.first->getName(), current.first->getNamespace(), current.first->getAttributes()); - foreach(ParserElement::ref child, current.first->getAllChildren()) { - stack.push_back(ElementState(child, true)); - } - } else { - parser->handleCharacterData(current.first->getText()); - parser->handleEndElement(current.first->getName(), current.first->getNamespace()); - } - - } - - boost::shared_ptr<Payload> payload = parser->getPayload(); - delete parser; - return payload; +std::shared_ptr<Payload> TreeReparser::parseTree(ParserElement::ref root, PayloadParserFactoryCollection* collection) { + PayloadParser* parser = collection->getPayloadParserFactory(root->getName(), root->getNamespace(), root->getAttributes())->createPayloadParser(); + std::deque<ElementState > stack; + stack.push_back(ElementState(root, true)); + while (!stack.empty()) { + ElementState current = stack.back(); + stack.pop_back(); + if (current.second) { + stack.push_back(ElementState(current.first, false)); + parser->handleStartElement(current.first->getName(), current.first->getNamespace(), current.first->getAttributes()); + for (const auto& child : current.first->getAllChildren()) { + stack.push_back(ElementState(child, true)); + } + } else { + parser->handleCharacterData(current.first->getText()); + parser->handleEndElement(current.first->getName(), current.first->getNamespace()); + } + + } + + std::shared_ptr<Payload> payload = parser->getPayload(); + delete parser; + return payload; } } diff --git a/Swiften/Parser/Tree/TreeReparser.h b/Swiften/Parser/Tree/TreeReparser.h index 212c518..435922b 100644 --- a/Swiften/Parser/Tree/TreeReparser.h +++ b/Swiften/Parser/Tree/TreeReparser.h @@ -1,19 +1,20 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Parser/GenericPayloadTreeParser.h> #include <Swiften/Parser/PayloadParsers/MUCItemParser.h> namespace Swift { - class PayloadParserFactoryCollection; - class TreeReparser { - public: - static boost::shared_ptr<Payload> parseTree(ParserElement::ref root, PayloadParserFactoryCollection* collection); + class PayloadParserFactoryCollection; + class SWIFTEN_API TreeReparser { + public: + static std::shared_ptr<Payload> parseTree(ParserElement::ref root, PayloadParserFactoryCollection* collection); - }; + }; } diff --git a/Swiften/Parser/UnitTest/AttributeMapTest.cpp b/Swiften/Parser/UnitTest/AttributeMapTest.cpp index d6c3c01..d9335c1 100644 --- a/Swiften/Parser/UnitTest/AttributeMapTest.cpp +++ b/Swiften/Parser/UnitTest/AttributeMapTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,73 +13,90 @@ using namespace Swift; class AttributeMapTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(AttributeMapTest); - CPPUNIT_TEST(testGetAttribute_Namespaced); - CPPUNIT_TEST(testGetBoolAttribute_True); - CPPUNIT_TEST(testGetBoolAttribute_1); - CPPUNIT_TEST(testGetBoolAttribute_False); - CPPUNIT_TEST(testGetBoolAttribute_0); - CPPUNIT_TEST(testGetBoolAttribute_Invalid); - CPPUNIT_TEST(testGetBoolAttribute_UnknownWithDefaultTrue); - CPPUNIT_TEST(testGetBoolAttribute_UnknownWithDefaultFalse); - CPPUNIT_TEST_SUITE_END(); - - public: - void testGetAttribute_Namespaced() { - AttributeMap testling; - testling.addAttribute("lang", "", "nl"); - testling.addAttribute("lang", "http://www.w3.org/XML/1998/namespace", "en"); - testling.addAttribute("lang", "", "fr"); - - CPPUNIT_ASSERT_EQUAL(std::string("en"), testling.getAttribute("lang", "http://www.w3.org/XML/1998/namespace")); - } - - void testGetBoolAttribute_True() { - AttributeMap testling; - testling.addAttribute("foo", "", "true"); - - CPPUNIT_ASSERT(testling.getBoolAttribute("foo")); - } - - void testGetBoolAttribute_1() { - AttributeMap testling; - testling.addAttribute("foo", "", "1"); - - CPPUNIT_ASSERT(testling.getBoolAttribute("foo")); - } - - void testGetBoolAttribute_False() { - AttributeMap testling; - testling.addAttribute("foo", "", "false"); - - CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true)); - } - - void testGetBoolAttribute_0() { - AttributeMap testling; - testling.addAttribute("foo", "", "0"); - - CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true)); - } - - void testGetBoolAttribute_Invalid() { - AttributeMap testling; - testling.addAttribute("foo", "", "bla"); - - CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true)); - } - - void testGetBoolAttribute_UnknownWithDefaultTrue() { - AttributeMap testling; - - CPPUNIT_ASSERT(testling.getBoolAttribute("foo", true)); - } - - void testGetBoolAttribute_UnknownWithDefaultFalse() { - AttributeMap testling; - - CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", false)); - } + CPPUNIT_TEST_SUITE(AttributeMapTest); + CPPUNIT_TEST(testGetAttribute_Namespaced); + CPPUNIT_TEST(testGetAttribute_Namespaced_Prefix); + CPPUNIT_TEST(testGetBoolAttribute_True); + CPPUNIT_TEST(testGetBoolAttribute_1); + CPPUNIT_TEST(testGetBoolAttribute_False); + CPPUNIT_TEST(testGetBoolAttribute_0); + CPPUNIT_TEST(testGetBoolAttribute_Invalid); + CPPUNIT_TEST(testGetBoolAttribute_UnknownWithDefaultTrue); + CPPUNIT_TEST(testGetBoolAttribute_UnknownWithDefaultFalse); + CPPUNIT_TEST_SUITE_END(); + + public: + void testGetAttribute_Namespaced() { + AttributeMap testling; + testling.addAttribute("lang", "", "nl"); + testling.addAttribute("lang", "http://www.w3.org/XML/1998/namespace", "en"); + testling.addAttribute("lang", "", "fr"); + + CPPUNIT_ASSERT_EQUAL(std::string("en"), testling.getAttribute("lang", "http://www.w3.org/XML/1998/namespace")); + } + + void testGetAttribute_Namespaced_Prefix() { + AttributeMap testling; + testling.addAttribute("lang", "", "prefix", "nl"); + testling.addAttribute("lang", "http://www.w3.org/XML/1998/namespace", "prefix", "en"); + testling.addAttribute("lang", "", "prefix", "fr"); + + CPPUNIT_ASSERT_EQUAL(std::string("en"), testling.getAttribute("lang", "http://www.w3.org/XML/1998/namespace")); + const auto& entries = testling.getEntries(); + auto it = std::find_if(entries.begin(), entries.end(), [](const AttributeMap::Entry& e) { + return e.getValue() == "en"; + }); + const bool found = it != entries.end(); + CPPUNIT_ASSERT_EQUAL(true, found); + CPPUNIT_ASSERT_EQUAL(std::string("prefix"), it->getAttribute().getPrefix()); + } + + void testGetBoolAttribute_True() { + AttributeMap testling; + testling.addAttribute("foo", "", "true"); + + CPPUNIT_ASSERT(testling.getBoolAttribute("foo")); + } + + void testGetBoolAttribute_1() { + AttributeMap testling; + testling.addAttribute("foo", "", "1"); + + CPPUNIT_ASSERT(testling.getBoolAttribute("foo")); + } + + void testGetBoolAttribute_False() { + AttributeMap testling; + testling.addAttribute("foo", "", "false"); + + CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true)); + } + + void testGetBoolAttribute_0() { + AttributeMap testling; + testling.addAttribute("foo", "", "0"); + + CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true)); + } + + void testGetBoolAttribute_Invalid() { + AttributeMap testling; + testling.addAttribute("foo", "", "bla"); + + CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true)); + } + + void testGetBoolAttribute_UnknownWithDefaultTrue() { + AttributeMap testling; + + CPPUNIT_ASSERT(testling.getBoolAttribute("foo", true)); + } + + void testGetBoolAttribute_UnknownWithDefaultFalse() { + AttributeMap testling; + + CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", false)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(AttributeMapTest); diff --git a/Swiften/Parser/UnitTest/BOSHBodyExtractorTest.cpp b/Swiften/Parser/UnitTest/BOSHBodyExtractorTest.cpp index fc7d17b..f7ed80f 100644 --- a/Swiften/Parser/UnitTest/BOSHBodyExtractorTest.cpp +++ b/Swiften/Parser/UnitTest/BOSHBodyExtractorTest.cpp @@ -1,104 +1,104 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PlatformXMLParserFactory.h> #include <Swiften/Parser/BOSHBodyExtractor.h> +#include <Swiften/Parser/PlatformXMLParserFactory.h> using namespace Swift; class BOSHBodyExtractorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(BOSHBodyExtractorTest); - CPPUNIT_TEST(testGetBody); - CPPUNIT_TEST(testGetBody_EmptyContent); - CPPUNIT_TEST(testGetBody_EmptyContent2); - CPPUNIT_TEST(testGetBody_EmptyElementEmptyContent); - CPPUNIT_TEST(testGetBody_InvalidStartTag); - CPPUNIT_TEST(testGetBody_InvalidStartTag2); - CPPUNIT_TEST(testGetBody_IncompleteStartTag); - CPPUNIT_TEST(testGetBody_InvalidEndTag); - CPPUNIT_TEST(testGetBody_InvalidEndTag2); - CPPUNIT_TEST_SUITE_END(); - - public: - void testGetBody() { - BOSHBodyExtractor testling(&parserFactory, createByteArray( - "<body a1='a\"1' a2=\"a'2\" boo='bar' >" - "foo <message> <body> bar" - "</body > ")); - - CPPUNIT_ASSERT(testling.getBody()); - CPPUNIT_ASSERT_EQUAL(std::string("a\"1"), testling.getBody()->attributes.getAttribute("a1")); - CPPUNIT_ASSERT_EQUAL(std::string("foo <message> <body> bar"), testling.getBody()->content); - } - - void testGetBody_EmptyContent() { - BOSHBodyExtractor testling(&parserFactory, createByteArray( - "<body foo='bar'/>")); - - CPPUNIT_ASSERT(testling.getBody()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getBody()->attributes.getAttribute("foo")); - CPPUNIT_ASSERT(testling.getBody()->content.empty()); - } - - void testGetBody_EmptyContent2() { - BOSHBodyExtractor testling(&parserFactory, createByteArray( - "<body foo='bar'></body>")); - - CPPUNIT_ASSERT(testling.getBody()); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getBody()->attributes.getAttribute("foo")); - CPPUNIT_ASSERT(testling.getBody()->content.empty()); - } - - void testGetBody_EmptyElementEmptyContent() { - BOSHBodyExtractor testling(&parserFactory, createByteArray( - "<body/>")); - - CPPUNIT_ASSERT(testling.getBody()); - } - - void testGetBody_InvalidStartTag() { - BOSHBodyExtractor testling(&parserFactory, createByteArray( - "<bodi></body>")); - - CPPUNIT_ASSERT(!testling.getBody()); - } - - void testGetBody_InvalidStartTag2() { - BOSHBodyExtractor testling(&parserFactory, createByteArray( - "<bodyy></body>")); - - CPPUNIT_ASSERT(!testling.getBody()); - } - - void testGetBody_IncompleteStartTag() { - BOSHBodyExtractor testling(&parserFactory, createByteArray( - "<body")); - - CPPUNIT_ASSERT(!testling.getBody()); - } - - void testGetBody_InvalidEndTag() { - BOSHBodyExtractor testling(&parserFactory, createByteArray( - "<body></bodi>")); - - CPPUNIT_ASSERT(!testling.getBody()); - } - - void testGetBody_InvalidEndTag2() { - BOSHBodyExtractor testling(&parserFactory, createByteArray( - "<body><b/body>")); - - CPPUNIT_ASSERT(!testling.getBody()); - } - - private: - PlatformXMLParserFactory parserFactory; + CPPUNIT_TEST_SUITE(BOSHBodyExtractorTest); + CPPUNIT_TEST(testGetBody); + CPPUNIT_TEST(testGetBody_EmptyContent); + CPPUNIT_TEST(testGetBody_EmptyContent2); + CPPUNIT_TEST(testGetBody_EmptyElementEmptyContent); + CPPUNIT_TEST(testGetBody_InvalidStartTag); + CPPUNIT_TEST(testGetBody_InvalidStartTag2); + CPPUNIT_TEST(testGetBody_IncompleteStartTag); + CPPUNIT_TEST(testGetBody_InvalidEndTag); + CPPUNIT_TEST(testGetBody_InvalidEndTag2); + CPPUNIT_TEST_SUITE_END(); + + public: + void testGetBody() { + BOSHBodyExtractor testling(&parserFactory, createByteArray( + "<body a1='a\"1' a2=\"a'2\" boo='bar' >" + "foo <message> <body> bar" + "</body > ")); + + CPPUNIT_ASSERT(testling.getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("a\"1"), testling.getBody()->attributes.getAttribute("a1")); + CPPUNIT_ASSERT_EQUAL(std::string("foo <message> <body> bar"), testling.getBody()->content); + } + + void testGetBody_EmptyContent() { + BOSHBodyExtractor testling(&parserFactory, createByteArray( + "<body foo='bar'/>")); + + CPPUNIT_ASSERT(testling.getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getBody()->attributes.getAttribute("foo")); + CPPUNIT_ASSERT(testling.getBody()->content.empty()); + } + + void testGetBody_EmptyContent2() { + BOSHBodyExtractor testling(&parserFactory, createByteArray( + "<body foo='bar'></body>")); + + CPPUNIT_ASSERT(testling.getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getBody()->attributes.getAttribute("foo")); + CPPUNIT_ASSERT(testling.getBody()->content.empty()); + } + + void testGetBody_EmptyElementEmptyContent() { + BOSHBodyExtractor testling(&parserFactory, createByteArray( + "<body/>")); + + CPPUNIT_ASSERT(testling.getBody()); + } + + void testGetBody_InvalidStartTag() { + BOSHBodyExtractor testling(&parserFactory, createByteArray( + "<bodi></body>")); + + CPPUNIT_ASSERT(!testling.getBody()); + } + + void testGetBody_InvalidStartTag2() { + BOSHBodyExtractor testling(&parserFactory, createByteArray( + "<bodyy></body>")); + + CPPUNIT_ASSERT(!testling.getBody()); + } + + void testGetBody_IncompleteStartTag() { + BOSHBodyExtractor testling(&parserFactory, createByteArray( + "<body")); + + CPPUNIT_ASSERT(!testling.getBody()); + } + + void testGetBody_InvalidEndTag() { + BOSHBodyExtractor testling(&parserFactory, createByteArray( + "<body></bodi>")); + + CPPUNIT_ASSERT(!testling.getBody()); + } + + void testGetBody_InvalidEndTag2() { + BOSHBodyExtractor testling(&parserFactory, createByteArray( + "<body><b/body>")); + + CPPUNIT_ASSERT(!testling.getBody()); + } + + private: + PlatformXMLParserFactory parserFactory; }; CPPUNIT_TEST_SUITE_REGISTRATION(BOSHBodyExtractorTest); diff --git a/Swiften/Parser/UnitTest/ElementParserTester.h b/Swiften/Parser/UnitTest/ElementParserTester.h index 76b8870..299fb50 100644 --- a/Swiften/Parser/UnitTest/ElementParserTester.h +++ b/Swiften/Parser/UnitTest/ElementParserTester.h @@ -1,14 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once - #include <Swiften/Parser/UnitTest/ParserTester.h> namespace Swift { - typedef ParserTester<ElementParser> ElementParserTester; + typedef ParserTester<ElementParser> ElementParserTester; } diff --git a/Swiften/Parser/UnitTest/EnumParserTest.cpp b/Swiften/Parser/UnitTest/EnumParserTest.cpp index 44a30c0..82b3fa1 100644 --- a/Swiften/Parser/UnitTest/EnumParserTest.cpp +++ b/Swiften/Parser/UnitTest/EnumParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -12,25 +12,25 @@ using namespace Swift; class EnumParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(EnumParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_NoValue); - CPPUNIT_TEST_SUITE_END(); - - public: - enum MyEnum { - MyValue1, - MyValue2, - MyValue3 - }; - - void testParse() { - CPPUNIT_ASSERT(MyValue2 == EnumParser<MyEnum>()(MyValue1, "my-value-1")(MyValue2, "my-value-2")(MyValue3, "my-value-3").parse("my-value-2")); - } - - void testParse_NoValue() { - CPPUNIT_ASSERT(!EnumParser<MyEnum>()(MyValue1, "my-value-1")(MyValue2, "my-value-2")(MyValue3, "my-value-3").parse("my-value-4")); - } + CPPUNIT_TEST_SUITE(EnumParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_NoValue); + CPPUNIT_TEST_SUITE_END(); + + public: + enum MyEnum { + MyValue1, + MyValue2, + MyValue3 + }; + + void testParse() { + CPPUNIT_ASSERT(MyValue2 == EnumParser<MyEnum>()(MyValue1, "my-value-1")(MyValue2, "my-value-2")(MyValue3, "my-value-3").parse("my-value-2")); + } + + void testParse_NoValue() { + CPPUNIT_ASSERT(!EnumParser<MyEnum>()(MyValue1, "my-value-1")(MyValue2, "my-value-2")(MyValue3, "my-value-3").parse("my-value-4")); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(EnumParserTest); diff --git a/Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp b/Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp index 93d4e7f..cd94ed8 100644 --- a/Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp +++ b/Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp @@ -1,16 +1,16 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Base/Platform.h> +#include <Swiften/Elements/RawXMLPayload.h> #include <Swiften/Parser/GenericPayloadTreeParser.h> #include <Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h> -#include <Swiften/Elements/RawXMLPayload.h> using namespace Swift; @@ -22,44 +22,44 @@ template class __declspec(dllimport) Swift::GenericPayloadParser<RawXMLPayload>; #endif class GenericPayloadTreeParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(GenericPayloadTreeParserTest); - CPPUNIT_TEST(testTree); - CPPUNIT_TEST_SUITE_END(); - - public: - void testTree() { - MyParser testling; - - std::string data = "<topLevel xmlns='urn:test:top'><firstLevelInheritedEmpty/><firstLevelInherited><secondLevelMultiChildren num='1'/><secondLevelMultiChildren num='2'/></firstLevelInherited><firstLevelNS xmlns='urn:test:first'/></topLevel>"; - - PayloadParserTester tester(&testling); - tester.parse(data); - - ParserElement::ref tree = testling.tree; - - CPPUNIT_ASSERT_EQUAL(std::string("topLevel"), tree->getName()); - CPPUNIT_ASSERT_EQUAL(std::string("urn:test:top"), tree->getNamespace()); - CPPUNIT_ASSERT(tree->getChild("firstLevelInheritedEmpty", "urn:test:top")); - CPPUNIT_ASSERT(!*tree->getChild("firstLevelInheritedEmpty", "")); - CPPUNIT_ASSERT(tree->getChild("firstLevelInherited", "urn:test:top")); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top").size()); - CPPUNIT_ASSERT_EQUAL(std::string("1"), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top")[0]->getAttributes().getAttribute("num")); - CPPUNIT_ASSERT_EQUAL(std::string("2"), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top")[1]->getAttributes().getAttribute("num")); - CPPUNIT_ASSERT(tree->getChild("firstLevelNS", "urn:test:first")); - } - - private: - - - class MyParser : public GenericPayloadTreeParser<RawXMLPayload> - { - public: - virtual ~MyParser() {} - virtual void handleTree(ParserElement::ref root) { - tree = root; - } - ParserElement::ref tree; - }; + CPPUNIT_TEST_SUITE(GenericPayloadTreeParserTest); + CPPUNIT_TEST(testTree); + CPPUNIT_TEST_SUITE_END(); + + public: + void testTree() { + MyParser testling; + + std::string data = "<topLevel xmlns='urn:test:top'><firstLevelInheritedEmpty/><firstLevelInherited><secondLevelMultiChildren num='1'/><secondLevelMultiChildren num='2'/></firstLevelInherited><firstLevelNS xmlns='urn:test:first'/></topLevel>"; + + PayloadParserTester tester(&testling); + tester.parse(data); + + ParserElement::ref tree = testling.tree; + + CPPUNIT_ASSERT_EQUAL(std::string("topLevel"), tree->getName()); + CPPUNIT_ASSERT_EQUAL(std::string("urn:test:top"), tree->getNamespace()); + CPPUNIT_ASSERT(tree->getChild("firstLevelInheritedEmpty", "urn:test:top")); + CPPUNIT_ASSERT(!*tree->getChild("firstLevelInheritedEmpty", "")); + CPPUNIT_ASSERT(tree->getChild("firstLevelInherited", "urn:test:top")); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top").size()); + CPPUNIT_ASSERT_EQUAL(std::string("1"), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top")[0]->getAttributes().getAttribute("num")); + CPPUNIT_ASSERT_EQUAL(std::string("2"), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top")[1]->getAttributes().getAttribute("num")); + CPPUNIT_ASSERT(tree->getChild("firstLevelNS", "urn:test:first")); + } + + private: + + + class MyParser : public GenericPayloadTreeParser<RawXMLPayload> + { + public: + virtual ~MyParser() {} + virtual void handleTree(ParserElement::ref root) { + tree = root; + } + ParserElement::ref tree; + }; }; diff --git a/Swiften/Parser/UnitTest/IQParserTest.cpp b/Swiften/Parser/UnitTest/IQParserTest.cpp index 3c86a5d..5c07757 100644 --- a/Swiften/Parser/UnitTest/IQParserTest.cpp +++ b/Swiften/Parser/UnitTest/IQParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,60 +14,60 @@ using namespace Swift; class IQParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IQParserTest); - CPPUNIT_TEST(testParse_Set); - CPPUNIT_TEST(testParse_Get); - CPPUNIT_TEST(testParse_Result); - CPPUNIT_TEST(testParse_Error); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(IQParserTest); + CPPUNIT_TEST(testParse_Set); + CPPUNIT_TEST(testParse_Get); + CPPUNIT_TEST(testParse_Result); + CPPUNIT_TEST(testParse_Error); + CPPUNIT_TEST_SUITE_END(); - public: - void setUp() { - factoryCollection_ = new PayloadParserFactoryCollection(); - } + public: + void setUp() { + factoryCollection_ = new PayloadParserFactoryCollection(); + } - void tearDown() { - delete factoryCollection_; - } + void tearDown() { + delete factoryCollection_; + } - void testParse_Set() { - IQParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Set() { + IQParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<iq type=\"set\"/>")); + CPPUNIT_ASSERT(parser.parse("<iq type=\"set\"/>")); - CPPUNIT_ASSERT_EQUAL(IQ::Set, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(IQ::Set, testling.getStanzaGeneric()->getType()); + } - void testParse_Get() { - IQParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Get() { + IQParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<iq type=\"get\"/>")); + CPPUNIT_ASSERT(parser.parse("<iq type=\"get\"/>")); - CPPUNIT_ASSERT_EQUAL(IQ::Get, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(IQ::Get, testling.getStanzaGeneric()->getType()); + } - void testParse_Result() { - IQParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Result() { + IQParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<iq type=\"result\"/>")); + CPPUNIT_ASSERT(parser.parse("<iq type=\"result\"/>")); - CPPUNIT_ASSERT_EQUAL(IQ::Result, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(IQ::Result, testling.getStanzaGeneric()->getType()); + } - void testParse_Error() { - IQParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Error() { + IQParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<iq type=\"error\"/>")); + CPPUNIT_ASSERT(parser.parse("<iq type=\"error\"/>")); - CPPUNIT_ASSERT_EQUAL(IQ::Error, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(IQ::Error, testling.getStanzaGeneric()->getType()); + } - private: - PayloadParserFactoryCollection* factoryCollection_; + private: + PayloadParserFactoryCollection* factoryCollection_; }; CPPUNIT_TEST_SUITE_REGISTRATION(IQParserTest); diff --git a/Swiften/Parser/UnitTest/MessageParserTest.cpp b/Swiften/Parser/UnitTest/MessageParserTest.cpp index 8ab59ed..dc55711 100644 --- a/Swiften/Parser/UnitTest/MessageParserTest.cpp +++ b/Swiften/Parser/UnitTest/MessageParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,70 +14,70 @@ using namespace Swift; class MessageParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(MessageParserTest); - CPPUNIT_TEST(testParse_Normal); - CPPUNIT_TEST(testParse_Chat); - CPPUNIT_TEST(testParse_Error); - CPPUNIT_TEST(testParse_Groupchat); - CPPUNIT_TEST(testParse_Headline); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(MessageParserTest); + CPPUNIT_TEST(testParse_Normal); + CPPUNIT_TEST(testParse_Chat); + CPPUNIT_TEST(testParse_Error); + CPPUNIT_TEST(testParse_Groupchat); + CPPUNIT_TEST(testParse_Headline); + CPPUNIT_TEST_SUITE_END(); - public: - void setUp() { - factoryCollection_ = new PayloadParserFactoryCollection(); - } + public: + void setUp() { + factoryCollection_ = new PayloadParserFactoryCollection(); + } - void tearDown() { - delete factoryCollection_; - } + void tearDown() { + delete factoryCollection_; + } - void testParse_Chat() { - MessageParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Chat() { + MessageParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<message type=\"chat\"/>")); + CPPUNIT_ASSERT(parser.parse("<message type=\"chat\"/>")); - CPPUNIT_ASSERT_EQUAL(Message::Chat, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Message::Chat, testling.getStanzaGeneric()->getType()); + } - void testParse_Groupchat() { - MessageParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Groupchat() { + MessageParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<message type=\"groupchat\"/>")); + CPPUNIT_ASSERT(parser.parse("<message type=\"groupchat\"/>")); - CPPUNIT_ASSERT_EQUAL(Message::Groupchat, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Message::Groupchat, testling.getStanzaGeneric()->getType()); + } - void testParse_Error() { - MessageParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Error() { + MessageParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<message type=\"error\"/>")); + CPPUNIT_ASSERT(parser.parse("<message type=\"error\"/>")); - CPPUNIT_ASSERT_EQUAL(Message::Error, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Message::Error, testling.getStanzaGeneric()->getType()); + } - void testParse_Headline() { - MessageParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Headline() { + MessageParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<message type=\"headline\"/>")); + CPPUNIT_ASSERT(parser.parse("<message type=\"headline\"/>")); - CPPUNIT_ASSERT_EQUAL(Message::Headline, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Message::Headline, testling.getStanzaGeneric()->getType()); + } - void testParse_Normal() { - MessageParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Normal() { + MessageParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<message/>")); + CPPUNIT_ASSERT(parser.parse("<message/>")); - CPPUNIT_ASSERT_EQUAL(Message::Normal, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Message::Normal, testling.getStanzaGeneric()->getType()); + } - private: - PayloadParserFactoryCollection* factoryCollection_; + private: + PayloadParserFactoryCollection* factoryCollection_; }; CPPUNIT_TEST_SUITE_REGISTRATION(MessageParserTest); diff --git a/Swiften/Parser/UnitTest/ParserTester.h b/Swiften/Parser/UnitTest/ParserTester.h index 73f013c..aa01d40 100644 --- a/Swiften/Parser/UnitTest/ParserTester.h +++ b/Swiften/Parser/UnitTest/ParserTester.h @@ -1,48 +1,42 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once - -#include <Swiften/Parser/XMLParserClient.h> #include <Swiften/Parser/PlatformXMLParserFactory.h> #include <Swiften/Parser/XMLParser.h> +#include <Swiften/Parser/XMLParserClient.h> namespace Swift { - class XMLParser; - - template<typename ParserType> - class ParserTester : public XMLParserClient { - public: - ParserTester(ParserType* parser) : parser_(parser) { - xmlParser_ = PlatformXMLParserFactory().createXMLParser(this); - } - - ~ParserTester() { - delete xmlParser_; - } - - bool parse(const std::string& data) { - return xmlParser_->parse(data); - } - - virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - parser_->handleStartElement(element, ns, attributes); - } - - virtual void handleEndElement(const std::string& element, const std::string& ns) { - parser_->handleEndElement(element, ns); - } - - virtual void handleCharacterData(const std::string& data) { - parser_->handleCharacterData(data); - } - - private: - XMLParser* xmlParser_; - ParserType* parser_; - }; + class XMLParser; + + template<typename ParserType> + class ParserTester : public XMLParserClient { + public: + ParserTester(ParserType* parser) : xmlParser_(PlatformXMLParserFactory().createXMLParser(this)), parser_(parser) { + } + + bool parse(const std::string& data) { + return xmlParser_->parse(data); + } + + virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + parser_->handleStartElement(element, ns, attributes); + } + + virtual void handleEndElement(const std::string& element, const std::string& ns) { + parser_->handleEndElement(element, ns); + } + + virtual void handleCharacterData(const std::string& data) { + parser_->handleCharacterData(data); + } + + private: + std::unique_ptr<XMLParser> xmlParser_; + ParserType* parser_; + }; } diff --git a/Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp b/Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp index fea64e2..f7234d9 100644 --- a/Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp +++ b/Swiften/Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp @@ -1,103 +1,103 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PayloadParserFactoryCollection.h> #include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> using namespace Swift; class PayloadParserFactoryCollectionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PayloadParserFactoryCollectionTest); - CPPUNIT_TEST(testGetPayloadParserFactory); - CPPUNIT_TEST(testGetPayloadParserFactory_NoMatchingFactory); - CPPUNIT_TEST(testGetPayloadParserFactory_TwoMatchingFactories); - CPPUNIT_TEST(testGetPayloadParserFactory_MatchWithDefaultFactory); - CPPUNIT_TEST(testGetPayloadParserFactory_NoMatchWithDefaultFactory); - CPPUNIT_TEST_SUITE_END(); - - public: - PayloadParserFactoryCollectionTest() {} - - void setUp() { - } - - void tearDown() { - } - - void testGetPayloadParserFactory() { - PayloadParserFactoryCollection testling; - DummyFactory factory1("foo"); - testling.addFactory(&factory1); - DummyFactory factory2("bar"); - testling.addFactory(&factory2); - DummyFactory factory3("baz"); - testling.addFactory(&factory3); - - PayloadParserFactory* factory = testling.getPayloadParserFactory("bar", "", AttributeMap()); - - CPPUNIT_ASSERT(factory == &factory2); - } - - void testGetPayloadParserFactory_NoMatchingFactory() { - PayloadParserFactoryCollection testling; - DummyFactory factory("foo"); - - CPPUNIT_ASSERT(!testling.getPayloadParserFactory("bar", "", AttributeMap())); - } - - void testGetPayloadParserFactory_TwoMatchingFactories() { - PayloadParserFactoryCollection testling; - DummyFactory factory1("foo"); - testling.addFactory(&factory1); - DummyFactory factory2("foo"); - testling.addFactory(&factory2); - - PayloadParserFactory* factory = testling.getPayloadParserFactory("foo", "", AttributeMap()); - - CPPUNIT_ASSERT(factory == &factory2); - } - - void testGetPayloadParserFactory_MatchWithDefaultFactory() { - PayloadParserFactoryCollection testling; - DummyFactory factory1("foo"); - testling.addFactory(&factory1); - DummyFactory factory2; - testling.setDefaultFactory(&factory2); - - PayloadParserFactory* factory = testling.getPayloadParserFactory("foo", "", AttributeMap()); - - CPPUNIT_ASSERT(factory == &factory1); - } - - void testGetPayloadParserFactory_NoMatchWithDefaultFactory() { - PayloadParserFactoryCollection testling; - DummyFactory factory1("foo"); - testling.addFactory(&factory1); - DummyFactory factory2; - testling.setDefaultFactory(&factory2); - - PayloadParserFactory* factory = testling.getPayloadParserFactory("baz", "", AttributeMap()); - - CPPUNIT_ASSERT(factory == &factory2); - } - - - private: - struct DummyFactory : public PayloadParserFactory { - DummyFactory(const std::string& element = "") : element(element) {} - virtual bool canParse(const std::string& e, const std::string&, const AttributeMap&) const { - return element.empty() ? true : element == e; - } - virtual PayloadParser* createPayloadParser() { return NULL; } - std::string element; - }; + CPPUNIT_TEST_SUITE(PayloadParserFactoryCollectionTest); + CPPUNIT_TEST(testGetPayloadParserFactory); + CPPUNIT_TEST(testGetPayloadParserFactory_NoMatchingFactory); + CPPUNIT_TEST(testGetPayloadParserFactory_TwoMatchingFactories); + CPPUNIT_TEST(testGetPayloadParserFactory_MatchWithDefaultFactory); + CPPUNIT_TEST(testGetPayloadParserFactory_NoMatchWithDefaultFactory); + CPPUNIT_TEST_SUITE_END(); + + public: + PayloadParserFactoryCollectionTest() {} + + void setUp() { + } + + void tearDown() { + } + + void testGetPayloadParserFactory() { + PayloadParserFactoryCollection testling; + DummyFactory factory1("foo"); + testling.addFactory(&factory1); + DummyFactory factory2("bar"); + testling.addFactory(&factory2); + DummyFactory factory3("baz"); + testling.addFactory(&factory3); + + PayloadParserFactory* factory = testling.getPayloadParserFactory("bar", "", AttributeMap()); + + CPPUNIT_ASSERT(factory == &factory2); + } + + void testGetPayloadParserFactory_NoMatchingFactory() { + PayloadParserFactoryCollection testling; + DummyFactory factory("foo"); + + CPPUNIT_ASSERT(!testling.getPayloadParserFactory("bar", "", AttributeMap())); + } + + void testGetPayloadParserFactory_TwoMatchingFactories() { + PayloadParserFactoryCollection testling; + DummyFactory factory1("foo"); + testling.addFactory(&factory1); + DummyFactory factory2("foo"); + testling.addFactory(&factory2); + + PayloadParserFactory* factory = testling.getPayloadParserFactory("foo", "", AttributeMap()); + + CPPUNIT_ASSERT(factory == &factory2); + } + + void testGetPayloadParserFactory_MatchWithDefaultFactory() { + PayloadParserFactoryCollection testling; + DummyFactory factory1("foo"); + testling.addFactory(&factory1); + DummyFactory factory2; + testling.setDefaultFactory(&factory2); + + PayloadParserFactory* factory = testling.getPayloadParserFactory("foo", "", AttributeMap()); + + CPPUNIT_ASSERT(factory == &factory1); + } + + void testGetPayloadParserFactory_NoMatchWithDefaultFactory() { + PayloadParserFactoryCollection testling; + DummyFactory factory1("foo"); + testling.addFactory(&factory1); + DummyFactory factory2; + testling.setDefaultFactory(&factory2); + + PayloadParserFactory* factory = testling.getPayloadParserFactory("baz", "", AttributeMap()); + + CPPUNIT_ASSERT(factory == &factory2); + } + + + private: + struct DummyFactory : public PayloadParserFactory { + DummyFactory(const std::string& element = "") : element(element) {} + virtual bool canParse(const std::string& e, const std::string&, const AttributeMap&) const { + return element.empty() ? true : element == e; + } + virtual PayloadParser* createPayloadParser() { return nullptr; } + std::string element; + }; }; CPPUNIT_TEST_SUITE_REGISTRATION(PayloadParserFactoryCollectionTest); diff --git a/Swiften/Parser/UnitTest/PresenceParserTest.cpp b/Swiften/Parser/UnitTest/PresenceParserTest.cpp index f9d6cf6..2b2c242 100644 --- a/Swiften/Parser/UnitTest/PresenceParserTest.cpp +++ b/Swiften/Parser/UnitTest/PresenceParserTest.cpp @@ -1,113 +1,113 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/PresenceParser.h> #include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PresenceParser.h> #include <Swiften/Parser/UnitTest/StanzaParserTester.h> using namespace Swift; class PresenceParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PresenceParserTest); - CPPUNIT_TEST(testParse_Available); - CPPUNIT_TEST(testParse_Unavailable); - CPPUNIT_TEST(testParse_Subscribe); - CPPUNIT_TEST(testParse_Subscribed); - CPPUNIT_TEST(testParse_Unsubscribe); - CPPUNIT_TEST(testParse_Unsubscribed); - CPPUNIT_TEST(testParse_Probe); - CPPUNIT_TEST(testParse_Error); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(PresenceParserTest); + CPPUNIT_TEST(testParse_Available); + CPPUNIT_TEST(testParse_Unavailable); + CPPUNIT_TEST(testParse_Subscribe); + CPPUNIT_TEST(testParse_Subscribed); + CPPUNIT_TEST(testParse_Unsubscribe); + CPPUNIT_TEST(testParse_Unsubscribed); + CPPUNIT_TEST(testParse_Probe); + CPPUNIT_TEST(testParse_Error); + CPPUNIT_TEST_SUITE_END(); - public: - void setUp() { - factoryCollection_ = new PayloadParserFactoryCollection(); - } + public: + void setUp() { + factoryCollection_ = new PayloadParserFactoryCollection(); + } - void tearDown() { - delete factoryCollection_; - } + void tearDown() { + delete factoryCollection_; + } - void testParse_Available() { - PresenceParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Available() { + PresenceParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<presence/>")); + CPPUNIT_ASSERT(parser.parse("<presence/>")); - CPPUNIT_ASSERT_EQUAL(Presence::Available, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Presence::Available, testling.getStanzaGeneric()->getType()); + } - void testParse_Unavailable() { - PresenceParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Unavailable() { + PresenceParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<presence type=\"unavailable\"/>")); + CPPUNIT_ASSERT(parser.parse("<presence type=\"unavailable\"/>")); - CPPUNIT_ASSERT_EQUAL(Presence::Unavailable, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Presence::Unavailable, testling.getStanzaGeneric()->getType()); + } - void testParse_Probe() { - PresenceParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Probe() { + PresenceParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<presence type=\"probe\"/>")); + CPPUNIT_ASSERT(parser.parse("<presence type=\"probe\"/>")); - CPPUNIT_ASSERT_EQUAL(Presence::Probe, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Presence::Probe, testling.getStanzaGeneric()->getType()); + } - void testParse_Subscribe() { - PresenceParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Subscribe() { + PresenceParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<presence type=\"subscribe\"/>")); + CPPUNIT_ASSERT(parser.parse("<presence type=\"subscribe\"/>")); - CPPUNIT_ASSERT_EQUAL(Presence::Subscribe, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Presence::Subscribe, testling.getStanzaGeneric()->getType()); + } - void testParse_Subscribed() { - PresenceParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Subscribed() { + PresenceParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<presence type=\"subscribed\"/>")); + CPPUNIT_ASSERT(parser.parse("<presence type=\"subscribed\"/>")); - CPPUNIT_ASSERT_EQUAL(Presence::Subscribed, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Presence::Subscribed, testling.getStanzaGeneric()->getType()); + } - void testParse_Unsubscribe() { - PresenceParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Unsubscribe() { + PresenceParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<presence type=\"unsubscribe\"/>")); + CPPUNIT_ASSERT(parser.parse("<presence type=\"unsubscribe\"/>")); - CPPUNIT_ASSERT_EQUAL(Presence::Unsubscribe, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Presence::Unsubscribe, testling.getStanzaGeneric()->getType()); + } - void testParse_Unsubscribed() { - PresenceParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Unsubscribed() { + PresenceParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<presence type=\"unsubscribed\"/>")); + CPPUNIT_ASSERT(parser.parse("<presence type=\"unsubscribed\"/>")); - CPPUNIT_ASSERT_EQUAL(Presence::Unsubscribed, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Presence::Unsubscribed, testling.getStanzaGeneric()->getType()); + } - void testParse_Error() { - PresenceParser testling(factoryCollection_); - StanzaParserTester parser(&testling); + void testParse_Error() { + PresenceParser testling(factoryCollection_); + StanzaParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<presence type=\"error\"/>")); + CPPUNIT_ASSERT(parser.parse("<presence type=\"error\"/>")); - CPPUNIT_ASSERT_EQUAL(Presence::Error, testling.getStanzaGeneric()->getType()); - } + CPPUNIT_ASSERT_EQUAL(Presence::Error, testling.getStanzaGeneric()->getType()); + } - private: - PayloadParserFactoryCollection* factoryCollection_; + private: + PayloadParserFactoryCollection* factoryCollection_; }; CPPUNIT_TEST_SUITE_REGISTRATION(PresenceParserTest); diff --git a/Swiften/Parser/UnitTest/SerializingParserTest.cpp b/Swiften/Parser/UnitTest/SerializingParserTest.cpp index aef1dfb..1b4eb57 100644 --- a/Swiften/Parser/UnitTest/SerializingParserTest.cpp +++ b/Swiften/Parser/UnitTest/SerializingParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -14,51 +14,51 @@ using namespace Swift; class SerializingParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SerializingParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_Empty); - CPPUNIT_TEST(testParse_ToplevelCharacterData); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(SerializingParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_Empty); + CPPUNIT_TEST(testParse_ToplevelCharacterData); + CPPUNIT_TEST_SUITE_END(); - public: - SerializingParserTest() {} + public: + SerializingParserTest() {} - void testParse() { - SerializingParser testling; - ParserTester<SerializingParser> parser(&testling); + void testParse() { + SerializingParser testling; + ParserTester<SerializingParser> parser(&testling); - CPPUNIT_ASSERT(parser.parse( - "<message type=\"chat\" to=\"me@foo.com\">" - "<body>Hello<&World</body>" - "<html xmlns=\"http://www.w3.org/1999/xhtml\">" - "foo<b>bar</b>baz" - "</html>" - "</message>")); + CPPUNIT_ASSERT(parser.parse( + "<message type=\"chat\" to=\"me@foo.com\">" + "<body>Hello<&World</body>" + "<html xmlns=\"http://www.w3.org/1999/xhtml\">" + "foo<b>bar</b>baz" + "</html>" + "</message>")); - CPPUNIT_ASSERT_EQUAL(std::string( - "<message to=\"me@foo.com\" type=\"chat\">" - "<body>Hello<&World</body>" - "<html xmlns=\"http://www.w3.org/1999/xhtml\">foo<b xmlns=\"http://www.w3.org/1999/xhtml\">bar</b>baz</html>" - "</message>"), testling.getResult()); - } + CPPUNIT_ASSERT_EQUAL(std::string( + "<message to=\"me@foo.com\" type=\"chat\">" + "<body>Hello<&World</body>" + "<html xmlns=\"http://www.w3.org/1999/xhtml\">foo<b xmlns=\"http://www.w3.org/1999/xhtml\">bar</b>baz</html>" + "</message>"), testling.getResult()); + } - void testParse_Empty() { - SerializingParser testling; + void testParse_Empty() { + SerializingParser testling; - CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getResult()); - } + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getResult()); + } - void testParse_ToplevelCharacterData() { - SerializingParser testling; - - AttributeMap attributes; - testling.handleCharacterData("foo"); - testling.handleStartElement("message", "", attributes); - testling.handleEndElement("message", ""); - testling.handleCharacterData("bar"); + void testParse_ToplevelCharacterData() { + SerializingParser testling; - CPPUNIT_ASSERT_EQUAL(std::string("<message/>"), testling.getResult()); - } + AttributeMap attributes; + testling.handleCharacterData("foo"); + testling.handleStartElement("message", "", attributes); + testling.handleEndElement("message", ""); + testling.handleCharacterData("bar"); + + CPPUNIT_ASSERT_EQUAL(std::string("<message/>"), testling.getResult()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(SerializingParserTest); diff --git a/Swiften/Parser/UnitTest/StanzaAckParserTest.cpp b/Swiften/Parser/UnitTest/StanzaAckParserTest.cpp index b68fb30..4591640 100644 --- a/Swiften/Parser/UnitTest/StanzaAckParserTest.cpp +++ b/Swiften/Parser/UnitTest/StanzaAckParserTest.cpp @@ -1,53 +1,53 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/StanzaAckParser.h> #include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/StanzaAckParser.h> #include <Swiften/Parser/UnitTest/ElementParserTester.h> using namespace Swift; class StanzaAckParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StanzaAckParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_Invalid); - CPPUNIT_TEST(testParse_Empty); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(StanzaAckParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_Invalid); + CPPUNIT_TEST(testParse_Empty); + CPPUNIT_TEST_SUITE_END(); - public: - void testParse() { - StanzaAckParser testling; - ElementParserTester parser(&testling); + public: + void testParse() { + StanzaAckParser testling; + ElementParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<a h=\"12\" xmlns=\"urn:xmpp:sm:2\"/>")); + CPPUNIT_ASSERT(parser.parse("<a h=\"12\" xmlns=\"urn:xmpp:sm:2\"/>")); - CPPUNIT_ASSERT(testling.getElementGeneric()->isValid()); - CPPUNIT_ASSERT_EQUAL(12U, testling.getElementGeneric()->getHandledStanzasCount()); - } + CPPUNIT_ASSERT(testling.getElementGeneric()->isValid()); + CPPUNIT_ASSERT_EQUAL(12U, testling.getElementGeneric()->getHandledStanzasCount()); + } - void testParse_Invalid() { - StanzaAckParser testling; - ElementParserTester parser(&testling); + void testParse_Invalid() { + StanzaAckParser testling; + ElementParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<a h=\"invalid\" xmlns=\"urn:xmpp:sm:2\"/>")); + CPPUNIT_ASSERT(parser.parse("<a h=\"invalid\" xmlns=\"urn:xmpp:sm:2\"/>")); - CPPUNIT_ASSERT(!testling.getElementGeneric()->isValid()); - } + CPPUNIT_ASSERT(!testling.getElementGeneric()->isValid()); + } - void testParse_Empty() { - StanzaAckParser testling; - ElementParserTester parser(&testling); + void testParse_Empty() { + StanzaAckParser testling; + ElementParserTester parser(&testling); - CPPUNIT_ASSERT(parser.parse("<a xmlns=\"urn:xmpp:sm:2\"/>")); + CPPUNIT_ASSERT(parser.parse("<a xmlns=\"urn:xmpp:sm:2\"/>")); - CPPUNIT_ASSERT(!testling.getElementGeneric()->isValid()); - } + CPPUNIT_ASSERT(!testling.getElementGeneric()->isValid()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StanzaAckParserTest); diff --git a/Swiften/Parser/UnitTest/StanzaParserTest.cpp b/Swiften/Parser/UnitTest/StanzaParserTest.cpp index 88e6dec..6febdbc 100644 --- a/Swiften/Parser/UnitTest/StanzaParserTest.cpp +++ b/Swiften/Parser/UnitTest/StanzaParserTest.cpp @@ -1,212 +1,212 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Parser/StanzaParser.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/Elements/Stanza.h> #include <Swiften/Parser/GenericPayloadParser.h> #include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Elements/Stanza.h> -#include <Swiften/Elements/Payload.h> +#include <Swiften/Parser/StanzaParser.h> using namespace Swift; class StanzaParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StanzaParserTest); - CPPUNIT_TEST(testHandleEndElement_OnePayload); - CPPUNIT_TEST(testHandleEndElement_MultiplePayloads); - CPPUNIT_TEST(testHandleEndElement_StrayCharacterData); - CPPUNIT_TEST(testHandleEndElement_UnknownPayload); - CPPUNIT_TEST(testHandleParse_BasicAttributes); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - factoryCollection_ = new PayloadParserFactoryCollection(); - factoryCollection_->addFactory(&factory1_); - factoryCollection_->addFactory(&factory2_); - } - - void tearDown() { - delete factoryCollection_; - } - - void testHandleEndElement_OnePayload() { - MyStanzaParser testling(factoryCollection_); - - AttributeMap attributes; - attributes.addAttribute("foo", "", "fum"); - attributes.addAttribute("bar", "", "baz"); - testling.handleStartElement("mystanza", "", attributes); - testling.handleStartElement("mypayload1", "", attributes); - testling.handleStartElement("child", "", attributes); - testling.handleEndElement("child", ""); - testling.handleEndElement("mypayload1", ""); - testling.handleEndElement("mystanza", ""); - - CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()); - CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()->hasChild); - } - - void testHandleEndElement_MultiplePayloads() { - MyStanzaParser testling(factoryCollection_); - - AttributeMap attributes; - testling.handleStartElement("mystanza", "", attributes); - testling.handleStartElement("mypayload1", "", attributes); - testling.handleEndElement("mypayload1", ""); - testling.handleStartElement("mypayload2", "", attributes); - testling.handleEndElement("mypayload2", ""); - testling.handleEndElement("mystanza", ""); - - CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()); - CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload2>()); - } - - void testHandleEndElement_StrayCharacterData() { - MyStanzaParser testling(factoryCollection_); - - AttributeMap attributes; - testling.handleStartElement("mystanza", "", attributes); - testling.handleStartElement("mypayload1", "", attributes); - testling.handleEndElement("mypayload1", ""); - testling.handleCharacterData("bla"); - testling.handleStartElement("mypayload2", "", attributes); - testling.handleEndElement("mypayload2", ""); - testling.handleEndElement("mystanza", ""); - - CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()); - CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload2>()); - } - - void testHandleEndElement_UnknownPayload() { - MyStanzaParser testling(factoryCollection_); - - AttributeMap attributes; - testling.handleStartElement("mystanza", "", attributes); - testling.handleStartElement("mypayload1", "", attributes); - testling.handleEndElement("mypayload1", ""); - testling.handleStartElement("unknown-payload", "", attributes); - testling.handleStartElement("unknown-payload-child", "", attributes); - testling.handleEndElement("unknown-payload-child", ""); - testling.handleEndElement("unknown-payload", ""); - testling.handleStartElement("mypayload2", "", attributes); - testling.handleEndElement("mypayload2", ""); - testling.handleEndElement("mystanza", ""); - - CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()); - CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload2>()); - } - - void testHandleParse_BasicAttributes() { - MyStanzaParser testling(factoryCollection_); - - AttributeMap attributes; - attributes.addAttribute("to", "", "foo@example.com/blo"); - attributes.addAttribute("from", "", "bar@example.com/baz"); - attributes.addAttribute("id", "", "id-123"); - testling.handleStartElement("mystanza", "", attributes); - testling.handleEndElement("mypayload1", ""); - - CPPUNIT_ASSERT_EQUAL(JID("foo@example.com/blo"), testling.getStanza()->getTo()); - CPPUNIT_ASSERT_EQUAL(JID("bar@example.com/baz"), testling.getStanza()->getFrom()); - CPPUNIT_ASSERT_EQUAL(std::string("id-123"), testling.getStanza()->getID()); - } - - private: - class MyPayload1 : public Payload - { - public: - MyPayload1() : hasChild(false) {} - - bool hasChild; - }; - - class MyPayload1Parser : public GenericPayloadParser<MyPayload1> - { - public: - MyPayload1Parser() {} - - virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap&) { - if (element != "mypayload1") { - getPayloadInternal()->hasChild = true; - } - } - - virtual void handleEndElement(const std::string&, const std::string&) {} - virtual void handleCharacterData(const std::string&) {} - }; - - class MyPayload1ParserFactory : public PayloadParserFactory - { - public: - MyPayload1ParserFactory() {} - - PayloadParser* createPayloadParser() { return new MyPayload1Parser(); } - - bool canParse(const std::string& element, const std::string&, const AttributeMap&) const { - return element == "mypayload1"; - } - }; - - class MyPayload2 : public Payload - { - public: - MyPayload2() {} - }; - - class MyPayload2Parser : public GenericPayloadParser<MyPayload2> - { - public: - MyPayload2Parser() {} - - virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&) {} - virtual void handleEndElement(const std::string&, const std::string&) {} - virtual void handleCharacterData(const std::string&) {} - }; - - - class MyPayload2ParserFactory : public PayloadParserFactory - { - public: - MyPayload2ParserFactory() {} - - PayloadParser* createPayloadParser() { return new MyPayload2Parser(); } - bool canParse(const std::string& element, const std::string&, const AttributeMap&) const { - return element == "mypayload2"; - } - }; - - class MyStanza : public Stanza - { - public: - MyStanza() {} - }; - - class MyStanzaParser : public StanzaParser - { - public: - MyStanzaParser(PayloadParserFactoryCollection* collection) : StanzaParser(collection) - { - stanza_ = boost::make_shared<MyStanza>(); - } - - virtual boost::shared_ptr<Element> getElement() const { - return stanza_; - } - - private: - boost::shared_ptr<MyStanza> stanza_; - }; - - MyPayload1ParserFactory factory1_; - MyPayload2ParserFactory factory2_; - PayloadParserFactoryCollection* factoryCollection_; + CPPUNIT_TEST_SUITE(StanzaParserTest); + CPPUNIT_TEST(testHandleEndElement_OnePayload); + CPPUNIT_TEST(testHandleEndElement_MultiplePayloads); + CPPUNIT_TEST(testHandleEndElement_StrayCharacterData); + CPPUNIT_TEST(testHandleEndElement_UnknownPayload); + CPPUNIT_TEST(testHandleParse_BasicAttributes); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + factoryCollection_ = new PayloadParserFactoryCollection(); + factoryCollection_->addFactory(&factory1_); + factoryCollection_->addFactory(&factory2_); + } + + void tearDown() { + delete factoryCollection_; + } + + void testHandleEndElement_OnePayload() { + MyStanzaParser testling(factoryCollection_); + + AttributeMap attributes; + attributes.addAttribute("foo", "", "fum"); + attributes.addAttribute("bar", "", "baz"); + testling.handleStartElement("mystanza", "", attributes); + testling.handleStartElement("mypayload1", "", attributes); + testling.handleStartElement("child", "", attributes); + testling.handleEndElement("child", ""); + testling.handleEndElement("mypayload1", ""); + testling.handleEndElement("mystanza", ""); + + CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()); + CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()->hasChild); + } + + void testHandleEndElement_MultiplePayloads() { + MyStanzaParser testling(factoryCollection_); + + AttributeMap attributes; + testling.handleStartElement("mystanza", "", attributes); + testling.handleStartElement("mypayload1", "", attributes); + testling.handleEndElement("mypayload1", ""); + testling.handleStartElement("mypayload2", "", attributes); + testling.handleEndElement("mypayload2", ""); + testling.handleEndElement("mystanza", ""); + + CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()); + CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload2>()); + } + + void testHandleEndElement_StrayCharacterData() { + MyStanzaParser testling(factoryCollection_); + + AttributeMap attributes; + testling.handleStartElement("mystanza", "", attributes); + testling.handleStartElement("mypayload1", "", attributes); + testling.handleEndElement("mypayload1", ""); + testling.handleCharacterData("bla"); + testling.handleStartElement("mypayload2", "", attributes); + testling.handleEndElement("mypayload2", ""); + testling.handleEndElement("mystanza", ""); + + CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()); + CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload2>()); + } + + void testHandleEndElement_UnknownPayload() { + MyStanzaParser testling(factoryCollection_); + + AttributeMap attributes; + testling.handleStartElement("mystanza", "", attributes); + testling.handleStartElement("mypayload1", "", attributes); + testling.handleEndElement("mypayload1", ""); + testling.handleStartElement("unknown-payload", "", attributes); + testling.handleStartElement("unknown-payload-child", "", attributes); + testling.handleEndElement("unknown-payload-child", ""); + testling.handleEndElement("unknown-payload", ""); + testling.handleStartElement("mypayload2", "", attributes); + testling.handleEndElement("mypayload2", ""); + testling.handleEndElement("mystanza", ""); + + CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload1>()); + CPPUNIT_ASSERT(testling.getStanza()->getPayload<MyPayload2>()); + } + + void testHandleParse_BasicAttributes() { + MyStanzaParser testling(factoryCollection_); + + AttributeMap attributes; + attributes.addAttribute("to", "", "foo@example.com/blo"); + attributes.addAttribute("from", "", "bar@example.com/baz"); + attributes.addAttribute("id", "", "id-123"); + testling.handleStartElement("mystanza", "", attributes); + testling.handleEndElement("mypayload1", ""); + + CPPUNIT_ASSERT_EQUAL(JID("foo@example.com/blo"), testling.getStanza()->getTo()); + CPPUNIT_ASSERT_EQUAL(JID("bar@example.com/baz"), testling.getStanza()->getFrom()); + CPPUNIT_ASSERT_EQUAL(std::string("id-123"), testling.getStanza()->getID()); + } + + private: + class MyPayload1 : public Payload + { + public: + MyPayload1() : hasChild(false) {} + + bool hasChild; + }; + + class MyPayload1Parser : public GenericPayloadParser<MyPayload1> + { + public: + MyPayload1Parser() {} + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap&) { + if (element != "mypayload1") { + getPayloadInternal()->hasChild = true; + } + } + + virtual void handleEndElement(const std::string&, const std::string&) {} + virtual void handleCharacterData(const std::string&) {} + }; + + class MyPayload1ParserFactory : public PayloadParserFactory + { + public: + MyPayload1ParserFactory() {} + + PayloadParser* createPayloadParser() { return new MyPayload1Parser(); } + + bool canParse(const std::string& element, const std::string&, const AttributeMap&) const { + return element == "mypayload1"; + } + }; + + class MyPayload2 : public Payload + { + public: + MyPayload2() {} + }; + + class MyPayload2Parser : public GenericPayloadParser<MyPayload2> + { + public: + MyPayload2Parser() {} + + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&) {} + virtual void handleEndElement(const std::string&, const std::string&) {} + virtual void handleCharacterData(const std::string&) {} + }; + + + class MyPayload2ParserFactory : public PayloadParserFactory + { + public: + MyPayload2ParserFactory() {} + + PayloadParser* createPayloadParser() { return new MyPayload2Parser(); } + bool canParse(const std::string& element, const std::string&, const AttributeMap&) const { + return element == "mypayload2"; + } + }; + + class MyStanza : public Stanza + { + public: + MyStanza() {} + }; + + class MyStanzaParser : public StanzaParser + { + public: + MyStanzaParser(PayloadParserFactoryCollection* collection) : StanzaParser(collection) + { + stanza_ = std::make_shared<MyStanza>(); + } + + virtual std::shared_ptr<ToplevelElement> getElement() const { + return stanza_; + } + + private: + std::shared_ptr<MyStanza> stanza_; + }; + + MyPayload1ParserFactory factory1_; + MyPayload2ParserFactory factory2_; + PayloadParserFactoryCollection* factoryCollection_; }; CPPUNIT_TEST_SUITE_REGISTRATION(StanzaParserTest); diff --git a/Swiften/Parser/UnitTest/StanzaParserTester.h b/Swiften/Parser/UnitTest/StanzaParserTester.h index e4ce48e..36f41c9 100644 --- a/Swiften/Parser/UnitTest/StanzaParserTester.h +++ b/Swiften/Parser/UnitTest/StanzaParserTester.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,5 +10,5 @@ #include <Swiften/Parser/UnitTest/ParserTester.h> namespace Swift { - typedef ParserTester<StanzaParser> StanzaParserTester; + typedef ParserTester<StanzaParser> StanzaParserTester; } diff --git a/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp b/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp index 4bc971f..4664df2 100644 --- a/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp +++ b/Swiften/Parser/UnitTest/StreamFeaturesParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,58 +13,96 @@ using namespace Swift; class StreamFeaturesParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StreamFeaturesParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testParse_Empty); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse() { - StreamFeaturesParser testling; - ElementParserTester parser(&testling); - - CPPUNIT_ASSERT(parser.parse( - "<stream:features xmlns:stream='http://etherx.jabber.org/streams'>" - "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>" - "<compression xmlns=\"http://jabber.org/features/compress\">" - "<method>zlib</method>" - "<method>lzw</method>" - "</compression>" - "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "<mechanism>DIGEST-MD5</mechanism>" - "<mechanism>PLAIN</mechanism>" - "</mechanisms>" - "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>" - "<sm xmlns='urn:xmpp:sm:2'/>" - "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>" - "<ver xmlns=\"urn:xmpp:features:rosterver\"/>" - "</stream:features>")); - - StreamFeatures::ref element = boost::dynamic_pointer_cast<StreamFeatures>(testling.getElement()); - CPPUNIT_ASSERT(element->hasStartTLS()); - CPPUNIT_ASSERT(element->hasSession()); - CPPUNIT_ASSERT(element->hasResourceBind()); - CPPUNIT_ASSERT(element->hasCompressionMethod("zlib")); - CPPUNIT_ASSERT(element->hasCompressionMethod("lzw")); - CPPUNIT_ASSERT(element->hasAuthenticationMechanisms()); - CPPUNIT_ASSERT(element->hasAuthenticationMechanism("DIGEST-MD5")); - CPPUNIT_ASSERT(element->hasAuthenticationMechanism("PLAIN")); - CPPUNIT_ASSERT(element->hasStreamManagement()); - CPPUNIT_ASSERT(element->hasRosterVersioning()); - } - - void testParse_Empty() { - StreamFeaturesParser testling; - ElementParserTester parser(&testling); - - CPPUNIT_ASSERT(parser.parse("<stream:features xmlns:stream='http://etherx.jabber.org/streams'/>")); - - StreamFeatures::ref element = boost::dynamic_pointer_cast<StreamFeatures>(testling.getElement()); - CPPUNIT_ASSERT(!element->hasStartTLS()); - CPPUNIT_ASSERT(!element->hasSession()); - CPPUNIT_ASSERT(!element->hasResourceBind()); - CPPUNIT_ASSERT(!element->hasAuthenticationMechanisms()); - } + CPPUNIT_TEST_SUITE(StreamFeaturesParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParse_Empty); + CPPUNIT_TEST(testParse_AuthenticationHostname); + CPPUNIT_TEST(testParse_AuthenticationHostnameEmpty); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse() { + StreamFeaturesParser testling; + ElementParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse( + "<stream:features xmlns:stream='http://etherx.jabber.org/streams'>" + "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>" + "<compression xmlns=\"http://jabber.org/features/compress\">" + "<method>zlib</method>" + "<method>lzw</method>" + "</compression>" + "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "<mechanism>DIGEST-MD5</mechanism>" + "<mechanism>PLAIN</mechanism>" + "</mechanisms>" + "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>" + "<sm xmlns='urn:xmpp:sm:2'/>" + "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>" + "<ver xmlns=\"urn:xmpp:features:rosterver\"/>" + "</stream:features>")); + + StreamFeatures::ref element = std::dynamic_pointer_cast<StreamFeatures>(testling.getElement()); + CPPUNIT_ASSERT(element->hasStartTLS()); + CPPUNIT_ASSERT(element->hasSession()); + CPPUNIT_ASSERT(element->hasResourceBind()); + CPPUNIT_ASSERT(element->hasCompressionMethod("zlib")); + CPPUNIT_ASSERT(element->hasCompressionMethod("lzw")); + CPPUNIT_ASSERT(element->hasAuthenticationMechanisms()); + CPPUNIT_ASSERT(element->hasAuthenticationMechanism("DIGEST-MD5")); + CPPUNIT_ASSERT(element->hasAuthenticationMechanism("PLAIN")); + CPPUNIT_ASSERT(!element->getAuthenticationHostname()); + CPPUNIT_ASSERT(element->hasStreamManagement()); + CPPUNIT_ASSERT(element->hasRosterVersioning()); + } + + void testParse_Empty() { + StreamFeaturesParser testling; + ElementParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse("<stream:features xmlns:stream='http://etherx.jabber.org/streams'/>")); + + StreamFeatures::ref element = std::dynamic_pointer_cast<StreamFeatures>(testling.getElement()); + CPPUNIT_ASSERT(!element->hasStartTLS()); + CPPUNIT_ASSERT(!element->hasSession()); + CPPUNIT_ASSERT(!element->hasResourceBind()); + CPPUNIT_ASSERT(!element->hasAuthenticationMechanisms()); + } + + void testParse_AuthenticationHostname() { + StreamFeaturesParser testling; + ElementParserTester parser(&testling); + std::string hostname("auth42.us.example.com"); + + CPPUNIT_ASSERT(parser.parse( + "<stream:features xmlns:stream='http://etherx.jabber.org/streams'>" + "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "<mechanism>GSSAPI</mechanism>" + "<hostname xmlns=\"urn:xmpp:domain-based-name:1\">auth42.us.example.com</hostname>" + "</mechanisms>" + "</stream:features>")); + + StreamFeatures::ref element = std::dynamic_pointer_cast<StreamFeatures>(testling.getElement()); + CPPUNIT_ASSERT(element->hasAuthenticationMechanism("GSSAPI")); + CPPUNIT_ASSERT_EQUAL(*element->getAuthenticationHostname(), hostname); + } + + void testParse_AuthenticationHostnameEmpty() { + StreamFeaturesParser testling; + ElementParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse( + "<stream:features xmlns:stream='http://etherx.jabber.org/streams'>" + "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "<mechanism>GSSAPI</mechanism>" + "<hostname xmlns=\"urn:xmpp:domain-based-name:1\"></hostname>" + "</mechanisms>" + "</stream:features>")); + + StreamFeatures::ref element = std::dynamic_pointer_cast<StreamFeatures>(testling.getElement()); + CPPUNIT_ASSERT(element->hasAuthenticationMechanism("GSSAPI")); + CPPUNIT_ASSERT(element->getAuthenticationHostname()->empty()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StreamFeaturesParserTest); diff --git a/Swiften/Parser/UnitTest/StreamManagementEnabledParserTest.cpp b/Swiften/Parser/UnitTest/StreamManagementEnabledParserTest.cpp index 07b7b31..704a89f 100644 --- a/Swiften/Parser/UnitTest/StreamManagementEnabledParserTest.cpp +++ b/Swiften/Parser/UnitTest/StreamManagementEnabledParserTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,22 +13,22 @@ using namespace Swift; class StreamManagementEnabledParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StreamManagementEnabledParserTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse() { - StreamManagementEnabledParser testling; - ElementParserTester parser(&testling); - - CPPUNIT_ASSERT(parser.parse( - "<enabled xmlns=\"urn:xmpp:sm:3\" id=\"some-long-sm-id\" resume=\"true\"/>")); - - boost::shared_ptr<StreamManagementEnabled> element = boost::dynamic_pointer_cast<StreamManagementEnabled>(testling.getElement()); - CPPUNIT_ASSERT(element->getResumeSupported()); - CPPUNIT_ASSERT_EQUAL(std::string("some-long-sm-id"), element->getResumeID()); - } + CPPUNIT_TEST_SUITE(StreamManagementEnabledParserTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse() { + StreamManagementEnabledParser testling; + ElementParserTester parser(&testling); + + CPPUNIT_ASSERT(parser.parse( + "<enabled xmlns=\"urn:xmpp:sm:3\" id=\"some-long-sm-id\" resume=\"true\"/>")); + + std::shared_ptr<StreamManagementEnabled> element = std::dynamic_pointer_cast<StreamManagementEnabled>(testling.getElement()); + CPPUNIT_ASSERT(element->getResumeSupported()); + CPPUNIT_ASSERT_EQUAL(std::string("some-long-sm-id"), element->getResumeID()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StreamManagementEnabledParserTest); diff --git a/Swiften/Parser/UnitTest/XMLParserTest.cpp b/Swiften/Parser/UnitTest/XMLParserTest.cpp index 4bdeb54..89229c9 100644 --- a/Swiften/Parser/UnitTest/XMLParserTest.cpp +++ b/Swiften/Parser/UnitTest/XMLParserTest.cpp @@ -1,11 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <unordered_map> #include <vector> #include <string> @@ -21,337 +22,470 @@ using namespace Swift; template <typename ParserType> class XMLParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(XMLParserTest); - CPPUNIT_TEST(testParse_NestedElements); - CPPUNIT_TEST(testParse_ElementInNamespacedElement); - CPPUNIT_TEST(testParse_CharacterData); - CPPUNIT_TEST(testParse_XMLEntity); - CPPUNIT_TEST(testParse_NamespacePrefix); - CPPUNIT_TEST(testParse_UnhandledXML); - CPPUNIT_TEST(testParse_InvalidXML); - CPPUNIT_TEST(testParse_InErrorState); - CPPUNIT_TEST(testParse_Incremental); - CPPUNIT_TEST(testParse_WhitespaceInAttribute); - CPPUNIT_TEST(testParse_AttributeWithoutNamespace); - CPPUNIT_TEST(testParse_AttributeWithNamespace); - CPPUNIT_TEST(testParse_BillionLaughs); - CPPUNIT_TEST(testParse_InternalEntity); - //CPPUNIT_TEST(testParse_UndefinedPrefix); - //CPPUNIT_TEST(testParse_UndefinedAttributePrefix); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(XMLParserTest); + CPPUNIT_TEST(testParse_NestedElements); + CPPUNIT_TEST(testParse_ElementInNamespacedElement); + CPPUNIT_TEST(testParse_CharacterData); + CPPUNIT_TEST(testParse_XMLEntity); + CPPUNIT_TEST(testParse_NamespacePrefix); + CPPUNIT_TEST(testParse_UnhandledXML); + CPPUNIT_TEST(testParse_InvalidXML); + CPPUNIT_TEST(testParse_InErrorState); + CPPUNIT_TEST(testParse_Incremental); + CPPUNIT_TEST(testParse_WhitespaceInAttribute); + CPPUNIT_TEST(testParse_AttributeWithoutNamespace); + CPPUNIT_TEST(testParse_AttributeWithNamespace); + CPPUNIT_TEST(testParse_AttributeWithNamespaceNoPrefix); + CPPUNIT_TEST(testParse_BillionLaughs); + CPPUNIT_TEST(testParse_InternalEntity); + //CPPUNIT_TEST(testParse_UndefinedPrefix); + //CPPUNIT_TEST(testParse_UndefinedAttributePrefix); + CPPUNIT_TEST(testParse_AllowCommentsInXML); + CPPUNIT_TEST(testParse_DisallowCommentsInXML); + CPPUNIT_TEST(testParse_Doctype); + CPPUNIT_TEST(testParse_ProcessingInstructions); + CPPUNIT_TEST(testParse_ProcessingPrefixedElement); + CPPUNIT_TEST(testParse_InvalidlyEncodedInput); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse_NestedElements() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(testling.parse( + "<iq type=\"get\">" + "<query xmlns='jabber:iq:version'/>" + "</iq>")); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size()); + + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[0].data); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); + CPPUNIT_ASSERT_EQUAL(std::string("get"), client_.events[0].attributes.getAttribute("type")); + CPPUNIT_ASSERT_EQUAL(std::string(), client_.events[0].ns); + + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[1].data); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.getEntries().size()); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[1].namespaces.size()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[1].namespaces.count("")); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].namespaces[""]); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); + CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[2].data); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[2].ns); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); + CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[3].data); + CPPUNIT_ASSERT_EQUAL(std::string(), client_.events[3].ns); + } + + void testParse_ElementInNamespacedElement() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(testling.parse( + "<query xmlns='jabber:iq:version'>" + "<name>Swift</name>" + "</query>")); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), client_.events.size()); + + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[0].data); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.getEntries().size()); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[0].ns); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].namespaces.size()); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[0].namespaces[""]); + + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("name"), client_.events[1].data); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].namespaces.size()); + + CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[2].type); + CPPUNIT_ASSERT_EQUAL(std::string("Swift"), client_.events[2].data); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); + CPPUNIT_ASSERT_EQUAL(std::string("name"), client_.events[3].data); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[3].ns); - public: - void testParse_NestedElements() { - ParserType testling(&client_); + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[4].type); + CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[4].data); + CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[4].ns); + } - CPPUNIT_ASSERT(testling.parse( - "<iq type=\"get\">" - "<query xmlns='jabber:iq:version'/>" - "</iq>")); + void testParse_CharacterData() { + ParserType testling(&client_); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size()); + CPPUNIT_ASSERT(testling.parse("<html>bla<i>bli</i>blo</html>")); - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[0].data); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); - CPPUNIT_ASSERT_EQUAL(std::string("get"), client_.events[0].attributes.getAttribute("type")); - CPPUNIT_ASSERT_EQUAL(std::string(), client_.events[0].ns); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(7), client_.events.size()); - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); - CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[1].data); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.getEntries().size()); - CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns); + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("html"), client_.events[0].data); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); - CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[2].data); - CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[2].ns); + CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[1].data); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); - CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[3].data); - CPPUNIT_ASSERT_EQUAL(std::string(), client_.events[3].ns); - } + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[2].type); + CPPUNIT_ASSERT_EQUAL(std::string("i"), client_.events[2].data); - void testParse_ElementInNamespacedElement() { - ParserType testling(&client_); + CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[3].type); + CPPUNIT_ASSERT_EQUAL(std::string("bli"), client_.events[3].data); - CPPUNIT_ASSERT(testling.parse( - "<query xmlns='jabber:iq:version'>" - "<name>Swift</name>" - "</query>")); + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[4].type); + CPPUNIT_ASSERT_EQUAL(std::string("i"), client_.events[4].data); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), client_.events.size()); + CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[5].type); + CPPUNIT_ASSERT_EQUAL(std::string("blo"), client_.events[5].data); - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[0].data); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.getEntries().size()); - CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[0].ns); + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[6].type); + CPPUNIT_ASSERT_EQUAL(std::string("html"), client_.events[6].data); + } - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); - CPPUNIT_ASSERT_EQUAL(std::string("name"), client_.events[1].data); - CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns); + void testParse_XMLEntity() { + ParserType testling(&client_); - CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[2].type); - CPPUNIT_ASSERT_EQUAL(std::string("Swift"), client_.events[2].data); + CPPUNIT_ASSERT(testling.parse("<html><></html>")); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); - CPPUNIT_ASSERT_EQUAL(std::string("name"), client_.events[3].data); - CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[3].ns); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size()); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[4].type); - CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[4].data); - CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[4].ns); - } + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("html"), client_.events[0].data); - void testParse_CharacterData() { - ParserType testling(&client_); + CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("<"), client_.events[1].data); - CPPUNIT_ASSERT(testling.parse("<html>bla<i>bli</i>blo</html>")); + CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[2].type); + CPPUNIT_ASSERT_EQUAL(std::string(">"), client_.events[2].data); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(7), client_.events.size()); + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); + CPPUNIT_ASSERT_EQUAL(std::string("html"), client_.events[3].data); + } - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("html"), client_.events[0].data); + void testParse_NamespacePrefix() { + ParserType testling(&client_); - CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[1].type); - CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[1].data); + CPPUNIT_ASSERT(testling.parse("<p:x xmlns:p='bla'><p:y/></p:x>")); - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[2].type); - CPPUNIT_ASSERT_EQUAL(std::string("i"), client_.events[2].data); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size()); - CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[3].type); - CPPUNIT_ASSERT_EQUAL(std::string("bli"), client_.events[3].data); + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("x"), client_.events[0].data); + CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[0].ns); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].namespaces.size()); + CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[0].namespaces["p"]); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[4].type); - CPPUNIT_ASSERT_EQUAL(std::string("i"), client_.events[4].data); + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("y"), client_.events[1].data); + CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[1].ns); - CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[5].type); - CPPUNIT_ASSERT_EQUAL(std::string("blo"), client_.events[5].data); + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); + CPPUNIT_ASSERT_EQUAL(std::string("y"), client_.events[2].data); + CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[2].ns); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[6].type); - CPPUNIT_ASSERT_EQUAL(std::string("html"), client_.events[6].data); - } + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); + CPPUNIT_ASSERT_EQUAL(std::string("x"), client_.events[3].data); + CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[3].ns); + } - void testParse_XMLEntity() { - ParserType testling(&client_); + void testParse_UnhandledXML() { + ParserType testling(&client_, true); - CPPUNIT_ASSERT(testling.parse("<html><></html>")); + CPPUNIT_ASSERT(testling.parse("<iq><!-- Testing --></iq>")); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events.size()); - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("html"), client_.events[0].data); + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[0].data); - CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[1].type); - CPPUNIT_ASSERT_EQUAL(std::string("<"), client_.events[1].data); + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[1].data); + } - CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[2].type); - CPPUNIT_ASSERT_EQUAL(std::string(">"), client_.events[2].data); + void testParse_InvalidXML() { + ParserType testling(&client_); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); - CPPUNIT_ASSERT_EQUAL(std::string("html"), client_.events[3].data); - } + CPPUNIT_ASSERT(!testling.parse("<iq><bla></iq>")); + } - void testParse_NamespacePrefix() { - ParserType testling(&client_); + void testParse_InErrorState() { + ParserType testling(&client_); - CPPUNIT_ASSERT(testling.parse("<p:x xmlns:p='bla'><p:y/></p:x>")); + CPPUNIT_ASSERT(!testling.parse("<iq><bla></iq>")); + CPPUNIT_ASSERT(!testling.parse("<iq/>")); + } - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size()); + void testParse_Incremental() { + ParserType testling(&client_); - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("x"), client_.events[0].data); - CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[0].ns); + CPPUNIT_ASSERT(testling.parse("<iq")); + CPPUNIT_ASSERT(testling.parse("></iq>")); - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); - CPPUNIT_ASSERT_EQUAL(std::string("y"), client_.events[1].data); - CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[1].ns); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events.size()); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); - CPPUNIT_ASSERT_EQUAL(std::string("y"), client_.events[2].data); - CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[2].ns); + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[0].data); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); - CPPUNIT_ASSERT_EQUAL(std::string("x"), client_.events[3].data); - CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[3].ns); - } + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[1].data); + } - void testParse_UnhandledXML() { - ParserType testling(&client_); + void testParse_CompleteDocument() { + ParserType testling(&client_); - CPPUNIT_ASSERT(testling.parse("<iq><!-- Testing --></iq>")); + CPPUNIT_ASSERT(!testling.parse("<iq", true)); + CPPUNIT_ASSERT(!testling.parse("<iq>", true)); + CPPUNIT_ASSERT(!testling.parse("<iq><child>foo</child>", true)); + CPPUNIT_ASSERT(testling.parse("<iq><child>foo</child></iq>", true)); + } - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events.size()); + void testParse_WhitespaceInAttribute() { + ParserType testling(&client_); - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[0].data); + CPPUNIT_ASSERT(testling.parse( + "<query xmlns='http://www.xmpp.org/extensions/xep-0084.html#ns-data '>")); + CPPUNIT_ASSERT(testling.parse( + "<presence/>")); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), client_.events.size()); + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[0].data); + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("presence"), client_.events[1].data); + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); + CPPUNIT_ASSERT_EQUAL(std::string("presence"), client_.events[2].data); + } - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[1].type); - CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[1].data); - } + void testParse_AttributeWithoutNamespace() { + ParserType testling(&client_); - void testParse_InvalidXML() { - ParserType testling(&client_); + CPPUNIT_ASSERT(testling.parse( + "<query xmlns='http://swift.im' attr='3'/>")); - CPPUNIT_ASSERT(!testling.parse("<iq><bla></iq>")); - } + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); + CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); + CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace()); + CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].attributes.getEntries()[0].getAttribute().getPrefix()); + } - void testParse_InErrorState() { - ParserType testling(&client_); + void testParse_AttributeWithNamespace() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(testling.parse( + "<query xmlns='http://swift.im' xmlns:f='http://swift.im/f' f:attr='3'/>")); - CPPUNIT_ASSERT(!testling.parse("<iq><bla></iq>")); - CPPUNIT_ASSERT(!testling.parse("<iq/>")); - } + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); + CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); + CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace()); + CPPUNIT_ASSERT_EQUAL(std::string("f"), client_.events[0].attributes.getEntries()[0].getAttribute().getPrefix()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events[0].namespaces.size()); + CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im"), client_.events[0].namespaces[""]); + CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].namespaces["f"]); + } - void testParse_Incremental() { - ParserType testling(&client_); + void testParse_AttributeWithNamespaceNoPrefix() { + ParserType testling(&client_); - CPPUNIT_ASSERT(testling.parse("<iq")); - CPPUNIT_ASSERT(testling.parse("></iq>")); + CPPUNIT_ASSERT(testling.parse( + "<query xmlns='http://swift.im' xmlns:f='http://swift.im/f' attr='3'/>")); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events.size()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); + CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); + CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace()); + CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].attributes.getEntries()[0].getAttribute().getPrefix()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events[0].namespaces.size()); + CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im"), client_.events[0].namespaces[""]); + CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].namespaces["f"]); + } - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[0].data); + void testParse_BillionLaughs() { + ParserType testling(&client_); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[1].type); - CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[1].data); - } - - void testParse_WhitespaceInAttribute() { - ParserType testling(&client_); - - CPPUNIT_ASSERT(testling.parse( - "<query xmlns='http://www.xmpp.org/extensions/xep-0084.html#ns-data '>")); - CPPUNIT_ASSERT(testling.parse( - "<presence/>")); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), client_.events.size()); - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[0].data); - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); - CPPUNIT_ASSERT_EQUAL(std::string("presence"), client_.events[1].data); - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); - CPPUNIT_ASSERT_EQUAL(std::string("presence"), client_.events[2].data); - } - - void testParse_AttributeWithoutNamespace() { - ParserType testling(&client_); - - CPPUNIT_ASSERT(testling.parse( - "<query xmlns='http://swift.im' attr='3'/>")); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); - CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); - CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace()); - } - - void testParse_AttributeWithNamespace() { - ParserType testling(&client_); - - CPPUNIT_ASSERT(testling.parse( - "<query xmlns='http://swift.im' xmlns:f='http://swift.im/f' f:attr='3'/>")); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); - CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); - CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace()); - } - - void testParse_BillionLaughs() { - ParserType testling(&client_); - - CPPUNIT_ASSERT(!testling.parse( - "<?xml version=\"1.0\"?>" - "<!DOCTYPE lolz [" - " <!ENTITY lol \"lol\">" - " <!ENTITY lol2 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">" - " <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">" - " <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">" - " <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">" - " <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">" - " <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">" - " <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">" - " <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">" - "]>" - "<lolz>&lol9;</lolz>" - )); - } - - void testParse_InternalEntity() { - ParserType testling(&client_); - - CPPUNIT_ASSERT(!testling.parse("<!DOCTYPE foo [<!ENTITY bar \"Bar\">]><foo>&bar;</foo>")); - } - - void testParse_UndefinedPrefix() { - ParserType testling(&client_); - - CPPUNIT_ASSERT(testling.parse( - "<foo:bar><bla/></foo:bar>")); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size()); - - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("foo:bar"), client_.events[0].data); - CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].ns); - - CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); - CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[1].data); - CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[1].ns); - - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); - CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[2].data); - CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[2].ns); - - CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); - CPPUNIT_ASSERT_EQUAL(std::string("foo:bar"), client_.events[3].data); - CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[3].ns); - } - - void testParse_UndefinedAttributePrefix() { - ParserType testling(&client_); - - CPPUNIT_ASSERT(testling.parse( - "<foo bar:baz='bla'/>")); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); - CPPUNIT_ASSERT_EQUAL(std::string("bar:baz"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); - } - - private: - class Client : public XMLParserClient { - public: - enum Type { StartElement, EndElement, CharacterData }; - struct Event { - Event( - Type type, - const std::string& data, - const std::string& ns, - const AttributeMap& attributes) - : type(type), data(data), ns(ns), attributes(attributes) {} - Event(Type type, const std::string& data, const std::string& ns = std::string()) - : type(type), data(data), ns(ns) {} - - Type type; - std::string data; - std::string ns; - AttributeMap attributes; - }; - - Client() {} - - virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - events.push_back(Event(StartElement, element, ns, attributes)); - } - - virtual void handleEndElement(const std::string& element, const std::string& ns) { - events.push_back(Event(EndElement, element, ns)); - } - - virtual void handleCharacterData(const std::string& data) { - events.push_back(Event(CharacterData, data)); - } - - std::vector<Event> events; - } client_; + CPPUNIT_ASSERT(!testling.parse( + "<?xml version=\"1.0\"?>" + "<!DOCTYPE lolz [" + " <!ENTITY lol \"lol\">" + " <!ENTITY lol2 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">" + " <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">" + " <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">" + " <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">" + " <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">" + " <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">" + " <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">" + " <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">" + "]>" + "<lolz>&lol9;</lolz>" + )); + } + + void testParse_InternalEntity() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(!testling.parse("<!DOCTYPE foo [<!ENTITY bar \"Bar\">]><foo>&bar;</foo>")); + } + + void testParse_UndefinedPrefix() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(testling.parse( + "<foo:bar><bla/></foo:bar>")); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size()); + + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("foo:bar"), client_.events[0].data); + CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].ns); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].namespaces.size()); + + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[1].data); + CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[1].ns); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); + CPPUNIT_ASSERT_EQUAL(std::string("bla"), client_.events[2].data); + CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[2].ns); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type); + CPPUNIT_ASSERT_EQUAL(std::string("foo:bar"), client_.events[3].data); + CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[3].ns); + } + + void testParse_UndefinedAttributePrefix() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(testling.parse("<foo bar:baz='bla'/>")); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); + CPPUNIT_ASSERT_EQUAL(std::string("bar:baz"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); + } + + void testParse_AllowCommentsInXML() { + ParserType testling(&client_, true); + + CPPUNIT_ASSERT(testling.parse("<message><!-- Some More Comments Testing --></message>")); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events.size()); + + CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("message"), client_.events[0].data); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("message"), client_.events[1].data); + } + + void testParse_DisallowCommentsInXML() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(!testling.parse("<message><!-- Some More Comments Testing --></message>")); + } + + void testParse_Doctype() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(!testling.parse("<!DOCTYPE greeting SYSTEM \"hello.dtd\">")); + } + + void testParse_ProcessingInstructions() { + ParserType testling(&client_); + + CPPUNIT_ASSERT(!testling.parse("<?xml-stylesheet type=\"text/xsl\" href=\"Sample.xsl\"?>")); + } + + void testParse_ProcessingPrefixedElement() { + client_.testingStartElementPrefix = true; + ParserType testling(&client_); + + CPPUNIT_ASSERT(testling.parse("<prefix:message xmlns='uri' xmlns:prefix='uriPrefix'/>")); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), client_.events.size()); + + CPPUNIT_ASSERT_EQUAL(Client::StartElementPrefix, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("message"), client_.events[0].data); + CPPUNIT_ASSERT_EQUAL(std::string("uriPrefix"), client_.events[0].ns); + CPPUNIT_ASSERT_EQUAL(std::string("prefix"), client_.events[0].prefix); + + CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(std::string("message"), client_.events[1].data); + CPPUNIT_ASSERT_EQUAL(std::string("uriPrefix"), client_.events[1].ns); + } + + void testParse_InvalidlyEncodedInput() { + ParserType testling(&client_); + + // The following input was generated by a fuzzer, and triggered a crash in the LibXML2 parser because + // some types of error (buffer I/O errors, for instance) will not update the error in the parser context, + // and the code used to rely on that error always being set if parsing failed. + // This particular input will trick the parser into believing the encoding is UTF-16LE, which eventually will lead + // to two invalid encodings, followed by an I/O error. The latter will end parsing without updating the + // error in the parsing context, which used to trigger a crash. + testling.parse(std::string("<\0?\0\x80q type='get' id='aab9a'<<query xmlns='jabber:iq:roster'/>\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9br:i><quq:private'><storage xml s='s'\x00\x10</query></iq>", 271)); + testling.parse("<iq type='get'\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e to='ad5d8d2b25' ext='ca cs min@wonderland.t' id='aabda'><vCard xmlnr='vcard-temp'/>O/iq>"); + testling.parse("<\xff\xff\xff\x7fype:'get' to='won\x84" "erland.lit' id='aabea'><tuery xmlns='\xd8Vtp://jabber.org/p\x88ot\x8b" "col/disco#info'/>abber.org/protocol/disco#Nnfo'/></iq>"); + } + + private: + class Client : public XMLParserClient { + public: + using NamespaceMap = std::unordered_map<std::string /* prefix */, std::string /* uri */>; + enum Type { StartElement, StartElementPrefix, EndElement, CharacterData, NamespaceDefined }; + struct Event { + Event( + Type type, + const std::string& data, + const std::string& ns, + const std::string& prefix, + const AttributeMap& attributes, + NamespaceMap namespaces) + : type(type), data(data), ns(ns), prefix(prefix), attributes(attributes), namespaces(std::move(namespaces)) {} + Event( + Type type, + const std::string& data, + const std::string& ns, + const AttributeMap& attributes, + NamespaceMap namespaces = {}) + : Event(type, data, ns, {}, attributes, std::move(namespaces)) {} + Event(Type type, const std::string& data, const std::string& ns = std::string()) + : Event(type, data, ns, "", AttributeMap(), NamespaceMap()) {} + + Type type; + std::string data; + std::string ns; + std::string prefix; + AttributeMap attributes; + NamespaceMap namespaces; + }; + + Client() {} + + void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) override { + if (testingStartElementPrefix) return; + events.push_back(Event(StartElement, element, ns, attributes, std::move(namespaces_))); + } + + void handleStartElementPrefix(const std::string& prefix, const std::string& uri, const std::string& name, const AttributeMap&) override { + if (!testingStartElementPrefix) return; + events.push_back(Event(StartElementPrefix, name, uri, prefix, AttributeMap(), NamespaceMap())); + } + + void handleEndElement(const std::string& element, const std::string& ns) override { + events.push_back(Event(EndElement, element, ns)); + } + + void handleCharacterData(const std::string& data) override { + events.push_back(Event(CharacterData, data)); + } + + void handleNamespaceDeclaration(const std::string& prefix, const std::string& uri) override { + namespaces_[prefix] = uri; + } + + std::vector<Event> events; + bool testingStartElementPrefix = false; + private: + NamespaceMap namespaces_; + } client_; }; #ifdef HAVE_EXPAT diff --git a/Swiften/Parser/UnitTest/XMPPParserTest.cpp b/Swiften/Parser/UnitTest/XMPPParserTest.cpp index f8d60f2..2424d4d 100644 --- a/Swiften/Parser/UnitTest/XMPPParserTest.cpp +++ b/Swiften/Parser/UnitTest/XMPPParserTest.cpp @@ -1,196 +1,197 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <string> +#include <vector> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <vector> -#include <Swiften/Elements/ProtocolHeader.h> -#include <string> -#include <Swiften/Parser/XMPPParser.h> -#include <Swiften/Parser/ElementParser.h> -#include <Swiften/Parser/XMPPParserClient.h> -#include <Swiften/Parser/PayloadParserFactoryCollection.h> -#include <Swiften/Parser/PlatformXMLParserFactory.h> -#include <Swiften/Elements/Presence.h> #include <Swiften/Elements/IQ.h> #include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/ProtocolHeader.h> #include <Swiften/Elements/StreamFeatures.h> #include <Swiften/Elements/UnknownElement.h> +#include <Swiften/Parser/ElementParser.h> +#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PlatformXMLParserFactory.h> +#include <Swiften/Parser/XMPPParser.h> +#include <Swiften/Parser/XMPPParserClient.h> using namespace Swift; class XMPPParserTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(XMPPParserTest); - CPPUNIT_TEST(testParse_SimpleSession); - CPPUNIT_TEST(testParse_SimpleClientFromServerSession); - CPPUNIT_TEST(testParse_Presence); - CPPUNIT_TEST(testParse_IQ); - CPPUNIT_TEST(testParse_Message); - CPPUNIT_TEST(testParse_StreamFeatures); - CPPUNIT_TEST(testParse_UnknownElement); - CPPUNIT_TEST(testParse_StrayCharacterData); - CPPUNIT_TEST(testParse_InvalidStreamStart); - CPPUNIT_TEST(testParse_ElementEndAfterInvalidStreamStart); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse_SimpleSession() { - XMPPParser testling(&client_, &factories_, &xmlParserFactory_); - - CPPUNIT_ASSERT(testling.parse("<?xml version='1.0'?>")); - CPPUNIT_ASSERT(testling.parse("<stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' >")); - CPPUNIT_ASSERT(testling.parse("<presence/>")); - CPPUNIT_ASSERT(testling.parse("<presence/>")); - CPPUNIT_ASSERT(testling.parse("<iq/>")); - CPPUNIT_ASSERT(testling.parse("</stream:stream>")); - - CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(client_.events.size())); - CPPUNIT_ASSERT_EQUAL(Client::StreamStart, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("example.com"), client_.events[0].header->getTo()); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[2].type); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[3].type); - CPPUNIT_ASSERT_EQUAL(Client::StreamEnd, client_.events[4].type); - } - - void testParse_SimpleClientFromServerSession() { - XMPPParser testling(&client_, &factories_, &xmlParserFactory_); - - CPPUNIT_ASSERT(testling.parse("<?xml version='1.0'?>")); - CPPUNIT_ASSERT(testling.parse("<stream:stream from='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='aeab'>")); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(client_.events.size())); - CPPUNIT_ASSERT_EQUAL(Client::StreamStart, client_.events[0].type); - CPPUNIT_ASSERT_EQUAL(std::string("example.com"), client_.events[0].header->getFrom()); - CPPUNIT_ASSERT_EQUAL(std::string("aeab"), client_.events[0].header->getID()); - } - - - void testParse_Presence() { - XMPPParser testling(&client_, &factories_, &xmlParserFactory_); - - CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); - CPPUNIT_ASSERT(testling.parse("<presence/>")); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size())); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); - CPPUNIT_ASSERT(dynamic_cast<Presence*>(client_.events[1].element.get())); - } - - void testParse_IQ() { - XMPPParser testling(&client_, &factories_, &xmlParserFactory_); - - CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); - CPPUNIT_ASSERT(testling.parse("<iq/>")); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size())); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); - CPPUNIT_ASSERT(dynamic_cast<IQ*>(client_.events[1].element.get())); - } - - void testParse_Message() { - XMPPParser testling(&client_, &factories_, &xmlParserFactory_); - - CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); - CPPUNIT_ASSERT(testling.parse("<message/>")); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size())); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); - CPPUNIT_ASSERT(dynamic_cast<Message*>(client_.events[1].element.get())); - } - - void testParse_StreamFeatures() { - XMPPParser testling(&client_, &factories_, &xmlParserFactory_); - - CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); - CPPUNIT_ASSERT(testling.parse("<stream:features/>")); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size())); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); - CPPUNIT_ASSERT(dynamic_cast<StreamFeatures*>(client_.events[1].element.get())); - } - - void testParse_UnknownElement() { - XMPPParser testling(&client_, &factories_, &xmlParserFactory_); - - CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); - CPPUNIT_ASSERT(testling.parse("<presence/>")); - CPPUNIT_ASSERT(testling.parse("<foo/>")); - CPPUNIT_ASSERT(testling.parse("<bar/>")); - CPPUNIT_ASSERT(testling.parse("<presence/>")); - - CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(client_.events.size())); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[2].type); - CPPUNIT_ASSERT(dynamic_cast<UnknownElement*>(client_.events[2].element.get())); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[3].type); - CPPUNIT_ASSERT(dynamic_cast<UnknownElement*>(client_.events[3].element.get())); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[4].type); - CPPUNIT_ASSERT(dynamic_cast<Presence*>(client_.events[4].element.get())); - } - - void testParse_StrayCharacterData() { - XMPPParser testling(&client_, &factories_, &xmlParserFactory_); - - CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); - CPPUNIT_ASSERT(testling.parse("<presence/>")); - CPPUNIT_ASSERT(testling.parse("bla")); - CPPUNIT_ASSERT(testling.parse("<iq/>")); - - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(client_.events.size())); - CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[2].type); - CPPUNIT_ASSERT(dynamic_cast<IQ*>(client_.events[2].element.get())); - } - - void testParse_InvalidStreamStart() { - XMPPParser testling(&client_, &factories_, &xmlParserFactory_); - - CPPUNIT_ASSERT(!testling.parse("<tream>")); - } - - void testParse_ElementEndAfterInvalidStreamStart() { - XMPPParser testling(&client_, &factories_, &xmlParserFactory_); + CPPUNIT_TEST_SUITE(XMPPParserTest); + CPPUNIT_TEST(testParse_SimpleSession); + CPPUNIT_TEST(testParse_SimpleClientFromServerSession); + CPPUNIT_TEST(testParse_Presence); + CPPUNIT_TEST(testParse_IQ); + CPPUNIT_TEST(testParse_Message); + CPPUNIT_TEST(testParse_StreamFeatures); + CPPUNIT_TEST(testParse_UnknownElement); + CPPUNIT_TEST(testParse_StrayCharacterData); + CPPUNIT_TEST(testParse_InvalidStreamStart); + CPPUNIT_TEST(testParse_ElementEndAfterInvalidStreamStart); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse_SimpleSession() { + XMPPParser testling(&client_, &factories_, &xmlParserFactory_); + + CPPUNIT_ASSERT(testling.parse("<?xml version='1.0'?>")); + CPPUNIT_ASSERT(testling.parse("<stream:stream to='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' >")); + CPPUNIT_ASSERT(testling.parse("<presence/>")); + CPPUNIT_ASSERT(testling.parse("<presence/>")); + CPPUNIT_ASSERT(testling.parse("<iq/>")); + CPPUNIT_ASSERT(testling.parse("</stream:stream>")); + + CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(client_.events.size())); + CPPUNIT_ASSERT_EQUAL(Client::StreamStart, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("example.com"), client_.events[0].header->getTo()); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[2].type); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[3].type); + CPPUNIT_ASSERT_EQUAL(Client::StreamEnd, client_.events[4].type); + } + + void testParse_SimpleClientFromServerSession() { + XMPPParser testling(&client_, &factories_, &xmlParserFactory_); + + CPPUNIT_ASSERT(testling.parse("<?xml version='1.0'?>")); + CPPUNIT_ASSERT(testling.parse("<stream:stream from='example.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='aeab'>")); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(client_.events.size())); + CPPUNIT_ASSERT_EQUAL(Client::StreamStart, client_.events[0].type); + CPPUNIT_ASSERT_EQUAL(std::string("example.com"), client_.events[0].header->getFrom()); + CPPUNIT_ASSERT_EQUAL(std::string("aeab"), client_.events[0].header->getID()); + } + + + void testParse_Presence() { + XMPPParser testling(&client_, &factories_, &xmlParserFactory_); + + CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); + CPPUNIT_ASSERT(testling.parse("<presence/>")); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size())); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); + CPPUNIT_ASSERT(dynamic_cast<Presence*>(client_.events[1].element.get())); + } + + void testParse_IQ() { + XMPPParser testling(&client_, &factories_, &xmlParserFactory_); + + CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); + CPPUNIT_ASSERT(testling.parse("<iq/>")); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size())); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); + CPPUNIT_ASSERT(dynamic_cast<IQ*>(client_.events[1].element.get())); + } + + void testParse_Message() { + XMPPParser testling(&client_, &factories_, &xmlParserFactory_); + + CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); + CPPUNIT_ASSERT(testling.parse("<message/>")); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size())); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); + CPPUNIT_ASSERT(dynamic_cast<Message*>(client_.events[1].element.get())); + } + + void testParse_StreamFeatures() { + XMPPParser testling(&client_, &factories_, &xmlParserFactory_); + + CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); + CPPUNIT_ASSERT(testling.parse("<stream:features/>")); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(client_.events.size())); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[1].type); + CPPUNIT_ASSERT(dynamic_cast<StreamFeatures*>(client_.events[1].element.get())); + } + + void testParse_UnknownElement() { + XMPPParser testling(&client_, &factories_, &xmlParserFactory_); + + CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); + CPPUNIT_ASSERT(testling.parse("<presence/>")); + CPPUNIT_ASSERT(testling.parse("<foo/>")); + CPPUNIT_ASSERT(testling.parse("<bar/>")); + CPPUNIT_ASSERT(testling.parse("<presence/>")); + + CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(client_.events.size())); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[2].type); + CPPUNIT_ASSERT(dynamic_cast<UnknownElement*>(client_.events[2].element.get())); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[3].type); + CPPUNIT_ASSERT(dynamic_cast<UnknownElement*>(client_.events[3].element.get())); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[4].type); + CPPUNIT_ASSERT(dynamic_cast<Presence*>(client_.events[4].element.get())); + } + + void testParse_StrayCharacterData() { + XMPPParser testling(&client_, &factories_, &xmlParserFactory_); + + CPPUNIT_ASSERT(testling.parse("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>")); + CPPUNIT_ASSERT(testling.parse("<presence/>")); + CPPUNIT_ASSERT(testling.parse("bla")); + CPPUNIT_ASSERT(testling.parse("<iq/>")); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(client_.events.size())); + CPPUNIT_ASSERT_EQUAL(Client::ElementEvent, client_.events[2].type); + CPPUNIT_ASSERT(dynamic_cast<IQ*>(client_.events[2].element.get())); + } + + void testParse_InvalidStreamStart() { + XMPPParser testling(&client_, &factories_, &xmlParserFactory_); + + CPPUNIT_ASSERT(!testling.parse("<tream>")); + } + + void testParse_ElementEndAfterInvalidStreamStart() { + XMPPParser testling(&client_, &factories_, &xmlParserFactory_); - CPPUNIT_ASSERT(!testling.parse("<tream/>")); - } + CPPUNIT_ASSERT(!testling.parse("<tream/>")); + } - private: - class Client : public XMPPParserClient { - public: - enum Type { StreamStart, ElementEvent, StreamEnd }; - struct Event { - Event(Type type, boost::shared_ptr<Element> element) - : type(type), element(element) {} - Event(Type type, const ProtocolHeader& header) : type(type), header(header) {} + private: + class Client : public XMPPParserClient { + public: + enum Type { StreamStart, ElementEvent, StreamEnd }; + struct Event { + Event(Type type, std::shared_ptr<ToplevelElement> element) + : type(type), element(element) {} + Event(Type type, const ProtocolHeader& header) : type(type), header(header) {} - Event(Type type) : type(type) {} + Event(Type type) : type(type) {} - Type type; - boost::optional<ProtocolHeader> header; - boost::shared_ptr<Element> element; - }; + Type type; + boost::optional<ProtocolHeader> header; + std::shared_ptr<ToplevelElement> element; + }; - Client() {} - - void handleStreamStart(const ProtocolHeader& header) { - events.push_back(Event(StreamStart, header)); - } - - void handleElement(boost::shared_ptr<Element> element) { - events.push_back(Event(ElementEvent, element)); - } - - void handleStreamEnd() { - events.push_back(Event(StreamEnd)); - } - - std::vector<Event> events; - } client_; - PayloadParserFactoryCollection factories_; - PlatformXMLParserFactory xmlParserFactory_; + Client() {} + + void handleStreamStart(const ProtocolHeader& header) { + events.push_back(Event(StreamStart, header)); + } + + void handleElement(std::shared_ptr<ToplevelElement> element) { + events.push_back(Event(ElementEvent, element)); + } + + void handleStreamEnd() { + events.push_back(Event(StreamEnd)); + } + + std::vector<Event> events; + } client_; + PayloadParserFactoryCollection factories_; + PlatformXMLParserFactory xmlParserFactory_; }; CPPUNIT_TEST_SUITE_REGISTRATION(XMPPParserTest); diff --git a/Swiften/Parser/UnknownElementParser.h b/Swiften/Parser/UnknownElementParser.h index 59133de..44c5464 100644 --- a/Swiften/Parser/UnknownElementParser.h +++ b/Swiften/Parser/UnknownElementParser.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Parser/GenericElementParser.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/UnknownElement.h> +#include <Swiften/Parser/GenericElementParser.h> namespace Swift { - class UnknownElementParser : public GenericElementParser<UnknownElement> { - public: - UnknownElementParser() : GenericElementParser<UnknownElement>() {} - }; + class SWIFTEN_API UnknownElementParser : public GenericElementParser<UnknownElement> { + public: + UnknownElementParser() : GenericElementParser<UnknownElement>() {} + }; } diff --git a/Swiften/Parser/UnknownPayloadParser.h b/Swiften/Parser/UnknownPayloadParser.h index 0843f41..1553704 100644 --- a/Swiften/Parser/UnknownPayloadParser.h +++ b/Swiften/Parser/UnknownPayloadParser.h @@ -1,26 +1,27 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Parser/PayloadParser.h> namespace Swift { - class UnknownPayloadParser : public PayloadParser { - public: - UnknownPayloadParser() {} + class SWIFTEN_API UnknownPayloadParser : public PayloadParser { + public: + UnknownPayloadParser() {} - virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&) {} - virtual void handleEndElement(const std::string&, const std::string&) {} - virtual void handleCharacterData(const std::string&) {} + virtual void handleStartElement(const std::string&, const std::string&, const AttributeMap&) {} + virtual void handleEndElement(const std::string&, const std::string&) {} + virtual void handleCharacterData(const std::string&) {} - virtual boost::shared_ptr<Payload> getPayload() const { - return boost::shared_ptr<Payload>(); - } - }; + virtual std::shared_ptr<Payload> getPayload() const { + return std::shared_ptr<Payload>(); + } + }; } diff --git a/Swiften/Parser/XMLParser.cpp b/Swiften/Parser/XMLParser.cpp index cd7baea..8a0799f 100644 --- a/Swiften/Parser/XMLParser.cpp +++ b/Swiften/Parser/XMLParser.cpp @@ -1,14 +1,14 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/XMLParser.h> namespace Swift { -XMLParser::XMLParser(XMLParserClient* client) : client_(client) { +XMLParser::XMLParser(XMLParserClient* client, bool allowComments) : client_(client), allowComments_(allowComments){ } XMLParser::~XMLParser() { diff --git a/Swiften/Parser/XMLParser.h b/Swiften/Parser/XMLParser.h index 6ecc626..3b09d22 100644 --- a/Swiften/Parser/XMLParser.h +++ b/Swiften/Parser/XMLParser.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,20 +11,25 @@ #include <Swiften/Base/API.h> namespace Swift { - class XMLParserClient; + class XMLParserClient; - class SWIFTEN_API XMLParser { - public: - XMLParser(XMLParserClient* client); - virtual ~XMLParser(); + class SWIFTEN_API XMLParser { + public: + XMLParser(XMLParserClient* client, bool allowComments = false); + virtual ~XMLParser(); - virtual bool parse(const std::string& data) = 0; + virtual bool parse(const std::string& data, bool finalData = false) = 0; - XMLParserClient* getClient() const { - return client_; - } + XMLParserClient* getClient() const { + return client_; + } - private: - XMLParserClient* client_; - }; + bool allowsComments() const { + return allowComments_; + } + + private: + XMLParserClient* client_; + const bool allowComments_ = false; + }; } diff --git a/Swiften/Parser/XMLParserClient.cpp b/Swiften/Parser/XMLParserClient.cpp index 46d57b7..6698900 100644 --- a/Swiften/Parser/XMLParserClient.cpp +++ b/Swiften/Parser/XMLParserClient.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/XMLParserClient.h> @@ -11,5 +11,14 @@ namespace Swift { XMLParserClient::~XMLParserClient() { } +void XMLParserClient::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { +} + +void XMLParserClient::handleStartElementPrefix(const std::string&, const std::string&, const std::string&, const AttributeMap&) { +} + +void XMLParserClient::handleNamespaceDeclaration(const std::string&, const std::string&) { +} + } diff --git a/Swiften/Parser/XMLParserClient.h b/Swiften/Parser/XMLParserClient.h index 956eacf..2f0bc9e 100644 --- a/Swiften/Parser/XMLParserClient.h +++ b/Swiften/Parser/XMLParserClient.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,12 +10,26 @@ #include <Swiften/Parser/AttributeMap.h> namespace Swift { - class SWIFTEN_API XMLParserClient { - public: - virtual ~XMLParserClient(); + class SWIFTEN_API XMLParserClient { + public: + virtual ~XMLParserClient(); - virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) = 0; - virtual void handleEndElement(const std::string& element, const std::string& ns) = 0; - virtual void handleCharacterData(const std::string& data) = 0; - }; + /** + * Client will have to implement only one of the following methods depending on whether + * he is interested in processing the element prefix or not. + */ + virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); + virtual void handleStartElementPrefix(const std::string& prefix, const std::string& uri, const std::string& element, const AttributeMap& attributes); + + virtual void handleEndElement(const std::string& element, const std::string& ns) = 0; + virtual void handleCharacterData(const std::string& data) = 0; + + /** + * Signal that a namespace prefix has been declared + * This callback might be called multiple times for a single element, + * and will trigger before the corresponding \ref handleStartElement + * is called. + */ + virtual void handleNamespaceDeclaration(const std::string& prefix, const std::string& uri); + }; } diff --git a/Swiften/Parser/XMLParserFactory.cpp b/Swiften/Parser/XMLParserFactory.cpp index af719bf..bb0d5f3 100644 --- a/Swiften/Parser/XMLParserFactory.cpp +++ b/Swiften/Parser/XMLParserFactory.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/XMLParserFactory.h> diff --git a/Swiften/Parser/XMLParserFactory.h b/Swiften/Parser/XMLParserFactory.h index 6979ea4..ae3c90e 100644 --- a/Swiften/Parser/XMLParserFactory.h +++ b/Swiften/Parser/XMLParserFactory.h @@ -1,21 +1,23 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <Swiften/Base/API.h> namespace Swift { - class XMLParser; - class XMLParserClient; + class XMLParser; + class XMLParserClient; - class SWIFTEN_API XMLParserFactory { - public: - virtual ~XMLParserFactory(); + class SWIFTEN_API XMLParserFactory { + public: + virtual ~XMLParserFactory(); - virtual XMLParser* createXMLParser(XMLParserClient*) = 0; - }; + virtual std::unique_ptr<XMLParser> createXMLParser(XMLParserClient*, bool allowComments = false) = 0; + }; } diff --git a/Swiften/Parser/XMPPParser.cpp b/Swiften/Parser/XMPPParser.cpp index 069a5bd..d2a5a98 100644 --- a/Swiften/Parser/XMPPParser.cpp +++ b/Swiften/Parser/XMPPParser.cpp @@ -1,46 +1,44 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/XMPPParser.h> -#include <iostream> #include <cassert> +#include <string> #include <Swiften/Elements/ProtocolHeader.h> -#include <string> -#include <Swiften/Parser/XMLParser.h> -#include <Swiften/Parser/XMPPParserClient.h> -#include <Swiften/Parser/XMPPParser.h> +#include <Swiften/Parser/AuthChallengeParser.h> +#include <Swiften/Parser/AuthFailureParser.h> +#include <Swiften/Parser/AuthRequestParser.h> +#include <Swiften/Parser/AuthResponseParser.h> +#include <Swiften/Parser/AuthSuccessParser.h> +#include <Swiften/Parser/ComponentHandshakeParser.h> +#include <Swiften/Parser/CompressFailureParser.h> +#include <Swiften/Parser/CompressParser.h> +#include <Swiften/Parser/CompressedParser.h> #include <Swiften/Parser/ElementParser.h> -#include <Swiften/Parser/PresenceParser.h> +#include <Swiften/Parser/EnableStreamManagementParser.h> #include <Swiften/Parser/IQParser.h> #include <Swiften/Parser/MessageParser.h> -#include <Swiften/Parser/StreamFeaturesParser.h> +#include <Swiften/Parser/PresenceParser.h> +#include <Swiften/Parser/StanzaAckParser.h> +#include <Swiften/Parser/StanzaAckRequestParser.h> +#include <Swiften/Parser/StartTLSFailureParser.h> +#include <Swiften/Parser/StartTLSParser.h> #include <Swiften/Parser/StreamErrorParser.h> -#include <Swiften/Parser/AuthRequestParser.h> -#include <Swiften/Parser/AuthSuccessParser.h> -#include <Swiften/Parser/AuthFailureParser.h> -#include <Swiften/Parser/AuthChallengeParser.h> -#include <Swiften/Parser/AuthResponseParser.h> -#include <Swiften/Parser/EnableStreamManagementParser.h> +#include <Swiften/Parser/StreamFeaturesParser.h> #include <Swiften/Parser/StreamManagementEnabledParser.h> #include <Swiften/Parser/StreamManagementFailedParser.h> #include <Swiften/Parser/StreamResumeParser.h> #include <Swiften/Parser/StreamResumedParser.h> -#include <Swiften/Parser/StanzaAckParser.h> -#include <Swiften/Parser/StanzaAckRequestParser.h> -#include <Swiften/Parser/StartTLSParser.h> -#include <Swiften/Parser/StartTLSFailureParser.h> -#include <Swiften/Parser/CompressParser.h> -#include <Swiften/Parser/CompressFailureParser.h> -#include <Swiften/Parser/CompressedParser.h> -#include <Swiften/Parser/UnknownElementParser.h> #include <Swiften/Parser/TLSProceedParser.h> -#include <Swiften/Parser/ComponentHandshakeParser.h> +#include <Swiften/Parser/UnknownElementParser.h> +#include <Swiften/Parser/XMLParser.h> #include <Swiften/Parser/XMLParserFactory.h> +#include <Swiften/Parser/XMPPParserClient.h> // TODO: Whenever an error occurs in the handlers, stop the parser by returing // a bool value, and stopping the XML parser @@ -48,159 +46,158 @@ namespace Swift { XMPPParser::XMPPParser( - XMPPParserClient* client, - PayloadParserFactoryCollection* payloadParserFactories, - XMLParserFactory* xmlParserFactory) : - xmlParser_(0), - client_(client), - payloadParserFactories_(payloadParserFactories), - level_(0), - currentElementParser_(0), - parseErrorOccurred_(false) { - xmlParser_ = xmlParserFactory->createXMLParser(this); + XMPPParserClient* client, + PayloadParserFactoryCollection* payloadParserFactories, + XMLParserFactory* xmlParserFactory) : + xmlParser_(nullptr), + client_(client), + payloadParserFactories_(payloadParserFactories), + level_(0), + currentElementParser_(nullptr), + parseErrorOccurred_(false) { + xmlParser_ = xmlParserFactory->createXMLParser(this); } XMPPParser::~XMPPParser() { - delete currentElementParser_; - delete xmlParser_; + delete currentElementParser_; } bool XMPPParser::parse(const std::string& data) { - bool xmlParseResult = xmlParser_->parse(data); - return xmlParseResult && !parseErrorOccurred_; + bool xmlParseResult = xmlParser_->parse(data); + return xmlParseResult && !parseErrorOccurred_; } void XMPPParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (!parseErrorOccurred_) { - if (level_ == TopLevel) { - if (element == "stream" && ns == "http://etherx.jabber.org/streams") { - ProtocolHeader header; - header.setFrom(attributes.getAttribute("from")); - header.setTo(attributes.getAttribute("to")); - header.setID(attributes.getAttribute("id")); - header.setVersion(attributes.getAttribute("version")); - client_->handleStreamStart(header); - } - else { - parseErrorOccurred_ = true; - } - } - else { - if (level_ == StreamLevel) { - assert(!currentElementParser_); - currentElementParser_ = createElementParser(element, ns); - } - currentElementParser_->handleStartElement(element, ns, attributes); - } - } - ++level_; + if (!parseErrorOccurred_) { + if (level_ == TopLevel) { + if (element == "stream" && ns == "http://etherx.jabber.org/streams") { + ProtocolHeader header; + header.setFrom(attributes.getAttribute("from")); + header.setTo(attributes.getAttribute("to")); + header.setID(attributes.getAttribute("id")); + header.setVersion(attributes.getAttribute("version")); + client_->handleStreamStart(header); + } + else { + parseErrorOccurred_ = true; + } + } + else { + if (level_ == StreamLevel) { + assert(!currentElementParser_); + currentElementParser_ = createElementParser(element, ns); + } + currentElementParser_->handleStartElement(element, ns, attributes); + } + } + ++level_; } void XMPPParser::handleEndElement(const std::string& element, const std::string& ns) { - assert(level_ > TopLevel); - --level_; - if (!parseErrorOccurred_) { - if (level_ == TopLevel) { - assert(element == "stream"); - client_->handleStreamEnd(); - } - else { - assert(currentElementParser_); - currentElementParser_->handleEndElement(element, ns); - if (level_ == StreamLevel) { - client_->handleElement(currentElementParser_->getElement()); - delete currentElementParser_; - currentElementParser_ = NULL; - } - } - } + assert(level_ > TopLevel); + --level_; + if (!parseErrorOccurred_) { + if (level_ == TopLevel) { + assert(element == "stream"); + client_->handleStreamEnd(); + } + else { + assert(currentElementParser_); + currentElementParser_->handleEndElement(element, ns); + if (level_ == StreamLevel) { + client_->handleElement(currentElementParser_->getElement()); + delete currentElementParser_; + currentElementParser_ = nullptr; + } + } + } } void XMPPParser::handleCharacterData(const std::string& data) { - if (!parseErrorOccurred_) { - if (currentElementParser_) { - currentElementParser_->handleCharacterData(data); - } - //else { - // std::cerr << "XMPPParser: Ignoring stray character data: " << data << std::endl; - //} - } + if (!parseErrorOccurred_) { + if (currentElementParser_) { + currentElementParser_->handleCharacterData(data); + } + //else { + // std::cerr << "XMPPParser: Ignoring stray character data: " << data << std::endl; + //} + } } ElementParser* XMPPParser::createElementParser(const std::string& element, const std::string& ns) { - if (element == "presence") { - return new PresenceParser(payloadParserFactories_); - } - else if (element == "iq") { - return new IQParser(payloadParserFactories_); - } - else if (element == "message") { - return new MessageParser(payloadParserFactories_); - } - else if (element == "features" && ns == "http://etherx.jabber.org/streams") { - return new StreamFeaturesParser(); - } - else if (element == "error" && ns == "http://etherx.jabber.org/streams") { - return new StreamErrorParser(); - } - else if (element == "auth") { - return new AuthRequestParser(); - } - else if (element == "success") { - return new AuthSuccessParser(); - } - else if (element == "failure" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") { - return new AuthFailureParser(); - } - else if (element == "challenge" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") { - return new AuthChallengeParser(); - } - else if (element == "response" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") { - return new AuthResponseParser(); - } - else if (element == "starttls") { - return new StartTLSParser(); - } - else if (element == "failure" && ns == "urn:ietf:params:xml:ns:xmpp-tls") { - return new StartTLSFailureParser(); - } - else if (element == "compress") { - return new CompressParser(); - } - else if (element == "compressed") { - return new CompressedParser(); - } - else if (element == "failure" && ns == "http://jabber.org/protocol/compress") { - return new CompressFailureParser(); - } - else if (element == "proceed") { - return new TLSProceedParser(); - } - else if (element == "enable" && ns == "urn:xmpp:sm:2") { - return new EnableStreamManagementParser(); - } - else if (element == "enabled" && ns == "urn:xmpp:sm:2") { - return new StreamManagementEnabledParser(); - } - else if (element == "failed" && ns == "urn:xmpp:sm:2") { - return new StreamManagementFailedParser(); - } - else if (element == "resume" && ns == "urn:xmpp:sm:2") { - return new StreamResumeParser(); - } - else if (element == "resumed" && ns == "urn:xmpp:sm:2") { - return new StreamResumedParser(); - } - else if (element == "a" && ns == "urn:xmpp:sm:2") { - return new StanzaAckParser(); - } - else if (element == "r" && ns == "urn:xmpp:sm:2") { - return new StanzaAckRequestParser(); - } - else if (element == "handshake") { - return new ComponentHandshakeParser(); - } - return new UnknownElementParser(); + if (element == "presence") { + return new PresenceParser(payloadParserFactories_); + } + else if (element == "iq") { + return new IQParser(payloadParserFactories_); + } + else if (element == "message") { + return new MessageParser(payloadParserFactories_); + } + else if (element == "features" && ns == "http://etherx.jabber.org/streams") { + return new StreamFeaturesParser(); + } + else if (element == "error" && ns == "http://etherx.jabber.org/streams") { + return new StreamErrorParser(); + } + else if (element == "auth") { + return new AuthRequestParser(); + } + else if (element == "success") { + return new AuthSuccessParser(); + } + else if (element == "failure" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") { + return new AuthFailureParser(); + } + else if (element == "challenge" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") { + return new AuthChallengeParser(); + } + else if (element == "response" && ns == "urn:ietf:params:xml:ns:xmpp-sasl") { + return new AuthResponseParser(); + } + else if (element == "starttls") { + return new StartTLSParser(); + } + else if (element == "failure" && ns == "urn:ietf:params:xml:ns:xmpp-tls") { + return new StartTLSFailureParser(); + } + else if (element == "compress") { + return new CompressParser(); + } + else if (element == "compressed") { + return new CompressedParser(); + } + else if (element == "failure" && ns == "http://jabber.org/protocol/compress") { + return new CompressFailureParser(); + } + else if (element == "proceed") { + return new TLSProceedParser(); + } + else if (element == "enable" && ns == "urn:xmpp:sm:2") { + return new EnableStreamManagementParser(); + } + else if (element == "enabled" && ns == "urn:xmpp:sm:2") { + return new StreamManagementEnabledParser(); + } + else if (element == "failed" && ns == "urn:xmpp:sm:2") { + return new StreamManagementFailedParser(); + } + else if (element == "resume" && ns == "urn:xmpp:sm:2") { + return new StreamResumeParser(); + } + else if (element == "resumed" && ns == "urn:xmpp:sm:2") { + return new StreamResumedParser(); + } + else if (element == "a" && ns == "urn:xmpp:sm:2") { + return new StanzaAckParser(); + } + else if (element == "r" && ns == "urn:xmpp:sm:2") { + return new StanzaAckRequestParser(); + } + else if (element == "handshake") { + return new ComponentHandshakeParser(); + } + return new UnknownElementParser(); } } diff --git a/Swiften/Parser/XMPPParser.h b/Swiften/Parser/XMPPParser.h index 757ee22..6595b94 100644 --- a/Swiften/Parser/XMPPParser.h +++ b/Swiften/Parser/XMPPParser.h @@ -1,56 +1,57 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/noncopyable.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Parser/XMLParserClient.h> #include <Swiften/Parser/AttributeMap.h> +#include <Swiften/Parser/XMLParserClient.h> namespace Swift { - class XMLParser; - class XMPPParserClient; - class XMLParserFactory; - class ElementParser; - class PayloadParserFactoryCollection; - - class SWIFTEN_API XMPPParser : public XMLParserClient, boost::noncopyable { - public: - XMPPParser( - XMPPParserClient* parserClient, - PayloadParserFactoryCollection* payloadParserFactories, - XMLParserFactory* xmlParserFactory); - ~XMPPParser(); - - bool parse(const std::string&); - - private: - virtual void handleStartElement( - const std::string& element, - const std::string& ns, - const AttributeMap& attributes); - virtual void handleEndElement(const std::string& element, const std::string& ns); - virtual void handleCharacterData(const std::string& data); - - ElementParser* createElementParser(const std::string& element, const std::string& xmlns); - - private: - XMLParser* xmlParser_; - XMPPParserClient* client_; - PayloadParserFactoryCollection* payloadParserFactories_; - enum Level { - TopLevel = 0, - StreamLevel = 1, - ElementLevel = 2 - }; - int level_; - ElementParser* currentElementParser_; - bool parseErrorOccurred_; - }; + class XMLParser; + class XMPPParserClient; + class XMLParserFactory; + class ElementParser; + class PayloadParserFactoryCollection; + + class SWIFTEN_API XMPPParser : public XMLParserClient, boost::noncopyable { + public: + XMPPParser( + XMPPParserClient* parserClient, + PayloadParserFactoryCollection* payloadParserFactories, + XMLParserFactory* xmlParserFactory); + virtual ~XMPPParser(); + + bool parse(const std::string&); + + private: + virtual void handleStartElement( + const std::string& element, + const std::string& ns, + const AttributeMap& attributes); + virtual void handleEndElement(const std::string& element, const std::string& ns); + virtual void handleCharacterData(const std::string& data); + + ElementParser* createElementParser(const std::string& element, const std::string& xmlns); + + private: + std::unique_ptr<XMLParser> xmlParser_; + XMPPParserClient* client_; + PayloadParserFactoryCollection* payloadParserFactories_; + enum Level { + TopLevel = 0, + StreamLevel = 1, + ElementLevel = 2 + }; + int level_; + ElementParser* currentElementParser_; + bool parseErrorOccurred_; + }; } diff --git a/Swiften/Parser/XMPPParserClient.cpp b/Swiften/Parser/XMPPParserClient.cpp index 4b7da04..34edcda 100644 --- a/Swiften/Parser/XMPPParserClient.cpp +++ b/Swiften/Parser/XMPPParserClient.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Parser/XMPPParserClient.h> diff --git a/Swiften/Parser/XMPPParserClient.h b/Swiften/Parser/XMPPParserClient.h index 85e0f86..97c0c64 100644 --- a/Swiften/Parser/XMPPParserClient.h +++ b/Swiften/Parser/XMPPParserClient.h @@ -1,26 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> -#include <Swiften/Elements/Element.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - - class ProtocolHeader; - class SWIFTEN_API XMPPParserClient { - public: - virtual ~XMPPParserClient(); + class ProtocolHeader; - virtual void handleStreamStart(const ProtocolHeader&) = 0; - virtual void handleElement(boost::shared_ptr<Element>) = 0; - virtual void handleStreamEnd() = 0; - }; + class SWIFTEN_API XMPPParserClient { + public: + virtual ~XMPPParserClient(); + + virtual void handleStreamStart(const ProtocolHeader&) = 0; + virtual void handleElement(std::shared_ptr<ToplevelElement>) = 0; + virtual void handleStreamEnd() = 0; + }; } diff --git a/Swiften/Presence/DirectedPresenceSender.cpp b/Swiften/Presence/DirectedPresenceSender.cpp index ec0bd3f..c1134c7 100644 --- a/Swiften/Presence/DirectedPresenceSender.cpp +++ b/Swiften/Presence/DirectedPresenceSender.cpp @@ -1,41 +1,40 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Presence/DirectedPresenceSender.h> -#include <Swiften/Base/foreach.h> namespace Swift { DirectedPresenceSender::DirectedPresenceSender(PresenceSender* sender) : sender(sender) { } -void DirectedPresenceSender::sendPresence(boost::shared_ptr<Presence> presence) { - if (!sender->isAvailable()) { - return; - } +void DirectedPresenceSender::sendPresence(std::shared_ptr<Presence> presence) { + if (!sender->isAvailable()) { + return; + } - sender->sendPresence(presence); + sender->sendPresence(presence); - if (!presence->getTo().isValid()) { - boost::shared_ptr<Presence> presenceCopy(new Presence(*presence)); - foreach(const JID& jid, directedPresenceReceivers) { - presenceCopy->setTo(jid); - sender->sendPresence(presenceCopy); - } + if (!presence->getTo().isValid()) { + std::shared_ptr<Presence> presenceCopy(new Presence(*presence)); + for (const auto& jid : directedPresenceReceivers) { + presenceCopy->setTo(jid); + sender->sendPresence(presenceCopy); + } - lastSentUndirectedPresence = presence; - } + lastSentUndirectedPresence = presence; + } } /** - * Gets either the last broadcast presence, or an empty stanza if none has been sent. + * Gets the last broadcast presence, if none has been send the returned optional is not set. */ -boost::shared_ptr<Presence> DirectedPresenceSender::getLastSentUndirectedPresence() { - boost::shared_ptr<Presence> presenceCopy(lastSentUndirectedPresence ? new Presence(*lastSentUndirectedPresence) : new Presence()); - return presenceCopy; +boost::optional<Presence::ref> DirectedPresenceSender::getLastSentUndirectedPresence() const { + boost::optional<Presence::ref> presenceCopy = lastSentUndirectedPresence ? boost::optional<Presence::ref>((*lastSentUndirectedPresence)->clone()) : boost::optional<Presence::ref>(); + return presenceCopy; } /** @@ -44,14 +43,14 @@ boost::shared_ptr<Presence> DirectedPresenceSender::getLastSentUndirectedPresenc * @param sendPresence Also send the current global presence immediately. */ void DirectedPresenceSender::addDirectedPresenceReceiver(const JID& jid, SendPresence sendPresence) { - directedPresenceReceivers.insert(jid); - if (sendPresence == AndSendPresence && sender->isAvailable()) { - if (lastSentUndirectedPresence && lastSentUndirectedPresence->getType() == Presence::Available) { - boost::shared_ptr<Presence> presenceCopy(new Presence(*lastSentUndirectedPresence)); - presenceCopy->setTo(jid); - sender->sendPresence(presenceCopy); - } - } + directedPresenceReceivers.insert(jid); + if (sendPresence == AndSendPresence && sender->isAvailable()) { + if (lastSentUndirectedPresence && (*lastSentUndirectedPresence)->getType() == Presence::Available) { + std::shared_ptr<Presence> presenceCopy((*lastSentUndirectedPresence)->clone()); + presenceCopy->setTo(jid); + sender->sendPresence(presenceCopy); + } + } } /** @@ -60,17 +59,17 @@ void DirectedPresenceSender::addDirectedPresenceReceiver(const JID& jid, SendPre * @param sendPresence Also send presence type=unavailable immediately to jid. */ void DirectedPresenceSender::removeDirectedPresenceReceiver(const JID& jid, SendPresence sendPresence) { - directedPresenceReceivers.erase(jid); - if (sendPresence == AndSendPresence && sender->isAvailable()) { - boost::shared_ptr<Presence> presence(new Presence()); - presence->setType(Presence::Unavailable); - presence->setTo(jid); - sender->sendPresence(presence); - } + directedPresenceReceivers.erase(jid); + if (sendPresence == AndSendPresence && sender->isAvailable()) { + std::shared_ptr<Presence> presence(new Presence()); + presence->setType(Presence::Unavailable); + presence->setTo(jid); + sender->sendPresence(presence); + } } bool DirectedPresenceSender::isAvailable() const { - return sender->isAvailable(); + return sender->isAvailable(); } } diff --git a/Swiften/Presence/DirectedPresenceSender.h b/Swiften/Presence/DirectedPresenceSender.h index 0eb16a4..a397776 100644 --- a/Swiften/Presence/DirectedPresenceSender.h +++ b/Swiften/Presence/DirectedPresenceSender.h @@ -1,35 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <set> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Presence.h> #include <Swiften/Presence/PresenceSender.h> -#include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API DirectedPresenceSender : public PresenceSender { - public: - enum SendPresence {AndSendPresence, DontSendPresence}; - DirectedPresenceSender(PresenceSender*); + class SWIFTEN_API DirectedPresenceSender : public PresenceSender { + public: + enum SendPresence {AndSendPresence, DontSendPresence}; + DirectedPresenceSender(PresenceSender*); - void addDirectedPresenceReceiver(const JID&, SendPresence); - void removeDirectedPresenceReceiver(const JID&, SendPresence); + void addDirectedPresenceReceiver(const JID&, SendPresence); + void removeDirectedPresenceReceiver(const JID&, SendPresence); - void sendPresence(Presence::ref); + void sendPresence(Presence::ref); - Presence::ref getLastSentUndirectedPresence(); + boost::optional<Presence::ref> getLastSentUndirectedPresence() const; - bool isAvailable() const; + bool isAvailable() const; - private: - Presence::ref lastSentUndirectedPresence; - PresenceSender* sender; - std::set<JID> directedPresenceReceivers; - }; + private: + boost::optional<Presence::ref> lastSentUndirectedPresence; + PresenceSender* sender; + std::set<JID> directedPresenceReceivers; + }; } diff --git a/Swiften/Presence/PayloadAddingPresenceSender.cpp b/Swiften/Presence/PayloadAddingPresenceSender.cpp index 5e8cd81..e5d2688 100644 --- a/Swiften/Presence/PayloadAddingPresenceSender.cpp +++ b/Swiften/Presence/PayloadAddingPresenceSender.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Presence/PayloadAddingPresenceSender.h> @@ -12,37 +12,37 @@ PayloadAddingPresenceSender::PayloadAddingPresenceSender(PresenceSender* sender) } void PayloadAddingPresenceSender::sendPresence(Presence::ref presence) { - if (presence->isAvailable()) { - if (!presence->getTo().isValid()) { - lastSentPresence = presence; - } - } - else { - lastSentPresence.reset(); - } - if (payload) { - Presence::ref sentPresence = Presence::create(presence); - sentPresence->updatePayload(payload); - sender->sendPresence(sentPresence); - } - else { - sender->sendPresence(presence); - } + if (presence->isAvailable()) { + if (!presence->getTo().isValid()) { + lastSentPresence = presence; + } + } + else { + lastSentPresence.reset(); + } + if (payload) { + Presence::ref sentPresence = Presence::create(presence); + sentPresence->updatePayload(payload); + sender->sendPresence(sentPresence); + } + else { + sender->sendPresence(presence); + } } bool PayloadAddingPresenceSender::isAvailable() const { - return sender->isAvailable(); + return sender->isAvailable(); } -void PayloadAddingPresenceSender::setPayload(boost::shared_ptr<Payload> payload) { - this->payload = payload; - if (lastSentPresence) { - sendPresence(lastSentPresence); - } +void PayloadAddingPresenceSender::setPayload(std::shared_ptr<Payload> payload) { + this->payload = payload; + if (lastSentPresence) { + sendPresence(lastSentPresence); + } } void PayloadAddingPresenceSender::reset() { - lastSentPresence.reset(); + lastSentPresence.reset(); } } diff --git a/Swiften/Presence/PayloadAddingPresenceSender.h b/Swiften/Presence/PayloadAddingPresenceSender.h index 4845865..010b77e 100644 --- a/Swiften/Presence/PayloadAddingPresenceSender.h +++ b/Swiften/Presence/PayloadAddingPresenceSender.h @@ -1,49 +1,47 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Presence/PresenceSender.h> #include <Swiften/Elements/Payload.h> +#include <Swiften/Presence/PresenceSender.h> namespace Swift { - class StanzaChannel; - - /** - * This presence sender adds payloads to outgoing presences. - * - * This class isn't meant to be used with directed presence. - */ - class SWIFTEN_API PayloadAddingPresenceSender : public PresenceSender { - public: - PayloadAddingPresenceSender(PresenceSender*); - - void sendPresence(boost::shared_ptr<Presence>); - bool isAvailable() const; - - /** - * Sets the payload to be added to outgoing presences. - * If initial presence has been sent, this will resend the last sent presence - * with an updated payload. Initial presence is reset when unavailable presence is - * sent, or when reset() is called. - */ - void setPayload(boost::shared_ptr<Payload>); - - /** - * Resets the presence sender. - * This puts the presence sender back in the initial state (before initial - * presence has been sent). - * This also resets the chained sender. - */ - void reset(); - - private: - boost::shared_ptr<Presence> lastSentPresence; - PresenceSender* sender; - boost::shared_ptr<Payload> payload; - }; + /** + * This presence sender adds payloads to outgoing presences. + * + * This class isn't meant to be used with directed presence. + */ + class SWIFTEN_API PayloadAddingPresenceSender : public PresenceSender { + public: + PayloadAddingPresenceSender(PresenceSender*); + + void sendPresence(std::shared_ptr<Presence>); + bool isAvailable() const; + + /** + * Sets the payload to be added to outgoing presences. + * If initial presence has been sent, this will resend the last sent presence + * with an updated payload. Initial presence is reset when unavailable presence is + * sent, or when reset() is called. + */ + void setPayload(std::shared_ptr<Payload>); + + /** + * Resets the presence sender. + * This puts the presence sender back in the initial state (before initial + * presence has been sent). + * This also resets the chained sender. + */ + void reset(); + + private: + std::shared_ptr<Presence> lastSentPresence; + PresenceSender* sender; + std::shared_ptr<Payload> payload; + }; } diff --git a/Swiften/Presence/PresenceOracle.cpp b/Swiften/Presence/PresenceOracle.cpp index bfb5a3d..1c9d0ea 100644 --- a/Swiften/Presence/PresenceOracle.cpp +++ b/Swiften/Presence/PresenceOracle.cpp @@ -1,115 +1,214 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include "PresenceOracle.h" +#include <Swiften/Presence/PresenceOracle.h> + +#include <queue> #include <boost/bind.hpp> #include <Swiften/Client/StanzaChannel.h> +#include <Swiften/Elements/StatusShow.h> +#include <Swiften/Roster/XMPPRoster.h> namespace Swift { -PresenceOracle::PresenceOracle(StanzaChannel* stanzaChannel) { - stanzaChannel_ = stanzaChannel; - stanzaChannel_->onPresenceReceived.connect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1)); - stanzaChannel_->onAvailableChanged.connect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1)); +PresenceOracle::PresenceOracle(StanzaChannel* stanzaChannel, XMPPRoster* roster) : stanzaChannel_(stanzaChannel), xmppRoster_(roster) { + stanzaChannel_->onPresenceReceived.connect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1)); + stanzaChannel_->onAvailableChanged.connect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1)); + xmppRoster_->onJIDRemoved.connect(boost::bind(&PresenceOracle::handleJIDRemoved, this, _1)); } PresenceOracle::~PresenceOracle() { - stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1)); - stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1)); + stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1)); + stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1)); + xmppRoster_->onJIDRemoved.disconnect(boost::bind(&PresenceOracle::handleJIDRemoved, this, _1)); } void PresenceOracle::handleStanzaChannelAvailableChanged(bool available) { - if (available) { - entries_.clear(); - } + if (available) { + entries_.clear(); + } } - void PresenceOracle::handleIncomingPresence(Presence::ref presence) { - JID bareJID(presence->getFrom().toBare()); - if (presence->getType() == Presence::Subscribe) { - } - else { - Presence::ref passedPresence = presence; - if (presence->getType() == Presence::Unsubscribe) { - /* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */ - passedPresence = Presence::ref(new Presence()); - passedPresence->setType(Presence::Unavailable); - passedPresence->setFrom(bareJID); - passedPresence->setStatus(presence->getStatus()); - } - std::map<JID, boost::shared_ptr<Presence> > jidMap = entries_[bareJID]; - if (passedPresence->getFrom().isBare() && presence->getType() == Presence::Unavailable) { - /* Have a bare-JID only presence of offline */ - jidMap.clear(); - } else if (passedPresence->getType() == Presence::Available) { - /* Don't have a bare-JID only offline presence once there are available presences */ - jidMap.erase(bareJID); - } - if (passedPresence->getType() == Presence::Unavailable && jidMap.size() > 1) { - jidMap.erase(passedPresence->getFrom()); - } else { - jidMap[passedPresence->getFrom()] = passedPresence; - } - entries_[bareJID] = jidMap; - onPresenceChange(passedPresence); - } + JID bareJID(presence->getFrom().toBare()); + if (presence->getType() == Presence::Subscribe) { + } + else { + Presence::ref passedPresence = presence; + if (presence->getType() == Presence::Unsubscribe) { + /* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */ + passedPresence = Presence::ref(new Presence()); + passedPresence->setType(Presence::Unavailable); + passedPresence->setFrom(bareJID); + passedPresence->setStatus(presence->getStatus()); + } + PresenceMap jidMap = entries_[bareJID]; + if (passedPresence->getFrom().isBare() && presence->getType() == Presence::Unavailable) { + /* Have a bare-JID only presence of offline */ + jidMap.clear(); + } else if (passedPresence->getType() == Presence::Available) { + /* Don't have a bare-JID only offline presence once there are available presences */ + jidMap.erase(bareJID); + } + if (passedPresence->getType() == Presence::Unavailable && jidMap.size() > 1) { + jidMap.erase(passedPresence->getFrom()); + } else { + jidMap[passedPresence->getFrom()] = passedPresence; + } + entries_[bareJID] = jidMap; + onPresenceChange(passedPresence); + } +} + +void PresenceOracle::handleJIDRemoved(const JID& removedJID) { + /* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */ + Presence::ref unavailablePresence = Presence::ref(new Presence()); + unavailablePresence->setType(Presence::Unavailable); + unavailablePresence->setFrom(removedJID); + + if (entries_.find(removedJID) != entries_.end()) { + entries_[removedJID].clear(); + entries_[removedJID][removedJID] = unavailablePresence; + } + + onPresenceChange(unavailablePresence); } Presence::ref PresenceOracle::getLastPresence(const JID& jid) const { - PresencesMap::const_iterator i = entries_.find(jid.toBare()); - if (i == entries_.end()) { - return Presence::ref(); - } - PresenceMap presenceMap = i->second; - PresenceMap::const_iterator j = presenceMap.find(jid); - if (j != presenceMap.end()) { - return j->second; - } - else { - return Presence::ref(); - } + PresencesMap::const_iterator i = entries_.find(jid.toBare()); + if (i == entries_.end()) { + return Presence::ref(); + } + PresenceMap presenceMap = i->second; + PresenceMap::const_iterator j = presenceMap.find(jid); + if (j != presenceMap.end()) { + return j->second; + } + else { + return Presence::ref(); + } } std::vector<Presence::ref> PresenceOracle::getAllPresence(const JID& bareJID) const { - std::vector<Presence::ref> results; - PresencesMap::const_iterator i = entries_.find(bareJID); - if (i == entries_.end()) { - return results; - } - PresenceMap presenceMap = i->second; - PresenceMap::const_iterator j = presenceMap.begin(); - for (; j != presenceMap.end(); ++j) { - Presence::ref current = j->second; - results.push_back(current); - } - return results; + std::vector<Presence::ref> results; + PresencesMap::const_iterator i = entries_.find(bareJID); + if (i == entries_.end()) { + return results; + } + for (const auto& jidPresence : i->second) { + if (jidPresence.second) { + results.push_back(jidPresence.second); + } + } + return results; +} + +struct PresenceAccountCmp { + static int preferenceFromStatusShow(StatusShow::Type showType) { + switch (showType) { + case StatusShow::FFC: + return 5; + case StatusShow::Online: + return 4; + case StatusShow::DND: + return 3; + case StatusShow::Away: + return 2; + case StatusShow::XA: + return 1; + case StatusShow::None: + return 0; + } + assert(false); + return -1; + } + + bool operator()(const Presence::ref& a, const Presence::ref& b) { + int aPreference = preferenceFromStatusShow(a->getShow()); + int bPreference = preferenceFromStatusShow(b->getShow()); + + if (aPreference != bPreference) { + return aPreference < bPreference; + } + if (a->getPriority() != b->getPriority()) { + return a->getPriority() < b->getPriority(); + } + return a->getFrom().getResource() < b->getFrom().getResource(); + } +}; + +typedef std::priority_queue<Presence::ref, std::vector<Presence::ref>, PresenceAccountCmp> PresenceAccountPriorityQueue; + +Presence::ref PresenceOracle::getActivePresence(const std::vector<Presence::ref> presences) { + Presence::ref accountPresence; + + PresenceAccountPriorityQueue online; + PresenceAccountPriorityQueue away; + PresenceAccountPriorityQueue offline; + + for (auto&& presence : presences) { + switch (presence->getShow()) { + case StatusShow::Online: + online.push(presence); + break; + case StatusShow::Away: + away.push(presence); + break; + case StatusShow::FFC: + online.push(presence); + break; + case StatusShow::XA: + away.push(presence); + break; + case StatusShow::DND: + away.push(presence); + break; + case StatusShow::None: + offline.push(presence); + break; + } + } + + if (!online.empty()) { + accountPresence = online.top(); + } + else if (!away.empty()) { + accountPresence = away.top(); + } + else if (!offline.empty()) { + accountPresence = offline.top(); + } + return accountPresence; +} + +Presence::ref PresenceOracle::getAccountPresence(const JID& jid) const { + Presence::ref accountPresence; + std::vector<Presence::ref> allPresences = getAllPresence(jid.toBare()); + accountPresence = getActivePresence(allPresences); + return accountPresence; } Presence::ref PresenceOracle::getHighestPriorityPresence(const JID& bareJID) const { - PresencesMap::const_iterator i = entries_.find(bareJID); - if (i == entries_.end()) { - return Presence::ref(); - } - PresenceMap presenceMap = i->second; - PresenceMap::const_iterator j = presenceMap.begin(); - Presence::ref highest; - for (; j != presenceMap.end(); ++j) { - Presence::ref current = j->second; - if (!highest - || current->getPriority() > highest->getPriority() - || (current->getPriority() == highest->getPriority() - && StatusShow::typeToAvailabilityOrdering(current->getShow()) > StatusShow::typeToAvailabilityOrdering(highest->getShow()))) { - highest = current; - } - - } - return highest; + PresencesMap::const_iterator i = entries_.find(bareJID); + if (i == entries_.end()) { + return Presence::ref(); + } + Presence::ref highest; + for (const auto& jidPresence : i->second) { + Presence::ref current = jidPresence.second; + if (!highest + || current->getPriority() > highest->getPriority() + || (current->getPriority() == highest->getPriority() + && StatusShow::typeToAvailabilityOrdering(current->getShow()) > StatusShow::typeToAvailabilityOrdering(highest->getShow()))) { + highest = current; + } + } + return highest; } } diff --git a/Swiften/Presence/PresenceOracle.h b/Swiften/Presence/PresenceOracle.h index fcf974f..decc0ee 100644 --- a/Swiften/Presence/PresenceOracle.h +++ b/Swiften/Presence/PresenceOracle.h @@ -1,43 +1,79 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <map> - #include <string> -#include <Swiften/Elements/Presence.h> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Elements/Presence.h> namespace Swift { - class StanzaChannel; - - class SWIFTEN_API PresenceOracle { - public: - PresenceOracle(StanzaChannel* stanzaChannel); - ~PresenceOracle(); - - Presence::ref getLastPresence(const JID&) const; - Presence::ref getHighestPriorityPresence(const JID& bareJID) const; - std::vector<Presence::ref> getAllPresence(const JID& bareJID) const; - - public: - boost::signal<void (Presence::ref)> onPresenceChange; - - private: - void handleIncomingPresence(Presence::ref presence); - void handleStanzaChannelAvailableChanged(bool); - - private: - typedef std::map<JID, Presence::ref> PresenceMap; - typedef std::map<JID, PresenceMap> PresencesMap; - PresencesMap entries_; - StanzaChannel* stanzaChannel_; - }; + class StanzaChannel; + class XMPPRoster; + + /** + * The PresenceOracle class observes all received presence stanzas for + * the \ref StanzaChannel class passed in the constructor and maintains a + * cache. + */ + class SWIFTEN_API PresenceOracle { + public: + PresenceOracle(StanzaChannel* stanzaChannel, XMPPRoster* roster); + ~PresenceOracle(); + + Presence::ref getLastPresence(const JID&) const; + Presence::ref getHighestPriorityPresence(const JID& bareJID) const; + std::vector<Presence::ref> getAllPresence(const JID& bareJID) const; + + /** + * \brief Returns the relevant presence for a list of resource presences. + * + * It only takes the presence show type into account. Priorities are + * ignored as various clients set them to arbitrary values unrelated + * to actual end point availability. + * + * The presences of the resources are group by availablilty and sorted + * by show type in the following order: + * + * -# Online + * -# Free for Chat + * -# Available + * -# Away + * -# DND + * -# Extended Away + * -# Away + * -# Offline + * -# Unavailable + */ + static Presence::ref getActivePresence(const std::vector<Presence::ref> presences); + + /** + * \brief This considers all online resources of a bare JID and returns + * the value returned by \ref getActivePresence when passing this list. + */ + Presence::ref getAccountPresence(const JID& jid) const; + + public: + boost::signals2::signal<void (Presence::ref)> onPresenceChange; + + private: + void handleIncomingPresence(Presence::ref presence); + void handleStanzaChannelAvailableChanged(bool); + void handleJIDRemoved(const JID& removedJID); + + private: + typedef std::map<JID, Presence::ref> PresenceMap; + typedef std::map<JID, PresenceMap> PresencesMap; + PresencesMap entries_; + StanzaChannel* stanzaChannel_; + XMPPRoster* xmppRoster_; + }; } diff --git a/Swiften/Presence/PresenceSender.cpp b/Swiften/Presence/PresenceSender.cpp index b75141d..20d284a 100644 --- a/Swiften/Presence/PresenceSender.cpp +++ b/Swiften/Presence/PresenceSender.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Presence/PresenceSender.h> diff --git a/Swiften/Presence/PresenceSender.h b/Swiften/Presence/PresenceSender.h index c302074..9d4e175 100644 --- a/Swiften/Presence/PresenceSender.h +++ b/Swiften/Presence/PresenceSender.h @@ -1,20 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Elements/Presence.h> namespace Swift { - class PresenceSender { - public: - virtual ~PresenceSender(); + class SWIFTEN_API PresenceSender { + public: + virtual ~PresenceSender(); - virtual void sendPresence(Presence::ref) = 0; + virtual void sendPresence(Presence::ref) = 0; - virtual bool isAvailable() const = 0; - }; + virtual bool isAvailable() const = 0; + }; } diff --git a/Swiften/Presence/SConscript b/Swiften/Presence/SConscript index 33acbd3..c3e32f2 100644 --- a/Swiften/Presence/SConscript +++ b/Swiften/Presence/SConscript @@ -1,11 +1,11 @@ Import("swiften_env") objects = swiften_env.SwiftenObject([ - "PresenceOracle.cpp", - "PresenceSender.cpp", - "DirectedPresenceSender.cpp", - "PayloadAddingPresenceSender.cpp", - "StanzaChannelPresenceSender.cpp", - "SubscriptionManager.cpp", - ]) + "PresenceOracle.cpp", + "PresenceSender.cpp", + "DirectedPresenceSender.cpp", + "PayloadAddingPresenceSender.cpp", + "StanzaChannelPresenceSender.cpp", + "SubscriptionManager.cpp", + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Presence/StanzaChannelPresenceSender.cpp b/Swiften/Presence/StanzaChannelPresenceSender.cpp index 5863a2d..a96f40f 100644 --- a/Swiften/Presence/StanzaChannelPresenceSender.cpp +++ b/Swiften/Presence/StanzaChannelPresenceSender.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Presence/StanzaChannelPresenceSender.h> + #include <Swiften/Client/StanzaChannel.h> namespace Swift { @@ -13,11 +14,11 @@ StanzaChannelPresenceSender::StanzaChannelPresenceSender(StanzaChannel* channel) } void StanzaChannelPresenceSender::sendPresence(Presence::ref presence) { - channel->sendPresence(presence); + channel->sendPresence(presence); } bool StanzaChannelPresenceSender::isAvailable() const { - return channel->isAvailable(); + return channel->isAvailable(); } } diff --git a/Swiften/Presence/StanzaChannelPresenceSender.h b/Swiften/Presence/StanzaChannelPresenceSender.h index 8649acb..2112d06 100644 --- a/Swiften/Presence/StanzaChannelPresenceSender.h +++ b/Swiften/Presence/StanzaChannelPresenceSender.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,17 +10,17 @@ #include <Swiften/Presence/PresenceSender.h> namespace Swift { - class StanzaChannel; + class StanzaChannel; - class SWIFTEN_API StanzaChannelPresenceSender : public PresenceSender { - public: - StanzaChannelPresenceSender(StanzaChannel*); + class SWIFTEN_API StanzaChannelPresenceSender : public PresenceSender { + public: + StanzaChannelPresenceSender(StanzaChannel*); - void sendPresence(Presence::ref); + void sendPresence(Presence::ref); - bool isAvailable() const; + bool isAvailable() const; - private: - StanzaChannel* channel; - }; + private: + StanzaChannel* channel; + }; } diff --git a/Swiften/Presence/SubscriptionManager.cpp b/Swiften/Presence/SubscriptionManager.cpp index 01525dd..83009e9 100644 --- a/Swiften/Presence/SubscriptionManager.cpp +++ b/Swiften/Presence/SubscriptionManager.cpp @@ -1,56 +1,55 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Presence/SubscriptionManager.h> #include <boost/bind.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/Client/StanzaChannel.h> namespace Swift { SubscriptionManager::SubscriptionManager(StanzaChannel* channel) : stanzaChannel(channel) { - stanzaChannel->onPresenceReceived.connect(boost::bind(&SubscriptionManager::handleIncomingPresence, this, _1)); + stanzaChannel->onPresenceReceived.connect(boost::bind(&SubscriptionManager::handleIncomingPresence, this, _1)); } SubscriptionManager::~SubscriptionManager() { - stanzaChannel->onPresenceReceived.disconnect(boost::bind(&SubscriptionManager::handleIncomingPresence, this, _1)); + stanzaChannel->onPresenceReceived.disconnect(boost::bind(&SubscriptionManager::handleIncomingPresence, this, _1)); } void SubscriptionManager::cancelSubscription(const JID& jid) { - Presence::ref stanza(new Presence()); - stanza->setType(Presence::Unsubscribed); - stanza->setTo(jid); - stanzaChannel->sendPresence(stanza); + Presence::ref stanza(new Presence()); + stanza->setType(Presence::Unsubscribed); + stanza->setTo(jid); + stanzaChannel->sendPresence(stanza); } void SubscriptionManager::confirmSubscription(const JID& jid) { - Presence::ref stanza(new Presence()); - stanza->setType(Presence::Subscribed); - stanza->setTo(jid); - stanzaChannel->sendPresence(stanza); + Presence::ref stanza(new Presence()); + stanza->setType(Presence::Subscribed); + stanza->setTo(jid); + stanzaChannel->sendPresence(stanza); } void SubscriptionManager::requestSubscription(const JID& jid) { - Presence::ref stanza(new Presence()); - stanza->setType(Presence::Subscribe); - stanza->setTo(jid); - stanzaChannel->sendPresence(stanza); + Presence::ref stanza(new Presence()); + stanza->setType(Presence::Subscribe); + stanza->setTo(jid); + stanzaChannel->sendPresence(stanza); } void SubscriptionManager::handleIncomingPresence(Presence::ref presence) { - JID bareJID(presence->getFrom().toBare()); - if (presence->getType() == Presence::Subscribe) { - onPresenceSubscriptionRequest(bareJID, presence->getStatus(), presence); - } - else if (presence->getType() == Presence::Unsubscribe) { - onPresenceSubscriptionRevoked(bareJID, presence->getStatus()); - } + JID bareJID(presence->getFrom().toBare()); + if (presence->getType() == Presence::Subscribe) { + onPresenceSubscriptionRequest(bareJID, presence->getStatus(), presence); + } + else if (presence->getType() == Presence::Unsubscribe) { + onPresenceSubscriptionRevoked(bareJID, presence->getStatus()); + } } diff --git a/Swiften/Presence/SubscriptionManager.h b/Swiften/Presence/SubscriptionManager.h index 5fabb04..c1997bd 100644 --- a/Swiften/Presence/SubscriptionManager.h +++ b/Swiften/Presence/SubscriptionManager.h @@ -1,47 +1,48 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <map> - #include <string> -#include <Swiften/JID/JID.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Elements/Presence.h> + +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/JID/JID.h> namespace Swift { - class StanzaChannel; - - class SWIFTEN_API SubscriptionManager { - public: - SubscriptionManager(StanzaChannel* stanzaChannel); - ~SubscriptionManager(); - - void cancelSubscription(const JID& jid); - void confirmSubscription(const JID& jid); - void requestSubscription(const JID& jid); - - /** - * This signal is emitted when a presence subscription request is - * received. - * - * The third parameter of this signal is the original presence stanza - * received. This is useful when the subscriber adds extensions to - * the request. - */ - boost::signal<void (const JID&, const std::string&, Presence::ref)> onPresenceSubscriptionRequest; - - boost::signal<void (const JID&, const std::string&)> onPresenceSubscriptionRevoked; - - private: - void handleIncomingPresence(Presence::ref presence); - - private: - StanzaChannel* stanzaChannel; - }; + class StanzaChannel; + + class SWIFTEN_API SubscriptionManager { + public: + SubscriptionManager(StanzaChannel* stanzaChannel); + ~SubscriptionManager(); + + void cancelSubscription(const JID& jid); + void confirmSubscription(const JID& jid); + void requestSubscription(const JID& jid); + + /** + * This signal is emitted when a presence subscription request is + * received. + * + * The third parameter of this signal is the original presence stanza + * received. This is useful when the subscriber adds extensions to + * the request. + */ + boost::signals2::signal<void (const JID&, const std::string&, Presence::ref)> onPresenceSubscriptionRequest; + + boost::signals2::signal<void (const JID&, const std::string&)> onPresenceSubscriptionRevoked; + + private: + void handleIncomingPresence(Presence::ref presence); + + private: + StanzaChannel* stanzaChannel; + }; } diff --git a/Swiften/Presence/UnitTest/DirectedPresenceSenderTest.cpp b/Swiften/Presence/UnitTest/DirectedPresenceSenderTest.cpp index 0da78e6..e313124 100644 --- a/Swiften/Presence/UnitTest/DirectedPresenceSenderTest.cpp +++ b/Swiften/Presence/UnitTest/DirectedPresenceSenderTest.cpp @@ -1,9 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -14,140 +16,135 @@ using namespace Swift; class DirectedPresenceSenderTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DirectedPresenceSenderTest); - CPPUNIT_TEST(testSendPresence); - CPPUNIT_TEST(testSendPresence_UndirectedPresenceWithDirectedPresenceReceivers); - CPPUNIT_TEST(testSendPresence_DirectedPresenceWithDirectedPresenceReceivers); - CPPUNIT_TEST(testAddDirectedPresenceReceiver); - CPPUNIT_TEST(testAddDirectedPresenceReceiver_WithoutSendingPresence); - CPPUNIT_TEST(testAddDirectedPresenceReceiver_AfterSendingDirectedPresence); - CPPUNIT_TEST(testRemoveDirectedPresenceReceiver); - CPPUNIT_TEST(testRemoveDirectedPresenceReceiver_WithoutSendingPresence); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - channel = new DummyStanzaChannel(); - testPresence = boost::make_shared<Presence>(); - testPresence->setStatus("Foo"); - secondTestPresence = boost::make_shared<Presence>(); - secondTestPresence->setStatus("Bar"); - stanzaChannelPresenceSender = new StanzaChannelPresenceSender(channel); - } - - void tearDown() { - delete stanzaChannelPresenceSender; - delete channel; - } - - void testSendPresence() { - boost::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); - testling->sendPresence(testPresence); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); - boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(channel->sentStanzas[0]); - CPPUNIT_ASSERT(testPresence == presence); - } - - void testSendPresence_UndirectedPresenceWithDirectedPresenceReceivers() { - boost::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); - testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); - - testling->sendPresence(testPresence); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel->sentStanzas.size())); - boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(channel->sentStanzas[0]); - CPPUNIT_ASSERT(testPresence == presence); - presence = boost::dynamic_pointer_cast<Presence>(channel->sentStanzas[1]); - CPPUNIT_ASSERT_EQUAL(testPresence->getStatus(), presence->getStatus()); - CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/teaparty"), presence->getTo()); - } - - void testSendPresence_DirectedPresenceWithDirectedPresenceReceivers() { - boost::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); - testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); - channel->sentStanzas.clear(); - - testPresence->setTo(JID("foo@bar.com")); - testling->sendPresence(testPresence); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); - boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(channel->sentStanzas[0]); - CPPUNIT_ASSERT(testPresence == presence); - } - - void testAddDirectedPresenceReceiver() { - boost::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); - testling->sendPresence(testPresence); - channel->sentStanzas.clear(); - - testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); - boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(channel->sentStanzas[0]); - CPPUNIT_ASSERT_EQUAL(testPresence->getStatus(), presence->getStatus()); - CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/teaparty"), presence->getTo()); - } - - void testAddDirectedPresenceReceiver_WithoutSendingPresence() { - boost::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); - testling->sendPresence(testPresence); - channel->sentStanzas.clear(); - - testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::DontSendPresence); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(channel->sentStanzas.size())); - } - - void testAddDirectedPresenceReceiver_AfterSendingDirectedPresence() { - boost::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); - testling->sendPresence(testPresence); - secondTestPresence->setTo(JID("foo@bar.com")); - testling->sendPresence(secondTestPresence); - channel->sentStanzas.clear(); - - testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); - boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(channel->sentStanzas[0]); - CPPUNIT_ASSERT_EQUAL(testPresence->getStatus(), presence->getStatus()); - CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/teaparty"), presence->getTo()); - } - - void testRemoveDirectedPresenceReceiver() { - boost::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); - testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::DontSendPresence); - - testling->removeDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); - testling->sendPresence(testPresence); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel->sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(boost::dynamic_pointer_cast<Presence>(channel->sentStanzas[0])->getType(), Presence::Unavailable); - CPPUNIT_ASSERT(channel->sentStanzas[1] == testPresence); - } - - void testRemoveDirectedPresenceReceiver_WithoutSendingPresence() { - boost::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); - testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); - channel->sentStanzas.clear(); - - testling->removeDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::DontSendPresence); - testling->sendPresence(testPresence); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); - CPPUNIT_ASSERT(channel->sentStanzas[0] == testPresence); - } - - private: - DirectedPresenceSender* createPresenceSender() { - return new DirectedPresenceSender(stanzaChannelPresenceSender); - } - - private: - DummyStanzaChannel* channel; - StanzaChannelPresenceSender* stanzaChannelPresenceSender; - boost::shared_ptr<Presence> testPresence; - boost::shared_ptr<Presence> secondTestPresence; + CPPUNIT_TEST_SUITE(DirectedPresenceSenderTest); + CPPUNIT_TEST(testSendPresence); + CPPUNIT_TEST(testSendPresence_UndirectedPresenceWithDirectedPresenceReceivers); + CPPUNIT_TEST(testSendPresence_DirectedPresenceWithDirectedPresenceReceivers); + CPPUNIT_TEST(testAddDirectedPresenceReceiver); + CPPUNIT_TEST(testAddDirectedPresenceReceiver_WithoutSendingPresence); + CPPUNIT_TEST(testAddDirectedPresenceReceiver_AfterSendingDirectedPresence); + CPPUNIT_TEST(testRemoveDirectedPresenceReceiver); + CPPUNIT_TEST(testRemoveDirectedPresenceReceiver_WithoutSendingPresence); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + channel = std::make_unique<DummyStanzaChannel>(); + testPresence = std::make_shared<Presence>(); + testPresence->setStatus("Foo"); + secondTestPresence = std::make_shared<Presence>(); + secondTestPresence->setStatus("Bar"); + stanzaChannelPresenceSender = std::make_unique<StanzaChannelPresenceSender>(channel.get()); + } + + void testSendPresence() { + std::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); + testling->sendPresence(testPresence); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); + std::shared_ptr<Presence> presence = std::dynamic_pointer_cast<Presence>(channel->sentStanzas[0]); + CPPUNIT_ASSERT(testPresence == presence); + } + + void testSendPresence_UndirectedPresenceWithDirectedPresenceReceivers() { + std::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); + testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); + + testling->sendPresence(testPresence); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel->sentStanzas.size())); + std::shared_ptr<Presence> presence = std::dynamic_pointer_cast<Presence>(channel->sentStanzas[0]); + CPPUNIT_ASSERT(testPresence == presence); + presence = std::dynamic_pointer_cast<Presence>(channel->sentStanzas[1]); + CPPUNIT_ASSERT_EQUAL(testPresence->getStatus(), presence->getStatus()); + CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/teaparty"), presence->getTo()); + } + + void testSendPresence_DirectedPresenceWithDirectedPresenceReceivers() { + std::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); + testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); + channel->sentStanzas.clear(); + + testPresence->setTo(JID("foo@bar.com")); + testling->sendPresence(testPresence); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); + std::shared_ptr<Presence> presence = std::dynamic_pointer_cast<Presence>(channel->sentStanzas[0]); + CPPUNIT_ASSERT(testPresence == presence); + } + + void testAddDirectedPresenceReceiver() { + std::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); + testling->sendPresence(testPresence); + channel->sentStanzas.clear(); + + testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); + std::shared_ptr<Presence> presence = std::dynamic_pointer_cast<Presence>(channel->sentStanzas[0]); + CPPUNIT_ASSERT_EQUAL(testPresence->getStatus(), presence->getStatus()); + CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/teaparty"), presence->getTo()); + } + + void testAddDirectedPresenceReceiver_WithoutSendingPresence() { + std::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); + testling->sendPresence(testPresence); + channel->sentStanzas.clear(); + + testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::DontSendPresence); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(channel->sentStanzas.size())); + } + + void testAddDirectedPresenceReceiver_AfterSendingDirectedPresence() { + std::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); + testling->sendPresence(testPresence); + secondTestPresence->setTo(JID("foo@bar.com")); + testling->sendPresence(secondTestPresence); + channel->sentStanzas.clear(); + + testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); + std::shared_ptr<Presence> presence = std::dynamic_pointer_cast<Presence>(channel->sentStanzas[0]); + CPPUNIT_ASSERT_EQUAL(testPresence->getStatus(), presence->getStatus()); + CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/teaparty"), presence->getTo()); + } + + void testRemoveDirectedPresenceReceiver() { + std::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); + testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::DontSendPresence); + + testling->removeDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); + testling->sendPresence(testPresence); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel->sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(std::dynamic_pointer_cast<Presence>(channel->sentStanzas[0])->getType(), Presence::Unavailable); + CPPUNIT_ASSERT(channel->sentStanzas[1] == testPresence); + } + + void testRemoveDirectedPresenceReceiver_WithoutSendingPresence() { + std::shared_ptr<DirectedPresenceSender> testling(createPresenceSender()); + testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::AndSendPresence); + channel->sentStanzas.clear(); + + testling->removeDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"), DirectedPresenceSender::DontSendPresence); + testling->sendPresence(testPresence); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size())); + CPPUNIT_ASSERT(channel->sentStanzas[0] == testPresence); + } + + private: + DirectedPresenceSender* createPresenceSender() { + return new DirectedPresenceSender(stanzaChannelPresenceSender.get()); + } + + private: + std::unique_ptr<DummyStanzaChannel> channel; + std::unique_ptr<StanzaChannelPresenceSender> stanzaChannelPresenceSender; + std::shared_ptr<Presence> testPresence; + std::shared_ptr<Presence> secondTestPresence; }; CPPUNIT_TEST_SUITE_REGISTRATION(DirectedPresenceSenderTest); diff --git a/Swiften/Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp b/Swiften/Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp index 3a6ab31..234f303 100644 --- a/Swiften/Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp +++ b/Swiften/Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp @@ -1,144 +1,146 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> #include <vector> + #include <boost/bind.hpp> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Elements/Body.h> #include <Swiften/Presence/PayloadAddingPresenceSender.h> #include <Swiften/Presence/StanzaChannelPresenceSender.h> -#include <Swiften/Elements/Body.h> -#include <Swiften/Client/DummyStanzaChannel.h> using namespace Swift; class PayloadAddingPresenceSenderTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PayloadAddingPresenceSenderTest); - CPPUNIT_TEST(testSetPayloadAddsPayloadOnPresenceSend); - CPPUNIT_TEST(testSetNullPayloadDoesNotAddPayloadOnPresenceSend); - CPPUNIT_TEST(testSendPresenceDoesNotAlterOriginalPayload); - CPPUNIT_TEST(testSetPayloadAfterInitialPresenceResendsPresence); - CPPUNIT_TEST(testSetPayloadAfterUnavailablePresenceDoesNotResendPresence); - CPPUNIT_TEST(testSetPayloadAfterResetDoesNotResendPresence); - CPPUNIT_TEST(testSendDirectedPresenceIsNotResent); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(PayloadAddingPresenceSenderTest); + CPPUNIT_TEST(testSetPayloadAddsPayloadOnPresenceSend); + CPPUNIT_TEST(testSetNullPayloadDoesNotAddPayloadOnPresenceSend); + CPPUNIT_TEST(testSendPresenceDoesNotAlterOriginalPayload); + CPPUNIT_TEST(testSetPayloadAfterInitialPresenceResendsPresence); + CPPUNIT_TEST(testSetPayloadAfterUnavailablePresenceDoesNotResendPresence); + CPPUNIT_TEST(testSetPayloadAfterResetDoesNotResendPresence); + CPPUNIT_TEST(testSendDirectedPresenceIsNotResent); + CPPUNIT_TEST_SUITE_END(); - public: - void setUp() { - stanzaChannel = new DummyStanzaChannel(); - presenceSender = new StanzaChannelPresenceSender(stanzaChannel); - } + public: + void setUp() { + stanzaChannel = new DummyStanzaChannel(); + presenceSender = new StanzaChannelPresenceSender(stanzaChannel); + } - void tearDown() { - delete presenceSender; - delete stanzaChannel; - } + void tearDown() { + delete presenceSender; + delete stanzaChannel; + } - void testSetPayloadAddsPayloadOnPresenceSend() { - boost::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); + void testSetPayloadAddsPayloadOnPresenceSend() { + std::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); - testling->setPayload(MyPayload::create("foo")); - testling->sendPresence(Presence::create("bar")); + testling->setPayload(MyPayload::create("foo")); + testling->sendPresence(Presence::create("bar")); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), stanzaChannel->getStanzaAtIndex<Presence>(0)->getStatus()); - CPPUNIT_ASSERT(stanzaChannel->getStanzaAtIndex<Presence>(0)->getPayload<MyPayload>()); - } + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), stanzaChannel->getStanzaAtIndex<Presence>(0)->getStatus()); + CPPUNIT_ASSERT(stanzaChannel->getStanzaAtIndex<Presence>(0)->getPayload<MyPayload>()); + } - void testSetNullPayloadDoesNotAddPayloadOnPresenceSend() { - boost::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); + void testSetNullPayloadDoesNotAddPayloadOnPresenceSend() { + std::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); - testling->setPayload(MyPayload::ref()); - testling->sendPresence(Presence::create("bar")); + testling->setPayload(MyPayload::ref()); + testling->sendPresence(Presence::create("bar")); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), stanzaChannel->getStanzaAtIndex<Presence>(0)->getStatus()); - CPPUNIT_ASSERT(!stanzaChannel->getStanzaAtIndex<Presence>(0)->getPayload<MyPayload>()); - } + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), stanzaChannel->getStanzaAtIndex<Presence>(0)->getStatus()); + CPPUNIT_ASSERT(!stanzaChannel->getStanzaAtIndex<Presence>(0)->getPayload<MyPayload>()); + } - void testSendPresenceDoesNotAlterOriginalPayload() { - boost::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); + void testSendPresenceDoesNotAlterOriginalPayload() { + std::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); - testling->setPayload(MyPayload::create("foo")); - Presence::ref presence(Presence::create("bar")); - testling->sendPresence(presence); + testling->setPayload(MyPayload::create("foo")); + Presence::ref presence(Presence::create("bar")); + testling->sendPresence(presence); - CPPUNIT_ASSERT(!presence->getPayload<MyPayload>()); - } + CPPUNIT_ASSERT(!presence->getPayload<MyPayload>()); + } - void testSetPayloadAfterInitialPresenceResendsPresence() { - boost::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); + void testSetPayloadAfterInitialPresenceResendsPresence() { + std::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); - testling->sendPresence(Presence::create("bar")); - testling->setPayload(MyPayload::create("foo")); + testling->sendPresence(Presence::create("bar")); + testling->setPayload(MyPayload::create("foo")); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), stanzaChannel->getStanzaAtIndex<Presence>(1)->getStatus()); - CPPUNIT_ASSERT(stanzaChannel->getStanzaAtIndex<Presence>(1)->getPayload<MyPayload>()); - } + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), stanzaChannel->getStanzaAtIndex<Presence>(1)->getStatus()); + CPPUNIT_ASSERT(stanzaChannel->getStanzaAtIndex<Presence>(1)->getPayload<MyPayload>()); + } - void testSetPayloadAfterUnavailablePresenceDoesNotResendPresence() { - boost::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); + void testSetPayloadAfterUnavailablePresenceDoesNotResendPresence() { + std::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); - testling->sendPresence(Presence::create("bar")); + testling->sendPresence(Presence::create("bar")); - Presence::ref presence = Presence::create("bar"); - presence->setType(Presence::Unavailable); - testling->sendPresence(presence); + Presence::ref presence = Presence::create("bar"); + presence->setType(Presence::Unavailable); + testling->sendPresence(presence); - testling->setPayload(MyPayload::create("foo")); + testling->setPayload(MyPayload::create("foo")); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - } + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + } - void testSetPayloadAfterResetDoesNotResendPresence() { - boost::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); - testling->sendPresence(Presence::create("bar")); + void testSetPayloadAfterResetDoesNotResendPresence() { + std::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); + testling->sendPresence(Presence::create("bar")); - testling->reset(); - testling->setPayload(MyPayload::create("foo")); + testling->reset(); + testling->setPayload(MyPayload::create("foo")); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - } + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + } - void testSendDirectedPresenceIsNotResent() { - boost::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); + void testSendDirectedPresenceIsNotResent() { + std::shared_ptr<PayloadAddingPresenceSender> testling(createSender()); - testling->sendPresence(Presence::create("bar")); - Presence::ref directedPresence = Presence::create("baz"); - directedPresence->setTo(JID("foo@bar.com")); - testling->sendPresence(directedPresence); - testling->setPayload(MyPayload::create("foo")); + testling->sendPresence(Presence::create("bar")); + Presence::ref directedPresence = Presence::create("baz"); + directedPresence->setTo(JID("foo@bar.com")); + testling->sendPresence(directedPresence); + testling->setPayload(MyPayload::create("foo")); - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), stanzaChannel->getStanzaAtIndex<Presence>(2)->getStatus()); - } + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), stanzaChannel->getStanzaAtIndex<Presence>(2)->getStatus()); + } - private: - boost::shared_ptr<PayloadAddingPresenceSender> createSender() { - boost::shared_ptr<PayloadAddingPresenceSender> sender(new PayloadAddingPresenceSender(presenceSender)); - return sender; - } + private: + std::shared_ptr<PayloadAddingPresenceSender> createSender() { + std::shared_ptr<PayloadAddingPresenceSender> sender(new PayloadAddingPresenceSender(presenceSender)); + return sender; + } - struct MyPayload : public Payload { - typedef boost::shared_ptr<MyPayload> ref; + struct MyPayload : public Payload { + typedef std::shared_ptr<MyPayload> ref; - MyPayload(const std::string& body) : body(body) {} + MyPayload(const std::string& body) : body(body) {} - static ref create(const std::string& body) { - return ref(new MyPayload(body)); - } + static ref create(const std::string& body) { + return ref(new MyPayload(body)); + } - std::string body; - }; + std::string body; + }; - private: - DummyStanzaChannel* stanzaChannel; - StanzaChannelPresenceSender* presenceSender; + private: + DummyStanzaChannel* stanzaChannel; + StanzaChannelPresenceSender* presenceSender; }; CPPUNIT_TEST_SUITE_REGISTRATION(PayloadAddingPresenceSenderTest); diff --git a/Swiften/Presence/UnitTest/PresenceOracleTest.cpp b/Swiften/Presence/UnitTest/PresenceOracleTest.cpp index 179538e..86a7925 100644 --- a/Swiften/Presence/UnitTest/PresenceOracleTest.cpp +++ b/Swiften/Presence/UnitTest/PresenceOracleTest.cpp @@ -1,196 +1,249 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <Swiften/Presence/PresenceOracle.h> #include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Presence/PresenceOracle.h> #include <Swiften/Presence/SubscriptionManager.h> +#include <Swiften/Roster/XMPPRoster.h> +#include <Swiften/Roster/XMPPRosterImpl.h> using namespace Swift; class PresenceOracleTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PresenceOracleTest); - CPPUNIT_TEST(testReceivePresence); - CPPUNIT_TEST(testReceivePresenceFromDifferentResources); - CPPUNIT_TEST(testSubscriptionRequest); - CPPUNIT_TEST(testReconnectResetsPresences); - CPPUNIT_TEST(testHighestPresenceSingle); - CPPUNIT_TEST(testHighestPresenceMultiple); - CPPUNIT_TEST(testHighestPresenceGlobal); - CPPUNIT_TEST(testHighestPresenceChangePriority); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - stanzaChannel_ = new DummyStanzaChannel(); - oracle_ = new PresenceOracle(stanzaChannel_); - oracle_->onPresenceChange.connect(boost::bind(&PresenceOracleTest::handlePresenceChange, this, _1)); - subscriptionManager_ = new SubscriptionManager(stanzaChannel_); - subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&PresenceOracleTest::handlePresenceSubscriptionRequest, this, _1, _2)); - user1 = JID("user1@foo.com/Foo"); - user1alt = JID("user1@foo.com/Bar"); - user2 = JID("user2@bar.com/Bar"); - } - - void tearDown() { - delete subscriptionManager_; - delete oracle_; - delete stanzaChannel_; - } - - void testHighestPresenceSingle() { - JID bareJID("alice@wonderland.lit"); - Presence::ref fiveOn = makeOnline("blah", 5); - Presence::ref fiveOff = makeOffline("/blah"); - CPPUNIT_ASSERT_EQUAL(Presence::ref(), oracle_->getHighestPriorityPresence(bareJID)); - stanzaChannel_->onPresenceReceived(fiveOn); - CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); - stanzaChannel_->onPresenceReceived(fiveOff); - CPPUNIT_ASSERT_EQUAL(fiveOff, oracle_->getHighestPriorityPresence(bareJID)); - } - - void testHighestPresenceMultiple() { - JID bareJID("alice@wonderland.lit"); - Presence::ref fiveOn = makeOnline("blah", 5); - Presence::ref fiveOff = makeOffline("/blah"); - Presence::ref tenOn = makeOnline("bert", 10); - Presence::ref tenOff = makeOffline("/bert"); - stanzaChannel_->onPresenceReceived(fiveOn); - stanzaChannel_->onPresenceReceived(tenOn); - CPPUNIT_ASSERT_EQUAL(tenOn, oracle_->getHighestPriorityPresence(bareJID)); - stanzaChannel_->onPresenceReceived(fiveOff); - CPPUNIT_ASSERT_EQUAL(tenOn, oracle_->getHighestPriorityPresence(bareJID)); - stanzaChannel_->onPresenceReceived(fiveOn); - stanzaChannel_->onPresenceReceived(tenOff); - CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); - } - - void testHighestPresenceGlobal() { - JID bareJID("alice@wonderland.lit"); - Presence::ref fiveOn = makeOnline("blah", 5); - Presence::ref fiveOff = makeOffline("/blah"); - Presence::ref tenOn = makeOnline("bert", 10); - Presence::ref allOff = makeOffline(""); - stanzaChannel_->onPresenceReceived(fiveOn); - stanzaChannel_->onPresenceReceived(tenOn); - stanzaChannel_->onPresenceReceived(allOff); - CPPUNIT_ASSERT_EQUAL(allOff, oracle_->getHighestPriorityPresence(bareJID)); - } - - void testHighestPresenceChangePriority() { - JID bareJID("alice@wonderland.lit"); - Presence::ref fiveOn = makeOnline("blah", 5); - Presence::ref fiveOff = makeOffline("/blah"); - Presence::ref tenOn = makeOnline("bert", 10); - Presence::ref tenOnThree = makeOnline("bert", 3); - Presence::ref tenOff = makeOffline("/bert"); - stanzaChannel_->onPresenceReceived(fiveOn); - stanzaChannel_->onPresenceReceived(tenOn); - stanzaChannel_->onPresenceReceived(tenOnThree); - CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); - stanzaChannel_->onPresenceReceived(fiveOff); - CPPUNIT_ASSERT_EQUAL(tenOnThree, oracle_->getHighestPriorityPresence(bareJID)); - stanzaChannel_->onPresenceReceived(fiveOn); - CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); - } - - void testReceivePresence() { - boost::shared_ptr<Presence> sentPresence(createPresence(user1)); - stanzaChannel_->onPresenceReceived(sentPresence); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(subscriptionRequests.size())); - CPPUNIT_ASSERT_EQUAL(sentPresence, changes[0]); - CPPUNIT_ASSERT_EQUAL(sentPresence, oracle_->getLastPresence(user1)); - } - - void testReceivePresenceFromDifferentResources() { - boost::shared_ptr<Presence> sentPresence1(createPresence(user1)); - boost::shared_ptr<Presence> sentPresence2(createPresence(user1alt)); - stanzaChannel_->onPresenceReceived(sentPresence1); - stanzaChannel_->onPresenceReceived(sentPresence2); - - CPPUNIT_ASSERT_EQUAL(sentPresence1, oracle_->getLastPresence(user1)); - CPPUNIT_ASSERT_EQUAL(sentPresence2, oracle_->getLastPresence(user1alt)); - } - - void testSubscriptionRequest() { - std::string reasonText = "Because I want to"; - JID sentJID = JID("me@example.com"); - - boost::shared_ptr<Presence> sentPresence(new Presence()); - sentPresence->setType(Presence::Subscribe); - sentPresence->setFrom(sentJID); - sentPresence->setStatus(reasonText); - stanzaChannel_->onPresenceReceived(sentPresence); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(subscriptionRequests.size())); - CPPUNIT_ASSERT_EQUAL(sentJID, subscriptionRequests[0].jid); - CPPUNIT_ASSERT_EQUAL(reasonText, subscriptionRequests[0].reason); - } - - void testReconnectResetsPresences() { - boost::shared_ptr<Presence> sentPresence(createPresence(user1)); - stanzaChannel_->onPresenceReceived(sentPresence); - stanzaChannel_->setAvailable(false); - stanzaChannel_->setAvailable(true); - - CPPUNIT_ASSERT(!oracle_->getLastPresence(user1)); - } - - private: - Presence::ref makeOnline(const std::string& resource, int priority) { - Presence::ref presence(new Presence()); - presence->setPriority(priority); - presence->setFrom(JID("alice@wonderland.lit/" + resource)); - return presence; - } - - Presence::ref makeOffline(const std::string& resource) { - Presence::ref presence(new Presence()); - presence->setFrom(JID("alice@wonderland.lit" + resource)); - presence->setType(Presence::Unavailable); - return presence; - } - - void handlePresenceChange(boost::shared_ptr<Presence> newPresence) { - changes.push_back(newPresence); - } - - void handlePresenceSubscriptionRequest(const JID& jid, const std::string& reason) { - SubscriptionRequestInfo subscriptionRequest; - subscriptionRequest.jid = jid; - subscriptionRequest.reason = reason; - subscriptionRequests.push_back(subscriptionRequest); - } - - boost::shared_ptr<Presence> createPresence(const JID& jid) { - boost::shared_ptr<Presence> sentPresence(new Presence("blarb")); - sentPresence->setFrom(jid); - return sentPresence; - } - - private: - struct SubscriptionRequestInfo { - JID jid; - std::string reason; - }; - PresenceOracle* oracle_; - SubscriptionManager* subscriptionManager_; - DummyStanzaChannel* stanzaChannel_; - std::vector<Presence::ref> changes; - std::vector<SubscriptionRequestInfo> subscriptionRequests; - JID user1; - JID user1alt; - JID user2; + CPPUNIT_TEST_SUITE(PresenceOracleTest); + CPPUNIT_TEST(testReceivePresence); + CPPUNIT_TEST(testReceivePresenceFromDifferentResources); + CPPUNIT_TEST(testSubscriptionRequest); + CPPUNIT_TEST(testReconnectResetsPresences); + CPPUNIT_TEST(testHighestPresenceSingle); + CPPUNIT_TEST(testHighestPresenceMultiple); + CPPUNIT_TEST(testHighestPresenceGlobal); + CPPUNIT_TEST(testHighestPresenceChangePriority); + CPPUNIT_TEST(testGetActivePresence); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + stanzaChannel_ = new DummyStanzaChannel(); + xmppRoster_ = new XMPPRosterImpl(); + + oracle_ = new PresenceOracle(stanzaChannel_, xmppRoster_); + oracle_->onPresenceChange.connect(boost::bind(&PresenceOracleTest::handlePresenceChange, this, _1)); + subscriptionManager_ = new SubscriptionManager(stanzaChannel_); + subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&PresenceOracleTest::handlePresenceSubscriptionRequest, this, _1, _2)); + user1 = JID("user1@foo.com/Foo"); + user1alt = JID("user1@foo.com/Bar"); + user2 = JID("user2@bar.com/Bar"); + } + + void tearDown() { + delete subscriptionManager_; + delete oracle_; + delete xmppRoster_; + delete stanzaChannel_; + } + + void testHighestPresenceSingle() { + JID bareJID("alice@wonderland.lit"); + Presence::ref fiveOn = makeOnline("blah", 5); + Presence::ref fiveOff = makeOffline("/blah"); + CPPUNIT_ASSERT_EQUAL(Presence::ref(), oracle_->getHighestPriorityPresence(bareJID)); + stanzaChannel_->onPresenceReceived(fiveOn); + CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); + stanzaChannel_->onPresenceReceived(fiveOff); + CPPUNIT_ASSERT_EQUAL(fiveOff, oracle_->getHighestPriorityPresence(bareJID)); + } + + void testHighestPresenceMultiple() { + JID bareJID("alice@wonderland.lit"); + Presence::ref fiveOn = makeOnline("blah", 5); + Presence::ref fiveOff = makeOffline("/blah"); + Presence::ref tenOn = makeOnline("bert", 10); + Presence::ref tenOff = makeOffline("/bert"); + stanzaChannel_->onPresenceReceived(fiveOn); + stanzaChannel_->onPresenceReceived(tenOn); + CPPUNIT_ASSERT_EQUAL(tenOn, oracle_->getHighestPriorityPresence(bareJID)); + stanzaChannel_->onPresenceReceived(fiveOff); + CPPUNIT_ASSERT_EQUAL(tenOn, oracle_->getHighestPriorityPresence(bareJID)); + stanzaChannel_->onPresenceReceived(fiveOn); + stanzaChannel_->onPresenceReceived(tenOff); + CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); + } + + void testHighestPresenceGlobal() { + JID bareJID("alice@wonderland.lit"); + Presence::ref fiveOn = makeOnline("blah", 5); + Presence::ref fiveOff = makeOffline("/blah"); + Presence::ref tenOn = makeOnline("bert", 10); + Presence::ref allOff = makeOffline(""); + stanzaChannel_->onPresenceReceived(fiveOn); + stanzaChannel_->onPresenceReceived(tenOn); + stanzaChannel_->onPresenceReceived(allOff); + CPPUNIT_ASSERT_EQUAL(allOff, oracle_->getHighestPriorityPresence(bareJID)); + } + + void testHighestPresenceChangePriority() { + JID bareJID("alice@wonderland.lit"); + Presence::ref fiveOn = makeOnline("blah", 5); + Presence::ref fiveOff = makeOffline("/blah"); + Presence::ref tenOn = makeOnline("bert", 10); + Presence::ref tenOnThree = makeOnline("bert", 3); + Presence::ref tenOff = makeOffline("/bert"); + stanzaChannel_->onPresenceReceived(fiveOn); + stanzaChannel_->onPresenceReceived(tenOn); + stanzaChannel_->onPresenceReceived(tenOnThree); + CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); + stanzaChannel_->onPresenceReceived(fiveOff); + CPPUNIT_ASSERT_EQUAL(tenOnThree, oracle_->getHighestPriorityPresence(bareJID)); + stanzaChannel_->onPresenceReceived(fiveOn); + CPPUNIT_ASSERT_EQUAL(fiveOn, oracle_->getHighestPriorityPresence(bareJID)); + } + + void testReceivePresence() { + std::shared_ptr<Presence> sentPresence(createPresence(user1)); + stanzaChannel_->onPresenceReceived(sentPresence); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(subscriptionRequests.size())); + CPPUNIT_ASSERT_EQUAL(sentPresence, changes[0]); + CPPUNIT_ASSERT_EQUAL(sentPresence, oracle_->getLastPresence(user1)); + } + + void testReceivePresenceFromDifferentResources() { + std::shared_ptr<Presence> sentPresence1(createPresence(user1)); + std::shared_ptr<Presence> sentPresence2(createPresence(user1alt)); + stanzaChannel_->onPresenceReceived(sentPresence1); + stanzaChannel_->onPresenceReceived(sentPresence2); + + CPPUNIT_ASSERT_EQUAL(sentPresence1, oracle_->getLastPresence(user1)); + CPPUNIT_ASSERT_EQUAL(sentPresence2, oracle_->getLastPresence(user1alt)); + } + + void testSubscriptionRequest() { + std::string reasonText = "Because I want to"; + JID sentJID = JID("me@example.com"); + + std::shared_ptr<Presence> sentPresence(new Presence()); + sentPresence->setType(Presence::Subscribe); + sentPresence->setFrom(sentJID); + sentPresence->setStatus(reasonText); + stanzaChannel_->onPresenceReceived(sentPresence); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(subscriptionRequests.size())); + CPPUNIT_ASSERT_EQUAL(sentJID, subscriptionRequests[0].jid); + CPPUNIT_ASSERT_EQUAL(reasonText, subscriptionRequests[0].reason); + } + + void testReconnectResetsPresences() { + std::shared_ptr<Presence> sentPresence(createPresence(user1)); + stanzaChannel_->onPresenceReceived(sentPresence); + stanzaChannel_->setAvailable(false); + stanzaChannel_->setAvailable(true); + + CPPUNIT_ASSERT(!oracle_->getLastPresence(user1)); + } + + void testGetActivePresence() { + { + std::vector<Presence::ref> presenceList; + presenceList.push_back(createPresence("alice@wonderland.lit/resourceA", 10, Presence::Available, StatusShow::Away)); + presenceList.push_back(createPresence("alice@wonderland.lit/resourceB", 5, Presence::Available, StatusShow::Online)); + + CPPUNIT_ASSERT_EQUAL(StatusShow::Online, PresenceOracle::getActivePresence(presenceList)->getShow()); + } + + { + std::vector<Presence::ref> presenceList; + presenceList.push_back(createPresence("alice@wonderland.lit/resourceA", 10, Presence::Available, StatusShow::Away)); + presenceList.push_back(createPresence("alice@wonderland.lit/resourceB", 5, Presence::Available, StatusShow::DND)); + + CPPUNIT_ASSERT_EQUAL(StatusShow::DND, PresenceOracle::getActivePresence(presenceList)->getShow()); + } + + { + std::vector<Presence::ref> presenceList; + presenceList.push_back(createPresence("alice@wonderland.lit/resourceA", 0, Presence::Available, StatusShow::Online)); + presenceList.push_back(createPresence("alice@wonderland.lit/resourceB", 0, Presence::Available, StatusShow::DND)); + + CPPUNIT_ASSERT_EQUAL(StatusShow::Online, PresenceOracle::getActivePresence(presenceList)->getShow()); + } + + { + std::vector<Presence::ref> presenceList; + presenceList.push_back(createPresence("alice@wonderland.lit/resourceA", 1, Presence::Available, StatusShow::Online)); + presenceList.push_back(createPresence("alice@wonderland.lit/resourceB", 0, Presence::Available, StatusShow::Online)); + + CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit/resourceA"), PresenceOracle::getActivePresence(presenceList)->getFrom()); + } + } + + private: + Presence::ref createPresence(const JID &jid, int priority, Presence::Type type, const StatusShow::Type& statusShow) { + Presence::ref presence = std::make_shared<Presence>(); + presence->setFrom(jid); + presence->setPriority(priority); + presence->setType(type); + presence->setShow(statusShow); + return presence; + } + + + Presence::ref makeOnline(const std::string& resource, int priority) { + Presence::ref presence(new Presence()); + presence->setPriority(priority); + presence->setFrom(JID("alice@wonderland.lit/" + resource)); + return presence; + } + + Presence::ref makeOffline(const std::string& resource) { + Presence::ref presence(new Presence()); + presence->setFrom(JID("alice@wonderland.lit" + resource)); + presence->setType(Presence::Unavailable); + return presence; + } + + void handlePresenceChange(std::shared_ptr<Presence> newPresence) { + changes.push_back(newPresence); + } + + void handlePresenceSubscriptionRequest(const JID& jid, const std::string& reason) { + SubscriptionRequestInfo subscriptionRequest; + subscriptionRequest.jid = jid; + subscriptionRequest.reason = reason; + subscriptionRequests.push_back(subscriptionRequest); + } + + std::shared_ptr<Presence> createPresence(const JID& jid) { + std::shared_ptr<Presence> sentPresence(new Presence("blarb")); + sentPresence->setFrom(jid); + return sentPresence; + } + + private: + struct SubscriptionRequestInfo { + JID jid; + std::string reason; + }; + PresenceOracle* oracle_; + SubscriptionManager* subscriptionManager_; + DummyStanzaChannel* stanzaChannel_; + XMPPRoster* xmppRoster_; + std::vector<Presence::ref> changes; + std::vector<SubscriptionRequestInfo> subscriptionRequests; + JID user1; + JID user1alt; + JID user2; }; CPPUNIT_TEST_SUITE_REGISTRATION(PresenceOracleTest); diff --git a/Swiften/PubSub/PubSubManager.cpp b/Swiften/PubSub/PubSubManager.cpp index 8899b1e..4b71019d4 100644 --- a/Swiften/PubSub/PubSubManager.cpp +++ b/Swiften/PubSub/PubSubManager.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Swiften/PubSub/PubSubManager.h b/Swiften/PubSub/PubSubManager.h index 2f3c84d..477b3de 100644 --- a/Swiften/PubSub/PubSubManager.h +++ b/Swiften/PubSub/PubSubManager.h @@ -1,53 +1,52 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <boost/signals2.hpp> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Queries/PubSubRequest.h> -#include <Swiften/PubSub/PubSubUtil.h> +#include <Swiften/Elements/IQ.h> #include <Swiften/Elements/PubSub.h> -#include <Swiften/Elements/PubSubOwnerPubSub.h> -#include <Swiften/Elements/PubSubCreate.h> -#include <Swiften/Elements/PubSubSubscribe.h> #include <Swiften/Elements/PubSubAffiliations.h> +#include <Swiften/Elements/PubSubCreate.h> #include <Swiften/Elements/PubSubDefault.h> +#include <Swiften/Elements/PubSubEventPayload.h> #include <Swiften/Elements/PubSubItems.h> -#include <Swiften/Elements/PubSubPublish.h> -#include <Swiften/Elements/PubSubRetract.h> -#include <Swiften/Elements/PubSubSubscription.h> -#include <Swiften/Elements/PubSubSubscriptions.h> -#include <Swiften/Elements/PubSubUnsubscribe.h> #include <Swiften/Elements/PubSubOwnerAffiliations.h> #include <Swiften/Elements/PubSubOwnerConfigure.h> #include <Swiften/Elements/PubSubOwnerDefault.h> #include <Swiften/Elements/PubSubOwnerDelete.h> +#include <Swiften/Elements/PubSubOwnerPubSub.h> #include <Swiften/Elements/PubSubOwnerPurge.h> #include <Swiften/Elements/PubSubOwnerSubscriptions.h> -#include <Swiften/Elements/IQ.h> -#include <Swiften/Elements/PubSubEventPayload.h> - +#include <Swiften/Elements/PubSubPublish.h> +#include <Swiften/Elements/PubSubRetract.h> +#include <Swiften/Elements/PubSubSubscribe.h> +#include <Swiften/Elements/PubSubSubscription.h> +#include <Swiften/Elements/PubSubSubscriptions.h> +#include <Swiften/Elements/PubSubUnsubscribe.h> +#include <Swiften/PubSub/PubSubUtil.h> +#include <Swiften/Queries/PubSubRequest.h> #define SWIFTEN_PUBSUBMANAGER_DECLARE_CREATE_REQUEST(payload, container, response) \ - virtual boost::shared_ptr< PubSubRequest<payload> > \ - createRequest(IQ::Type, const JID&, boost::shared_ptr<payload>) = 0; + virtual std::shared_ptr< PubSubRequest<payload> > \ + createRequest(IQ::Type, const JID&, std::shared_ptr<payload>) = 0; namespace Swift { - class JID; + class JID; + + class SWIFTEN_API PubSubManager { + public: + virtual ~PubSubManager(); - class SWIFTEN_API PubSubManager { - public: - virtual ~PubSubManager(); - - SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE( - SWIFTEN_PUBSUBMANAGER_DECLARE_CREATE_REQUEST) + SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE( + SWIFTEN_PUBSUBMANAGER_DECLARE_CREATE_REQUEST) - boost::signal<void (const JID&, const boost::shared_ptr<PubSubEventPayload>)> onEvent; - }; + boost::signals2::signal<void (const JID&, const std::shared_ptr<PubSubEventPayload>)> onEvent; + }; } diff --git a/Swiften/PubSub/PubSubManagerImpl.cpp b/Swiften/PubSub/PubSubManagerImpl.cpp index 38b02aa..12eb25c 100644 --- a/Swiften/PubSub/PubSubManagerImpl.cpp +++ b/Swiften/PubSub/PubSubManagerImpl.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -14,18 +14,18 @@ using namespace Swift; -PubSubManagerImpl::PubSubManagerImpl(StanzaChannel* stanzaChannel, IQRouter* router) : - stanzaChannel(stanzaChannel), - router(router) { - stanzaChannel->onMessageReceived.connect(boost::bind(&PubSubManagerImpl::handleMessageRecevied, this, _1)); +PubSubManagerImpl::PubSubManagerImpl(StanzaChannel* stanzaChannel, IQRouter* router) : + stanzaChannel(stanzaChannel), + router(router) { + stanzaChannel->onMessageReceived.connect(boost::bind(&PubSubManagerImpl::handleMessageRecevied, this, _1)); } PubSubManagerImpl::~PubSubManagerImpl() { - stanzaChannel->onMessageReceived.disconnect(boost::bind(&PubSubManagerImpl::handleMessageRecevied, this, _1)); + stanzaChannel->onMessageReceived.disconnect(boost::bind(&PubSubManagerImpl::handleMessageRecevied, this, _1)); } -void PubSubManagerImpl::handleMessageRecevied(boost::shared_ptr<Message> message) { - if (boost::shared_ptr<PubSubEvent> event = message->getPayload<PubSubEvent>()) { - onEvent(message->getFrom(), event->getPayload()); - } +void PubSubManagerImpl::handleMessageRecevied(std::shared_ptr<Message> message) { + if (std::shared_ptr<PubSubEvent> event = message->getPayload<PubSubEvent>()) { + onEvent(message->getFrom(), event->getPayload()); + } } diff --git a/Swiften/PubSub/PubSubManagerImpl.h b/Swiften/PubSub/PubSubManagerImpl.h index ba363ef..0d0739c 100644 --- a/Swiften/PubSub/PubSubManagerImpl.h +++ b/Swiften/PubSub/PubSubManagerImpl.h @@ -1,41 +1,38 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/PubSub/PubSubManager.h> - #define SWIFTEN_PUBSUBMANAGERIMPL_DECLARE_CREATE_REQUEST(payload, container, response) \ - virtual boost::shared_ptr< PubSubRequest<payload> > \ - createRequest(IQ::Type type, const JID& receiver, boost::shared_ptr<payload> p) SWIFTEN_OVERRIDE { \ - return boost::make_shared< PubSubRequest<payload> >(type, receiver, p, router); \ - } + virtual std::shared_ptr< PubSubRequest<payload> > \ + createRequest(IQ::Type type, const JID& receiver, std::shared_ptr<payload> p) override { \ + return std::make_shared< PubSubRequest<payload> >(type, receiver, p, router); \ + } namespace Swift { - class JID; - class StanzaChannel; - class Message; + class StanzaChannel; + class Message; - class SWIFTEN_API PubSubManagerImpl : public PubSubManager { - public: - PubSubManagerImpl(StanzaChannel* stanzaChannel, IQRouter* router); - virtual ~PubSubManagerImpl(); + class SWIFTEN_API PubSubManagerImpl : public PubSubManager { + public: + PubSubManagerImpl(StanzaChannel* stanzaChannel, IQRouter* router); + virtual ~PubSubManagerImpl() override; - SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE( - SWIFTEN_PUBSUBMANAGERIMPL_DECLARE_CREATE_REQUEST) + SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE( + SWIFTEN_PUBSUBMANAGERIMPL_DECLARE_CREATE_REQUEST) - private: - void handleMessageRecevied(boost::shared_ptr<Message>); + private: + void handleMessageRecevied(std::shared_ptr<Message>); - private: - StanzaChannel* stanzaChannel; - IQRouter* router; - }; + private: + StanzaChannel* stanzaChannel; + IQRouter* router; + }; } diff --git a/Swiften/PubSub/PubSubUtil.h b/Swiften/PubSub/PubSubUtil.h index 3342659..ac23092 100644 --- a/Swiften/PubSub/PubSubUtil.h +++ b/Swiften/PubSub/PubSubUtil.h @@ -1,27 +1,26 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once - #define SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE(action) \ - action(PubSubCreate, PubSub, PubSubCreate) \ - action(PubSubAffiliations, PubSub, PubSubAffiliations) \ - action(PubSubDefault, PubSub, PubSubDefault) \ - action(PubSubItems, PubSub, PubSubItems) \ - action(PubSubOptions, PubSub, PubSubOptions) \ - action(PubSubPublish, PubSub, PubSubPublish) \ - action(PubSubRetract, PubSub, PubSubRetract) \ - action(PubSubSubscription, PubSub, PubSubSubscription) \ - action(PubSubSubscriptions, PubSub, PubSubSubscriptions) \ - action(PubSubSubscribe, PubSub, PubSubSubscription) \ - action(PubSubUnsubscribe, PubSub, PubSubUnsubscribe) \ - action(PubSubOwnerAffiliations, PubSubOwnerPubSub, PubSubOwnerAffiliations) \ - action(PubSubOwnerConfigure, PubSubOwnerPubSub, PubSubOwnerConfigure) \ - action(PubSubOwnerDefault, PubSubOwnerPubSub, PubSubOwnerDefault) \ - action(PubSubOwnerDelete, PubSubOwnerPubSub, PubSubOwnerDelete) \ - action(PubSubOwnerPurge, PubSubOwnerPubSub, PubSubOwnerPurge) \ - action(PubSubOwnerSubscriptions, PubSubOwnerPubSub, PubSubOwnerSubscriptions) + action(PubSubCreate, PubSub, PubSubCreate) \ + action(PubSubAffiliations, PubSub, PubSubAffiliations) \ + action(PubSubDefault, PubSub, PubSubDefault) \ + action(PubSubItems, PubSub, PubSubItems) \ + action(PubSubOptions, PubSub, PubSubOptions) \ + action(PubSubPublish, PubSub, PubSubPublish) \ + action(PubSubRetract, PubSub, PubSubRetract) \ + action(PubSubSubscription, PubSub, PubSubSubscription) \ + action(PubSubSubscriptions, PubSub, PubSubSubscriptions) \ + action(PubSubSubscribe, PubSub, PubSubSubscription) \ + action(PubSubUnsubscribe, PubSub, PubSubUnsubscribe) \ + action(PubSubOwnerAffiliations, PubSubOwnerPubSub, PubSubOwnerAffiliations) \ + action(PubSubOwnerConfigure, PubSubOwnerPubSub, PubSubOwnerConfigure) \ + action(PubSubOwnerDefault, PubSubOwnerPubSub, PubSubOwnerDefault) \ + action(PubSubOwnerDelete, PubSubOwnerPubSub, PubSubOwnerDelete) \ + action(PubSubOwnerPurge, PubSubOwnerPubSub, PubSubOwnerPurge) \ + action(PubSubOwnerSubscriptions, PubSubOwnerPubSub, PubSubOwnerSubscriptions) diff --git a/Swiften/QA/ClientTest/ClientTest.cpp b/Swiften/QA/ClientTest/ClientTest.cpp index e88e5ac..c5117fa 100644 --- a/Swiften/QA/ClientTest/ClientTest.cpp +++ b/Swiften/QA/ClientTest/ClientTest.cpp @@ -1,98 +1,110 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/bind.hpp> -#include <boost/thread.hpp> #include <iostream> +#include <thread> + +#include <boost/bind.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Client/Client.h> -#include <Swiften/Network/TimerFactory.h> -#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Client/ClientXMLTracer.h> #include <Swiften/EventLoop/EventLoop.h> #include <Swiften/EventLoop/SimpleEventLoop.h> +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Network/TimerFactory.h> #include <Swiften/Roster/GetRosterRequest.h> -#include <Swiften/Client/ClientXMLTracer.h> using namespace Swift; static SimpleEventLoop eventLoop; static BoostNetworkFactories networkFactories(&eventLoop); -static Client* client = 0; +static Client* client = nullptr; static bool rosterReceived = false; enum TestStage { - FirstConnect, - Reconnect + FirstConnect, + Reconnect }; static TestStage stage; static ClientOptions options; static void handleDisconnected(boost::optional<ClientError> e) { - std::cout << "Disconnected: " << e << std::endl; - if (stage == FirstConnect) { - stage = Reconnect; - client->connect(options); - } - else { - eventLoop.stop(); - } + std::cout << "Disconnected: " << (e ? e.get().getType() : ClientError::UnknownError) << std::endl; + if (stage == FirstConnect) { + stage = Reconnect; + client->connect(options); + } + else { + eventLoop.stop(); + } } -static void handleRosterReceived(boost::shared_ptr<Payload>) { - rosterReceived = true; - std::cout << "Disconnecting" << std::endl; - client->disconnect(); +static void handleRosterReceived(std::shared_ptr<Payload>) { + rosterReceived = true; + std::cout << "Disconnecting" << std::endl; + client->disconnect(); } static void handleConnected() { - std::cout << "Connected" << std::endl; - rosterReceived = false; - GetRosterRequest::ref rosterRequest = GetRosterRequest::create(client->getIQRouter()); - rosterRequest->onResponse.connect(boost::bind(&handleRosterReceived, _1)); - rosterRequest->send(); + std::cout << "Connected" << std::endl; + rosterReceived = false; + GetRosterRequest::ref rosterRequest = GetRosterRequest::create(client->getIQRouter()); + rosterRequest->onResponse.connect(boost::bind(&handleRosterReceived, _1)); + rosterRequest->send(); } int main(int, char**) { - char* jid = getenv("SWIFT_CLIENTTEST_JID"); - if (!jid) { - std::cerr << "Please set the SWIFT_CLIENTTEST_JID environment variable" << std::endl; - return -1; - } - char* pass = getenv("SWIFT_CLIENTTEST_PASS"); - if (!pass) { - std::cerr << "Please set the SWIFT_CLIENTTEST_PASS environment variable" << std::endl; - return -1; - } - - char* boshHost = getenv("SWIFT_CLIENTTEST_BOSH_HOST"); - char* boshPort = getenv("SWIFT_CLIENTTEST_BOSH_PORT"); - char* boshPath = getenv("SWIFT_CLIENTTEST_BOSH_PATH"); - - if (boshHost && boshPort && boshPath) { - std::cout << "Using BOSH with URL: http://" << boshHost << ":" << boshPort << "/" << boshPath << std::endl; - options.boshURL = URL("http", boshHost, atoi(boshPort), boshPath); - } - - client = new Swift::Client(JID(jid), std::string(pass), &networkFactories); - ClientXMLTracer* tracer = new ClientXMLTracer(client, !options.boshURL.isEmpty()); - client->onConnected.connect(&handleConnected); - client->onDisconnected.connect(boost::bind(&handleDisconnected, _1)); - client->setAlwaysTrustCertificates(); - stage = FirstConnect; - client->connect(options); - - { - Timer::ref timer = networkFactories.getTimerFactory()->createTimer(60000); - timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); - timer->start(); - - eventLoop.run(); - } - - delete tracer; - delete client; - return !rosterReceived; + char* jid = getenv("SWIFT_CLIENTTEST_JID"); + if (!jid) { + std::cerr << "Please set the SWIFT_CLIENTTEST_JID environment variable" << std::endl; + return -1; + } + char* pass = getenv("SWIFT_CLIENTTEST_PASS"); + if (!pass) { + std::cerr << "Please set the SWIFT_CLIENTTEST_PASS environment variable" << std::endl; + return -1; + } + + char* boshHost = getenv("SWIFT_CLIENTTEST_BOSH_HOST"); + char* boshPort = getenv("SWIFT_CLIENTTEST_BOSH_PORT"); + char* boshPath = getenv("SWIFT_CLIENTTEST_BOSH_PATH"); + + if (boshHost && boshPort && boshPath) { + std::cout << "Using BOSH with URL: http://" << boshHost << ":" << boshPort << boshPath << std::endl; + try { + options.boshURL = URL("http", boshHost, boost::numeric_cast<unsigned short>(boost::lexical_cast<int>(boshPort)), boshPath); + } + catch (const boost::numeric::bad_numeric_cast& e) { + std::cerr << "SWIFT_CLIENTTEST_BOSH_PORT doesn't hold a valid port number: " << e.what() << std::endl; + return -1; + } + catch (const boost::bad_lexical_cast& e) { + std::cerr << "SWIFT_CLIENTTEST_BOSH_PORT doesn't hold a valid port number: " << e.what() << std::endl; + return -1; + } + } + + client = new Swift::Client(JID(jid), std::string(pass), &networkFactories); + ClientXMLTracer* tracer = new ClientXMLTracer(client, !options.boshURL.isEmpty()); + client->onConnected.connect(&handleConnected); + client->onDisconnected.connect(boost::bind(&handleDisconnected, _1)); + client->setAlwaysTrustCertificates(); + stage = FirstConnect; + client->connect(options); + + { + Timer::ref timer = networkFactories.getTimerFactory()->createTimer(60000); + timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); + timer->start(); + + eventLoop.run(); + } + + delete tracer; + delete client; + return !rosterReceived; } diff --git a/Swiften/QA/ClientTest/SConscript b/Swiften/QA/ClientTest/SConscript index 15a68c6..812c472 100644 --- a/Swiften/QA/ClientTest/SConscript +++ b/Swiften/QA/ClientTest/SConscript @@ -3,15 +3,15 @@ import os Import("env") if env["TEST"] : - myenv = env.Clone() - myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) - myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) + myenv = env.Clone() + myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) + myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) - for i in ["SWIFT_CLIENTTEST_JID", "SWIFT_CLIENTTEST_PASS"]: - if ARGUMENTS.get(i.lower(), False) : - myenv["ENV"][i] = ARGUMENTS[i.lower()] - elif os.environ.get(i, "") : - myenv["ENV"][i] = os.environ[i] + for i in ["SWIFT_CLIENTTEST_JID", "SWIFT_CLIENTTEST_PASS"]: + if ARGUMENTS.get(i.lower(), False) : + myenv["ENV"][i] = ARGUMENTS[i.lower()] + elif os.environ.get(i, "") : + myenv["ENV"][i] = os.environ[i] - tester = myenv.Program("ClientTest", ["ClientTest.cpp"]) - myenv.Test(tester, "system") + tester = myenv.Program("ClientTest", ["ClientTest.cpp"]) + myenv.Test(tester, "system") diff --git a/Swiften/QA/ConcurrentFileTransferTest/ConcurrentFileTransferTest.cpp b/Swiften/QA/ConcurrentFileTransferTest/ConcurrentFileTransferTest.cpp new file mode 100644 index 0000000..22ee9d7 --- /dev/null +++ b/Swiften/QA/ConcurrentFileTransferTest/ConcurrentFileTransferTest.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <fstream> +#include <map> +#include <string> + +#include <boost/filesystem.hpp> +#include <boost/numeric/conversion/cast.hpp> + +#include <Swiften/Base/Debug.h> +#include <Swiften/Base/Log.h> +#include <Swiften/Base/sleep.h> +#include <Swiften/Base/StdRandomGenerator.h> +#include <Swiften/Client/Client.h> +#include <Swiften/Client/ClientXMLTracer.h> +#include <Swiften/Disco/ClientDiscoManager.h> +#include <Swiften/Disco/EntityCapsProvider.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/EventLoop/SimpleEventLoop.h> +#include <Swiften/FileTransfer/FileReadBytestream.h> +#include <Swiften/FileTransfer/FileTransferManager.h> +#include <Swiften/FileTransfer/FileWriteBytestream.h> +#include <Swiften/FileTransfer/OutgoingFileTransfer.h> +#include <Swiften/FileTransfer/ReadBytestream.h> +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Network/Timer.h> +#include <Swiften/Network/TimerFactory.h> + +using namespace Swift; + +static const std::string CLIENT_NAME = "Swiften FT Test"; +static const std::string CLIENT_NODE = "http://swift.im"; + +static std::shared_ptr<SimpleEventLoop> eventLoop; +static std::shared_ptr<BoostNetworkFactories> networkFactories; + +StdRandomGenerator randGen; + +enum Candidate { + InBandBytestream = 1, + S5B_Direct = 2, + S5B_Proxied = 4, + S5B_Assisted = 8, +}; + +class ConcurrentFileTransferTest { + public: + ConcurrentFileTransferTest(int clientACandidates, int clientBCandidates) : clientACandidates_(clientACandidates), clientBCandidates_(clientBCandidates) { + + } + + private: + int clientACandidates_; + std::shared_ptr<Client> clientA_; + std::map<std::string, ByteArray> clientASendFiles_; + + + int clientBCandidates_; + std::shared_ptr<Client> clientB_; +}; + +/** + * This program tests the concurrent transfer of multiple file-transfers. + * + */ +int main(int argc, char** argv) { + int failedTests = 0; + + if (!env("SWIFT_FILETRANSFERTEST_JID") && !env("SWIFT_FILETRANSFERTEST_PASS") && !env("SWIFT_FILETRANSFERTEST2_JID") && !env("SWIFT_FILETRANSFERTEST2_PASS")) { + + return -1; + } + + + return failedTests; +} diff --git a/Swiften/QA/ConcurrentFileTransferTest/SConscript b/Swiften/QA/ConcurrentFileTransferTest/SConscript new file mode 100644 index 0000000..94b37fd --- /dev/null +++ b/Swiften/QA/ConcurrentFileTransferTest/SConscript @@ -0,0 +1,17 @@ +import os + +Import("env") + +if env["TEST"] : + myenv = env.Clone() + myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) + myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) + + for i in ["SWIFT_FILETRANSFERTEST_JID", "SWIFT_FILETRANSFERTEST_PASS", "SWIFT_FILETRANSFERTEST2_JID", "SWIFT_FILETRANSFERTEST2_PASS"]: + if ARGUMENTS.get(i.lower(), False) : + myenv["ENV"][i] = ARGUMENTS[i.lower()] + elif os.environ.get(i, "") : + myenv["ENV"][i] = os.environ[i] + + tester = myenv.Program("ConcurrentFileTransferTest", ["ConcurrentFileTransferTest.cpp"]) + myenv.Test(tester, "system") diff --git a/Swiften/QA/DNSSDTest/DNSSDTest.cpp b/Swiften/QA/DNSSDTest/DNSSDTest.cpp index 7e2a189..5a78d2f 100644 --- a/Swiften/QA/DNSSDTest/DNSSDTest.cpp +++ b/Swiften/QA/DNSSDTest/DNSSDTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ // TODO: Test registering on different interfaces @@ -28,120 +28,120 @@ using namespace Swift; template <typename DNSSDQuerierType> class DNSSDTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DNSSDTest); - CPPUNIT_TEST(testPublish); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - eventLoop = new DummyEventLoop(); - querier = boost::shared_ptr<DNSSDQuerier>(new DNSSDQuerierType()); - querier->start(); - } - - void tearDown() { - querier->stop(); - querier.reset(); - delete eventLoop; - } - - void testPublish() { - boost::shared_ptr<DNSSDBrowseQuery> browseQuery = querier->createBrowseQuery(); - browseQuery->onServiceAdded.connect(boost::bind(&DNSSDTest::handleServiceAdded, this, _1)); - browseQuery->onServiceRemoved.connect(boost::bind(&DNSSDTest::handleServiceRemoved, this, _1)); - browseQuery->onError.connect(boost::bind(&DNSSDTest::handleBrowseError, this)); - browseQuery->startBrowsing(); - eventLoop->processEvents(); - - // Publish the service - LinkLocalServiceInfo info; - boost::shared_ptr<DNSSDRegisterQuery> registerQuery = querier->createRegisterQuery("DNSSDTest", 1234, info.toTXTRecord()); - registerQuery->onRegisterFinished.connect(boost::bind(&DNSSDTest::handleRegisterFinished, this, _1)); - registerQuery->registerService(); - - // Wait for a while - wait(); - - // Check that our registered queries are correct - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>((registered.size()))); - CPPUNIT_ASSERT_EQUAL(std::string("DNSSDTest"), registered[0].getName()); - CPPUNIT_ASSERT_EQUAL(std::string("local"), registered[0].getDomain()); - CPPUNIT_ASSERT_EQUAL(std::string("_presence._tcp"), registered[0].getType()); - - // Check that our browse query discovered us - std::sort(added.begin(), added.end()); - CPPUNIT_ASSERT(added.size() >= 1); - //for (size_t i = 0; i < added.size(); ++i) { - for (size_t i = 0; i < added.size(); ++i) { - CPPUNIT_ASSERT_EQUAL(std::string("DNSSDTest"), added[i].getName()); - CPPUNIT_ASSERT_EQUAL(std::string("local"), added[i].getDomain()); - CPPUNIT_ASSERT_EQUAL(std::string("_presence._tcp"), added[i].getType()); - CPPUNIT_ASSERT(added[i].getNetworkInterfaceID() != 0); - } - - // Resolve all added services - for (size_t i = 0; i < added.size(); ++i) { - resolvedServices.clear(); - boost::shared_ptr<DNSSDResolveServiceQuery> resolveServiceQuery = querier->createResolveServiceQuery(added[i]); - resolveServiceQuery->onServiceResolved.connect(boost::bind(&DNSSDTest::handleResolveFinished, this, _1)); - resolveServiceQuery->start(); - wait(); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(resolvedServices.size())); - resolveServiceQuery->stop(); - } - - // Unregister the service & check if the browse query picks this up - toRemove.clear(); - toRemove.insert(toRemove.begin(), added.begin(), added.end()); - registerQuery->unregisterService(); - while (!toRemove.empty()) { - Swift::sleep(100); - eventLoop->processEvents(); - } - - browseQuery->stopBrowsing(); - eventLoop->processEvents(); - } - - private: - void handleServiceAdded(const DNSSDServiceID& id) { - std::cout << "Service added: " << id.getNetworkInterfaceID() << std::endl; - added.push_back(id); - } - - void handleServiceRemoved(const DNSSDServiceID& id) { - CPPUNIT_ASSERT(std::find(toRemove.begin(), toRemove.end(), id) != toRemove.end()); - erase(toRemove, id); - } - - void handleRegisterFinished(boost::optional<DNSSDServiceID> id) { - if (id) { - registered.push_back(*id); - } - } - - void handleBrowseError() { - } - - void wait() { - for (int i = 0; i < SLEEP_INTERVALS; ++i) { - Swift::sleep(100); - eventLoop->processEvents(); - } - } - - void handleResolveFinished(const boost::optional<DNSSDResolveServiceQuery::Result>& result) { - CPPUNIT_ASSERT(result); - resolvedServices.push_back(*result); - } - - private: - DummyEventLoop* eventLoop; - boost::shared_ptr<DNSSDQuerier> querier; - std::vector<DNSSDServiceID> added; - std::vector<DNSSDServiceID> registered; - std::vector<DNSSDServiceID> toRemove; - std::vector<DNSSDResolveServiceQuery::Result> resolvedServices; + CPPUNIT_TEST_SUITE(DNSSDTest); + CPPUNIT_TEST(testPublish); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + eventLoop = new DummyEventLoop(); + querier = std::make_shared<DNSSDQuerierType>(eventLoop); + querier->start(); + } + + void tearDown() { + querier->stop(); + querier.reset(); + delete eventLoop; + } + + void testPublish() { + std::shared_ptr<DNSSDBrowseQuery> browseQuery = querier->createBrowseQuery(); + browseQuery->onServiceAdded.connect(boost::bind(&DNSSDTest::handleServiceAdded, this, _1)); + browseQuery->onServiceRemoved.connect(boost::bind(&DNSSDTest::handleServiceRemoved, this, _1)); + browseQuery->onError.connect(boost::bind(&DNSSDTest::handleBrowseError, this)); + browseQuery->startBrowsing(); + eventLoop->processEvents(); + + // Publish the service + LinkLocalServiceInfo info; + std::shared_ptr<DNSSDRegisterQuery> registerQuery = querier->createRegisterQuery("DNSSDTest", 1234, *info.toTXTRecord()); + registerQuery->onRegisterFinished.connect(boost::bind(&DNSSDTest::handleRegisterFinished, this, _1)); + registerQuery->registerService(); + + // Wait for a while + wait(); + + // Check that our registered queries are correct + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>((registered.size()))); + CPPUNIT_ASSERT_EQUAL(std::string("DNSSDTest"), registered[0].getName()); + CPPUNIT_ASSERT_EQUAL(std::string("local"), registered[0].getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("_presence._tcp"), registered[0].getType()); + + // Check that our browse query discovered us + std::sort(added.begin(), added.end()); + CPPUNIT_ASSERT(added.size() >= 1); + //for (size_t i = 0; i < added.size(); ++i) { + for (size_t i = 0; i < added.size(); ++i) { + CPPUNIT_ASSERT_EQUAL(std::string("DNSSDTest"), added[i].getName()); + CPPUNIT_ASSERT_EQUAL(std::string("local"), added[i].getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("_presence._tcp"), added[i].getType()); + CPPUNIT_ASSERT(added[i].getNetworkInterfaceID() != 0); + } + + // Resolve all added services + for (size_t i = 0; i < added.size(); ++i) { + resolvedServices.clear(); + std::shared_ptr<DNSSDResolveServiceQuery> resolveServiceQuery = querier->createResolveServiceQuery(added[i]); + resolveServiceQuery->onServiceResolved.connect(boost::bind(&DNSSDTest::handleResolveFinished, this, _1)); + resolveServiceQuery->start(); + wait(); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(resolvedServices.size())); + resolveServiceQuery->stop(); + } + + // Unregister the service & check if the browse query picks this up + toRemove.clear(); + toRemove.insert(toRemove.begin(), added.begin(), added.end()); + registerQuery->unregisterService(); + while (!toRemove.empty()) { + Swift::sleep(100); + eventLoop->processEvents(); + } + + browseQuery->stopBrowsing(); + eventLoop->processEvents(); + } + + private: + void handleServiceAdded(const DNSSDServiceID& id) { + std::cout << "Service added: " << id.getNetworkInterfaceID() << std::endl; + added.push_back(id); + } + + void handleServiceRemoved(const DNSSDServiceID& id) { + CPPUNIT_ASSERT(std::find(toRemove.begin(), toRemove.end(), id) != toRemove.end()); + erase(toRemove, id); + } + + void handleRegisterFinished(boost::optional<DNSSDServiceID> id) { + if (id) { + registered.push_back(*id); + } + } + + void handleBrowseError() { + } + + void wait() { + for (int i = 0; i < SLEEP_INTERVALS; ++i) { + Swift::sleep(100); + eventLoop->processEvents(); + } + } + + void handleResolveFinished(const boost::optional<DNSSDResolveServiceQuery::Result>& result) { + CPPUNIT_ASSERT(result); + resolvedServices.push_back(*result); + } + + private: + DummyEventLoop* eventLoop; + std::shared_ptr<DNSSDQuerierType> querier; + std::vector<DNSSDServiceID> added; + std::vector<DNSSDServiceID> registered; + std::vector<DNSSDServiceID> toRemove; + std::vector<DNSSDResolveServiceQuery::Result> resolvedServices; }; #ifdef HAVE_AVAHI diff --git a/Swiften/QA/DNSSDTest/SConscript b/Swiften/QA/DNSSDTest/SConscript index d35d06f..d9c9b04 100644 --- a/Swiften/QA/DNSSDTest/SConscript +++ b/Swiften/QA/DNSSDTest/SConscript @@ -3,19 +3,21 @@ import os Import("env") if env["TEST"] : - myenv = env.Clone() - myenv.MergeFlags(myenv["CHECKER_FLAGS"]) - myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) - myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) - myenv.MergeFlags(myenv["BOOST_FLAGS"]) - myenv.MergeFlags(myenv["LIBIDN_FLAGS"]) - if myenv.get("HAVE_BONJOUR", 0) : - myenv.Append(CPPDEFINES = "HAVE_BONJOUR") - elif myenv.get("HAVE_AVAHI", 0) : - myenv.Append(CPPDEFINES = ["HAVE_AVAHI"]) - myenv.MergeFlags(myenv["AVAHI_FLAGS"]) + myenv = env.Clone() + myenv.MergeFlags(myenv["CHECKER_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) + myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) + myenv.MergeFlags(myenv["GOOGLETEST_FLAGS"]) + myenv.MergeFlags(myenv["BOOST_FLAGS"]) + myenv.MergeFlags(myenv["LIBIDN_FLAGS"]) + if myenv.get("HAVE_BONJOUR", 0) : + myenv.Append(CPPDEFINES = "HAVE_BONJOUR") + elif myenv.get("HAVE_AVAHI", 0) : + myenv.Append(CPPDEFINES = ["HAVE_AVAHI"]) + myenv.MergeFlags(myenv["AVAHI_FLAGS"]) + myenv.MergeFlags(myenv["PLATFORM_FLAGS"]) - tester = myenv.Program("DNSSDTest", [ - "DNSSDTest.cpp", - ]) - myenv.Test(tester, "system") + tester = myenv.Program("DNSSDTest", [ + "DNSSDTest.cpp", + ]) + myenv.Test(tester, "system") diff --git a/Swiften/QA/FileTransferTest/.gitignore b/Swiften/QA/FileTransferTest/.gitignore new file mode 100644 index 0000000..768c501 --- /dev/null +++ b/Swiften/QA/FileTransferTest/.gitignore @@ -0,0 +1 @@ +FileTransferTest diff --git a/Swiften/QA/FileTransferTest/FileTransferTest.cpp b/Swiften/QA/FileTransferTest/FileTransferTest.cpp new file mode 100644 index 0000000..7d69277 --- /dev/null +++ b/Swiften/QA/FileTransferTest/FileTransferTest.cpp @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2014-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <fstream> + +#include <boost/algorithm/string.hpp> +#include <boost/filesystem.hpp> + + +#include <Swiften/Base/Debug.h> +#include <Swiften/Base/Log.h> +#include <Swiften/Base/sleep.h> +#include <Swiften/Base/StdRandomGenerator.h> +#include <Swiften/Client/Client.h> +#include <Swiften/Client/ClientXMLTracer.h> +#include <Swiften/Disco/ClientDiscoManager.h> +#include <Swiften/Disco/EntityCapsProvider.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/EventLoop/SimpleEventLoop.h> +#include <Swiften/FileTransfer/FileReadBytestream.h> +#include <Swiften/FileTransfer/FileTransferManager.h> +#include <Swiften/FileTransfer/FileWriteBytestream.h> +#include <Swiften/FileTransfer/OutgoingFileTransfer.h> +#include <Swiften/FileTransfer/ReadBytestream.h> +#include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/Network/Timer.h> +#include <Swiften/Network/TimerFactory.h> + +using namespace Swift; + +static const std::string CLIENT_NAME = "Swiften FT Test"; +static const std::string CLIENT_NODE = "http://swift.im"; + +static std::shared_ptr<SimpleEventLoop> eventLoop; +static std::shared_ptr<BoostNetworkFactories> networkFactories; + +StdRandomGenerator randGen; + +enum Candidate { + InBandBytestream = 1, + S5B_Direct = 2, + S5B_Proxied = 4, + S5B_Assisted = 8, +}; + +class FileTransferTest { + public: + FileTransferTest(int senderCandidates, int receiverCandidates) : senderCandidates_(senderCandidates), senderError_(FileTransferError::UnknownError), senderIsDone_(false), receiverCandidates_(receiverCandidates), receiverError_(FileTransferError::UnknownError), receiverIsDone_(false) { + sender_ = std::make_shared<Client>(JID(getenv("SWIFT_FILETRANSFERTEST_JID")), getenv("SWIFT_FILETRANSFERTEST_PASS"), networkFactories.get()); + sender_->onDisconnected.connect(boost::bind(&FileTransferTest::handleSenderDisconnected, this, _1)); + sender_->onConnected.connect(boost::bind(&FileTransferTest::handleSenderConnected, this)); + sender_->getEntityCapsProvider()->onCapsChanged.connect(boost::bind(&FileTransferTest::handleSenderCapsChanged, this, _1)); + + receiver_ = std::make_shared<Client>(JID(getenv("SWIFT_FILETRANSFERTEST2_JID")), getenv("SWIFT_FILETRANSFERTEST2_PASS"), networkFactories.get()); + receiver_->onConnected.connect(boost::bind(&FileTransferTest::handleReceiverConnected, this)); + receiver_->onDisconnected.connect(boost::bind(&FileTransferTest::handleReceiverDisconnected, this, _1)); + + senderTracer_ = new ClientXMLTracer(sender_.get()); + receiverTracer_ = new ClientXMLTracer(receiver_.get()); + + ClientOptions options; + options.useTLS = ClientOptions::NeverUseTLS; + options.useStreamCompression = false; + options.useStreamResumption = false; + options.useAcks = false; + + sender_->connect(options); + receiver_->connect(options); + + timeOut_ = networkFactories->getTimerFactory()->createTimer(60000); + timeOut_->onTick.connect(boost::bind(&FileTransferTest::handleTimeOut, this)); + + // Create randomly sized data to exchange. + sendFilePath_ = boost::filesystem::unique_path("ft_send_%%%%%%%%%%%%%%%%.bin"); + receiveFilePath_ = boost::filesystem::unique_path("ft_receive_%%%%%%%%%%%%%%%%.bin"); + + size_t size = 1024 + static_cast<size_t>(randGen.generateRandomInteger(1024 * 10)); + sendData_.resize(size); + for (unsigned char& n : sendData_) { + n = static_cast<unsigned char>(randGen.generateRandomInteger(255)); + } + + std::ofstream outfile(sendFilePath_.native().c_str(), std::ios::out | std::ios::binary); + outfile.write(reinterpret_cast<char *>(&sendData_[0]), static_cast<ptrdiff_t>(sendData_.size())); + outfile.close(); + } + + ~FileTransferTest() { + timeOut_->stop(); + + delete senderTracer_; + delete receiverTracer_; + + // Free file-transfer objects so file handles are closed and files can be removed afterwards. + assert(!outgoingFileTransfer_ && incomingFileTransfers_.empty()); + + if(boost::filesystem::exists(sendFilePath_)) { + boost::filesystem::remove(sendFilePath_); + } + + if(boost::filesystem::exists(receiveFilePath_)) { + boost::filesystem::remove(receiveFilePath_); + } + } + + void handleSenderConnected() { + DiscoInfo discoInfo; + discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc")); + discoInfo.addFeature(DiscoInfo::JingleFeature); + discoInfo.addFeature(DiscoInfo::JingleFTFeature); + discoInfo.addFeature(DiscoInfo::Bytestream); + if (senderCandidates_ & InBandBytestream) { + discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); + } + if (senderCandidates_ & (S5B_Direct | S5B_Assisted | S5B_Proxied)) { + discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature); + } + sender_->getDiscoManager()->setCapsNode(CLIENT_NODE); + sender_->getDiscoManager()->setDiscoInfo(discoInfo); + sender_->sendPresence(Presence::create()); + } + + void handleReceiverConnected() { + receiver_->getFileTransferManager()->onIncomingFileTransfer.connect(boost::bind(&FileTransferTest::handleReceiverIncomingFileTransfer, this, _1)); + + DiscoInfo discoInfo; + discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc")); + discoInfo.addFeature(DiscoInfo::JingleFeature); + discoInfo.addFeature(DiscoInfo::JingleFTFeature); + discoInfo.addFeature(DiscoInfo::Bytestream); + if (receiverCandidates_ & InBandBytestream) { + discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); + } + if (receiverCandidates_ & (S5B_Direct | S5B_Assisted | S5B_Proxied)) { + discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature); + } + receiver_->getDiscoManager()->setCapsNode(CLIENT_NODE); + receiver_->getDiscoManager()->setDiscoInfo(discoInfo); + receiver_->getPresenceSender()->sendPresence(Presence::create()); + } + + void handleReceiverIncomingFileTransfer(IncomingFileTransfer::ref transfer) { + incomingFileTransfers_.push_back(transfer); + std::shared_ptr<FileWriteBytestream> out = std::make_shared<FileWriteBytestream>(receiveFilePath_.native()); + transfer->onFinished.connect(boost::bind(&FileTransferTest::handleReceiverFileTransferFinished, this, _1, out)); + + FileTransferOptions options; + options = options.withInBandAllowed(receiverCandidates_ & InBandBytestream); + options = options.withDirectAllowed(receiverCandidates_ & S5B_Direct); + options = options.withAssistedAllowed(receiverCandidates_ & S5B_Assisted); + options = options.withProxiedAllowed(receiverCandidates_ & S5B_Proxied); + + std::cout << "Incoming transfer options: " << "IBB (" << options.isInBandAllowed() << ")" << ", "; + std::cout << "S5B Direct (" << options.isDirectAllowed() << ")" << ", "; + std::cout << "S5B Assisted (" << options.isAssistedAllowed() << ")" << ", "; + std::cout << "S5B Proxied (" << options.isProxiedAllowed() << ")" << std::endl; + + transfer->accept(out, options); + } + + void handleSenderCapsChanged(const JID &jid) { + if (receiver_ && (receiver_->getJID().toBare() == jid.toBare())) { + std::shared_ptr<FileReadBytestream> fileStream = std::make_shared<FileReadBytestream>(sendFilePath_); + + FileTransferOptions options; + options = options.withInBandAllowed(senderCandidates_ & InBandBytestream); + options = options.withDirectAllowed(senderCandidates_ & S5B_Direct); + options = options.withAssistedAllowed(senderCandidates_ & S5B_Assisted); + options = options.withProxiedAllowed(senderCandidates_ & S5B_Proxied); + + std::cout << "Outgoing transfer options: " << "IBB (" << options.isInBandAllowed() << ")" << ", "; + std::cout << "S5B Direct (" << options.isDirectAllowed() << ")" << ", "; + std::cout << "S5B Assisted (" << options.isAssistedAllowed() << ")" << ", "; + std::cout << "S5B Proxied (" << options.isProxiedAllowed() << ")" << std::endl; + + outgoingFileTransfer_ = sender_->getFileTransferManager()->createOutgoingFileTransfer(jid.toBare(), sendFilePath_, "Some File!", fileStream, options); + + if (outgoingFileTransfer_) { + outgoingFileTransfer_->onFinished.connect(boost::bind(&FileTransferTest::handleSenderFileTransferFinished, this, _1)); + outgoingFileTransfer_->start(); + } else { + std::cout << "ERROR: No outgoing file transfer returned." << std::endl; + receiverIsDone_ = true; + senderIsDone_ = true; + endTest(); + } + } + } + + void handleReceiverFileTransferFinished(const boost::optional<FileTransferError>& error, std::shared_ptr<FileWriteBytestream> out) { + out->close(); + receiverError_ = error; + receiverIsDone_ = true; + if (senderIsDone_) { + timeOut_->stop(); + timeOut_ = networkFactories->getTimerFactory()->createTimer(1000); + timeOut_->onTick.connect(boost::bind(&FileTransferTest::endTest, this)); + timeOut_->start(); + } + } + + void handleSenderDisconnected(const boost::optional<ClientError>& error) { + if (error) { + std::cout << this << " " << "handleSenderDisconnected: error: " << error.get() << std::endl; + } + + // All file-transfers related to a Client instance need to be freed + // *before* freeing the Client instance. + outgoingFileTransfer_.reset(); + + sender_.reset(); + if (!sender_ && !receiver_) { + eventLoop->stop(); + } + } + + void handleReceiverDisconnected(const boost::optional<ClientError>& error) { + if (error) { + std::cout << this << " " << "handleReceiverDisconnected: error: " << error.get() << std::endl; + } + + // All file-transfers related to a Client instance need to be freed + // *before* freeing the Client instance. + incomingFileTransfers_.clear(); + + receiver_.reset(); + if (!sender_ && !receiver_) { + eventLoop->stop(); + } + } + + void handleSenderFileTransferFinished(const boost::optional<FileTransferError>& error) { + senderError_ = error; + senderIsDone_ = true; + if (receiverIsDone_) { + timeOut_->stop(); + timeOut_ = networkFactories->getTimerFactory()->createTimer(1000); + timeOut_->onTick.connect(boost::bind(&FileTransferTest::endTest, this)); + timeOut_->start(); + } + else if (error) { + endTest(); + } + } + + void run() { + timeOut_->start(); + eventLoop->run(); + } + + void endTest() { + if (sender_) { + sender_->disconnect(); + } + if (receiver_) { + receiver_->disconnect(); + } + } + + void handleTimeOut() { + std::cout << "Test timed out!!!" << std::endl; + endTest(); + } + + bool isDone() const { + return senderIsDone_ && receiverIsDone_; + } + + bool wasSuccessful() const { + return !senderError_ && !receiverError_; + } + + private: + int senderCandidates_; + std::shared_ptr<Client> sender_; + ClientXMLTracer* senderTracer_; + ByteArray sendData_; + OutgoingFileTransfer::ref outgoingFileTransfer_; + boost::filesystem::path sendFilePath_; + boost::optional<FileTransferError> senderError_; + bool senderIsDone_; + + int receiverCandidates_; + std::shared_ptr<Client> receiver_; + ClientXMLTracer* receiverTracer_; + ByteArray receiveData_; + std::vector<IncomingFileTransfer::ref> incomingFileTransfers_; + boost::filesystem::path receiveFilePath_; + boost::optional<FileTransferError> receiverError_; + bool receiverIsDone_; + + Timer::ref timeOut_; +}; + +static bool runTest(int senderCandidates, int receiverCandidates) { + bool success = false; + + std::cout << "senderCandidates: " << senderCandidates << ", receiverCandidates: " << receiverCandidates << std::endl; + bool expectSuccess = (senderCandidates & receiverCandidates) > 0; + + eventLoop = std::make_shared<SimpleEventLoop>(); + networkFactories = std::make_shared<BoostNetworkFactories>(eventLoop.get()); + + std::shared_ptr<FileTransferTest> testRun = std::make_shared<FileTransferTest>(senderCandidates, receiverCandidates); + + testRun->run(); + + bool wasSuccessful = testRun->wasSuccessful(); + if (expectSuccess == wasSuccessful) { + success = true; + } + else { + if (!testRun->isDone()) { + std::cout << "Test did not finish transfer. Sender candidates = " << senderCandidates << ", receiver candidates = " << receiverCandidates << "." << std::endl; + } + } + std::cout << "expected success: " << expectSuccess << ", wasSuccessful: " << wasSuccessful << std::endl; + + + testRun.reset(); + networkFactories.reset(); + eventLoop->runUntilEvents(); + + eventLoop->stop(); + eventLoop.reset(); + + return success; +} + +/** + * This program test file-transfer interop between Swift and itself with various connection candidates. + * The all combinations of the candidates, IBB, S5B (direct) and S5B (proxied), on sender and receiver side are tested. + */ +int main(int argc, char** argv) { + int failedTests = 0; + + std::vector<std::pair<int, int> > failedTestPairs; + std::cout << "Swiften File-Transfer Connectivity Test Suite" << std::endl; + if (argc == 1) { + if (getenv("SWIFT_FILETRANSFERTEST_CONFIG")) { + // test configuration described in SWIFT_FILETRANSFERTEST_CONFIG environment variable, e.g. "1:1|2:2" + std::vector<std::string> configurations; + std::string configs_env = std::string(getenv("SWIFT_FILETRANSFERTEST_CONFIG")); + boost::split(configurations, configs_env, boost::is_any_of("|")); + for (const auto& config : configurations) { + std::vector<std::string> split_config; + boost::split(split_config, config, boost::is_any_of(":")); + assert(split_config.size() == 2); + + int senderCandidates = atoi(split_config[0].c_str()); + int receiverCandidates = atoi(split_config[1].c_str()); + + if (!runTest(senderCandidates, receiverCandidates)) { + failedTests++; + failedTestPairs.push_back(std::pair<int, int>(senderCandidates, receiverCandidates)); + } + } + + for (auto&& failedTest : failedTestPairs) { + std::cout << "Failed test: " << "( " << failedTest.first << ", " << failedTest.second << ") " << std::endl; + } + } + else { + // test all configurations + for (int n = 0; n < (1 << 7); n++) { + int senderCandidates = n & 0xF; + int receiverCandidates = (n >> 4) & 0xF; + std::cout << "Run test " << n + 1 << " of " << (1 << 7) << ", (" << senderCandidates << ", " << receiverCandidates << ")" << std::endl; + if (!runTest(senderCandidates, receiverCandidates)) { + failedTests++; + failedTestPairs.push_back(std::pair<int, int>(senderCandidates, receiverCandidates)); + } + } + + for (auto&& failedTest : failedTestPairs) { + std::cout << "Failed test: " << "( " << failedTest.first << ", " << failedTest.second << ") " << std::endl; + } + } + } + else if (argc == 3) { + Log::setLogLevel(Log::debug); + int senderCandidates = atoi(argv[1]); + int receiverCandidates = atoi(argv[2]); + if (!runTest(senderCandidates, receiverCandidates)) { + failedTests++; + } + } + else { + std::cout << "Usage:" << std::endl; + std::cout << "\t- to test all combinations pass no arguments" << std::endl; + std::cout << "\t- to test a specific combination pass two integers describing sender and receiver candidates" << std::endl; + } + return failedTests; +} diff --git a/Swiften/QA/FileTransferTest/SConscript b/Swiften/QA/FileTransferTest/SConscript new file mode 100644 index 0000000..4b77674 --- /dev/null +++ b/Swiften/QA/FileTransferTest/SConscript @@ -0,0 +1,20 @@ +import os + +Import("env") + +if env["TEST"] : + myenv = env.Clone() + myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) + myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) + + for i in ["SWIFT_FILETRANSFERTEST_JID", "SWIFT_FILETRANSFERTEST_PASS", "SWIFT_FILETRANSFERTEST2_JID", "SWIFT_FILETRANSFERTEST2_PASS"]: + if ARGUMENTS.get(i.lower(), False) : + myenv["ENV"][i] = ARGUMENTS[i.lower()] + elif os.environ.get(i, "") : + myenv["ENV"][i] = os.environ[i] + + # test in-band transfers, direct SOCKS5 bytestream transfers and proxied SOCKS5 bytestream transfers + myenv["ENV"]["SWIFT_FILETRANSFERTEST_CONFIG"] = "1:1|2:2|4:4" + + tester = myenv.Program("FileTransferTest", ["FileTransferTest.cpp"]) + myenv.Test(tester, "system") diff --git a/Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp b/Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp index 14da358..6982c0c 100644 --- a/Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp +++ b/Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp @@ -1,81 +1,215 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> +#include <string> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> -#include <string> +#include <Swiften/Base/sleep.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Network/BoostConnectionServer.h> #include <Swiften/Network/BoostIOServiceThread.h> -#include <Swiften/EventLoop/DummyEventLoop.h> using namespace Swift; class BoostConnectionServerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(BoostConnectionServerTest); - CPPUNIT_TEST(testConstructor_TwoServersOnSamePort); - CPPUNIT_TEST(testStart_Conflict); - CPPUNIT_TEST(testStop); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - boostIOServiceThread_ = new BoostIOServiceThread(); - eventLoop_ = new DummyEventLoop(); - stopped = false; - stoppedError.reset(); - } - - void tearDown() { - while (eventLoop_->hasEvents()) { - eventLoop_->processEvents(); - } - delete eventLoop_; - delete boostIOServiceThread_; - } - - void testConstructor_TwoServersOnSamePort() { - BoostConnectionServer::ref testling(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); - BoostConnectionServer::ref testling2(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); - } - - void testStart_Conflict() { - BoostConnectionServer::ref testling(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); - testling->start(); - - BoostConnectionServer::ref testling2(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); - testling2->onStopped.connect( - boost::bind(&BoostConnectionServerTest::handleStopped, this, _1)); - - testling->stop(); - } - - void testStop() { - BoostConnectionServer::ref testling(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); - testling->start(); - - testling->stop(); - - BoostConnectionServer::ref testling2(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); - testling2->start(); - - testling2->stop(); - } - - void handleStopped(boost::optional<BoostConnectionServer::Error> e) { - stopped = true; - stoppedError = e; - } - - private: - BoostIOServiceThread* boostIOServiceThread_; - DummyEventLoop* eventLoop_; - bool stopped; - boost::optional<BoostConnectionServer::Error> stoppedError; + CPPUNIT_TEST_SUITE(BoostConnectionServerTest); + CPPUNIT_TEST(testConstructor_TwoServersOnSamePort); + CPPUNIT_TEST(testStart_Conflict); + CPPUNIT_TEST(testStop); + CPPUNIT_TEST(testIPv4Server); + CPPUNIT_TEST(testIPv6Server); + CPPUNIT_TEST(testIPv4IPv6DualStackServer); + CPPUNIT_TEST(testIPv6DualStackServerPeerAddress); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + eventLoop_ = new DummyEventLoop(); + boostIOServiceThread_ = new BoostIOServiceThread(); + stopped_ = false; + stoppedError_.reset(); + receivedNewConnection_ = false; + connectFinished_ = false; + remoteAddress_ = boost::optional<HostAddressPort>(); + } + + void tearDown() { + delete boostIOServiceThread_; + while (eventLoop_->hasEvents()) { + eventLoop_->processEvents(); + } + delete eventLoop_; + } + + void testConstructor_TwoServersOnSamePort() { + BoostConnectionServer::ref testling(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); + BoostConnectionServer::ref testling2(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); + } + + void testStart_Conflict() { + BoostConnectionServer::ref testling(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); + testling->start(); + + BoostConnectionServer::ref testling2(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); + testling2->onStopped.connect( + boost::bind(&BoostConnectionServerTest::handleStopped_, this, _1)); + + testling->stop(); + } + + void testStop() { + BoostConnectionServer::ref testling(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); + testling->start(); + + testling->stop(); + + BoostConnectionServer::ref testling2(BoostConnectionServer::create(9999, boostIOServiceThread_->getIOService(), eventLoop_)); + testling2->start(); + + testling2->stop(); + } + + void testIPv4Server() { + BoostConnectionServer::ref testling = BoostConnectionServer::create(HostAddress::fromString("127.0.0.1").get(), 9999, boostIOServiceThread_->getIOService(), eventLoop_); + testling->onNewConnection.connect(boost::bind(&BoostConnectionServerTest::handleNewConnection, this, _1)); + testling->start(); + + BoostConnection::ref clientTestling = BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_); + clientTestling->onConnectFinished.connect(boost::bind(&BoostConnectionServerTest::handleConnectFinished, this, _1)); + clientTestling->connect(HostAddressPort(HostAddress::fromString("127.0.0.1").get(), 9999)); + + while (!connectFinished_) { + Swift::sleep(10); + eventLoop_->processEvents(); + } + + CPPUNIT_ASSERT_EQUAL(true, receivedNewConnection_); + + testling->stop(); + } + + void testIPv6Server() { + BoostConnectionServer::ref testling = BoostConnectionServer::create(HostAddress::fromString("::1").get(), 9999, boostIOServiceThread_->getIOService(), eventLoop_); + testling->onNewConnection.connect(boost::bind(&BoostConnectionServerTest::handleNewConnection, this, _1)); + testling->start(); + + BoostConnection::ref clientTestling = BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_); + clientTestling->onConnectFinished.connect(boost::bind(&BoostConnectionServerTest::handleConnectFinished, this, _1)); + clientTestling->connect(HostAddressPort(HostAddress::fromString("::1").get(), 9999)); + + while (!connectFinished_) { + Swift::sleep(10); + eventLoop_->processEvents(); + } + + CPPUNIT_ASSERT_EQUAL(true, receivedNewConnection_); + + testling->stop(); + } + + void testIPv4IPv6DualStackServer() { + BoostConnectionServer::ref testling = BoostConnectionServer::create(HostAddress::fromString("::").get(), 9999, boostIOServiceThread_->getIOService(), eventLoop_); + testling->onNewConnection.connect(boost::bind(&BoostConnectionServerTest::handleNewConnection, this, _1)); + testling->start(); + + // Test IPv4. + BoostConnection::ref clientTestling = BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_); + clientTestling->onConnectFinished.connect(boost::bind(&BoostConnectionServerTest::handleConnectFinished, this, _1)); + clientTestling->connect(HostAddressPort(HostAddress::fromString("127.0.0.1").get(), 9999)); + + while (!connectFinished_) { + Swift::sleep(10); + eventLoop_->processEvents(); + } + + CPPUNIT_ASSERT_EQUAL(true, receivedNewConnection_); + + receivedNewConnection_ = false; + connectFinished_ = false; + + // Test IPv6. + clientTestling = BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_); + clientTestling->onConnectFinished.connect(boost::bind(&BoostConnectionServerTest::handleConnectFinished, this, _1)); + clientTestling->connect(HostAddressPort(HostAddress::fromString("::1").get(), 9999)); + + while (!connectFinished_) { + Swift::sleep(10); + eventLoop_->processEvents(); + } + + CPPUNIT_ASSERT_EQUAL(true, receivedNewConnection_); + + testling->stop(); + } + + void testIPv6DualStackServerPeerAddress() { + BoostConnectionServer::ref testling = BoostConnectionServer::create(HostAddress::fromString("::").get(), 9999, boostIOServiceThread_->getIOService(), eventLoop_); + testling->onNewConnection.connect(boost::bind(&BoostConnectionServerTest::handleNewConnection, this, _1)); + testling->start(); + + // Test IPv4. + BoostConnection::ref clientTestling = BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_); + clientTestling->onConnectFinished.connect(boost::bind(&BoostConnectionServerTest::handleConnectFinished, this, _1)); + clientTestling->connect(HostAddressPort(HostAddress::fromString("127.0.0.1").get(), 9999)); + + while (!connectFinished_) { + Swift::sleep(10); + eventLoop_->processEvents(); + } + + CPPUNIT_ASSERT_EQUAL(true, receivedNewConnection_); + // The IPv4 localhost mapped to a IPv6 address is expected here. + CPPUNIT_ASSERT(HostAddress::fromString("::ffff:127.0.0.1").get() == remoteAddress_.get().getAddress()); + + receivedNewConnection_ = false; + connectFinished_ = false; + remoteAddress_ = boost::optional<HostAddressPort>(); + + // Test IPv6. + clientTestling = BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_); + clientTestling->onConnectFinished.connect(boost::bind(&BoostConnectionServerTest::handleConnectFinished, this, _1)); + clientTestling->connect(HostAddressPort(HostAddress::fromString("::1").get(), 9999)); + + while (!connectFinished_) { + Swift::sleep(10); + eventLoop_->processEvents(); + } + + CPPUNIT_ASSERT_EQUAL(true, receivedNewConnection_); + // The IPv6 local host is expected here. + CPPUNIT_ASSERT(HostAddress::fromString("::1").get() == remoteAddress_.get().getAddress()); + + testling->stop(); + } + + void handleStopped_(boost::optional<BoostConnectionServer::Error> e) { + stopped_ = true; + stoppedError_ = e; + } + + void handleNewConnection(std::shared_ptr<Connection> connection) { + receivedNewConnection_ = true; + remoteAddress_ = connection->getRemoteAddress(); + } + + void handleConnectFinished(bool /*error*/) { + connectFinished_ = true; + } + + private: + BoostIOServiceThread* boostIOServiceThread_; + DummyEventLoop* eventLoop_; + bool stopped_; + bool receivedNewConnection_; + bool connectFinished_; + boost::optional<BoostConnectionServer::Error> stoppedError_; + boost::optional<HostAddressPort> remoteAddress_; }; CPPUNIT_TEST_SUITE_REGISTRATION(BoostConnectionServerTest); diff --git a/Swiften/QA/NetworkTest/BoostConnectionTest.cpp b/Swiften/QA/NetworkTest/BoostConnectionTest.cpp index 53faff7..e0890bf 100644..100755 --- a/Swiften/QA/NetworkTest/BoostConnectionTest.cpp +++ b/Swiften/QA/NetworkTest/BoostConnectionTest.cpp @@ -1,155 +1,179 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> +#include <string> + +#include <boost/date_time/posix_time/posix_time_types.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <string> #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/sleep.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Network/BoostConnection.h> +#include <Swiften/Network/BoostIOServiceThread.h> #include <Swiften/Network/HostAddress.h> #include <Swiften/Network/HostAddressPort.h> -#include <Swiften/Network/BoostIOServiceThread.h> -#include <Swiften/EventLoop/DummyEventLoop.h> - -static const unsigned char* address = reinterpret_cast<const unsigned char*>("\x4A\x32\x3e\x31"); using namespace Swift; class BoostConnectionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(BoostConnectionTest); - CPPUNIT_TEST(testDestructor); - CPPUNIT_TEST(testDestructor_PendingEvents); - CPPUNIT_TEST(testWrite); - CPPUNIT_TEST(testWriteMultipleSimultaniouslyQueuesWrites); + CPPUNIT_TEST_SUITE(BoostConnectionTest); + CPPUNIT_TEST(testDestructor); + CPPUNIT_TEST(testDestructor_PendingEvents); + CPPUNIT_TEST(testWrite); + CPPUNIT_TEST(testWriteMultipleSimultaniouslyQueuesWrites); #ifdef TEST_IPV6 - CPPUNIT_TEST(testWrite_IPv6); + CPPUNIT_TEST(testWrite_IPv6); #endif - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - boostIOServiceThread_ = new BoostIOServiceThread(); - boostIOService = boost::make_shared<boost::asio::io_service>(); - eventLoop_ = new DummyEventLoop(); - disconnected = false; - connectFinished = false; - } - - void tearDown() { - delete eventLoop_; - delete boostIOServiceThread_; - } - - void testDestructor() { - { - BoostConnection::ref testling(BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_)); - testling->connect(HostAddressPort(HostAddress(address, 4), 5222)); - } - } - - void testDestructor_PendingEvents() { - { - BoostConnection::ref testling(BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_)); - testling->connect(HostAddressPort(HostAddress(address, 4), 5222)); - while (!eventLoop_->hasEvents()) { - Swift::sleep(10); - } - } - eventLoop_->processEvents(); - } - - void testWrite() { - BoostConnection::ref testling(BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_)); - testling->onConnectFinished.connect(boost::bind(&BoostConnectionTest::doWrite, this, testling.get())); - testling->onDataRead.connect(boost::bind(&BoostConnectionTest::handleDataRead, this, _1)); - testling->onDisconnected.connect(boost::bind(&BoostConnectionTest::handleDisconnected, this)); - testling->connect(HostAddressPort(HostAddress("74.50.62.49"), 5222)); - while (receivedData.empty()) { - Swift::sleep(10); - eventLoop_->processEvents(); - } - testling->disconnect(); - } - - void testWrite_IPv6() { - BoostConnection::ref testling(BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_)); - testling->onConnectFinished.connect(boost::bind(&BoostConnectionTest::doWrite, this, testling.get())); - testling->onDataRead.connect(boost::bind(&BoostConnectionTest::handleDataRead, this, _1)); - testling->onDisconnected.connect(boost::bind(&BoostConnectionTest::handleDisconnected, this)); - testling->connect(HostAddressPort(HostAddress("2001:470:1f0e:852::2"), 80)); - while (receivedData.empty()) { - Swift::sleep(10); - eventLoop_->processEvents(); - } - testling->disconnect(); - } - - - void testWriteMultipleSimultaniouslyQueuesWrites() { - BoostConnection::ref testling(BoostConnection::create(boostIOService, eventLoop_)); - testling->onConnectFinished.connect(boost::bind(&BoostConnectionTest::handleConnectFinished, this)); - testling->onDataRead.connect(boost::bind(&BoostConnectionTest::handleDataRead, this, _1)); - testling->onDisconnected.connect(boost::bind(&BoostConnectionTest::handleDisconnected, this)); - testling->connect(HostAddressPort(HostAddress("74.50.62.49"), 5222)); - while (!connectFinished) { - boostIOService->run_one(); - eventLoop_->processEvents(); - } - - testling->write(createSafeByteArray("<stream:strea")); - testling->write(createSafeByteArray("m")); - testling->write(createSafeByteArray(">")); - - // Check that we only did one write event, the others are queued - /*int runHandlers = */boostIOService->poll(); - // Disabling this test, because poll runns all handlers that are added during poll() as well, so - // this test doesn't really work any more. We'll have to trust that things are queued. - //CPPUNIT_ASSERT_EQUAL(1, runHandlers); - // Process the other events - while (receivedData.empty()) { - boostIOService->run_one(); - eventLoop_->processEvents(); - } - - // Disconnect & clean up - testling->disconnect(); - while (!disconnected) { - boostIOService->run_one(); - eventLoop_->processEvents(); - } - } - - void doWrite(BoostConnection* connection) { - connection->write(createSafeByteArray("<stream:stream>")); - connection->write(createSafeByteArray("\r\n\r\n")); // Temporarily, while we don't have an xmpp server running on ipv6 - } - - void handleDataRead(boost::shared_ptr<SafeByteArray> data) { - append(receivedData, *data); - } - - void handleDisconnected() { - disconnected = true; - } - - void handleConnectFinished() { - connectFinished = true; - } - - private: - BoostIOServiceThread* boostIOServiceThread_; - boost::shared_ptr<boost::asio::io_service> boostIOService; - DummyEventLoop* eventLoop_; - ByteArray receivedData; - bool disconnected; - bool connectFinished; + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + eventLoop_ = new DummyEventLoop(); + boostIOServiceThread_ = new BoostIOServiceThread(); + boostIOService_ = std::make_shared<boost::asio::io_service>(); + disconnected_ = false; + connectFinished_ = false; + } + + void tearDown() { + delete boostIOServiceThread_; + while (eventLoop_->hasEvents()) { + eventLoop_->processEvents(); + } + delete eventLoop_; + } + + void testDestructor() { + { + BoostConnection::ref testling(BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_)); + auto hostAddress = HostAddress::fromString(getenv("SWIFT_NETWORK_TEST_IPV4")); + CPPUNIT_ASSERT_EQUAL(true, hostAddress.is_initialized()); + testling->connect(HostAddressPort(hostAddress.get(), 5222)); + } + } + + void testDestructor_PendingEvents() { + { + BoostConnection::ref testling(BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_)); + auto hostAddress = HostAddress::fromString(getenv("SWIFT_NETWORK_TEST_IPV4")); + CPPUNIT_ASSERT_EQUAL(true, hostAddress.is_initialized()); + testling->connect(HostAddressPort(hostAddress.get(), 5222)); + while (!eventLoop_->hasEvents()) { + Swift::sleep(10); + } + } + eventLoop_->processEvents(); + } + + void testWrite() { + using namespace boost::posix_time; + + BoostConnection::ref testling(BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_)); + testling->onConnectFinished.connect(boost::bind(&BoostConnectionTest::doWrite, this, testling.get())); + testling->onDataRead.connect(boost::bind(&BoostConnectionTest::handleDataRead, this, _1)); + testling->onDisconnected.connect(boost::bind(&BoostConnectionTest::handleDisconnected, this)); + auto hostAddress = HostAddress::fromString(getenv("SWIFT_NETWORK_TEST_IPV4")); + CPPUNIT_ASSERT_EQUAL(true, hostAddress.is_initialized()); + testling->connect(HostAddressPort(hostAddress.get(), 5222)); + + boost::posix_time::ptime start = second_clock::local_time(); + while (receivedData_.empty() && ((second_clock::local_time() - start) < seconds(60))) { + Swift::sleep(10); + eventLoop_->processEvents(); + } + CPPUNIT_ASSERT_EQUAL(false, receivedData_.empty()); + testling->disconnect(); + } + + void testWrite_IPv6() { + using namespace boost::posix_time; + + BoostConnection::ref testling(BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_)); + testling->onConnectFinished.connect(boost::bind(&BoostConnectionTest::doWrite, this, testling.get())); + testling->onDataRead.connect(boost::bind(&BoostConnectionTest::handleDataRead, this, _1)); + testling->onDisconnected.connect(boost::bind(&BoostConnectionTest::handleDisconnected, this)); + auto hostAddress = HostAddress::fromString(getenv("SWIFT_NETWORK_TEST_IPV6")); + CPPUNIT_ASSERT_EQUAL(true, hostAddress.is_initialized()); + testling->connect(HostAddressPort(hostAddress.get(), 5222)); + + boost::posix_time::ptime start = second_clock::local_time(); + while (receivedData_.empty() && ((second_clock::local_time() - start) < seconds(60))) { + Swift::sleep(10); + eventLoop_->processEvents(); + } + CPPUNIT_ASSERT_EQUAL(false, receivedData_.empty()); + testling->disconnect(); + } + + + void testWriteMultipleSimultaniouslyQueuesWrites() { + BoostConnection::ref testling(BoostConnection::create(boostIOService_, eventLoop_)); + testling->onConnectFinished.connect(boost::bind(&BoostConnectionTest::handleConnectFinished, this)); + testling->onDataRead.connect(boost::bind(&BoostConnectionTest::handleDataRead, this, _1)); + testling->onDisconnected.connect(boost::bind(&BoostConnectionTest::handleDisconnected, this)); + + auto hostAddress = HostAddress::fromString(getenv("SWIFT_NETWORK_TEST_IPV4")); + CPPUNIT_ASSERT_EQUAL(true, hostAddress.is_initialized()); + testling->connect(HostAddressPort(hostAddress.get(), 5222)); + while (!connectFinished_) { + boostIOService_->run_one(); + eventLoop_->processEvents(); + } + + testling->write(createSafeByteArray("<stream:strea")); + testling->write(createSafeByteArray("m")); + testling->write(createSafeByteArray(">")); + + // Check that we only did one write event, the others are queued + /*int runHandlers = */boostIOService_->poll(); + // Disabling this test, because poll runns all handlers that are added during poll() as well, so + // this test doesn't really work any more. We'll have to trust that things are queued. + //CPPUNIT_ASSERT_EQUAL(1, runHandlers); + // Process the other events + while (receivedData_.empty()) { + boostIOService_->run_one(); + eventLoop_->processEvents(); + } + + // Disconnect & clean up + testling->disconnect(); + while (!disconnected_) { + boostIOService_->run_one(); + eventLoop_->processEvents(); + } + } + + void doWrite(BoostConnection* connection) { + connection->write(createSafeByteArray("<stream:stream>")); + connection->write(createSafeByteArray("\r\n\r\n")); // Temporarily, while we don't have an xmpp server running on ipv6 + } + + void handleDataRead(std::shared_ptr<SafeByteArray> data) { + append(receivedData_, *data); + } + + void handleDisconnected() { + disconnected_ = true; + } + + void handleConnectFinished() { + connectFinished_ = true; + } + + private: + BoostIOServiceThread* boostIOServiceThread_; + std::shared_ptr<boost::asio::io_service> boostIOService_; + DummyEventLoop* eventLoop_; + ByteArray receivedData_; + bool disconnected_; + bool connectFinished_; }; CPPUNIT_TEST_SUITE_REGISTRATION(BoostConnectionTest); diff --git a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp index bc4f1a3..69e6fe8 100644 --- a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp +++ b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp @@ -1,242 +1,254 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <algorithm> +#include <string> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> -#include <algorithm> -#include <Swiften/Base/sleep.h> -#include <string> #include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Platform.h> +#include <Swiften/Base/sleep.h> +#include <Swiften/EventLoop/DummyEventLoop.h> +#include <Swiften/IDN/IDNConverter.h> +#include <Swiften/IDN/PlatformIDNConverter.h> +#include <Swiften/Network/BoostIOServiceThread.h> +#include <Swiften/Network/BoostTimerFactory.h> +#include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/Network/DomainNameServiceQuery.h> +#include <Swiften/Network/NetworkFactories.h> #ifdef USE_UNBOUND #include <Swiften/Network/UnboundDomainNameResolver.h> #else #include <Swiften/Network/PlatformDomainNameResolver.h> #endif -#include <Swiften/Network/BoostTimerFactory.h> -#include <Swiften/Network/NetworkFactories.h> -#include <Swiften/Network/BoostIOServiceThread.h> -#include <Swiften/Network/DomainNameAddressQuery.h> -#include <Swiften/Network/DomainNameServiceQuery.h> -#include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/IDN/IDNConverter.h> -#include <Swiften/IDN/PlatformIDNConverter.h> using namespace Swift; struct CompareHostAddresses { - bool operator()(const HostAddress& h1, const HostAddress& h2) { - return h1.toString() < h2.toString(); - } + bool operator()(const HostAddress& h1, const HostAddress& h2) { + return h1.toString() < h2.toString(); + } }; class DomainNameResolverTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DomainNameResolverTest); - CPPUNIT_TEST(testResolveAddress); - CPPUNIT_TEST(testResolveAddress_Error); + CPPUNIT_TEST_SUITE(DomainNameResolverTest); + CPPUNIT_TEST(testResolveAddress); + CPPUNIT_TEST(testResolveAddress_Error); #ifndef USE_UNBOUND - CPPUNIT_TEST(testResolveAddress_IPv6); - CPPUNIT_TEST(testResolveAddress_IPv4and6); - CPPUNIT_TEST(testResolveAddress_International); + /** + * The native DNS resolver of Windows behaves oddly if the system has no global IPv6 + * routed address and no IPv6 reachability. It will not return IPv6 records from DNS + * requests for an unspecified protocol (IPv6 or IPv4). + * The following tests are only enabled on Windows if scons is run with the 'test_ipv6=1' + * argument, indicating working IPv6 on the test machine. + */ +#if !defined(SWIFTEN_PLATFORM_WINDOWS) || defined(TEST_IPV6) + CPPUNIT_TEST(testResolveAddress_IPv6); + CPPUNIT_TEST(testResolveAddress_IPv4and6); +#endif + CPPUNIT_TEST(testResolveAddress_International); #endif - CPPUNIT_TEST(testResolveAddress_Localhost); - CPPUNIT_TEST(testResolveAddress_Parallel); + CPPUNIT_TEST(testResolveAddress_Localhost); + CPPUNIT_TEST(testResolveAddress_Parallel); #ifndef USE_UNBOUND - CPPUNIT_TEST(testResolveService); + CPPUNIT_TEST(testResolveService); #endif - CPPUNIT_TEST(testResolveService_Error); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - ioServiceThread = new BoostIOServiceThread(); - eventLoop = new DummyEventLoop(); + CPPUNIT_TEST(testResolveService_Error); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + ioServiceThread = new BoostIOServiceThread(); + eventLoop = new DummyEventLoop(); + idnConverter = std::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); #ifdef USE_UNBOUND - resolver = new UnboundDomainNameResolver(ioServiceThread->getIOService(), eventLoop); + resolver = new UnboundDomainNameResolver(idnConverter.get(), ioServiceThread->getIOService(), eventLoop); #else - idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); - resolver = new PlatformDomainNameResolver(idnConverter.get(), eventLoop); + resolver = new PlatformDomainNameResolver(idnConverter.get(), eventLoop); #endif - resultsAvailable = false; - } - - void tearDown() { - delete ioServiceThread; - delete resolver; - delete eventLoop; - } - - void testResolveAddress() { - boost::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("xmpp.test.swift.im")); - - query->run(); - waitForResults(); - - CPPUNIT_ASSERT(!addressQueryError); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addressQueryResult.size())); - CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.0"), addressQueryResult[0].toString()); - } - - void testResolveAddress_Error() { - boost::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("invalid.test.swift.im")); - - query->run(); - waitForResults(); - - CPPUNIT_ASSERT(addressQueryError); - } - - void testResolveAddress_IPv6() { - boost::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("xmpp-ipv6.test.swift.im")); - - query->run(); - waitForResults(); - - CPPUNIT_ASSERT(!addressQueryError); - CPPUNIT_ASSERT_EQUAL(std::string("2001:470:1f0e:852::2"), addressQueryResult[0].toString()); - } - - void testResolveAddress_IPv4and6() { - boost::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("xmpp-ipv46.test.swift.im")); - - query->run(); - waitForResults(); - - CPPUNIT_ASSERT(!addressQueryError); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(addressQueryResult.size())); - CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.7"), addressQueryResult[0].toString()); - CPPUNIT_ASSERT_EQUAL(std::string("1234:5678:9abc:def0:fed:cba9:8765:4321"), addressQueryResult[1].toString()); - } - - void testResolveAddress_International() { - boost::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("tron\xc3\xa7on.test.swift.im")); - - query->run(); - waitForResults(); - - CPPUNIT_ASSERT(!addressQueryError); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addressQueryResult.size())); - CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.3"), addressQueryResult[0].toString()); - } - - void testResolveAddress_Localhost() { - boost::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("localhost")); - - query->run(); - waitForResults(); - - CPPUNIT_ASSERT(!addressQueryError); - CPPUNIT_ASSERT(std::find(addressQueryResult.begin(), addressQueryResult.end(), HostAddress("127.0.0.1")) != addressQueryResult.end()); - } - - void testResolveAddress_Parallel() { - std::vector<DomainNameAddressQuery::ref> queries; - static const size_t numQueries = 100; - for (size_t i = 0; i < numQueries; ++i) { - DomainNameAddressQuery::ref query(createAddressQuery("xmpp.test.swift.im")); - queries.push_back(query); - query->run(); - } - - eventLoop->processEvents(); - int ticks = 0; - while (allAddressQueryResults.size() < numQueries) { - ticks++; - if (ticks > 1000) { - CPPUNIT_ASSERT(false); - } - Swift::sleep(10); - eventLoop->processEvents(); - } - - CPPUNIT_ASSERT_EQUAL(numQueries, allAddressQueryResults.size()); - for (size_t i = 0; i < numQueries; ++i) { - CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.0"), allAddressQueryResults[i].toString()); - } - } - - void testResolveService() { - boost::shared_ptr<DomainNameServiceQuery> query(createServiceQuery("_xmpp-client._tcp.xmpp-srv.test.swift.im")); - - query->run(); - waitForResults(); - - CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(serviceQueryResult.size())); - CPPUNIT_ASSERT_EQUAL(std::string("xmpp1.test.swift.im"), serviceQueryResult[0].hostname); - CPPUNIT_ASSERT_EQUAL(5000, serviceQueryResult[0].port); - CPPUNIT_ASSERT_EQUAL(0, serviceQueryResult[0].priority); - CPPUNIT_ASSERT_EQUAL(1, serviceQueryResult[0].weight); - CPPUNIT_ASSERT_EQUAL(std::string("xmpp-invalid.test.swift.im"), serviceQueryResult[1].hostname); - CPPUNIT_ASSERT_EQUAL(5000, serviceQueryResult[1].port); - CPPUNIT_ASSERT_EQUAL(1, serviceQueryResult[1].priority); - CPPUNIT_ASSERT_EQUAL(100, serviceQueryResult[1].weight); - CPPUNIT_ASSERT_EQUAL(std::string("xmpp3.test.swift.im"), serviceQueryResult[2].hostname); - CPPUNIT_ASSERT_EQUAL(5000, serviceQueryResult[2].port); - CPPUNIT_ASSERT_EQUAL(3, serviceQueryResult[2].priority); - CPPUNIT_ASSERT_EQUAL(100, serviceQueryResult[2].weight); - CPPUNIT_ASSERT_EQUAL(std::string("xmpp2.test.swift.im"), serviceQueryResult[3].hostname); - CPPUNIT_ASSERT_EQUAL(5000, serviceQueryResult[3].port); - CPPUNIT_ASSERT_EQUAL(5, serviceQueryResult[3].priority); - CPPUNIT_ASSERT_EQUAL(100, serviceQueryResult[3].weight); - } - - void testResolveService_Error() { - } - - private: - boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& domain) { - boost::shared_ptr<DomainNameAddressQuery> result = resolver->createAddressQuery(domain); - result->onResult.connect(boost::bind(&DomainNameResolverTest::handleAddressQueryResult, this, _1, _2)); - return result; - } - - void handleAddressQueryResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error) { - addressQueryResult = addresses; - std::sort(addressQueryResult.begin(), addressQueryResult.end(), CompareHostAddresses()); - allAddressQueryResults.insert(allAddressQueryResults.begin(), addresses.begin(), addresses.end()); - addressQueryError = error; - resultsAvailable = true; - } - - boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& domain) { - boost::shared_ptr<DomainNameServiceQuery> result = resolver->createServiceQuery(domain); - result->onResult.connect(boost::bind(&DomainNameResolverTest::handleServiceQueryResult, this, _1)); - return result; - } - - void handleServiceQueryResult(const std::vector<DomainNameServiceQuery::Result>& result) { - serviceQueryResult = result; - resultsAvailable = true; - } - - void waitForResults() { - eventLoop->processEvents(); - int ticks = 0; - while (!resultsAvailable) { - ticks++; - if (ticks > 1000) { - CPPUNIT_ASSERT(false); - } - Swift::sleep(10); - eventLoop->processEvents(); - } - } - - private: - BoostIOServiceThread* ioServiceThread; - DummyEventLoop* eventLoop; - boost::shared_ptr<IDNConverter> idnConverter; - boost::shared_ptr<TimerFactory> timerFactory; - bool resultsAvailable; - std::vector<HostAddress> addressQueryResult; - std::vector<HostAddress> allAddressQueryResults; - boost::optional<DomainNameResolveError> addressQueryError; - std::vector<DomainNameServiceQuery::Result> serviceQueryResult; - DomainNameResolver* resolver; + resultsAvailable = false; + } + + void tearDown() { + delete ioServiceThread; + delete resolver; + delete eventLoop; + } + + void testResolveAddress() { + std::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("xmpp.test.swift.im")); + + query->run(); + waitForResults(); + + CPPUNIT_ASSERT(!addressQueryError); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addressQueryResult.size())); + CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.0"), addressQueryResult[0].toString()); + } + + void testResolveAddress_Error() { + std::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("invalid.test.swift.im")); + + query->run(); + waitForResults(); + + CPPUNIT_ASSERT(addressQueryError); + } + + void testResolveAddress_IPv6() { + std::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("xmpp-ipv6.test.swift.im")); + + query->run(); + waitForResults(); + + CPPUNIT_ASSERT(!addressQueryError); + CPPUNIT_ASSERT_EQUAL(std::string("2001:470:1f0e:852::2"), addressQueryResult[0].toString()); + } + + void testResolveAddress_IPv4and6() { + std::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("xmpp-ipv46.test.swift.im")); + + query->run(); + waitForResults(); + + CPPUNIT_ASSERT(!addressQueryError); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(addressQueryResult.size())); + CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.7"), addressQueryResult[0].toString()); + CPPUNIT_ASSERT_EQUAL(std::string("1234:5678:9abc:def0:fed:cba9:8765:4321"), addressQueryResult[1].toString()); + } + + void testResolveAddress_International() { + std::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("tron\xc3\xa7on.test.swift.im")); + + query->run(); + waitForResults(); + + CPPUNIT_ASSERT(!addressQueryError); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addressQueryResult.size())); + CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.3"), addressQueryResult[0].toString()); + } + + void testResolveAddress_Localhost() { + std::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("localhost")); + + query->run(); + waitForResults(); + + CPPUNIT_ASSERT(!addressQueryError); + CPPUNIT_ASSERT(std::find(addressQueryResult.begin(), addressQueryResult.end(), HostAddress::fromString("127.0.0.1").get()) != addressQueryResult.end()); + } + + void testResolveAddress_Parallel() { + std::vector<DomainNameAddressQuery::ref> queries; + static const size_t numQueries = 100; + for (size_t i = 0; i < numQueries; ++i) { + DomainNameAddressQuery::ref query(createAddressQuery("xmpp.test.swift.im")); + queries.push_back(query); + query->run(); + } + + eventLoop->processEvents(); + int ticks = 0; + while (allAddressQueryResults.size() < numQueries) { + ticks++; + if (ticks > 1000) { + CPPUNIT_ASSERT(false); + } + Swift::sleep(10); + eventLoop->processEvents(); + } + + CPPUNIT_ASSERT_EQUAL(numQueries, allAddressQueryResults.size()); + for (size_t i = 0; i < numQueries; ++i) { + CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.0"), allAddressQueryResults[i].toString()); + } + } + + void testResolveService() { + std::shared_ptr<DomainNameServiceQuery> query(createServiceQuery("_xmpp-client._tcp.", "xmpp-srv.test.swift.im")); + + query->run(); + waitForResults(); + + CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(serviceQueryResult.size())); + CPPUNIT_ASSERT_EQUAL(std::string("xmpp1.test.swift.im"), serviceQueryResult[0].hostname); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(5000), serviceQueryResult[0].port); + CPPUNIT_ASSERT_EQUAL(0, serviceQueryResult[0].priority); + CPPUNIT_ASSERT_EQUAL(1, serviceQueryResult[0].weight); + CPPUNIT_ASSERT_EQUAL(std::string("xmpp-invalid.test.swift.im"), serviceQueryResult[1].hostname); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(5000), serviceQueryResult[1].port); + CPPUNIT_ASSERT_EQUAL(1, serviceQueryResult[1].priority); + CPPUNIT_ASSERT_EQUAL(100, serviceQueryResult[1].weight); + CPPUNIT_ASSERT_EQUAL(std::string("xmpp3.test.swift.im"), serviceQueryResult[2].hostname); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(5000), serviceQueryResult[2].port); + CPPUNIT_ASSERT_EQUAL(3, serviceQueryResult[2].priority); + CPPUNIT_ASSERT_EQUAL(100, serviceQueryResult[2].weight); + CPPUNIT_ASSERT_EQUAL(std::string("xmpp2.test.swift.im"), serviceQueryResult[3].hostname); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(5000), serviceQueryResult[3].port); + CPPUNIT_ASSERT_EQUAL(5, serviceQueryResult[3].priority); + CPPUNIT_ASSERT_EQUAL(100, serviceQueryResult[3].weight); + } + + void testResolveService_Error() { + } + + private: + std::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& domain) { + std::shared_ptr<DomainNameAddressQuery> result = resolver->createAddressQuery(domain); + result->onResult.connect(boost::bind(&DomainNameResolverTest::handleAddressQueryResult, this, _1, _2)); + return result; + } + + void handleAddressQueryResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error) { + addressQueryResult = addresses; + std::sort(addressQueryResult.begin(), addressQueryResult.end(), CompareHostAddresses()); + allAddressQueryResults.insert(allAddressQueryResults.begin(), addresses.begin(), addresses.end()); + addressQueryError = error; + resultsAvailable = true; + } + + std::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) { + std::shared_ptr<DomainNameServiceQuery> result = resolver->createServiceQuery(serviceLookupPrefix, domain); + result->onResult.connect(boost::bind(&DomainNameResolverTest::handleServiceQueryResult, this, _1)); + return result; + } + + void handleServiceQueryResult(const std::vector<DomainNameServiceQuery::Result>& result) { + serviceQueryResult = result; + resultsAvailable = true; + } + + void waitForResults() { + eventLoop->processEvents(); + int ticks = 0; + while (!resultsAvailable) { + ticks++; + if (ticks > 1000) { + CPPUNIT_ASSERT(false); + } + Swift::sleep(10); + eventLoop->processEvents(); + } + } + + private: + BoostIOServiceThread* ioServiceThread; + DummyEventLoop* eventLoop; + std::shared_ptr<IDNConverter> idnConverter; + std::shared_ptr<TimerFactory> timerFactory; + bool resultsAvailable; + std::vector<HostAddress> addressQueryResult; + std::vector<HostAddress> allAddressQueryResults; + boost::optional<DomainNameResolveError> addressQueryError; + std::vector<DomainNameServiceQuery::Result> serviceQueryResult; + DomainNameResolver* resolver; }; CPPUNIT_TEST_SUITE_REGISTRATION(DomainNameResolverTest); diff --git a/Swiften/QA/NetworkTest/SConscript b/Swiften/QA/NetworkTest/SConscript index b090165..606af5d 100644 --- a/Swiften/QA/NetworkTest/SConscript +++ b/Swiften/QA/NetworkTest/SConscript @@ -3,20 +3,21 @@ import os Import("env") if env["TEST"] : - myenv = env.Clone() - if "test_ipv6" in ARGUMENTS : - myenv.Append(CPPDEFINES = ["TEST_IPV6"]) - myenv.MergeFlags(myenv["CHECKER_FLAGS"]) - myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) - myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) - myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) + myenv = env.Clone() + if "test_ipv6" in ARGUMENTS : + myenv.Append(CPPDEFINES = ["TEST_IPV6"]) + myenv.MergeFlags(myenv["CHECKER_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) + myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) + myenv.MergeFlags(myenv["GOOGLETEST_FLAGS"]) - if env.get("unbound", False) : - myenv.Append(CPPDEFINES = ["USE_UNBOUND"]) + if env.get("unbound", False) : + myenv.Append(CPPDEFINES = ["USE_UNBOUND"]) - tester = myenv.Program("NetworkTest", [ - "BoostConnectionServerTest.cpp", - "BoostConnectionTest.cpp", - "DomainNameResolverTest.cpp", - ]) - myenv.Test(tester, "system", is_checker = True) + tester = myenv.Program("NetworkTest", [ + "BoostConnectionServerTest.cpp", + "BoostConnectionTest.cpp", + "DomainNameResolverTest.cpp", + ]) + myenv.Test(tester, "system", is_checker = True) diff --git a/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp b/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp index ddaee01..53f9e60 100644 --- a/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp +++ b/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp @@ -4,32 +4,37 @@ * See Documentation/Licenses/BSD.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <iostream> #include <Swiften/Network/PlatformProxyProvider.h> -#include <Swiften/Base/foreach.h> using namespace Swift; int main(void) { - int ret = 0; - HostAddressPort hap; - - std::cout << "constructing PlatfromProxyProvider instance ..." << std::endl; - PlatformProxyProvider ppp; - - hap = ppp.getSOCKS5Proxy(); - std::cout << "SOCKS5 Proxy configured: " << hap.isValid() << std::endl; - if(hap.isValid()) { - std::cout << "SOCKS5 Proxy: " << hap.getAddress().toString() << ":" << hap.getPort() << std::endl; - } - - hap = ppp.getHTTPConnectProxy(); - std::cout << "HTTPConnect Proxy configured: " << hap.isValid() << std::endl; - if(hap.isValid()) { - std::cout << "HTTPConnect Proxy: " << hap.getAddress().toString() << ":" << hap.getPort() << std::endl; - } - - return ret; + int ret = 0; + HostAddressPort hap; + + std::cout << "constructing PlatfromProxyProvider instance ..." << std::endl; + PlatformProxyProvider ppp; + + hap = ppp.getSOCKS5Proxy(); + std::cout << "SOCKS5 Proxy configured: " << hap.isValid() << std::endl; + if(hap.isValid()) { + std::cout << "SOCKS5 Proxy: " << hap.getAddress().toString() << ":" << hap.getPort() << std::endl; + } + + hap = ppp.getHTTPConnectProxy(); + std::cout << "HTTPConnect Proxy configured: " << hap.isValid() << std::endl; + if(hap.isValid()) { + std::cout << "HTTPConnect Proxy: " << hap.getAddress().toString() << ":" << hap.getPort() << std::endl; + } + + return ret; } diff --git a/Swiften/QA/ProxyProviderTest/SConscript b/Swiften/QA/ProxyProviderTest/SConscript index 2eb123d..3e28360 100644 --- a/Swiften/QA/ProxyProviderTest/SConscript +++ b/Swiften/QA/ProxyProviderTest/SConscript @@ -7,5 +7,5 @@ myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) myenv.Program("ProxyProviderTest", [ - "ProxyProviderTest.cpp", - ]) + "ProxyProviderTest.cpp", + ]) diff --git a/Swiften/QA/ReconnectTest/ReconnectTest.cpp b/Swiften/QA/ReconnectTest/ReconnectTest.cpp index 933d5d2..af3369c 100644 --- a/Swiften/QA/ReconnectTest/ReconnectTest.cpp +++ b/Swiften/QA/ReconnectTest/ReconnectTest.cpp @@ -1,20 +1,21 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <thread> + #include <boost/bind.hpp> -#include <boost/thread.hpp> #include <Swiften/Client/Client.h> -#include <Swiften/Network/BoostTimer.h> +#include <Swiften/Client/ClientXMLTracer.h> #include <Swiften/EventLoop/EventLoop.h> #include <Swiften/EventLoop/SimpleEventLoop.h> -#include <Swiften/Roster/GetRosterRequest.h> -#include <Swiften/Client/ClientXMLTracer.h> #include <Swiften/Network/BoostIOServiceThread.h> +#include <Swiften/Network/BoostTimer.h> #include <Swiften/Network/MainBoostIOServiceThread.h> +#include <Swiften/Roster/GetRosterRequest.h> using namespace Swift; @@ -25,49 +26,49 @@ Client* client_; SimpleEventLoop eventLoop_; int count = 0; -void handleTick(boost::shared_ptr<BoostTimer> timer) { - std::cout << "Count " << count++ << std::endl; - if (timer) { - timer->stop(); - } - if (connecting_) { - client_->disconnect(); - } else { - if (count > 60) { - eventLoop_.stop(); - return; - } - client_->connect(); - } - connecting_ = !connecting_; - - int delay = 500; -// int delay = 0; - boost::shared_ptr<BoostTimer> newTimer(BoostTimer::create(delay, &MainBoostIOServiceThread::getInstance().getIOService())); - newTimer->onTick.connect(boost::bind(&handleTick, timer)); - newTimer->start(); +void handleTick(std::shared_ptr<BoostTimer> timer) { + std::cout << "Count " << count++ << std::endl; + if (timer) { + timer->stop(); + } + if (connecting_) { + client_->disconnect(); + } else { + if (count > 60) { + eventLoop_.stop(); + return; + } + client_->connect(); + } + connecting_ = !connecting_; + + int delay = 500; +// int delay = 0; + std::shared_ptr<BoostTimer> newTimer(BoostTimer::create(delay, &MainBoostIOServiceThread::getInstance().getIOService())); + newTimer->onTick.connect(boost::bind(&handleTick, timer)); + newTimer->start(); } int main(int, char**) { - char* jidChars = getenv("SWIFT_CLIENTTEST_JID"); - if (!jidChars) { - std::cerr << "Please set the SWIFT_CLIENTTEST_JID environment variable" << std::endl; - return -1; - } - char* passChars = getenv("SWIFT_CLIENTTEST_PASS"); - if (!passChars) { - std::cerr << "Please set the SWIFT_CLIENTTEST_PASS environment variable" << std::endl; - return -1; - } - - JID jid(jidChars); - std::string pass(passChars); + char* jidChars = getenv("SWIFT_CLIENTTEST_JID"); + if (!jidChars) { + std::cerr << "Please set the SWIFT_CLIENTTEST_JID environment variable" << std::endl; + return -1; + } + char* passChars = getenv("SWIFT_CLIENTTEST_PASS"); + if (!passChars) { + std::cerr << "Please set the SWIFT_CLIENTTEST_PASS environment variable" << std::endl; + return -1; + } + + JID jid(jidChars); + std::string pass(passChars); + + client_ = new Swift::Client(jid, pass); + handleTick(std::shared_ptr<BoostTimer>()); + eventLoop_.run(); - client_ = new Swift::Client(jid, pass); - handleTick(boost::shared_ptr<BoostTimer>()); - eventLoop_.run(); - - delete client_; - return 0; + delete client_; + return 0; } diff --git a/Swiften/QA/ReconnectTest/SConscript b/Swiften/QA/ReconnectTest/SConscript index 6db6a6f..a94af5e 100644 --- a/Swiften/QA/ReconnectTest/SConscript +++ b/Swiften/QA/ReconnectTest/SConscript @@ -3,23 +3,23 @@ import os Import("env") if env["TEST"] : - myenv = env.Clone() - myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) - myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) - myenv.MergeFlags(myenv["LIBIDN_FLAGS"]) - myenv.MergeFlags(myenv["BOOST_FLAGS"]) - myenv.MergeFlags(myenv.get("SQLITE_FLAGS", "")) - myenv.MergeFlags(myenv["ZLIB_FLAGS"]) - myenv.MergeFlags(myenv["OPENSSL_FLAGS"]) - myenv.MergeFlags(myenv.get("LIBXML_FLAGS", "")) - myenv.MergeFlags(myenv.get("EXPAT_FLAGS", "")) - myenv.MergeFlags(myenv["PLATFORM_FLAGS"]) -# myenv.Append(LIBPATH = ["/opt/local/lib"]) -# myenv.Append(LIBS = ["efence"]) + myenv = env.Clone() + myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) + myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) + myenv.MergeFlags(myenv["LIBIDN_FLAGS"]) + myenv.MergeFlags(myenv["BOOST_FLAGS"]) + myenv.MergeFlags(myenv.get("SQLITE_FLAGS", "")) + myenv.MergeFlags(myenv["ZLIB_FLAGS"]) + myenv.MergeFlags(myenv["OPENSSL_FLAGS"]) + myenv.MergeFlags(myenv.get("LIBXML_FLAGS", "")) + myenv.MergeFlags(myenv.get("EXPAT_FLAGS", "")) + myenv.MergeFlags(myenv["PLATFORM_FLAGS"]) +# myenv.Append(LIBPATH = ["/opt/local/lib"]) +# myenv.Append(LIBS = ["efence"]) - for i in ["SWIFT_CLIENTTEST_JID", "SWIFT_CLIENTTEST_PASS"]: - if os.environ.get(i, "") : - myenv["ENV"][i] = os.environ[i] + for i in ["SWIFT_CLIENTTEST_JID", "SWIFT_CLIENTTEST_PASS"]: + if os.environ.get(i, "") : + myenv["ENV"][i] = os.environ[i] - tester = myenv.Program("ReconnectTest", ["ReconnectTest.cpp"]) - myenv.Test(tester, "system", is_checker = True) + tester = myenv.Program("ReconnectTest", ["ReconnectTest.cpp"]) + myenv.Test(tester, "system", is_checker = True) diff --git a/Swiften/QA/SConscript b/Swiften/QA/SConscript index 2f2be6e..2bb3e51 100644 --- a/Swiften/QA/SConscript +++ b/Swiften/QA/SConscript @@ -1,12 +1,13 @@ Import("swiften_env") SConscript(dirs = [ - "NetworkTest", -# "ReconnectTest", - "ClientTest", -# "DNSSDTest", -# "StorageTest", - "TLSTest", - "ScriptedTests", - "ProxyProviderTest", - ]) + "NetworkTest", +# "ReconnectTest", + "ClientTest", +# "DNSSDTest", + "StorageTest", + "TLSTest", + "ScriptedTests", + "ProxyProviderTest", + "FileTransferTest", + ]) diff --git a/Swiften/QA/ScriptedTests/MultipleClients.lua b/Swiften/QA/ScriptedTests/MultipleClients.lua index ddc7c44..ba29adb 100644 --- a/Swiften/QA/ScriptedTests/MultipleClients.lua +++ b/Swiften/QA/ScriptedTests/MultipleClients.lua @@ -1,7 +1,7 @@ -- --- Copyright (c) 2010-2013 Remko Tronçon --- Licensed under the GNU General Public License v3. --- See Documentation/Licenses/GPLv3.txt for more information. +-- Copyright (c) 2010-2013 Isode Limited. +-- All rights reserved.v3. +-- See the COPYING file for more information. -- require "sluift" diff --git a/Swiften/QA/ScriptedTests/PubSub.lua b/Swiften/QA/ScriptedTests/PubSub.lua index cb4679a..04a82ba 100644 --- a/Swiften/QA/ScriptedTests/PubSub.lua +++ b/Swiften/QA/ScriptedTests/PubSub.lua @@ -1,6 +1,6 @@ --[[ - Copyright (c) 2013 Remko Tronçon - Licensed under the GNU General Public License. + Copyright (c) 2013 Isode Limited. + All rights reserved. See the COPYING file for more information. --]] @@ -60,11 +60,15 @@ function test_entity_use_cases() -- 5.6 Subscriptions assert(node:create()) assert(subscriber_node:subscribe({ jid = subscriber_jid })) - local service_subscriptions = assert(pubsub:get_subscriptions()) - -- FIXME: Doesn't seem to return anything on M-Link. Test this later if this is supposed to work. - --print(service_subscriptions) - local node_subscriptions = assert(node:get_subscriptions()) - --print(node_subscriptions) + local service_subscriptions = assert(subscriber_pubsub:get_subscriptions()) + assert(#service_subscriptions == 1) + assert(service_subscriptions[1].node == node_id) + assert(service_subscriptions[1].jid == subscriber_jid) + assert(service_subscriptions[1].subscription == 'subscribed') + local node_subscriptions = assert(subscriber_node:get_subscriptions()) + assert(#node_subscriptions == 1) + assert(node_subscriptions[1].jid == subscriber_jid) + assert(node_subscriptions[1].subscription == 'subscribed') assert(node:delete()) -- 5.7 Retrieve affiliations @@ -282,7 +286,25 @@ function test_owner_use_cases() -- 8.7 Process pending subscription requests -- TODO - -- ... + -- 8.8 Manage Subscriptions + assert(node:create()) + assert(subscriber_node:subscribe({ jid = subscriber_jid })) + local items = assert(node:get_owner_subscriptions()) + assert(#items == 1) + assert(items[1].jid == subscriber_jid) + assert(items[1].subscription == "subscribed") + assert(node:delete()) + + -- 8.9 Manage Affiliations + assert(node:create()) + assert(node:set_owner_affiliations{affiliations = {{jid = subscriber_jid, type = 'publisher'}}}) + local items = assert(node:get_owner_affiliations()) + assert(#items == 2) + assert(items[1].jid == publisher_jid) + assert(items[1].type == "owner") + assert(items[2].jid == subscriber_jid) + assert(items[2].type == "publisher") + assert(node:delete()) end function run_tests() diff --git a/Swiften/QA/ScriptedTests/SConscript b/Swiften/QA/ScriptedTests/SConscript index 298c455..ae315fe 100644 --- a/Swiften/QA/ScriptedTests/SConscript +++ b/Swiften/QA/ScriptedTests/SConscript @@ -1,7 +1,7 @@ Import("env") if env["TEST"] : - env.ScriptTests([ - "SendMessage.lua", - "MultipleClients.lua", - ], "Swiften.QA.ScriptedTests", "system") + env.ScriptTests([ + "SendMessage.lua", + "MultipleClients.lua", + ], "Swiften.QA.ScriptedTests", "system") diff --git a/Swiften/QA/ScriptedTests/SendMessage.lua b/Swiften/QA/ScriptedTests/SendMessage.lua index 9623ef4..f6e5b00 100644 --- a/Swiften/QA/ScriptedTests/SendMessage.lua +++ b/Swiften/QA/ScriptedTests/SendMessage.lua @@ -1,7 +1,7 @@ -- --- Copyright (c) 2010-2013 Remko Tronçon --- Licensed under the GNU General Public License v3. --- See Documentation/Licenses/GPLv3.txt for more information. +-- Copyright (c) 2010-2013 Isode Limited. +-- All rights reserved.v3. +-- See the COPYING file for more information. -- require "sluift" diff --git a/Swiften/QA/StorageTest/FileReadBytestreamTest.cpp b/Swiften/QA/StorageTest/FileReadBytestreamTest.cpp index e090c6c..e601de9 100644 --- a/Swiften/QA/StorageTest/FileReadBytestreamTest.cpp +++ b/Swiften/QA/StorageTest/FileReadBytestreamTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -9,66 +9,67 @@ #include <Swiften/Base/ByteArray.h> #include <Swiften/FileTransfer/FileReadBytestream.h> -#include "SwifTools/Application/PlatformApplicationPathProvider.h" + +#include <SwifTools/Application/PlatformApplicationPathProvider.h> using namespace Swift; class FileReadBytestreamTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(FileReadBytestreamTest); - CPPUNIT_TEST(testRead); - CPPUNIT_TEST(testRead_Twice); - CPPUNIT_TEST(testIsFinished_NotFinished); - CPPUNIT_TEST(testIsFinished_IsFinished); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(FileReadBytestreamTest); + CPPUNIT_TEST(testRead); + CPPUNIT_TEST(testRead_Twice); + CPPUNIT_TEST(testIsFinished_NotFinished); + CPPUNIT_TEST(testIsFinished_IsFinished); + CPPUNIT_TEST_SUITE_END(); - public: - void setUp() { - pathProvider = new PlatformApplicationPathProvider("FileReadBytestreamTest"); - } + public: + void setUp() { + pathProvider = new PlatformApplicationPathProvider("FileReadBytestreamTest"); + } - void tearDown() { - delete pathProvider; - } + void tearDown() { + delete pathProvider; + } - void testRead() { - boost::shared_ptr<FileReadBytestream> testling(createTestling()); + void testRead() { + std::shared_ptr<FileReadBytestream> testling(createTestling()); - std::vector<unsigned char> result = testling->read(10); + std::shared_ptr< std::vector<unsigned char> > result = testling->read(10); - CPPUNIT_ASSERT(ByteArray::create("/*\n * Copy") == result); - } + CPPUNIT_ASSERT(createByteArray("/*\n * Copy") == *result.get()); + } - void testRead_Twice() { - boost::shared_ptr<FileReadBytestream> testling(createTestling()); + void testRead_Twice() { + std::shared_ptr<FileReadBytestream> testling(createTestling()); - testling->read(10); - ByteArray result(testling->read(10)); + testling->read(10); + std::shared_ptr< std::vector<unsigned char> > result = testling->read(10); - CPPUNIT_ASSERT_EQUAL(std::string("right (c) "), result.toString()); - } + CPPUNIT_ASSERT_EQUAL(std::string("right (c) "), byteArrayToString(*result)); + } - void testIsFinished_NotFinished() { - boost::shared_ptr<FileReadBytestream> testling(createTestling()); + void testIsFinished_NotFinished() { + std::shared_ptr<FileReadBytestream> testling(createTestling()); - testling->read(10); + testling->read(10); - CPPUNIT_ASSERT(!testling->isFinished()); - } + CPPUNIT_ASSERT(!testling->isFinished()); + } - void testIsFinished_IsFinished() { - boost::shared_ptr<FileReadBytestream> testling(createTestling()); + void testIsFinished_IsFinished() { + std::shared_ptr<FileReadBytestream> testling(createTestling()); - testling->read(4096); + testling->read(4096); - CPPUNIT_ASSERT(testling->isFinished()); - } + CPPUNIT_ASSERT(testling->isFinished()); + } - private: - FileReadBytestream* createTestling() { - return new FileReadBytestream(pathProvider->getExecutableDir() / "FileReadBytestreamTest.cpp"); - } + private: + FileReadBytestream* createTestling() { + return new FileReadBytestream(pathProvider->getExecutableDir() / "FileReadBytestreamTest.cpp"); + } - PlatformApplicationPathProvider* pathProvider; + PlatformApplicationPathProvider* pathProvider; }; CPPUNIT_TEST_SUITE_REGISTRATION(FileReadBytestreamTest); diff --git a/Swiften/QA/StorageTest/FileWriteBytestreamTest.cpp b/Swiften/QA/StorageTest/FileWriteBytestreamTest.cpp new file mode 100644 index 0000000..393d1d7 --- /dev/null +++ b/Swiften/QA/StorageTest/FileWriteBytestreamTest.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <boost/bind.hpp> +#include <boost/filesystem.hpp> +#include <boost/signals2.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/ByteArray.h> +#include <Swiften/FileTransfer/FileWriteBytestream.h> + +using namespace Swift; + +class FileWriteBytestreamTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(FileWriteBytestreamTest); + CPPUNIT_TEST(testSuccessfulWrite); + CPPUNIT_TEST(testFailingWrite); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + onWriteWasCalled = false; + } + + void testSuccessfulWrite() { + boost::filesystem::path filename = boost::filesystem::unique_path("write_file_bytestream_test_%%%%%%%%%%%%%%%%.bin"); + std::shared_ptr<WriteBytestream> writeBytestream = std::make_shared<FileWriteBytestream>(filename.string()); + writeBytestream->onWrite.connect(boost::bind(&FileWriteBytestreamTest::handleOnWrite, this, _1)); + + CPPUNIT_ASSERT_EQUAL(true, writeBytestream->write(createByteArray("Some data."))); + CPPUNIT_ASSERT_EQUAL(true, onWriteWasCalled); + writeBytestream->close(); + boost::filesystem::remove(filename); + } + + void testFailingWrite() { + std::shared_ptr<WriteBytestream> writeBytestream = std::make_shared<FileWriteBytestream>(""); + writeBytestream->onWrite.connect(boost::bind(&FileWriteBytestreamTest::handleOnWrite, this, _1)); + + CPPUNIT_ASSERT_EQUAL(false, writeBytestream->write(createByteArray("Some data."))); + CPPUNIT_ASSERT_EQUAL(false, onWriteWasCalled); + } + + + void handleOnWrite(const std::vector<unsigned char>& /*data*/) { + onWriteWasCalled = true; + } + + private: + bool onWriteWasCalled; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(FileWriteBytestreamTest); diff --git a/Swiften/QA/StorageTest/SConscript b/Swiften/QA/StorageTest/SConscript index 6d65b30..46107a0 100644 --- a/Swiften/QA/StorageTest/SConscript +++ b/Swiften/QA/StorageTest/SConscript @@ -3,19 +3,22 @@ import os Import("env") if env["TEST"] : - myenv = env.Clone() - myenv.MergeFlags(myenv["CHECKER_FLAGS"]) - myenv.MergeFlags(myenv["SWIFTOOLS_FLAGS"]) - myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) - myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) - myenv.MergeFlags(myenv["BOOST_FLAGS"]) - myenv.MergeFlags(myenv["LIBIDN_FLAGS"]) - myenv.MergeFlags(myenv.get("EXPAT_FLAGS", {})) - myenv.MergeFlags(myenv.get("LIBXML_FLAGS", {})) - myenv.MergeFlags(myenv["PLATFORM_FLAGS"]) + myenv = env.Clone() + myenv.MergeFlags(myenv["CHECKER_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTOOLS_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) + myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) + myenv.MergeFlags(myenv["GOOGLETEST_FLAGS"]) + myenv.MergeFlags(myenv["BOOST_FLAGS"]) + myenv.MergeFlags(myenv.get("LIBIDN_FLAGS", {})) + myenv.MergeFlags(myenv.get("ICU_FLAGS", {})) + myenv.MergeFlags(myenv.get("EXPAT_FLAGS", {})) + myenv.MergeFlags(myenv.get("LIBXML_FLAGS", {})) + myenv.MergeFlags(myenv["PLATFORM_FLAGS"]) - tester = myenv.Program("StorageTest", [ - "VCardFileStorageTest.cpp", - "FileReadBytestreamTest.cpp", - ]) - myenv.Test(tester, "system", is_checker = True) + tester = myenv.Program("StorageTest", [ + #"VCardFileStorageTest.cpp", + "FileReadBytestreamTest.cpp", + "FileWriteBytestreamTest.cpp", + ]) + myenv.Test(tester, "system", is_checker = True) diff --git a/Swiften/QA/StorageTest/VCardFileStorageTest.cpp b/Swiften/QA/StorageTest/VCardFileStorageTest.cpp index 4145696..1be2490 100644 --- a/Swiften/QA/StorageTest/VCardFileStorageTest.cpp +++ b/Swiften/QA/StorageTest/VCardFileStorageTest.cpp @@ -1,113 +1,117 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> +#include <sstream> + +#include <boost/algorithm/string.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/algorithm/string.hpp> -#include <sstream> -#include <Swiften/VCards/VCardFileStorage.h> -#include <Swiften/JID/JID.h> -#include "SwifTools/Application/PlatformApplicationPathProvider.h" #include <Swiften/Elements/VCard.h> +#include <Swiften/JID/JID.h> +#include <Swiften/VCards/VCardFileStorage.h> + +#include <SwifTools/Application/PlatformApplicationPathProvider.h> using namespace Swift; class VCardFileStorageTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(VCardFileStorageTest); - CPPUNIT_TEST(testSetVCard); - // Temporarily disabling this, because it generates error messages on console. Need to figure - // out something for not showing error messages during tests. - //CPPUNIT_TEST(testSetVCard_LargeFilename); - CPPUNIT_TEST(testGetVCard); - CPPUNIT_TEST(testGetVCard_FileDoesNotExist); - //CPPUNIT_TEST(testGetVCard_LargeFilename); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - pathProvider = new PlatformApplicationPathProvider("VCardStorageTest"); - vcardsPath = pathProvider->getExecutableDir() / "vcards"; - boost::filesystem::remove_all(vcardsPath); - } - - void tearDown() { - delete pathProvider; - boost::filesystem::remove_all(vcardsPath); - } - - void testSetVCard() { - boost::shared_ptr<VCardFileStorage> testling(createTestling()); - VCard::ref vcard(new VCard()); - vcard->setFullName("Alice In Wonderland"); - - testling->setVCard(JID("alice@wonderland.lit/TeaRoom"), vcard); - - boost::filesystem::path vcardFile(vcardsPath / "alice@wonderland.lit%2fTeaRoom.xml"); - CPPUNIT_ASSERT(boost::filesystem::exists(vcardFile)); - ByteArray data; - data.readFromFile(vcardFile); - CPPUNIT_ASSERT(boost::starts_with(data.toString(), "<vCard xmlns=\"vcard-temp\">")); - } - - void testSetVCard_LargeFilename() { - std::auto_ptr<VCardFileStorage> testling(createTestling()); - VCard::ref vcard(new VCard()); - vcard->setFullName("Alice In Wonderland"); - - std::ostringstream s; - for (int i = 0; i < 1000; ++i) { - s << "_"; - } - - JID jid("alice@wonderland.lit/" + s.str()); - testling->setVCard(jid, vcard); - - // Just check whether we don't crash - } - - void testGetVCard() { - boost::shared_ptr<VCardFileStorage> testling(createTestling()); - VCard::ref vcard(new VCard()); - vcard->setFullName("Alice In Wonderland"); - testling->setVCard(JID("alice@wonderland.lit"), vcard); - - VCard::ref result = testling->getVCard(JID("alice@wonderland.lit")); - CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland"), result->getFullName()); - } - - void testGetVCard_LargeFilename() { - std::auto_ptr<VCardFileStorage> testling(createTestling()); - VCard::ref vcard(new VCard()); - vcard->setFullName("Alice In Wonderland"); - - std::ostringstream s; - for (int i = 0; i < 1000; ++i) { - s << "_"; - } - JID jid("alice@wonderland.lit/" + s.str()); - - VCard::ref result = testling->getVCard(jid); - - // Just check that we don't have an exception - } - - void testGetVCard_FileDoesNotExist() { - boost::shared_ptr<VCardFileStorage> testling(createTestling()); - VCard::ref result = testling->getVCard(JID("alice@wonderland.lit")); - CPPUNIT_ASSERT(!result); - } - - private: - VCardFileStorage* createTestling() { - return new VCardFileStorage(vcardsPath); - } - - PlatformApplicationPathProvider* pathProvider; - boost::filesystem::path vcardsPath; + CPPUNIT_TEST_SUITE(VCardFileStorageTest); + CPPUNIT_TEST(testSetVCard); + // Temporarily disabling this, because it generates error messages on console. Need to figure + // out something for not showing error messages during tests. + //CPPUNIT_TEST(testSetVCard_LargeFilename); + CPPUNIT_TEST(testGetVCard); + CPPUNIT_TEST(testGetVCard_FileDoesNotExist); + //CPPUNIT_TEST(testGetVCard_LargeFilename); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + pathProvider = new PlatformApplicationPathProvider("VCardStorageTest"); + vcardsPath = pathProvider->getExecutableDir() / "vcards"; + boost::filesystem::remove_all(vcardsPath); + } + + void tearDown() { + delete pathProvider; + boost::filesystem::remove_all(vcardsPath); + } + + void testSetVCard() { + std::shared_ptr<VCardFileStorage> testling(createTestling()); + VCard::ref vcard(new VCard()); + vcard->setFullName("Alice In Wonderland"); + + testling->setVCard(JID("alice@wonderland.lit/TeaRoom"), vcard); + + boost::filesystem::path vcardFile(vcardsPath / "alice@wonderland.lit%2fTeaRoom.xml"); + CPPUNIT_ASSERT(boost::filesystem::exists(vcardFile)); + ByteArray data; + data.readFromFile(vcardFile); + CPPUNIT_ASSERT(boost::starts_with(data.toString(), "<vCard xmlns=\"vcard-temp\">")); + } + + void testSetVCard_LargeFilename() { + std::unique_ptr<VCardFileStorage> testling(createTestling()); + VCard::ref vcard(new VCard()); + vcard->setFullName("Alice In Wonderland"); + + std::ostringstream s; + for (int i = 0; i < 1000; ++i) { + s << "_"; + } + + JID jid("alice@wonderland.lit/" + s.str()); + testling->setVCard(jid, vcard); + + // Just check whether we don't crash + } + + void testGetVCard() { + std::shared_ptr<VCardFileStorage> testling(createTestling()); + VCard::ref vcard(new VCard()); + vcard->setFullName("Alice In Wonderland"); + testling->setVCard(JID("alice@wonderland.lit"), vcard); + + VCard::ref result = testling->getVCard(JID("alice@wonderland.lit")); + CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland"), result->getFullName()); + } + + void testGetVCard_LargeFilename() { + std::unique_ptr<VCardFileStorage> testling(createTestling()); + VCard::ref vcard(new VCard()); + vcard->setFullName("Alice In Wonderland"); + + std::ostringstream s; + for (int i = 0; i < 1000; ++i) { + s << "_"; + } + JID jid("alice@wonderland.lit/" + s.str()); + + VCard::ref result = testling->getVCard(jid); + + // Just check that we don't have an exception + } + + void testGetVCard_FileDoesNotExist() { + std::shared_ptr<VCardFileStorage> testling(createTestling()); + VCard::ref result = testling->getVCard(JID("alice@wonderland.lit")); + CPPUNIT_ASSERT(!result); + } + + private: + VCardFileStorage* createTestling() { + return new VCardFileStorage(vcardsPath); + } + + PlatformApplicationPathProvider* pathProvider; + boost::filesystem::path vcardsPath; }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardFileStorageTest); diff --git a/Swiften/QA/TLSTest/CertificateErrorTest.cpp b/Swiften/QA/TLSTest/CertificateErrorTest.cpp new file mode 100644 index 0000000..abd004e --- /dev/null +++ b/Swiften/QA/TLSTest/CertificateErrorTest.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + + /* + This file uses http://www.tls-o-matic.com/ to test the currently configured TLS backend for correct certificate validation behavior. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/Log.h> +#include <Swiften/EventLoop/DummyEventLoop.h> +#include <Swiften/IDN/IDNConverter.h> +#include <Swiften/IDN/PlatformIDNConverter.h> +#include <Swiften/Network/BoostConnectionFactory.h> +#include <Swiften/Network/BoostIOServiceThread.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Network/PlatformDomainNameResolver.h> +#include <Swiften/Network/TLSConnection.h> +#include <Swiften/Network/TLSConnectionFactory.h> +#include <Swiften/TLS/CertificateVerificationError.h> +#include <Swiften/TLS/PlatformTLSFactories.h> +#include <Swiften/TLS/TLSContext.h> +#include <Swiften/TLS/TLSContextFactory.h> + +using namespace Swift; + +class CertificateErrorTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(CertificateErrorTest); + + // These test require the TLS-O-Matic testing CA to be trusted. For more info see https://www.tls-o-matic.com/https/test1 . + CPPUNIT_TEST(testTLS_O_MaticTrusted); + CPPUNIT_TEST(testTLS_O_MaticCertificateFromTheFuture); + CPPUNIT_TEST(testTLS_O_MaticCertificateFromThePast); + CPPUNIT_TEST(testTLS_O_MaticCertificateFromUnknownCA); + CPPUNIT_TEST(testTLS_O_MaticCertificateWrongPurpose); + +#if !defined(HAVE_OPENSSL) + // Our OpenSSL backend does not support revocation. We excluded it from the revocation tests. + CPPUNIT_TEST(testRevokedCertificateRevocationDisabled); + CPPUNIT_TEST(testRevokedCertificateRevocationEnabled); +#endif + + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + eventLoop_ = new DummyEventLoop(); + boostIOServiceThread_ = new BoostIOServiceThread(); + boostIOService_ = std::make_shared<boost::asio::io_service>(); + connectionFactory_ = new BoostConnectionFactory(boostIOServiceThread_->getIOService(), eventLoop_); + idnConverter_ = PlatformIDNConverter::create(); + domainNameResolver_ = new PlatformDomainNameResolver(idnConverter_, eventLoop_); + + tlsFactories_ = new PlatformTLSFactories(); + tlsContextFactory_ = tlsFactories_->getTLSContextFactory(); + + tlsContextFactory_->setCheckCertificateRevocation(false); + + tlsConnectionFactory_ = new TLSConnectionFactory(tlsContextFactory_, connectionFactory_, TLSOptions()); + + connectFinished_ = false; + connectFinishedWithError_ = false; + } + + void tearDown() { + delete tlsConnectionFactory_; + delete tlsFactories_; + + delete domainNameResolver_; + delete idnConverter_; + delete connectionFactory_; + delete boostIOServiceThread_; + while (eventLoop_->hasEvents()) { + eventLoop_->processEvents(); + } + delete eventLoop_; + } + + HostAddress resolveName(const std::string& name) { + std::shared_ptr<DomainNameAddressQuery> query = domainNameResolver_->createAddressQuery(name); + query->onResult.connect(boost::bind(&CertificateErrorTest::handleAddressQueryResult, this, _1, _2)); + lastResoverResult_ = HostAddress(); + resolvingDone_ = false; + + query->run(); + while(!resolvingDone_) { + eventLoop_->processEvents(); + } + + return lastResoverResult_; + } + + void connectToServer(std::shared_ptr<TLSConnection> connection, const std::string& hostname, int port) { + connection->onConnectFinished.connect(boost::bind(&CertificateErrorTest::handleConnectFinished, this, _1)); + + HostAddress address = resolveName(hostname); + + connection->connect(HostAddressPort(address, port)); + + while (!connectFinished_) { + eventLoop_->processEvents(); + } + } + + void testTLS_O_MaticTrusted() { + std::shared_ptr<TLSConnection> connection = std::dynamic_pointer_cast<TLSConnection>(tlsConnectionFactory_->createConnection()); + TLSContext* context = connection->getTLSContext(); + + connectToServer(connection, "test1.tls-o-matic.com", 443); + + CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError_); + CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::ref(), context->getPeerCertificateVerificationError()); + } + + void testTLS_O_MaticCertificateFromTheFuture() { + std::shared_ptr<TLSConnection> connection = std::dynamic_pointer_cast<TLSConnection>(tlsConnectionFactory_->createConnection()); + TLSContext* context = connection->getTLSContext(); + + connectToServer(connection, "test5.tls-o-matic.com", 405); + + CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError_); + CPPUNIT_ASSERT(context->getPeerCertificateVerificationError()); +#if defined(HAVE_SCHANNEL) + // Windows SChannel API does not differentiate between expired and not yet valid. + CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::Expired, context->getPeerCertificateVerificationError()->getType()); +#else + CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::NotYetValid, context->getPeerCertificateVerificationError()->getType()); +#endif + } + + void testTLS_O_MaticCertificateFromThePast() { + std::shared_ptr<TLSConnection> connection = std::dynamic_pointer_cast<TLSConnection>(tlsConnectionFactory_->createConnection()); + TLSContext* context = connection->getTLSContext(); + + connectToServer(connection, "test6.tls-o-matic.com", 406); + + CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError_); + CPPUNIT_ASSERT(context->getPeerCertificateVerificationError()); + CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::Expired, context->getPeerCertificateVerificationError()->getType()); + } + + void testTLS_O_MaticCertificateFromUnknownCA() { + std::shared_ptr<TLSConnection> connection = std::dynamic_pointer_cast<TLSConnection>(tlsConnectionFactory_->createConnection()); + TLSContext* context = connection->getTLSContext(); + + connectToServer(connection, "test7.tls-o-matic.com", 407); + + CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError_); + CPPUNIT_ASSERT(context->getPeerCertificateVerificationError()); + CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::Untrusted, context->getPeerCertificateVerificationError()->getType()); + } + + // test14.tls-o-matic.com:414 + void testTLS_O_MaticCertificateWrongPurpose() { + std::shared_ptr<TLSConnection> connection = std::dynamic_pointer_cast<TLSConnection>(tlsConnectionFactory_->createConnection()); + TLSContext* context = connection->getTLSContext(); + + connectToServer(connection, "test14.tls-o-matic.com", 414); + + CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError_); + CPPUNIT_ASSERT(context->getPeerCertificateVerificationError()); + CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::InvalidPurpose, context->getPeerCertificateVerificationError()->getType()); + } + + void testRevokedCertificateRevocationDisabled() { + tlsContextFactory_->setCheckCertificateRevocation(false); + std::shared_ptr<TLSConnection> connection = std::dynamic_pointer_cast<TLSConnection>(tlsConnectionFactory_->createConnection()); + TLSContext* context = connection->getTLSContext(); + + connectToServer(connection, "revoked.grc.com", 443); + + CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError_); + CPPUNIT_ASSERT(!context->getPeerCertificateVerificationError()); + } + + void testRevokedCertificateRevocationEnabled() { + tlsContextFactory_->setCheckCertificateRevocation(true); + std::shared_ptr<TLSConnection> connection = std::dynamic_pointer_cast<TLSConnection>(tlsConnectionFactory_->createConnection()); + TLSContext* context = connection->getTLSContext(); + + connectToServer(connection, "revoked.grc.com", 443); + + CPPUNIT_ASSERT_EQUAL(false, connectFinishedWithError_); + CPPUNIT_ASSERT(context->getPeerCertificateVerificationError()); + CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::Revoked, context->getPeerCertificateVerificationError()->getType()); + } + + private: + void handleAddressQueryResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> /* error */) { + if (address.size() > 0) { + lastResoverResult_ = address[0]; + } + resolvingDone_ = true; + } + + void handleConnectFinished(bool error) { + connectFinished_ = true; + connectFinishedWithError_ = error; + } + + private: + BoostIOServiceThread* boostIOServiceThread_; + std::shared_ptr<boost::asio::io_service> boostIOService_; + DummyEventLoop* eventLoop_; + ConnectionFactory* connectionFactory_; + PlatformTLSFactories* tlsFactories_; + TLSContextFactory* tlsContextFactory_; + TLSConnectionFactory* tlsConnectionFactory_; + + IDNConverter* idnConverter_; + DomainNameResolver* domainNameResolver_; + HostAddress lastResoverResult_; + bool resolvingDone_; + + bool connectFinished_; + bool connectFinishedWithError_; +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(CertificateErrorTest); diff --git a/Swiften/QA/TLSTest/CertificateTest.cpp b/Swiften/QA/TLSTest/CertificateTest.cpp index 2fa4c04..463ef9e 100644 --- a/Swiften/QA/TLSTest/CertificateTest.cpp +++ b/Swiften/QA/TLSTest/CertificateTest.cpp @@ -1,99 +1,166 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> +#include <memory> + +#include <boost/bind.hpp> #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> +#include <Swiften/Base/ByteArray.h> #include <Swiften/TLS/CertificateFactory.h> -#include "SwifTools/Application/PlatformApplicationPathProvider.h" +#include <Swiften/TLS/TLSContext.h> +#include <Swiften/TLS/PlatformTLSFactories.h> +#include <Swiften/TLS/TLSContextFactory.h> + +#include <SwifTools/Application/PlatformApplicationPathProvider.h> using namespace Swift; template<typename CERTIFICATE_FACTORY> class CertificateTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(CertificateTest); - CPPUNIT_TEST(testConstructFromDER); - CPPUNIT_TEST(testToDER); - //CPPUNIT_TEST(testGetSubjectName); - CPPUNIT_TEST(testGetCommonNames); - CPPUNIT_TEST(testGetSRVNames); - CPPUNIT_TEST(testGetDNSNames); - CPPUNIT_TEST(testGetXMPPAddresses); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - pathProvider = new PlatformApplicationPathProvider("FileReadBytestreamTest"); - readByteArrayFromFile(certificateData, (pathProvider->getExecutableDir() / "jabber_org.crt")); - certificateFactory = new CERTIFICATE_FACTORY(); - } - - void tearDown() { - delete certificateFactory; - delete pathProvider; - } - - void testConstructFromDER() { - Certificate::ref testling = certificateFactory->createCertificateFromDER(certificateData); - - CPPUNIT_ASSERT_EQUAL(std::string("*.jabber.org"), testling->getCommonNames()[0]); - } - - void testToDER() { - Certificate::ref testling = certificateFactory->createCertificateFromDER(certificateData); - - CPPUNIT_ASSERT_EQUAL(certificateData, testling->toDER()); - } + CPPUNIT_TEST_SUITE(CertificateTest); + CPPUNIT_TEST(testConstructFromDER); + CPPUNIT_TEST(testToDER); + //CPPUNIT_TEST(testGetSubjectName); + CPPUNIT_TEST(testGetCommonNames); + CPPUNIT_TEST(testGetSRVNames); + CPPUNIT_TEST(testGetDNSNames); + CPPUNIT_TEST(testGetXMPPAddresses); + CPPUNIT_TEST(testCreateCertificateChain); + CPPUNIT_TEST(testCreateTlsContext); + CPPUNIT_TEST(testCreateTlsContextDisableSystemTAs); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + pathProvider = std::make_unique<PlatformApplicationPathProvider>("FileReadBytestreamTest"); + readByteArrayFromFile(certificateData, (pathProvider->getExecutableDir() / "jabber_org.crt")); + readByteArrayFromFile(chainData, (pathProvider->getExecutableDir() / "certificateChain.pem")); + readByteArrayFromFile(keyData, (pathProvider->getExecutableDir() / "privateKey.pem")); + certificateFactory = std::unique_ptr<CertificateFactory>(new CERTIFICATE_FACTORY()); + + PlatformTLSFactories* tlsFactories_ = new PlatformTLSFactories(); + tlsContextFactory_ = tlsFactories_->getTLSContextFactory(); + } + + void testConstructFromDER() { + Certificate::ref testling = Certificate::ref(certificateFactory->createCertificateFromDER(certificateData)); + + CPPUNIT_ASSERT_EQUAL(std::string("*.jabber.org"), testling->getCommonNames()[0]); + } + + void testToDER() { + Certificate::ref testling = Certificate::ref(certificateFactory->createCertificateFromDER(certificateData)); + + CPPUNIT_ASSERT_EQUAL(certificateData, testling->toDER()); + } /* - void testGetSubjectName() { - Certificate::ref testling = certificateFactory->createCertificateFromDER(certificateData); - - CPPUNIT_ASSERT_EQUAL(std::string("/description=114072-VMk8pdi1aj5kTXxO/C=US/ST=Colorado/L=Denver/O=Peter Saint-Andre/OU=StartCom Trusted Certificate Member/CN=*.jabber.org/emailAddress=hostmaster@jabber.org"), testling->getSubjectName()); - } - */ - - void testGetCommonNames() { - Certificate::ref testling = certificateFactory->createCertificateFromDER(certificateData); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling->getCommonNames().size())); - CPPUNIT_ASSERT_EQUAL(std::string("*.jabber.org"), testling->getCommonNames()[0]); - } - - void testGetSRVNames() { - Certificate::ref testling = certificateFactory->createCertificateFromDER(certificateData); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling->getSRVNames().size())); - CPPUNIT_ASSERT_EQUAL(std::string("*.jabber.org"), testling->getSRVNames()[0]); - } - - void testGetDNSNames() { - Certificate::ref testling = certificateFactory->createCertificateFromDER(certificateData); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(testling->getDNSNames().size())); - CPPUNIT_ASSERT_EQUAL(std::string("*.jabber.org"), testling->getDNSNames()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("jabber.org"), testling->getDNSNames()[1]); - } - - void testGetXMPPAddresses() { - Certificate::ref testling = certificateFactory->createCertificateFromDER(certificateData); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling->getXMPPAddresses().size())); - CPPUNIT_ASSERT_EQUAL(std::string("*.jabber.org"), testling->getXMPPAddresses()[0]); - } - - private: - PlatformApplicationPathProvider* pathProvider; - ByteArray certificateData; - CertificateFactory* certificateFactory; + void testGetSubjectName() { + Certificate::ref testling = Certificate::ref(certificateFactory->createCertificateFromDER(certificateData); + + CPPUNIT_ASSERT_EQUAL(std::string("/description=114072-VMk8pdi1aj5kTXxO/C=US/ST=Colorado/L=Denver/O=Peter Saint-Andre/OU=StartCom Trusted Certificate Member/CN=*.jabber.org/emailAddress=hostmaster@jabber.org"), testling->getSubjectName()); + } + */ + + void testGetCommonNames() { + Certificate::ref testling = Certificate::ref(certificateFactory->createCertificateFromDER(certificateData)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling->getCommonNames().size())); + CPPUNIT_ASSERT_EQUAL(std::string("*.jabber.org"), testling->getCommonNames()[0]); + } + + void testGetSRVNames() { + Certificate::ref testling = Certificate::ref(certificateFactory->createCertificateFromDER(certificateData)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling->getSRVNames().size())); + CPPUNIT_ASSERT_EQUAL(std::string("*.jabber.org"), testling->getSRVNames()[0]); + } + + void testGetDNSNames() { + Certificate::ref testling = Certificate::ref(certificateFactory->createCertificateFromDER(certificateData)); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(testling->getDNSNames().size())); + CPPUNIT_ASSERT_EQUAL(std::string("*.jabber.org"), testling->getDNSNames()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("jabber.org"), testling->getDNSNames()[1]); + } + + void testGetXMPPAddresses() { + Certificate::ref testling = Certificate::ref(certificateFactory->createCertificateFromDER(certificateData)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling->getXMPPAddresses().size())); + CPPUNIT_ASSERT_EQUAL(std::string("*.jabber.org"), testling->getXMPPAddresses()[0]); + } + + void testCreateCertificateChain() { + // The input chain contains a 2-certificate chain: + // the first certificate has: + // a subject of "O=messaging,CN=Mixer Messaging Configuration,CN=badger.isode.net" + // an issuer of "O=messaging, CN=New Messaging CA" + // the second certificate has: + // a subject of "O=messaging, CN=New Messaging CA" + // an issuer of "O=messaging, CN=New Messaging CA" + // i.e. it is a self-signed certificate + std::vector<std::shared_ptr<Certificate>> chain = certificateFactory->createCertificateChain(chainData); + CPPUNIT_ASSERT_EQUAL(2,static_cast<int>(chain.size())); + CPPUNIT_ASSERT_EQUAL(std::string("Mixer Messaging Configuration"), chain[0]->getCommonNames()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("badger.isode.net"), chain[0]->getCommonNames()[1]); + CPPUNIT_ASSERT_EQUAL(std::string("New Messaging CA"), chain[1]->getCommonNames()[0]); + } + + void testCreateTlsContext() { + // Create 2-certificate chain as in previous test + std::vector<std::shared_ptr<Certificate>> chain = certificateFactory->createCertificateChain(chainData); + CPPUNIT_ASSERT_EQUAL(2,static_cast<int>(chain.size())); + + // Load private key from string + PrivateKey::ref key = certificateFactory->createPrivateKey(Swift::createSafeByteArray(keyData)); + CPPUNIT_ASSERT(key); + + const TLSOptions options; + auto context = tlsContextFactory_->createTLSContext(options, TLSContext::Mode::Server); + CPPUNIT_ASSERT(context); + + context->setCertificateChain(chain); + context->setPrivateKey(key); + } + + /** + * This test does not actually verify that use of system TAs has been disabled, it just provides + * a convenient mechanism for testing via a debugger. + **/ + void testCreateTlsContextDisableSystemTAs() { + // Create 2-certificate chain as in previous test + std::vector<std::shared_ptr<Certificate>> chain = certificateFactory->createCertificateChain(chainData); + CPPUNIT_ASSERT_EQUAL(2,static_cast<int>(chain.size())); + + // Load private key from string + PrivateKey::ref key = certificateFactory->createPrivateKey(Swift::createSafeByteArray(keyData)); + CPPUNIT_ASSERT(key); + + // Turn off use of system TAs + TLSOptions options; + options.ignoreSystemTrustAnchors = true; + auto context = tlsContextFactory_->createTLSContext(options, TLSContext::Mode::Server); + CPPUNIT_ASSERT(context); + + context->setCertificateChain(chain); + context->setPrivateKey(key); + } + private: + std::unique_ptr<PlatformApplicationPathProvider> pathProvider; + ByteArray certificateData; + ByteArray chainData; + ByteArray keyData; + std::unique_ptr<CertificateFactory> certificateFactory; + TLSContextFactory* tlsContextFactory_; }; #ifdef HAVE_OPENSSL diff --git a/Swiften/QA/TLSTest/SConscript b/Swiften/QA/TLSTest/SConscript index 18f6998..81e2471 100644 --- a/Swiften/QA/TLSTest/SConscript +++ b/Swiften/QA/TLSTest/SConscript @@ -3,14 +3,25 @@ import os Import("env") if env["TEST"] : - myenv = env.Clone() - myenv.MergeFlags(myenv["CHECKER_FLAGS"]) - myenv.MergeFlags(myenv["SWIFTOOLS_FLAGS"]) - myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) - myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) - myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) - - tester = myenv.Program("TLSTest", [ - "CertificateTest.cpp", - ]) - myenv.Test(tester, "system") + myenv = env.Clone() + myenv.MergeFlags(myenv["CHECKER_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTOOLS_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) + myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) + myenv.MergeFlags(myenv["GOOGLETEST_FLAGS"]) + + if myenv.get("HAVE_OPENSSL", 0) : + myenv.Append(CPPDEFINES = "HAVE_OPENSSL") + myenv.MergeFlags(myenv["OPENSSL_FLAGS"]) + elif myenv.get("HAVE_SCHANNEL", 0) : + myenv.Append(CPPDEFINES = "HAVE_SCHANNEL") + elif myenv.get("HAVE_SECURETRANSPORT", 0) : + myenv.Append(CPPDEFINES = "HAVE_SECURETRANSPORT") + + tester = myenv.Program("TLSTest", [ + "CertificateTest.cpp", + # Reenable if either http://www.tls-o-matic.com/ is fixed or we have setup a replacement. + #"CertificateErrorTest.cpp" + ]) + myenv.Test(tester, "system") diff --git a/Swiften/QA/TLSTest/certificateChain.pem b/Swiften/QA/TLSTest/certificateChain.pem new file mode 100644 index 0000000..cb3c0fb --- /dev/null +++ b/Swiften/QA/TLSTest/certificateChain.pem @@ -0,0 +1,49 @@ +-----BEGIN CERTIFICATE----- +MIIFFTCCA/2gAwIBAgIKXmMION+1bnZpIzANBgkqhkiG9w0BAQsFADAvMRIwEAYD +VQQKEwltZXNzYWdpbmcxGTAXBgNVBAMTEE5ldyBNZXNzYWdpbmcgQ0EwHhcNMTkw +NzI5MTAxMjMxWhcNMjAwNzI5MTAxMjMxWjBXMRIwEAYDVQQKEwltZXNzYWdpbmcx +JjAkBgNVBAMTHU1peGVyIE1lc3NhZ2luZyBDb25maWd1cmF0aW9uMRkwFwYDVQQD +ExBiYWRnZXIuaXNvZGUubmV0MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKC +AYEAt42TMYe9oO4K6XmvST4kiy4cG+nmVDCtZRfAfF/A+1GQXTZ8OfLbPF5noLIF +f1Jj6fBDA2HiKoLQWfNnIklNEzgPbOREuAuCe660sW1JzJFr5O5qYyf6bHKkYmRr +CGHJ3G5kkXZOW3MhczPNHrTIUSL7lYLMZAcyWStkhgBy7lBuYtgDEXbdRH8OGgly +XC39AAU93y7ynw6W3SorU6h9cwvS0Ho8KVemCXoE38WLeSrIw1ks+Kf1YQopg9O3 +2SkXp6Z9elG5Wk5Rh0L0H2XHnAvmodr9TW6rtrPkJZfLL+NfcnGtI6QKnvL8EhYG +d+XiPOV8jyGAFRC1Be72wlF29Rw20zdoD3kAdeqBLWfL8H9mnQpebEIDj8Lmahub ++W4uuUqCG8NuY43lGJzJni9CFWvhD7ss1yVGz84zqRHu5iXNDncWH2luJT1gXvFW +6mxcfe+AwSiZ8PrhDQZBfTyx7ob4Ozdc1d59XTPyckj2msnCo2ayg+jKaViDd4vz +nNwhAgMBAAGjggGJMIIBhTAbBgNVHREEFDASghBiYWRnZXIuaXNvZGUubmV0MA4G +A1UdDwEB/wQEAwIF4DAMBgNVHRMBAf8EAjAAMHQGA1UdHwRtMGswaaBnoGWGY2xk +YXA6Ly9kaWFib2xvLmlzb2RlLm5ldDoxOTM4OS9jbj1OZXclMjBNZXNzYWdpbmcl +MjBDQSxvPW1lc3NhZ2luZz9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0O2JpbmFy +eTCBkQYIKwYBBQUHAQEEgYQwgYEwfwYIKwYBBQUHMAKGc2xkYXA6Ly9kaWFib2xv +Lmlzb2RlLm5ldDoxOTM4OS9jbj1OZXclMjBNZXNzYWdpbmclMjBDQSxvPW1lc3Nh +Z2luZz9jQUNlcnRpZmljYXRlO2JpbmFyeSxjcm9zc0NlcnRpZmljYXRlUGFpcjti +aW5hcnkwHQYDVR0OBBYEFFjf69BczlDoKiSBSvxCr9sy0OJ2MB8GA1UdIwQYMBaA +FJvoU0Lwg8vVCEmEMoKy29zFo/Y7MA0GCSqGSIb3DQEBCwUAA4IBAQCS4zLVH98S +Cl4gsmTkxM+lBsdzQ18ymA6p9ZRXGmJ405C9rN7um9XnbWwOHO6ach7zie2GxWLp +KOYKjX/5Pjt7mPwG8eKepPAxDenzKw5TocjscR9VxBsym0oEkWHPQG+xSqySQGUw +/5QoGy6v06yE8CZ7BKHPh91Jy7IjIDBxWaEtTAPyuH4i4DnsmA0/xSrJ7ez6g399 +YgqDnBInC63bYv5IDD1CmEr/0boBWpsOf50OC6JVhaPLAldwTAxLSOMBJ4q4onXC +ZqDHY3EMRtwYEffNg9ZorXJwLmU3Lq/R3B9lC22XNPDFj/bZ5RpwVFtuN5HfeZzO +aPbNoa0Nf+QB +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDJDCCAgygAwIBAgIKSm7KkUZOigMk9zANBgkqhkiG9w0BAQsFADAvMRIwEAYD +VQQKEwltZXNzYWdpbmcxGTAXBgNVBAMTEE5ldyBNZXNzYWdpbmcgQ0EwHhcNMTYw +MTI2MTU1MTU2WhcNMjYwMTI2MTU1MTU2WjAvMRIwEAYDVQQKEwltZXNzYWdpbmcx +GTAXBgNVBAMTEE5ldyBNZXNzYWdpbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDgcuX1s8EvO8GDHx7vSW9oeDnLUBx5E48Vb2qcJVc34ik1j6ZV +d8/+tzmyy/BskFbaOJ0KD5XYOoI8TJtu28lASWZj1vAEZkfrDdBbKeb1BQhShMt2 +ICgzp7l4ubwd6rqCGHpD/f12RVhSlU3y6TniaK62a9RwJOpL/wvnCcJLPjaTw8om +EY62EyUP+FymUbo3Rb3aWLM7avHl1/32pyzUgRzvZR63hlMHnlE5Sgc84j9KMwJH +k+mCyXIGPc+yhL33ljR63Eoiqynyk0HPU6pWai1WKuSv6zMDPwnNaJA3VpLNUHsd +eVe1GyOmPFePnhRPZYfC+Dk8lxDUmZfNFKZlAgMBAAGjQjBAMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSb6FNC8IPL1QhJhDKCstvc +xaP2OzANBgkqhkiG9w0BAQsFAAOCAQEApgA5oupwTS2Ylt9mhS/TDX9wzR0DqnC5 +t9skgU9B/1MnzgqEMKGmuhRBiqDyr0jsPegBFI/CpTdIpakpSUrIvBTZADzkrkI+ +3k2jnpEv0vodaFIHQonDysq5h4bXsCSdSprdhiUa1GKFtnJ92Ro/2Uaw5UcqFPCg +7kj7RmRVlAIynUAT81cefQww0HBFPN9SdBEpp6YP4P1u1x8GV0Bfq93r4G5jkiHN +dA6xejk7RZK4mTH+K2aFpWoHCqMr7RAzV5UiXis4cFAmtv+5K/G7eazNx0Y+ODo4 +fweh+xW+dOXuP1lzW4DzwhEf/8tgFgI0jIvscPgdgHY7t9SQRJPYQQ== +-----END CERTIFICATE----- diff --git a/Swiften/QA/TLSTest/privateKey.pem b/Swiften/QA/TLSTest/privateKey.pem new file mode 100644 index 0000000..5769000 --- /dev/null +++ b/Swiften/QA/TLSTest/privateKey.pem @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/wIBADANBgkqhkiG9w0BAQEFAASCBukwggblAgEAAoIBgQDu1QdEBrcWj+D/ +rkmh++QSu2f0qlJ6Re8dEBtbqpxLiyYZ5IeaLts9szXabfSTchdJr/d0IyHfHQFS +MGXDphKRaNnV5r//XuojUtorPyGe0DnZR2mp8S9adD7WxNjQLSQabr8PPPW8jrTx +eJyIvYToLs9lx1IIDcr/3ZTuhBe2FK3Q173M5GF36Jb4yKWLPIfJ6auZjO5G9LZF +3o2vVWxfc7ESnXvf3sAcWQPR08/ud0vLa3W3A8dC0XGk4BbE32cxvSuzWPHZd257 +HiHIW5pKLZXSMTu7fVNzBzDlo8BYQ5kad1ic+hhyIHBwTUO0Hz3EYP+9FG3TNG84 +65K9EeN3/Qw2P9468GHWAXqlzKFiIGikxYHGwvGd0CdegHtZ/TwIgVvpIDp6XB6U +ez/TYPEiMCqX8TCIQi8FU3obEouMoPMHKM8vzQdSItZtPn6gD16M4xKdMm6fbvCD +1okdcrWQnZo72pp8cfpS87KhP5z1ec9B/Wqysh4nrO35v8LXH60CAwEAAQKCAYEA +jPDUJ9XaqAriWaBtvZTbpB5KG72DjLrGgB0oN/E36PDF3FPbniZ2pTOj3TI0OesD +SS351uSAsZz5UZpUA6B2pq78llllBnvpqkzTiN/ppEH3UXzuIya8riGZj758wGVT +P/II+CIeVlbU+wcVQTCuRSKSq9pzU2NoX5RQtmznXUFYzbzzOf2wc0WkCk7GOqPO +8l3eMXBUkTUKd7L9Y/ICUVYBsh2To6pdLp1tPp9DvtNRvEq/HfCx34GgEg9YAHhg +1rcPhh71M+TLYHznl5r/Jm1kIVrP3zyr1Bm5DDgZLE3GTN/oFumgXQyFCPyslup1 +gdZzS6W+fbeKxoPzjPOhzHVUxVZ/yqJH1xa1gs4ECQ4QXxdnr7yY1H5k5S8dabO5 +bEvXP+tH95HcAtAbvoRt+NC+xIJ39d6X7X2c4TPLoMIxDxmbEOCi9sg+4Ws+7E2s +a/01fTZFT+lzuGBdp9Zz/tltDrwfYD0V+Q7qO0o/nJPINI+alAWlqQia00ZyZr4V +AoHBAPxwCls99/LUzY7IJc0TV3ukk3sFi3rt58u8BE4+RaCtmgPMDj1l+EnaY9RW +IOj91ECZ8+a23elNPZOkXKuYuJmJIpjOogOMM8r+Q4WF87xoRcdcjPh+PBat66HZ ++8mbm0VQ98cjxs0/kTRRayzz7UG9Onf1PhFfnw55sbMGItVssRDi9lRZJdSRU+CC +qyAt8TUEH0lo+8AKbRn7xW4VHiD0hmLKDi4F713QLCPgmNlPQ/C60FTIRYS18gzK +ARhuzwKBwQDyM9YiiFFQ3irGKtbj9W3bDHNmMl9YOHMYVXJAvh83Zcp80qRsShtw +n3mV3vcVI+KNeZtKFUrJIYNTspNBP/w8U4lGGW+7tAt0dd0WY9m3ygnZg0GOHoaC +uUusGicZR7FgbYlJzCiRhFhWcFyh0VOrm/k7OjznAvwfWbRKrlLvQdrWrLj7dyN3 +8n9lArq9ZxXJLpBXDUJ1R+F+hPIIIRKeYF2ULUFNE0U9Pj7SVTT7L7jPMWKnrVJh +U4/hVAEHyMMCgcB4hCTtmpAdZmscl4E0ft9tMA0Y1nTYo2veYEzN7fzf0QGOfoTt +2xjGaXTvko7zrPsAPH+szfDzyOR08Cst4SOAaXAS89N1TiIL74fc3y6V7FIj85N5 +rwqQ6UdtZdxHS/q9BQLGF9Z5drej+proQywqDmUzj+mp8bTF/GNRzMQkkFeYcEKZ +0lW1PgyFStzX6BcX8HffXDeUX2Xm2cRP4dUYdqUR1NUgM8UrTI9GMZvHY4hUDVwY +neRSj2qXoHkVaRECgcEArilkM9S+VF5Nd85aU/WqFzeuy7AxK2j8KmVXEQMlw1oo +7vUxUsU/Ug77CTAZkFQLlxv49J629kZo/wiMJwFxyZdwQL4NwHXJPud6IZ2Pcz+P +MZ/WxfFhXCMOLSVpNB5/iA18CVsLWQhH1XBay+mQNvijkVlhbeSRk6GXqZQNAwrh +6Divk/Opx5jSzrnVulikK9SV6mMYhOk5VxcWS44sq0I0SFb6fAf9Y/qchfbLcExy +olqqzFQvxtilv6v+SbCtAoHBAOXPUQ7VVuQZo4HA+CaQRYgQjGMxo4jeGiqrUAaX +b+MpUjU7VxiSrfH3wFxCuMfW7dfQJKp7BAG8PCNzP1eW3+LhPkRSPAT0nwk/bQ5E +N/n6NBqwsJFoTqueS0qDVdPichwKGvnIrraHSVeMeHZNv+TQdMjmTJ5AfBNCal9b +7EPTFQO0Tj4GAB77fVRzewyVB+qXccoD2Gts9aWbY9FVGyhkvRenL7CcbgrzLZvt +php/1crfbWtZ/3Nwz6L8LEdZHA== +-----END PRIVATE KEY----- diff --git a/Swiften/Queries/DummyIQChannel.h b/Swiften/Queries/DummyIQChannel.h index 6adcdb1..5ec68ca 100644 --- a/Swiften/Queries/DummyIQChannel.h +++ b/Swiften/Queries/DummyIQChannel.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,22 +11,22 @@ #include <Swiften/Queries/IQChannel.h> namespace Swift { - class DummyIQChannel : public IQChannel { - public: - DummyIQChannel() {} + class DummyIQChannel : public IQChannel { + public: + DummyIQChannel() {} - virtual void sendIQ(boost::shared_ptr<IQ> iq) { - iqs_.push_back(iq); - } + virtual void sendIQ(std::shared_ptr<IQ> iq) { + iqs_.push_back(iq); + } - virtual std::string getNewIQID() { - return "test-id"; - } + virtual std::string getNewIQID() { + return "test-id"; + } - virtual bool isAvailable() const { - return true; - } + virtual bool isAvailable() const { + return true; + } - std::vector<boost::shared_ptr<IQ> > iqs_; - }; + std::vector<std::shared_ptr<IQ> > iqs_; + }; } diff --git a/Swiften/Queries/GenericRequest.h b/Swiften/Queries/GenericRequest.h index b1b7f8a..312ecf2 100644 --- a/Swiften/Queries/GenericRequest.h +++ b/Swiften/Queries/GenericRequest.h @@ -1,78 +1,80 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Queries/Request.h> namespace Swift { - /** - * GenericRequest is used for managing the sending of, and handling of replies to, iq stanzas that do not have their own Request types. - * - * To create an iq stanza, call a constructor with the type of the iq that needs to be sent (either Set or Get), addressing information (clients should use the constructor that doesn't specify a sender), the payload that should be sent in the iq, and the IQRouter for the connection, obtained through the Client or CoreClient object. - * - * Having created a GenericRequest, connect to the onResponse signal to be told when a response (either a result or an error) has been received by Swiften. - * - * To send the iq, then call send() - onResponse will be called when a reply is received. - */ - template<typename PAYLOAD_TYPE> - class GenericRequest : public Request { - public: - typedef boost::shared_ptr<GenericRequest<PAYLOAD_TYPE> > ref; + /** + * GenericRequest is used for managing the sending of, and handling of replies to, iq stanzas that do not have their own Request types. + * + * To create an iq stanza, call a constructor with the type of the iq that needs to be sent (either Set or Get), addressing information (clients should use the constructor that doesn't specify a sender), the payload that should be sent in the iq, and the IQRouter for the connection, obtained through the Client or CoreClient object. + * + * Having created a GenericRequest, connect to the onResponse signal to be told when a response (either a result or an error) has been received by Swiften. + * + * To send the iq, then call send() - onResponse will be called when a reply is received. + */ + template<typename PAYLOAD_TYPE> + class SWIFTEN_API GenericRequest : public Request { + public: + typedef std::shared_ptr<GenericRequest<PAYLOAD_TYPE> > ref; - public: - /** - * Create a request suitable for client use. - * @param type Iq type - Get or Set. - * @param receiver JID to send request to. - * @param payload Payload to send in stanza. - * @param router IQRouter instance for current connection. - */ - GenericRequest( - IQ::Type type, - const JID& receiver, - boost::shared_ptr<Payload> payload, - IQRouter* router) : - Request(type, receiver, payload, router) { - } + public: + /** + * Create a request suitable for client use. + * @param type Iq type - Get or Set. + * @param receiver JID to send request to. + * @param payload Payload to send in stanza. + * @param router IQRouter instance for current connection. + */ + GenericRequest( + IQ::Type type, + const JID& receiver, + std::shared_ptr<Payload> payload, + IQRouter* router) : + Request(type, receiver, payload, router) { + } - /** - * Create a request suitable for component or server use. As a client, use the other constructor instead. - * @param type Iq type - Get or Set. - * @param sender JID to use in "from" of stanza. - * @param receiver JID to send request to. - * @param payload Payload to send in stanza. - * @param router IQRouter instance for current connection. - */ - GenericRequest( - IQ::Type type, - const JID& sender, - const JID& receiver, - boost::shared_ptr<Payload> payload, - IQRouter* router) : - Request(type, sender, receiver, payload, router) { - } + /** + * Create a request suitable for component or server use. As a client, use the other constructor instead. + * @param type Iq type - Get or Set. + * @param sender JID to use in "from" of stanza. + * @param receiver JID to send request to. + * @param payload Payload to send in stanza. + * @param router IQRouter instance for current connection. + */ + GenericRequest( + IQ::Type type, + const JID& sender, + const JID& receiver, + std::shared_ptr<Payload> payload, + IQRouter* router) : + Request(type, sender, receiver, payload, router) { + } - /** - * Internal method, do not use. - */ - virtual void handleResponse(boost::shared_ptr<Payload> payload, ErrorPayload::ref error) { - onResponse(boost::dynamic_pointer_cast<PAYLOAD_TYPE>(payload), error); - } + /** + * Internal method, do not use. + */ + virtual void handleResponse(std::shared_ptr<Payload> payload, ErrorPayload::ref error) { + onResponse(std::dynamic_pointer_cast<PAYLOAD_TYPE>(payload), error); + } - public: - boost::shared_ptr<PAYLOAD_TYPE> getPayloadGeneric() const { - return boost::dynamic_pointer_cast<PAYLOAD_TYPE>(getPayload()); - } + public: + std::shared_ptr<PAYLOAD_TYPE> getPayloadGeneric() const { + return std::dynamic_pointer_cast<PAYLOAD_TYPE>(getPayload()); + } - public: - /** - * Signal emitted when a reply to the iq has been received. Contains a payload if one was present, and an error if one was present. - */ - boost::signal<void (boost::shared_ptr<PAYLOAD_TYPE>, ErrorPayload::ref)> onResponse; - }; + public: + /** + * Signal emitted when a reply to the iq has been received. Contains a payload if one was present, and an error if one was present. + */ + boost::signals2::signal<void (std::shared_ptr<PAYLOAD_TYPE>, ErrorPayload::ref)> onResponse; + }; } diff --git a/Swiften/Queries/GetResponder.h b/Swiften/Queries/GetResponder.h index 213a52f..18dd694 100644 --- a/Swiften/Queries/GetResponder.h +++ b/Swiften/Queries/GetResponder.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,12 +10,12 @@ #include <Swiften/Queries/Responder.h> namespace Swift { - template<typename T> - class SWIFTEN_API GetResponder : public Responder<T> { - public: - GetResponder(IQRouter* router) : Responder<T>(router) {} + template<typename T> + class SWIFTEN_API GetResponder : public Responder<T> { + public: + GetResponder(IQRouter* router) : Responder<T>(router) {} - private: - virtual bool handleSetRequest(const JID&, const JID&, const std::string&, boost::shared_ptr<T>) { return false; } - }; + private: + virtual bool handleSetRequest(const JID&, const JID&, const std::string&, std::shared_ptr<T>) { return false; } + }; } diff --git a/Swiften/Queries/IQChannel.cpp b/Swiften/Queries/IQChannel.cpp index 815a617..b795128 100644 --- a/Swiften/Queries/IQChannel.cpp +++ b/Swiften/Queries/IQChannel.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Queries/IQChannel.h> diff --git a/Swiften/Queries/IQChannel.h b/Swiften/Queries/IQChannel.h index c9da593..fe32d89 100644 --- a/Swiften/Queries/IQChannel.h +++ b/Swiften/Queries/IQChannel.h @@ -1,28 +1,29 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> - +#include <memory> #include <string> + +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> #include <Swiften/Elements/IQ.h> namespace Swift { - class SWIFTEN_API IQChannel { - public: - virtual ~IQChannel(); + class SWIFTEN_API IQChannel { + public: + virtual ~IQChannel(); + + virtual void sendIQ(std::shared_ptr<IQ>) = 0; + virtual std::string getNewIQID() = 0; - virtual void sendIQ(boost::shared_ptr<IQ>) = 0; - virtual std::string getNewIQID() = 0; - - virtual bool isAvailable() const = 0; + virtual bool isAvailable() const = 0; - boost::signal<void (boost::shared_ptr<IQ>)> onIQReceived; - }; + boost::signals2::signal<void (std::shared_ptr<IQ>)> onIQReceived; + }; } diff --git a/Swiften/Queries/IQHandler.cpp b/Swiften/Queries/IQHandler.cpp index 01e4387..bdfad30 100644 --- a/Swiften/Queries/IQHandler.cpp +++ b/Swiften/Queries/IQHandler.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Queries/IQHandler.h> + #include <Swiften/Queries/IQRouter.h> namespace Swift { diff --git a/Swiften/Queries/IQHandler.h b/Swiften/Queries/IQHandler.h index 19e16a7..b5c1fc3 100644 --- a/Swiften/Queries/IQHandler.h +++ b/Swiften/Queries/IQHandler.h @@ -1,23 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Elements/IQ.h> namespace Swift { - class IQRouter; + class SWIFTEN_API IQHandler { + public: + virtual ~IQHandler(); - class SWIFTEN_API IQHandler { - public: - virtual ~IQHandler(); - - virtual bool handleIQ(boost::shared_ptr<IQ>) = 0; - }; + virtual bool handleIQ(std::shared_ptr<IQ>) = 0; + }; } diff --git a/Swiften/Queries/IQRouter.cpp b/Swiften/Queries/IQRouter.cpp index c84e1bb..286b65f 100644 --- a/Swiften/Queries/IQRouter.cpp +++ b/Swiften/Queries/IQRouter.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Queries/IQRouter.h> @@ -9,86 +9,85 @@ #include <boost/bind.hpp> #include <Swiften/Base/Algorithm.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Queries/IQHandler.h> -#include <Swiften/Queries/IQChannel.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Queries/IQChannel.h> +#include <Swiften/Queries/IQHandler.h> namespace Swift { static void noop(IQHandler*) {} IQRouter::IQRouter(IQChannel* channel) : channel_(channel), queueRemoves_(false) { - channel->onIQReceived.connect(boost::bind(&IQRouter::handleIQ, this, _1)); + channel->onIQReceived.connect(boost::bind(&IQRouter::handleIQ, this, _1)); } IQRouter::~IQRouter() { - channel_->onIQReceived.disconnect(boost::bind(&IQRouter::handleIQ, this, _1)); + channel_->onIQReceived.disconnect(boost::bind(&IQRouter::handleIQ, this, _1)); } bool IQRouter::isAvailable() { - return channel_->isAvailable(); + return channel_->isAvailable(); } -void IQRouter::handleIQ(boost::shared_ptr<IQ> iq) { - queueRemoves_ = true; - - bool handled = false; - // Go through the handlers in reverse order, to give precedence to the last added handler - std::vector<boost::shared_ptr<IQHandler> >::const_reverse_iterator i = handlers_.rbegin(); - std::vector<boost::shared_ptr<IQHandler> >::const_reverse_iterator rend = handlers_.rend(); - for (; i != rend; ++i) { - handled |= (*i)->handleIQ(iq); - if (handled) { - break; - } - } - if (!handled && (iq->getType() == IQ::Get || iq->getType() == IQ::Set) ) { - sendIQ(IQ::createError(iq->getFrom(), iq->getID(), ErrorPayload::FeatureNotImplemented, ErrorPayload::Cancel)); - } - - processPendingRemoves(); - - queueRemoves_ = false; +void IQRouter::handleIQ(std::shared_ptr<IQ> iq) { + queueRemoves_ = true; + + bool handled = false; + // Go through the handlers in reverse order, to give precedence to the last added handler + std::vector<std::shared_ptr<IQHandler> >::const_reverse_iterator i = handlers_.rbegin(); + std::vector<std::shared_ptr<IQHandler> >::const_reverse_iterator rend = handlers_.rend(); + for (; i != rend; ++i) { + handled |= (*i)->handleIQ(iq); + if (handled) { + break; + } + } + if (!handled && (iq->getType() == IQ::Get || iq->getType() == IQ::Set) ) { + sendIQ(IQ::createError(iq->getFrom(), iq->getID(), ErrorPayload::FeatureNotImplemented, ErrorPayload::Cancel)); + } + + processPendingRemoves(); + + queueRemoves_ = false; } void IQRouter::processPendingRemoves() { - foreach(boost::shared_ptr<IQHandler> handler, queuedRemoves_) { - erase(handlers_, handler); - } - queuedRemoves_.clear(); + for (auto&& handler : queuedRemoves_) { + erase(handlers_, handler); + } + queuedRemoves_.clear(); } void IQRouter::addHandler(IQHandler* handler) { - addHandler(boost::shared_ptr<IQHandler>(handler, noop)); + addHandler(std::shared_ptr<IQHandler>(handler, noop)); } void IQRouter::removeHandler(IQHandler* handler) { - removeHandler(boost::shared_ptr<IQHandler>(handler, noop)); + removeHandler(std::shared_ptr<IQHandler>(handler, noop)); } -void IQRouter::addHandler(boost::shared_ptr<IQHandler> handler) { - handlers_.push_back(handler); +void IQRouter::addHandler(std::shared_ptr<IQHandler> handler) { + handlers_.push_back(handler); } -void IQRouter::removeHandler(boost::shared_ptr<IQHandler> handler) { - if (queueRemoves_) { - queuedRemoves_.push_back(handler); - } - else { - erase(handlers_, handler); - } +void IQRouter::removeHandler(std::shared_ptr<IQHandler> handler) { + if (queueRemoves_) { + queuedRemoves_.push_back(handler); + } + else { + erase(handlers_, handler); + } } -void IQRouter::sendIQ(boost::shared_ptr<IQ> iq) { - if (from_.isValid() && !iq->getFrom().isValid()) { - iq->setFrom(from_); - } - channel_->sendIQ(iq); +void IQRouter::sendIQ(std::shared_ptr<IQ> iq) { + if (from_.isValid() && !iq->getFrom().isValid()) { + iq->setFrom(from_); + } + channel_->sendIQ(iq); } std::string IQRouter::getNewIQID() { - return channel_->getNewIQID(); + return channel_->getNewIQID(); } } diff --git a/Swiften/Queries/IQRouter.h b/Swiften/Queries/IQRouter.h index 0655035..eda7cfb 100644 --- a/Swiften/Queries/IQRouter.h +++ b/Swiften/Queries/IQRouter.h @@ -1,89 +1,89 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <vector> +#include <memory> #include <string> +#include <vector> #include <Swiften/Base/API.h> #include <Swiften/Elements/IQ.h> namespace Swift { - class IQChannel; - class IQHandler; + class IQChannel; + class IQHandler; + + class SWIFTEN_API IQRouter { + public: + IQRouter(IQChannel* channel); + ~IQRouter(); - class SWIFTEN_API IQRouter { - public: - IQRouter(IQChannel* channel); - ~IQRouter(); + /** + * Sets the JID of this IQ router. + * + * This JID is used by requests to check whether incoming + * results are addressed correctly. + */ + void setJID(const JID& jid) { + jid_ = jid; + } - /** - * Sets the JID of this IQ router. - * - * This JID is used by requests to check whether incoming - * results are addressed correctly. - */ - void setJID(const JID& jid) { - jid_ = jid; - } + const JID& getJID() const { + return jid_; + } - const JID& getJID() const { - return jid_; - } + /** + * Sets the 'from' JID for all outgoing IQ stanzas. + * + * By default, IQRouter does not add a from to IQ stanzas, since + * this is automatically added by the server. This overrides this + * default behavior, which is necessary for e.g. components. + */ + void setFrom(const JID& from) { + from_ = from; + } - /** - * Sets the 'from' JID for all outgoing IQ stanzas. - * - * By default, IQRouter does not add a from to IQ stanzas, since - * this is automatically added by the server. This overrides this - * default behavior, which is necessary for e.g. components. - */ - void setFrom(const JID& from) { - from_ = from; - } + void addHandler(IQHandler* handler); + void removeHandler(IQHandler* handler); + void addHandler(std::shared_ptr<IQHandler> handler); + void removeHandler(std::shared_ptr<IQHandler> handler); - void addHandler(IQHandler* handler); - void removeHandler(IQHandler* handler); - void addHandler(boost::shared_ptr<IQHandler> handler); - void removeHandler(boost::shared_ptr<IQHandler> handler); + /** + * Sends an IQ stanza. + * + * If a JID was specified using setFrom, the JID will + * be set as the 'from' address on iq before sending + * it. + */ + void sendIQ(std::shared_ptr<IQ> iq); + std::string getNewIQID(); - /** - * Sends an IQ stanza. - * - * If a JID was specified using setFrom, the JID will - * be set as the 'from' address on iq before sending - * it. - */ - void sendIQ(boost::shared_ptr<IQ> iq); - std::string getNewIQID(); - - bool isAvailable(); + bool isAvailable(); - /** - * Checks whether the given jid is the account JID (i.e. it is either - * the bare JID, or it is the empty JID). - * Can be used to check whether a stanza is sent by the server on behalf - * of the user's account. - */ - bool isAccountJID(const JID& jid) { - return jid.isValid() ? jid_.toBare().equals(jid, JID::WithResource) : true; - } + /** + * Checks whether the given jid is the account JID (i.e. it is either + * the bare JID, or it is the empty JID). + * Can be used to check whether a stanza is sent by the server on behalf + * of the user's account. + */ + bool isAccountJID(const JID& jid) { + return jid.isValid() ? jid_.toBare().equals(jid, JID::WithResource) : true; + } - private: - void handleIQ(boost::shared_ptr<IQ> iq); - void processPendingRemoves(); + private: + void handleIQ(std::shared_ptr<IQ> iq); + void processPendingRemoves(); - private: - IQChannel* channel_; - JID jid_; - JID from_; - std::vector< boost::shared_ptr<IQHandler> > handlers_; - std::vector< boost::shared_ptr<IQHandler> > queuedRemoves_; - bool queueRemoves_; - }; + private: + IQChannel* channel_; + JID jid_; + JID from_; + std::vector< std::shared_ptr<IQHandler> > handlers_; + std::vector< std::shared_ptr<IQHandler> > queuedRemoves_; + bool queueRemoves_; + }; } diff --git a/Swiften/Queries/PubSubRequest.h b/Swiften/Queries/PubSubRequest.h index 55bf9e3..b439748 100644 --- a/Swiften/Queries/PubSubRequest.h +++ b/Swiften/Queries/PubSubRequest.h @@ -1,90 +1,92 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Queries/Request.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/ContainerPayload.h> -#include <Swiften/PubSub/PubSubUtil.h> #include <Swiften/Elements/PubSub.h> -#include <Swiften/Elements/PubSubOwnerPubSub.h> -#include <Swiften/Elements/PubSubCreate.h> -#include <Swiften/Elements/PubSubSubscribe.h> #include <Swiften/Elements/PubSubAffiliations.h> +#include <Swiften/Elements/PubSubCreate.h> #include <Swiften/Elements/PubSubDefault.h> #include <Swiften/Elements/PubSubItems.h> -#include <Swiften/Elements/PubSubPublish.h> -#include <Swiften/Elements/PubSubRetract.h> -#include <Swiften/Elements/PubSubSubscription.h> -#include <Swiften/Elements/PubSubSubscriptions.h> -#include <Swiften/Elements/PubSubUnsubscribe.h> #include <Swiften/Elements/PubSubOwnerAffiliations.h> #include <Swiften/Elements/PubSubOwnerConfigure.h> #include <Swiften/Elements/PubSubOwnerDefault.h> #include <Swiften/Elements/PubSubOwnerDelete.h> +#include <Swiften/Elements/PubSubOwnerPubSub.h> #include <Swiften/Elements/PubSubOwnerPurge.h> #include <Swiften/Elements/PubSubOwnerSubscriptions.h> +#include <Swiften/Elements/PubSubPublish.h> +#include <Swiften/Elements/PubSubRetract.h> +#include <Swiften/Elements/PubSubSubscribe.h> +#include <Swiften/Elements/PubSubSubscription.h> +#include <Swiften/Elements/PubSubSubscriptions.h> +#include <Swiften/Elements/PubSubUnsubscribe.h> +#include <Swiften/PubSub/PubSubUtil.h> +#include <Swiften/Queries/Request.h> namespace Swift { - namespace Detail { - template<typename T> - struct PubSubPayloadTraits; + namespace Detail { + template<typename T> + struct PubSubPayloadTraits; #define SWIFTEN_PUBSUB_DECLARE_PAYLOAD_TRAITS(PAYLOAD, CONTAINER, RESPONSE) \ - template<> struct PubSubPayloadTraits< PAYLOAD > { \ - typedef CONTAINER ContainerType; \ - typedef RESPONSE ResponseType; \ - }; + template<> struct PubSubPayloadTraits< PAYLOAD > { \ + typedef CONTAINER ContainerType; \ + typedef RESPONSE ResponseType; \ + }; - SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE( - SWIFTEN_PUBSUB_DECLARE_PAYLOAD_TRAITS) - } + SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE( + SWIFTEN_PUBSUB_DECLARE_PAYLOAD_TRAITS) + } - template<typename T> - class PubSubRequest : public Request { - typedef typename Detail::PubSubPayloadTraits<T>::ContainerType ContainerType; - typedef typename Detail::PubSubPayloadTraits<T>::ResponseType ResponseType; + template<typename T> + class SWIFTEN_API PubSubRequest : public Request { + typedef typename Detail::PubSubPayloadTraits<T>::ContainerType ContainerType; + typedef typename Detail::PubSubPayloadTraits<T>::ResponseType ResponseType; - public: - PubSubRequest( - IQ::Type type, - const JID& receiver, - boost::shared_ptr<T> payload, - IQRouter* router) : - Request(type, receiver, router) { - boost::shared_ptr<ContainerType> wrapper = boost::make_shared<ContainerType>(); - wrapper->setPayload(payload); - setPayload(wrapper); - } + public: + PubSubRequest( + IQ::Type type, + const JID& receiver, + std::shared_ptr<T> payload, + IQRouter* router) : + Request(type, receiver, router) { + std::shared_ptr<ContainerType> wrapper = std::make_shared<ContainerType>(); + wrapper->setPayload(payload); + setPayload(wrapper); + } - PubSubRequest( - IQ::Type type, - const JID& sender, - const JID& receiver, - boost::shared_ptr<T> payload, - IQRouter* router) : - Request(type, sender, receiver, router) { - boost::shared_ptr<ContainerType> wrapper = boost::make_shared<ContainerType>(); - wrapper->setPayload(payload); - setPayload(wrapper); - } + PubSubRequest( + IQ::Type type, + const JID& sender, + const JID& receiver, + std::shared_ptr<T> payload, + IQRouter* router) : + Request(type, sender, receiver, router) { + std::shared_ptr<ContainerType> wrapper = std::make_shared<ContainerType>(); + wrapper->setPayload(payload); + setPayload(wrapper); + } - virtual void handleResponse( - boost::shared_ptr<Payload> payload, ErrorPayload::ref error) { - boost::shared_ptr<ResponseType> result; - if (boost::shared_ptr<ContainerType> container = boost::dynamic_pointer_cast<ContainerType>(payload)) { - result = boost::dynamic_pointer_cast<ResponseType>(container->getPayload()); - } - onResponse(result, error); - } + virtual void handleResponse( + std::shared_ptr<Payload> payload, ErrorPayload::ref error) { + std::shared_ptr<ResponseType> result; + if (std::shared_ptr<ContainerType> container = std::dynamic_pointer_cast<ContainerType>(payload)) { + result = std::dynamic_pointer_cast<ResponseType>(container->getPayload()); + } + onResponse(result, error); + } - public: - boost::signal<void (boost::shared_ptr<ResponseType>, ErrorPayload::ref)> onResponse; - }; + public: + boost::signals2::signal<void (std::shared_ptr<ResponseType>, ErrorPayload::ref)> onResponse; + }; } diff --git a/Swiften/Queries/RawRequest.h b/Swiften/Queries/RawRequest.h index efe0890..76c84f9 100644 --- a/Swiften/Queries/RawRequest.h +++ b/Swiften/Queries/RawRequest.h @@ -1,50 +1,52 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <typeinfo> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Queries/Request.h> -#include <Swiften/Elements/RawXMLPayload.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/RawXMLPayload.h> +#include <Swiften/Queries/Request.h> #include <Swiften/Serializer/PayloadSerializer.h> #include <Swiften/Serializer/PayloadSerializers/ErrorSerializer.h> #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> namespace Swift { - class RawRequest : public Request { - public: - typedef boost::shared_ptr<RawRequest> ref; - - static ref create(IQ::Type type, const JID& recipient, const std::string& data, IQRouter* router) { - return ref(new RawRequest(type, recipient, data, router)); - } - - boost::signal<void (const std::string&)> onResponse; - - private: - RawRequest(IQ::Type type, const JID& receiver, const std::string& data, IQRouter* router) : Request(type, receiver, boost::make_shared<RawXMLPayload>(data), router) { - } - - virtual void handleResponse(boost::shared_ptr<Payload> payload, ErrorPayload::ref error) { - if (error) { - onResponse(ErrorSerializer(&serializers).serializePayload(error)); - } - else { - assert(payload); - PayloadSerializer* serializer = serializers.getPayloadSerializer(payload); - assert(serializer); - onResponse(serializer->serialize(payload)); - } - } - - private: - FullPayloadSerializerCollection serializers; - }; + class SWIFTEN_API RawRequest : public Request { + public: + typedef std::shared_ptr<RawRequest> ref; + + static ref create(IQ::Type type, const JID& recipient, const std::string& data, IQRouter* router) { + return ref(new RawRequest(type, recipient, data, router)); + } + + boost::signals2::signal<void (const std::string&)> onResponse; + + private: + RawRequest(IQ::Type type, const JID& receiver, const std::string& data, IQRouter* router) : Request(type, receiver, std::make_shared<RawXMLPayload>(data), router) { + } + + virtual void handleResponse(std::shared_ptr<Payload> payload, ErrorPayload::ref error) { + if (error) { + onResponse(ErrorSerializer(&serializers).serializePayload(error)); + } + else { + assert(payload); + PayloadSerializer* serializer = serializers.getPayloadSerializer(payload); + assert(serializer); + onResponse(serializer->serialize(payload)); + } + } + + private: + FullPayloadSerializerCollection serializers; + }; } diff --git a/Swiften/Queries/Request.cpp b/Swiften/Queries/Request.cpp index 40c8f60..12eaae5 100644 --- a/Swiften/Queries/Request.cpp +++ b/Swiften/Queries/Request.cpp @@ -1,92 +1,93 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Queries/Request.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Elements/RawXMLPayload.h> + #include <Swiften/Base/Log.h> +#include <Swiften/Elements/RawXMLPayload.h> +#include <Swiften/Queries/IQRouter.h> namespace Swift { -Request::Request(IQ::Type type, const JID& receiver, boost::shared_ptr<Payload> payload, IQRouter* router) : router_(router), type_(type), receiver_(receiver), payload_(payload), sent_(false) { +Request::Request(IQ::Type type, const JID& receiver, std::shared_ptr<Payload> payload, IQRouter* router) : router_(router), type_(type), receiver_(receiver), payload_(payload), sent_(false) { } Request::Request(IQ::Type type, const JID& receiver, IQRouter* router) : router_(router), type_(type), receiver_(receiver), sent_(false) { } -Request::Request(IQ::Type type, const JID& sender, const JID& receiver, boost::shared_ptr<Payload> payload, IQRouter* router) : router_(router), type_(type), sender_(sender), receiver_(receiver), payload_(payload), sent_(false) { +Request::Request(IQ::Type type, const JID& sender, const JID& receiver, std::shared_ptr<Payload> payload, IQRouter* router) : router_(router), type_(type), sender_(sender), receiver_(receiver), payload_(payload), sent_(false) { } Request::Request(IQ::Type type, const JID& sender, const JID& receiver, IQRouter* router) : router_(router), type_(type), sender_(sender), receiver_(receiver), sent_(false) { } std::string Request::send() { - assert(payload_); - assert(!sent_); - sent_ = true; + assert(payload_); + assert(!sent_); + sent_ = true; - boost::shared_ptr<IQ> iq(new IQ(type_)); - iq->setTo(receiver_); - iq->setFrom(sender_); - iq->addPayload(payload_); - id_ = router_->getNewIQID(); - iq->setID(id_); + std::shared_ptr<IQ> iq(new IQ(type_)); + iq->setTo(receiver_); + iq->setFrom(sender_); + iq->addPayload(payload_); + id_ = router_->getNewIQID(); + iq->setID(id_); - try { - router_->addHandler(shared_from_this()); - } - catch (const std::exception&) { - router_->addHandler(this); - } + try { + router_->addHandler(shared_from_this()); + } + catch (const std::exception&) { + router_->addHandler(this); + } - router_->sendIQ(iq); - return id_; + router_->sendIQ(iq); + return id_; } -bool Request::handleIQ(boost::shared_ptr<IQ> iq) { - bool handled = false; - if (iq->getType() == IQ::Result || iq->getType() == IQ::Error) { - if (sent_ && iq->getID() == id_) { - if (isCorrectSender(iq->getFrom())) { - if (iq->getType() == IQ::Result) { - boost::shared_ptr<Payload> payload = iq->getPayloadOfSameType(payload_); - if (!payload && boost::dynamic_pointer_cast<RawXMLPayload>(payload_) && !iq->getPayloads().empty()) { - payload = iq->getPayloads().front(); - } - handleResponse(payload, ErrorPayload::ref()); - } - else { - ErrorPayload::ref errorPayload = iq->getPayload<ErrorPayload>(); - if (errorPayload) { - handleResponse(boost::shared_ptr<Payload>(), errorPayload); - } - else { - handleResponse(boost::shared_ptr<Payload>(), ErrorPayload::ref(new ErrorPayload(ErrorPayload::UndefinedCondition))); - } - } - router_->removeHandler(this); - handled = true; - } - } - } - return handled; +bool Request::handleIQ(std::shared_ptr<IQ> iq) { + bool handled = false; + if (iq->getType() == IQ::Result || iq->getType() == IQ::Error) { + if (sent_ && iq->getID() == id_) { + if (isCorrectSender(iq->getFrom())) { + if (iq->getType() == IQ::Result) { + std::shared_ptr<Payload> payload = iq->getPayloadOfSameType(payload_); + if (!payload && std::dynamic_pointer_cast<RawXMLPayload>(payload_) && !iq->getPayloads().empty()) { + payload = iq->getPayloads().front(); + } + handleResponse(payload, ErrorPayload::ref()); + } + else { + ErrorPayload::ref errorPayload = iq->getPayload<ErrorPayload>(); + if (errorPayload) { + handleResponse(std::shared_ptr<Payload>(), errorPayload); + } + else { + handleResponse(std::shared_ptr<Payload>(), ErrorPayload::ref(new ErrorPayload(ErrorPayload::UndefinedCondition))); + } + } + router_->removeHandler(this); + handled = true; + } + } + } + return handled; } bool Request::isCorrectSender(const JID& jid) { - if (router_->isAccountJID(receiver_)) { - if (jid.isValid() && jid.equals(router_->getJID(), JID::WithResource)) { - // This unspecified behavior seems to happen in ejabberd versions (e.g. 2.0.5) - SWIFT_LOG(warning) << "Server responded to an account request with a full JID, which is not allowed. Handling it anyway."; - return true; - } - return router_->isAccountJID(jid); - } - else { - return jid.equals(receiver_, JID::WithResource); - } + if (router_->isAccountJID(receiver_)) { + if (jid.isValid() && jid.equals(router_->getJID(), JID::WithResource)) { + // This unspecified behavior seems to happen in ejabberd versions (e.g. 2.0.5) + SWIFT_LOG(warning) << "Server responded to an account request with a full JID, which is not allowed. Handling it anyway."; + return true; + } + return router_->isAccountJID(jid); + } + else { + return jid.equals(receiver_, JID::WithResource); + } } diff --git a/Swiften/Queries/Request.h b/Swiften/Queries/Request.h index f17cc11..2cf5017 100644 --- a/Swiften/Queries/Request.h +++ b/Swiften/Queries/Request.h @@ -1,106 +1,108 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/optional.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <memory> #include <string> +#include <boost/optional.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Queries/IQHandler.h> +#include <Swiften/Elements/ErrorPayload.h> #include <Swiften/Elements/IQ.h> #include <Swiften/Elements/Payload.h> -#include <Swiften/Elements/ErrorPayload.h> #include <Swiften/JID/JID.h> +#include <Swiften/Queries/IQHandler.h> namespace Swift { - /** - * An IQ get/set request query. - */ - class SWIFTEN_API Request : public IQHandler, public boost::enable_shared_from_this<Request> { - public: - std::string send(); - - const JID& getReceiver() const { - return receiver_; - } - - /** - * Returns the ID of this request. - * This will only be set after send() is called. - */ - const std::string& getID() const { - return id_; - } - - - protected: - /** - * Constructs a request of a certain type to a specific receiver, and attaches the given - * payload. - */ - Request( - IQ::Type type, - const JID& receiver, - boost::shared_ptr<Payload> payload, - IQRouter* router); - - /** - * Constructs a request of a certain type to a specific receiver from a specific sender, and attaches the given - * payload. - */ - Request( - IQ::Type type, - const JID& sender, - const JID& receiver, - boost::shared_ptr<Payload> payload, - IQRouter* router); - - - /** - * Constructs a request of a certain type to a specific receiver. - */ - Request( - IQ::Type type, - const JID& receiver, - IQRouter* router); - - /** - * Constructs a request of a certain type to a specific receiver from a specific sender. - */ - Request( - IQ::Type type, - const JID& sender, - const JID& receiver, - IQRouter* router); - - - virtual void setPayload(boost::shared_ptr<Payload> payload) { - payload_ = payload; - } - - boost::shared_ptr<Payload> getPayload() const { - return payload_; - } - - virtual void handleResponse(boost::shared_ptr<Payload>, boost::shared_ptr<ErrorPayload>) = 0; - - private: - bool handleIQ(boost::shared_ptr<IQ>); - bool isCorrectSender(const JID& jid); - - private: - IQRouter* router_; - IQ::Type type_; - JID sender_; - JID receiver_; - boost::shared_ptr<Payload> payload_; - std::string id_; - bool sent_; - }; + class IQRouter; + + /** + * An IQ get/set request query. + */ + class SWIFTEN_API Request : public IQHandler, public std::enable_shared_from_this<Request> { + public: + std::string send(); + + const JID& getReceiver() const { + return receiver_; + } + + /** + * Returns the ID of this request. + * This will only be set after send() is called. + */ + const std::string& getID() const { + return id_; + } + + + protected: + /** + * Constructs a request of a certain type to a specific receiver, and attaches the given + * payload. + */ + Request( + IQ::Type type, + const JID& receiver, + std::shared_ptr<Payload> payload, + IQRouter* router); + + /** + * Constructs a request of a certain type to a specific receiver from a specific sender, and attaches the given + * payload. + */ + Request( + IQ::Type type, + const JID& sender, + const JID& receiver, + std::shared_ptr<Payload> payload, + IQRouter* router); + + + /** + * Constructs a request of a certain type to a specific receiver. + */ + Request( + IQ::Type type, + const JID& receiver, + IQRouter* router); + + /** + * Constructs a request of a certain type to a specific receiver from a specific sender. + */ + Request( + IQ::Type type, + const JID& sender, + const JID& receiver, + IQRouter* router); + + + virtual void setPayload(std::shared_ptr<Payload> payload) { + payload_ = payload; + } + + std::shared_ptr<Payload> getPayload() const { + return payload_; + } + + virtual void handleResponse(std::shared_ptr<Payload>, std::shared_ptr<ErrorPayload>) = 0; + + private: + bool handleIQ(std::shared_ptr<IQ>); + bool isCorrectSender(const JID& jid); + + private: + IQRouter* router_; + IQ::Type type_; + JID sender_; + JID receiver_; + std::shared_ptr<Payload> payload_; + std::string id_; + bool sent_; + }; } diff --git a/Swiften/Queries/Requests/EnableCarbonsRequest.h b/Swiften/Queries/Requests/EnableCarbonsRequest.h new file mode 100644 index 0000000..7762e68 --- /dev/null +++ b/Swiften/Queries/Requests/EnableCarbonsRequest.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsEnable.h> +#include <Swiften/Queries/GenericRequest.h> + +namespace Swift { + class SWIFTEN_API EnableCarbonsRequest : public GenericRequest<CarbonsEnable> { + public: + typedef std::shared_ptr<EnableCarbonsRequest> ref; + + static ref create(IQRouter* router) { + return ref(new EnableCarbonsRequest(router)); + } + + private: + EnableCarbonsRequest(IQRouter* router) : GenericRequest<CarbonsEnable>(IQ::Set, JID(), std::make_shared<CarbonsEnable>(), router) { + } + }; +} diff --git a/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.cpp b/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.cpp deleted file mode 100644 index 337375e..0000000 --- a/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.cpp +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/Queries/Requests/GetInBandRegistrationFormRequest.h> diff --git a/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.h b/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.h index c0488ad..b187fa5 100644 --- a/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.h +++ b/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.h @@ -1,26 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/InBandRegistrationPayload.h> - +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class GetInBandRegistrationFormRequest : public GenericRequest<InBandRegistrationPayload> { - public: - typedef boost::shared_ptr<GetInBandRegistrationFormRequest> ref; + class SWIFTEN_API GetInBandRegistrationFormRequest : public GenericRequest<InBandRegistrationPayload> { + public: + typedef std::shared_ptr<GetInBandRegistrationFormRequest> ref; - static ref create(const JID& to, IQRouter* router) { - return ref(new GetInBandRegistrationFormRequest(to, router)); - } + static ref create(const JID& to, IQRouter* router) { + return ref(new GetInBandRegistrationFormRequest(to, router)); + } - private: - GetInBandRegistrationFormRequest(const JID& to, IQRouter* router) : GenericRequest<InBandRegistrationPayload>(IQ::Get, to, InBandRegistrationPayload::ref(new InBandRegistrationPayload()), router) { - } - }; + private: + GetInBandRegistrationFormRequest(const JID& to, IQRouter* router) : GenericRequest<InBandRegistrationPayload>(IQ::Get, to, InBandRegistrationPayload::ref(new InBandRegistrationPayload()), router) { + } + }; } diff --git a/Swiften/Queries/Requests/GetPrivateStorageRequest.h b/Swiften/Queries/Requests/GetPrivateStorageRequest.h index b5fd97f..5fb0de5 100644 --- a/Swiften/Queries/Requests/GetPrivateStorageRequest.h +++ b/Swiften/Queries/Requests/GetPrivateStorageRequest.h @@ -1,44 +1,45 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Queries/Request.h> -#include <Swiften/Elements/PrivateStorage.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/PrivateStorage.h> +#include <Swiften/Queries/Request.h> namespace Swift { - template<typename PAYLOAD_TYPE> - class GetPrivateStorageRequest : public Request { - public: - typedef boost::shared_ptr<GetPrivateStorageRequest<PAYLOAD_TYPE> > ref; - - static ref create(IQRouter* router) { - return ref(new GetPrivateStorageRequest(router)); - } - - private: - GetPrivateStorageRequest(IQRouter* router) : Request(IQ::Get, JID(), boost::make_shared<PrivateStorage>(boost::shared_ptr<Payload>(new PAYLOAD_TYPE())), router) { - } - - virtual void handleResponse(boost::shared_ptr<Payload> payload, ErrorPayload::ref error) { - boost::shared_ptr<PrivateStorage> storage = boost::dynamic_pointer_cast<PrivateStorage>(payload); - if (storage) { - onResponse(boost::dynamic_pointer_cast<PAYLOAD_TYPE>(storage->getPayload()), error); - } - else { - onResponse(boost::shared_ptr<PAYLOAD_TYPE>(), error); - } - } - - public: - boost::signal<void (boost::shared_ptr<PAYLOAD_TYPE>, ErrorPayload::ref)> onResponse; - }; + template<typename PAYLOAD_TYPE> + class SWIFTEN_API GetPrivateStorageRequest : public Request { + public: + typedef std::shared_ptr<GetPrivateStorageRequest<PAYLOAD_TYPE> > ref; + + static ref create(IQRouter* router) { + return ref(new GetPrivateStorageRequest(router)); + } + + private: + GetPrivateStorageRequest(IQRouter* router) : Request(IQ::Get, JID(), std::make_shared<PrivateStorage>(std::make_shared<PAYLOAD_TYPE>()), router) { + } + + virtual void handleResponse(std::shared_ptr<Payload> payload, ErrorPayload::ref error) { + std::shared_ptr<PrivateStorage> storage = std::dynamic_pointer_cast<PrivateStorage>(payload); + if (storage) { + onResponse(std::dynamic_pointer_cast<PAYLOAD_TYPE>(storage->getPayload()), error); + } + else { + onResponse(std::shared_ptr<PAYLOAD_TYPE>(), error); + } + } + + public: + boost::signals2::signal<void (std::shared_ptr<PAYLOAD_TYPE>, ErrorPayload::ref)> onResponse; + }; } diff --git a/Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h b/Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h index 943adef..0a3502f 100644 --- a/Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h +++ b/Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h @@ -1,32 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/SecurityLabelsCatalog.h> - +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class GetSecurityLabelsCatalogRequest : public GenericRequest<SecurityLabelsCatalog> { - public: - typedef boost::shared_ptr<GetSecurityLabelsCatalogRequest> ref; + class SWIFTEN_API GetSecurityLabelsCatalogRequest : public GenericRequest<SecurityLabelsCatalog> { + public: + typedef std::shared_ptr<GetSecurityLabelsCatalogRequest> ref; - static ref create(const JID& recipient, IQRouter* router) { - return ref(new GetSecurityLabelsCatalogRequest(recipient, router)); - } + static ref create(const JID& recipient, IQRouter* router) { + return ref(new GetSecurityLabelsCatalogRequest(recipient, router)); + } - private: - GetSecurityLabelsCatalogRequest( - const JID& recipient, - IQRouter* router) : - GenericRequest<SecurityLabelsCatalog>( - IQ::Get, JID(), boost::make_shared<SecurityLabelsCatalog>(recipient), router) { - } - }; + private: + GetSecurityLabelsCatalogRequest( + const JID& recipient, + IQRouter* router) : + GenericRequest<SecurityLabelsCatalog>( + IQ::Get, JID(), std::make_shared<SecurityLabelsCatalog>(recipient), router) { + } + }; } diff --git a/Swiften/Queries/Requests/GetSoftwareVersionRequest.h b/Swiften/Queries/Requests/GetSoftwareVersionRequest.h index 18461bb..5660dd8 100644 --- a/Swiften/Queries/Requests/GetSoftwareVersionRequest.h +++ b/Swiften/Queries/Requests/GetSoftwareVersionRequest.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Queries/GenericRequest.h> -#include <Swiften/Elements/SoftwareVersion.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/SoftwareVersion.h> +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class GetSoftwareVersionRequest : public GenericRequest<SoftwareVersion> { - public: - typedef boost::shared_ptr<GetSoftwareVersionRequest> ref; + class SWIFTEN_API GetSoftwareVersionRequest : public GenericRequest<SoftwareVersion> { + public: + typedef std::shared_ptr<GetSoftwareVersionRequest> ref; - static ref create(const JID& recipient, IQRouter* router) { - return ref(new GetSoftwareVersionRequest(recipient, router)); - } + static ref create(const JID& recipient, IQRouter* router) { + return ref(new GetSoftwareVersionRequest(recipient, router)); + } - private: - GetSoftwareVersionRequest( - const JID& recipient, - IQRouter* router) : - GenericRequest<SoftwareVersion>( - IQ::Get, recipient, boost::make_shared<SoftwareVersion>(), router) { - } - }; + private: + GetSoftwareVersionRequest( + const JID& recipient, + IQRouter* router) : + GenericRequest<SoftwareVersion>( + IQ::Get, recipient, std::make_shared<SoftwareVersion>(), router) { + } + }; } diff --git a/Swiften/Queries/Requests/SetPrivateStorageRequest.h b/Swiften/Queries/Requests/SetPrivateStorageRequest.h index f65f819..f1dc77a 100644 --- a/Swiften/Queries/Requests/SetPrivateStorageRequest.h +++ b/Swiften/Queries/Requests/SetPrivateStorageRequest.h @@ -1,38 +1,39 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Queries/Request.h> -#include <Swiften/Elements/PrivateStorage.h> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/PrivateStorage.h> +#include <Swiften/Queries/Request.h> namespace Swift { - template<typename PAYLOAD_TYPE> - class SetPrivateStorageRequest : public Request { - public: - typedef boost::shared_ptr<SetPrivateStorageRequest<PAYLOAD_TYPE> > ref; - - static ref create(boost::shared_ptr<PAYLOAD_TYPE> payload, IQRouter* router) { - return ref(new SetPrivateStorageRequest<PAYLOAD_TYPE>(payload, router)); - } - - private: - SetPrivateStorageRequest(boost::shared_ptr<PAYLOAD_TYPE> payload, IQRouter* router) : Request(IQ::Set, JID(), boost::make_shared<PrivateStorage>(payload), router) { - } - - virtual void handleResponse(boost::shared_ptr<Payload>, ErrorPayload::ref error) { - onResponse(error); - } - - public: - boost::signal<void (ErrorPayload::ref)> onResponse; - }; + template<typename PAYLOAD_TYPE> + class SWIFTEN_API SetPrivateStorageRequest : public Request { + public: + typedef std::shared_ptr<SetPrivateStorageRequest<PAYLOAD_TYPE> > ref; + + static ref create(std::shared_ptr<PAYLOAD_TYPE> payload, IQRouter* router) { + return ref(new SetPrivateStorageRequest<PAYLOAD_TYPE>(payload, router)); + } + + private: + SetPrivateStorageRequest(std::shared_ptr<PAYLOAD_TYPE> payload, IQRouter* router) : Request(IQ::Set, JID(), std::make_shared<PrivateStorage>(payload), router) { + } + + virtual void handleResponse(std::shared_ptr<Payload>, ErrorPayload::ref error) { + onResponse(error); + } + + public: + boost::signals2::signal<void (ErrorPayload::ref)> onResponse; + }; } diff --git a/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.cpp b/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.cpp deleted file mode 100644 index f010e96..0000000 --- a/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.cpp +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h> diff --git a/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h b/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h index 8e0862b..1cf28c5 100644 --- a/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h +++ b/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h @@ -1,36 +1,37 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Queries/Request.h> -#include <Swiften/Elements/InBandRegistrationPayload.h> +#include <boost/signals2.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/InBandRegistrationPayload.h> +#include <Swiften/Queries/Request.h> namespace Swift { - class SetInBandRegistrationRequest : public Request { - public: - typedef boost::shared_ptr<SetInBandRegistrationRequest> ref; + class SWIFTEN_API SetInBandRegistrationRequest : public Request { + public: + typedef std::shared_ptr<SetInBandRegistrationRequest> ref; - static ref create(const JID& to, InBandRegistrationPayload::ref payload, IQRouter* router) { - return ref(new SetInBandRegistrationRequest(to, payload, router)); - } + static ref create(const JID& to, InBandRegistrationPayload::ref payload, IQRouter* router) { + return ref(new SetInBandRegistrationRequest(to, payload, router)); + } - private: - SetInBandRegistrationRequest(const JID& to, InBandRegistrationPayload::ref payload, IQRouter* router) : Request(IQ::Set, to, InBandRegistrationPayload::ref(payload), router) { - } + private: + SetInBandRegistrationRequest(const JID& to, InBandRegistrationPayload::ref payload, IQRouter* router) : Request(IQ::Set, to, InBandRegistrationPayload::ref(payload), router) { + } - virtual void handleResponse(boost::shared_ptr<Payload> payload, ErrorPayload::ref error) { - onResponse(payload, error); - } + virtual void handleResponse(std::shared_ptr<Payload> payload, ErrorPayload::ref error) { + onResponse(payload, error); + } - public: - boost::signal<void (boost::shared_ptr<Payload>, ErrorPayload::ref)> onResponse; - }; + public: + boost::signals2::signal<void (std::shared_ptr<Payload>, ErrorPayload::ref)> onResponse; + }; } diff --git a/Swiften/Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp b/Swiften/Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp index f3ecfb7..ed242f9 100644 --- a/Swiften/Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp +++ b/Swiften/Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp @@ -1,109 +1,110 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> -#include <boost/bind.hpp> -#include <Swiften/Queries/Requests/GetPrivateStorageRequest.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Queries/DummyIQChannel.h> #include <Swiften/Elements/Payload.h> +#include <Swiften/Queries/DummyIQChannel.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Queries/Requests/GetPrivateStorageRequest.h> using namespace Swift; class GetPrivateStorageRequestTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(GetPrivateStorageRequestTest); - CPPUNIT_TEST(testSend); - CPPUNIT_TEST(testHandleResponse); - CPPUNIT_TEST(testHandleResponse_Error); - CPPUNIT_TEST_SUITE_END(); - - public: - class MyPayload : public Payload { - public: - MyPayload(const std::string& text = "") : text(text) {} - std::string text; - }; - - public: - void setUp() { - channel = new DummyIQChannel(); - router = new IQRouter(channel); - } - - void tearDown() { - delete router; - delete channel; - } - - void testSend() { - GetPrivateStorageRequest<MyPayload>::ref request = GetPrivateStorageRequest<MyPayload>::create(router); - request->send(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->iqs_.size())); - CPPUNIT_ASSERT_EQUAL(JID(), channel->iqs_[0]->getTo()); - CPPUNIT_ASSERT_EQUAL(IQ::Get, channel->iqs_[0]->getType()); - boost::shared_ptr<PrivateStorage> storage = channel->iqs_[0]->getPayload<PrivateStorage>(); - CPPUNIT_ASSERT(storage); - boost::shared_ptr<MyPayload> payload = boost::dynamic_pointer_cast<MyPayload>(storage->getPayload()); - CPPUNIT_ASSERT(payload); - } - - void testHandleResponse() { - GetPrivateStorageRequest<MyPayload>::ref testling = GetPrivateStorageRequest<MyPayload>::create(router); - testling->onResponse.connect(boost::bind(&GetPrivateStorageRequestTest::handleResponse, this, _1, _2)); - testling->send(); - channel->onIQReceived(createResponse("test-id", "foo")); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(responses.size())); - CPPUNIT_ASSERT_EQUAL(std::string("foo"), boost::dynamic_pointer_cast<MyPayload>(responses[0])->text); - } - - void testHandleResponse_Error() { - GetPrivateStorageRequest<MyPayload>::ref testling = GetPrivateStorageRequest<MyPayload>::create(router); - testling->onResponse.connect(boost::bind(&GetPrivateStorageRequestTest::handleResponse, this, _1, _2)); - testling->send(); - channel->onIQReceived(createError("test-id")); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(responses.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(errors.size())); - } - - private: - void handleResponse(boost::shared_ptr<Payload> p, ErrorPayload::ref e) { - if (e) { - errors.push_back(*e); - } - else { - responses.push_back(p); - } - } - - boost::shared_ptr<IQ> createResponse(const std::string& id, const std::string& text) { - boost::shared_ptr<IQ> iq(new IQ(IQ::Result)); - boost::shared_ptr<PrivateStorage> storage(new PrivateStorage()); - storage->setPayload(boost::shared_ptr<Payload>(new MyPayload(text))); - iq->addPayload(storage); - iq->setID(id); - return iq; - } - - boost::shared_ptr<IQ> createError(const std::string& id) { - boost::shared_ptr<IQ> iq(new IQ(IQ::Error)); - iq->setID(id); - return iq; - } - - private: - IQRouter* router; - DummyIQChannel* channel; - std::vector< ErrorPayload > errors; - std::vector< boost::shared_ptr<Payload> > responses; + CPPUNIT_TEST_SUITE(GetPrivateStorageRequestTest); + CPPUNIT_TEST(testSend); + CPPUNIT_TEST(testHandleResponse); + CPPUNIT_TEST(testHandleResponse_Error); + CPPUNIT_TEST_SUITE_END(); + + public: + class MyPayload : public Payload { + public: + MyPayload(const std::string& text = "") : text(text) {} + std::string text; + }; + + public: + void setUp() { + channel = std::make_unique<DummyIQChannel>(); + router = std::make_unique<IQRouter>(channel.get()); + } + + void tearDown() { + router.reset(); + } + + void testSend() { + GetPrivateStorageRequest<MyPayload>::ref request = GetPrivateStorageRequest<MyPayload>::create(router.get()); + request->send(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->iqs_.size())); + CPPUNIT_ASSERT_EQUAL(JID(), channel->iqs_[0]->getTo()); + CPPUNIT_ASSERT_EQUAL(IQ::Get, channel->iqs_[0]->getType()); + std::shared_ptr<PrivateStorage> storage = channel->iqs_[0]->getPayload<PrivateStorage>(); + CPPUNIT_ASSERT(storage); + std::shared_ptr<MyPayload> payload = std::dynamic_pointer_cast<MyPayload>(storage->getPayload()); + CPPUNIT_ASSERT(payload); + } + + void testHandleResponse() { + GetPrivateStorageRequest<MyPayload>::ref testling = GetPrivateStorageRequest<MyPayload>::create(router.get()); + testling->onResponse.connect(boost::bind(&GetPrivateStorageRequestTest::handleResponse, this, _1, _2)); + testling->send(); + channel->onIQReceived(createResponse("test-id", "foo")); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(responses.size())); + CPPUNIT_ASSERT_EQUAL(std::string("foo"), std::dynamic_pointer_cast<MyPayload>(responses[0])->text); + } + + void testHandleResponse_Error() { + GetPrivateStorageRequest<MyPayload>::ref testling = GetPrivateStorageRequest<MyPayload>::create(router.get()); + testling->onResponse.connect(boost::bind(&GetPrivateStorageRequestTest::handleResponse, this, _1, _2)); + testling->send(); + channel->onIQReceived(createError("test-id")); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(responses.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(errors.size())); + } + + private: + void handleResponse(std::shared_ptr<Payload> p, ErrorPayload::ref e) { + if (e) { + errors.push_back(*e); + } + else { + responses.push_back(p); + } + } + + std::shared_ptr<IQ> createResponse(const std::string& id, const std::string& text) { + std::shared_ptr<IQ> iq(new IQ(IQ::Result)); + std::shared_ptr<PrivateStorage> storage(new PrivateStorage()); + storage->setPayload(std::make_shared<MyPayload>(text)); + iq->addPayload(storage); + iq->setID(id); + return iq; + } + + std::shared_ptr<IQ> createError(const std::string& id) { + std::shared_ptr<IQ> iq(new IQ(IQ::Error)); + iq->setID(id); + return iq; + } + + private: + std::unique_ptr<IQRouter> router; + std::unique_ptr<DummyIQChannel> channel; + std::vector< ErrorPayload > errors; + std::vector< std::shared_ptr<Payload> > responses; }; CPPUNIT_TEST_SUITE_REGISTRATION(GetPrivateStorageRequestTest); diff --git a/Swiften/Queries/Responder.h b/Swiften/Queries/Responder.h index edcaa52..0974adf 100644 --- a/Swiften/Queries/Responder.h +++ b/Swiften/Queries/Responder.h @@ -1,125 +1,136 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ErrorPayload.h> #include <Swiften/Queries/IQHandler.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Elements/ErrorPayload.h> namespace Swift { - /** - * A class for handling incoming IQ Get and Set requests of a specific payload type. - * - * Concrete subclasses of this class need to implement handleGetRequest() and handleSetRequest() to - * implement the behavior of the responder. - * - * \tparam PAYLOAD_TYPE The type of payload this Responder handles. Only IQ requests containing this - * payload type will be passed to handleGetRequest() and handleSetRequest() - */ - template<typename PAYLOAD_TYPE> - class Responder : public IQHandler { - public: - Responder(IQRouter* router) : router_(router) { - } - - ~Responder() { - } - - /** - * Starts the responder. - * - * After the responder has started, it will start receiving and responding to requests. - * - * \see stop() - */ - void start() { - router_->addHandler(this); - } - - /** - * Stops the responder. - * - * When the responder is stopped, it will no longer receive incoming requests. - * - * \see start() - */ - void stop() { - router_->removeHandler(this); - } - - protected: - /** - * Handle an incoming IQ-Get request containing a payload of class PAYLOAD_TYPE. - * - * This method is implemented in the concrete subclasses. - */ - virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<PAYLOAD_TYPE> payload) = 0; - - /** - * Handle an incoming IQ-Set request containing a payload of class PAYLOAD_TYPE. - * - * This method is implemented in the concrete subclasses. - */ - virtual bool handleSetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<PAYLOAD_TYPE> payload) = 0; - - /** - * Convenience function for sending an IQ response. - */ - void sendResponse(const JID& to, const std::string& id, boost::shared_ptr<PAYLOAD_TYPE> payload) { - router_->sendIQ(IQ::createResult(to, id, payload)); - } - - /** - * Convenience function for sending an IQ response, with a specific from address. - */ - void sendResponse(const JID& to, const JID& from, const std::string& id, boost::shared_ptr<PAYLOAD_TYPE> payload) { - router_->sendIQ(IQ::createResult(to, from, id, payload)); - } - - /** - * Convenience function for responding with an error. - */ - void sendError(const JID& to, const std::string& id, ErrorPayload::Condition condition, ErrorPayload::Type type, Payload::ref payload = Payload::ref()) { - router_->sendIQ(IQ::createError(to, id, condition, type, payload)); - } - - /** - * Convenience function for responding with an error from a specific from address. - */ - void sendError(const JID& to, const JID& from, const std::string& id, ErrorPayload::Condition condition, ErrorPayload::Type type, Payload::ref payload = Payload::ref()) { - router_->sendIQ(IQ::createError(to, from, id, condition, type, payload)); - } - - IQRouter* getIQRouter() const { - return router_; - } - - private: - virtual bool handleIQ(boost::shared_ptr<IQ> iq) { - if (iq->getType() == IQ::Set || iq->getType() == IQ::Get) { - boost::shared_ptr<PAYLOAD_TYPE> payload(iq->getPayload<PAYLOAD_TYPE>()); - if (payload) { - bool result; - if (iq->getType() == IQ::Set) { - result = handleSetRequest(iq->getFrom(), iq->getTo(), iq->getID(), payload); - } - else { - result = handleGetRequest(iq->getFrom(), iq->getTo(), iq->getID(), payload); - } - if (!result) { - router_->sendIQ(IQ::createError(iq->getFrom(), iq->getID(), ErrorPayload::NotAllowed, ErrorPayload::Cancel)); - } - return true; - } - } - return false; - } - - private: - IQRouter* router_; - }; + /** + * A class for handling incoming IQ Get and Set requests of a specific payload type. + * + * Concrete subclasses of this class need to implement handleGetRequest() and handleSetRequest() to + * implement the behavior of the responder. + * + * \tparam PAYLOAD_TYPE The type of payload this Responder handles. Only IQ requests containing this + * payload type will be passed to handleGetRequest() and handleSetRequest() + */ + template<typename PAYLOAD_TYPE> + class SWIFTEN_API Responder : public IQHandler { + public: + Responder(IQRouter* router) : router_(router), isFinalResonder_(true) { + } + + ~Responder() { + } + + /** + * Starts the responder. + * + * After the responder has started, it will start receiving and responding to requests. + * + * \see stop() + */ + void start() { + router_->addHandler(this); + } + + /** + * Stops the responder. + * + * When the responder is stopped, it will no longer receive incoming requests. + * + * \see start() + */ + void stop() { + router_->removeHandler(this); + } + + protected: + /** + * Handle an incoming IQ-Get request containing a payload of class PAYLOAD_TYPE. + * + * This method is implemented in the concrete subclasses. + */ + virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, std::shared_ptr<PAYLOAD_TYPE> payload) = 0; + + /** + * Handle an incoming IQ-Set request containing a payload of class PAYLOAD_TYPE. + * + * This method is implemented in the concrete subclasses. + */ + virtual bool handleSetRequest(const JID& from, const JID& to, const std::string& id, std::shared_ptr<PAYLOAD_TYPE> payload) = 0; + + /** + * Convenience function for sending an IQ response. + */ + void sendResponse(const JID& to, const std::string& id, std::shared_ptr<PAYLOAD_TYPE> payload) { + router_->sendIQ(IQ::createResult(to, id, payload)); + } + + /** + * Convenience function for sending an IQ response, with a specific from address. + */ + void sendResponse(const JID& to, const JID& from, const std::string& id, std::shared_ptr<PAYLOAD_TYPE> payload) { + router_->sendIQ(IQ::createResult(to, from, id, payload)); + } + + /** + * Convenience function for responding with an error. + */ + void sendError(const JID& to, const std::string& id, ErrorPayload::Condition condition, ErrorPayload::Type type, Payload::ref payload = Payload::ref()) { + router_->sendIQ(IQ::createError(to, id, condition, type, payload)); + } + + /** + * Convenience function for responding with an error from a specific from address. + */ + void sendError(const JID& to, const JID& from, const std::string& id, ErrorPayload::Condition condition, ErrorPayload::Type type, Payload::ref payload = Payload::ref()) { + router_->sendIQ(IQ::createError(to, from, id, condition, type, payload)); + } + + IQRouter* getIQRouter() const { + return router_; + } + + void setFinal(bool isFinal) { + isFinalResonder_ = isFinal; + } + + private: + virtual bool handleIQ(std::shared_ptr<IQ> iq) { + if (iq->getType() == IQ::Set || iq->getType() == IQ::Get) { + std::shared_ptr<PAYLOAD_TYPE> payload(iq->getPayload<PAYLOAD_TYPE>()); + if (payload) { + bool result; + if (iq->getType() == IQ::Set) { + result = handleSetRequest(iq->getFrom(), iq->getTo(), iq->getID(), payload); + } + else { + result = handleGetRequest(iq->getFrom(), iq->getTo(), iq->getID(), payload); + } + if (!result) { + if (isFinalResonder_) { + router_->sendIQ(IQ::createError(iq->getFrom(), iq->getID(), ErrorPayload::NotAllowed, ErrorPayload::Cancel)); + } + else { + return false; + } + } + return true; + } + } + return false; + } + + private: + IQRouter* router_; + bool isFinalResonder_; + }; } diff --git a/Swiften/Queries/Responders/SoftwareVersionResponder.cpp b/Swiften/Queries/Responders/SoftwareVersionResponder.cpp index 55328fb..5071f6e 100644 --- a/Swiften/Queries/Responders/SoftwareVersionResponder.cpp +++ b/Swiften/Queries/Responders/SoftwareVersionResponder.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Queries/Responders/SoftwareVersionResponder.h> + +#include <memory> + #include <Swiften/Queries/IQRouter.h> namespace Swift { @@ -15,14 +16,14 @@ SoftwareVersionResponder::SoftwareVersionResponder(IQRouter* router) : GetRespon } void SoftwareVersionResponder::setVersion(const std::string& client, const std::string& version, const std::string& os) { - this->client = client; - this->version = version; - this->os = os; + this->client = client; + this->version = version; + this->os = os; } -bool SoftwareVersionResponder::handleGetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<SoftwareVersion>) { - sendResponse(from, id, boost::make_shared<SoftwareVersion>(client, version, os)); - return true; +bool SoftwareVersionResponder::handleGetRequest(const JID& from, const JID&, const std::string& id, std::shared_ptr<SoftwareVersion>) { + sendResponse(from, id, std::make_shared<SoftwareVersion>(client, version, os)); + return true; } } diff --git a/Swiften/Queries/Responders/SoftwareVersionResponder.h b/Swiften/Queries/Responders/SoftwareVersionResponder.h index 4957c0f..4bb3425 100644 --- a/Swiften/Queries/Responders/SoftwareVersionResponder.h +++ b/Swiften/Queries/Responders/SoftwareVersionResponder.h @@ -1,30 +1,30 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Queries/GetResponder.h> #include <Swiften/Elements/SoftwareVersion.h> +#include <Swiften/Queries/GetResponder.h> namespace Swift { - class IQRouter; + class IQRouter; - class SWIFTEN_API SoftwareVersionResponder : public GetResponder<SoftwareVersion> { - public: - SoftwareVersionResponder(IQRouter* router); + class SWIFTEN_API SoftwareVersionResponder : public GetResponder<SoftwareVersion> { + public: + SoftwareVersionResponder(IQRouter* router); - void setVersion(const std::string& client, const std::string& version, const std::string& os = ""); + void setVersion(const std::string& client, const std::string& version, const std::string& os = ""); - private: - virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<SoftwareVersion> payload); + private: + virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, std::shared_ptr<SoftwareVersion> payload); - private: - std::string client; - std::string version; - std::string os; - }; + private: + std::string client; + std::string version; + std::string os; + }; } diff --git a/Swiften/Queries/SetResponder.h b/Swiften/Queries/SetResponder.h index 331aa46..e2842f4 100644 --- a/Swiften/Queries/SetResponder.h +++ b/Swiften/Queries/SetResponder.h @@ -1,20 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Queries/Responder.h> namespace Swift { - template<typename T> - class SetResponder : public Responder<T> { - public: - SetResponder(IQRouter* router) : Responder<T>(router) {} + template<typename T> + class SWIFTEN_API SetResponder : public Responder<T> { + public: + SetResponder(IQRouter* router) : Responder<T>(router) {} - private: - virtual bool handleGetRequest(const JID&, const JID&, const std::string&, boost::shared_ptr<T>) { return false; } - }; + private: + virtual bool handleGetRequest(const JID&, const JID&, const std::string&, std::shared_ptr<T>) { return false; } + }; } diff --git a/Swiften/Queries/UnitTest/IQRouterTest.cpp b/Swiften/Queries/UnitTest/IQRouterTest.cpp index ee27a67..0acb87b 100644 --- a/Swiften/Queries/UnitTest/IQRouterTest.cpp +++ b/Swiften/Queries/UnitTest/IQRouterTest.cpp @@ -1,177 +1,178 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/bind.hpp> +#include <Swiften/Queries/DummyIQChannel.h> #include <Swiften/Queries/IQHandler.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Queries/DummyIQChannel.h> using namespace Swift; class IQRouterTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IQRouterTest); - CPPUNIT_TEST(testRemoveHandler); - CPPUNIT_TEST(testRemoveHandler_AfterHandleIQ); - CPPUNIT_TEST(testHandleIQ_SuccesfulHandlerFirst); - CPPUNIT_TEST(testHandleIQ_SuccesfulHandlerLast); - CPPUNIT_TEST(testHandleIQ_NoSuccesfulHandler); - CPPUNIT_TEST(testHandleIQ_HandlerRemovedDuringHandle); - CPPUNIT_TEST(testSendIQ_WithFrom); - CPPUNIT_TEST(testSendIQ_WithoutFrom); - CPPUNIT_TEST(testHandleIQ_WithFrom); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(IQRouterTest); + CPPUNIT_TEST(testRemoveHandler); + CPPUNIT_TEST(testRemoveHandler_AfterHandleIQ); + CPPUNIT_TEST(testHandleIQ_SuccesfulHandlerFirst); + CPPUNIT_TEST(testHandleIQ_SuccesfulHandlerLast); + CPPUNIT_TEST(testHandleIQ_NoSuccesfulHandler); + CPPUNIT_TEST(testHandleIQ_HandlerRemovedDuringHandle); + CPPUNIT_TEST(testSendIQ_WithFrom); + CPPUNIT_TEST(testSendIQ_WithoutFrom); + CPPUNIT_TEST(testHandleIQ_WithFrom); + CPPUNIT_TEST_SUITE_END(); - public: - void setUp() { - channel_ = new DummyIQChannel(); - } + public: + void setUp() { + channel_ = new DummyIQChannel(); + } - void tearDown() { - delete channel_; - } + void tearDown() { + delete channel_; + } - void testRemoveHandler() { - IQRouter testling(channel_); - DummyIQHandler handler1(true, &testling); - DummyIQHandler handler2(true, &testling); - testling.removeHandler(&handler1); + void testRemoveHandler() { + IQRouter testling(channel_); + DummyIQHandler handler1(true, &testling); + DummyIQHandler handler2(true, &testling); + testling.removeHandler(&handler1); - channel_->onIQReceived(boost::make_shared<IQ>()); + channel_->onIQReceived(std::make_shared<IQ>()); - CPPUNIT_ASSERT_EQUAL(0, handler1.called); - CPPUNIT_ASSERT_EQUAL(1, handler2.called); - } + CPPUNIT_ASSERT_EQUAL(0, handler1.called); + CPPUNIT_ASSERT_EQUAL(1, handler2.called); + } - void testRemoveHandler_AfterHandleIQ() { - IQRouter testling(channel_); - DummyIQHandler handler2(true, &testling); - DummyIQHandler handler1(true, &testling); - - channel_->onIQReceived(boost::make_shared<IQ>()); - testling.removeHandler(&handler1); - channel_->onIQReceived(boost::make_shared<IQ>()); - - CPPUNIT_ASSERT_EQUAL(1, handler1.called); - CPPUNIT_ASSERT_EQUAL(1, handler2.called); - } - - void testHandleIQ_SuccesfulHandlerFirst() { - IQRouter testling(channel_); - DummyIQHandler handler2(false, &testling); - DummyIQHandler handler1(true, &testling); - - channel_->onIQReceived(boost::make_shared<IQ>()); - - CPPUNIT_ASSERT_EQUAL(1, handler1.called); - CPPUNIT_ASSERT_EQUAL(0, handler2.called); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_SuccesfulHandlerLast() { - IQRouter testling(channel_); - DummyIQHandler handler2(true, &testling); - DummyIQHandler handler1(false, &testling); - - channel_->onIQReceived(boost::make_shared<IQ>()); - - CPPUNIT_ASSERT_EQUAL(1, handler1.called); - CPPUNIT_ASSERT_EQUAL(1, handler2.called); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_NoSuccesfulHandler() { - IQRouter testling(channel_); - DummyIQHandler handler(false, &testling); - - channel_->onIQReceived(boost::make_shared<IQ>()); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - CPPUNIT_ASSERT(channel_->iqs_[0]->getPayload<ErrorPayload>()); - } - - - void testHandleIQ_HandlerRemovedDuringHandle() { - IQRouter testling(channel_); - DummyIQHandler handler2(true, &testling); - RemovingIQHandler handler1(&testling); - - channel_->onIQReceived(boost::make_shared<IQ>()); - channel_->onIQReceived(boost::make_shared<IQ>()); - - CPPUNIT_ASSERT_EQUAL(1, handler1.called); - CPPUNIT_ASSERT_EQUAL(2, handler2.called); - } - - void testSendIQ_WithFrom() { - IQRouter testling(channel_); - testling.setFrom(JID("foo@bar.com/baz")); - - testling.sendIQ(boost::make_shared<IQ>()); - - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), channel_->iqs_[0]->getFrom()); - } - - void testSendIQ_WithoutFrom() { - IQRouter testling(channel_); + void testRemoveHandler_AfterHandleIQ() { + IQRouter testling(channel_); + DummyIQHandler handler2(true, &testling); + DummyIQHandler handler1(true, &testling); + + channel_->onIQReceived(std::make_shared<IQ>()); + testling.removeHandler(&handler1); + channel_->onIQReceived(std::make_shared<IQ>()); + + CPPUNIT_ASSERT_EQUAL(1, handler1.called); + CPPUNIT_ASSERT_EQUAL(1, handler2.called); + } + + void testHandleIQ_SuccesfulHandlerFirst() { + IQRouter testling(channel_); + DummyIQHandler handler2(false, &testling); + DummyIQHandler handler1(true, &testling); + + channel_->onIQReceived(std::make_shared<IQ>()); + + CPPUNIT_ASSERT_EQUAL(1, handler1.called); + CPPUNIT_ASSERT_EQUAL(0, handler2.called); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_SuccesfulHandlerLast() { + IQRouter testling(channel_); + DummyIQHandler handler2(true, &testling); + DummyIQHandler handler1(false, &testling); + + channel_->onIQReceived(std::make_shared<IQ>()); + + CPPUNIT_ASSERT_EQUAL(1, handler1.called); + CPPUNIT_ASSERT_EQUAL(1, handler2.called); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_NoSuccesfulHandler() { + IQRouter testling(channel_); + DummyIQHandler handler(false, &testling); + + channel_->onIQReceived(std::make_shared<IQ>()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + CPPUNIT_ASSERT(channel_->iqs_[0]->getPayload<ErrorPayload>()); + } + + + void testHandleIQ_HandlerRemovedDuringHandle() { + IQRouter testling(channel_); + DummyIQHandler handler2(true, &testling); + RemovingIQHandler handler1(&testling); + + channel_->onIQReceived(std::make_shared<IQ>()); + channel_->onIQReceived(std::make_shared<IQ>()); + + CPPUNIT_ASSERT_EQUAL(1, handler1.called); + CPPUNIT_ASSERT_EQUAL(2, handler2.called); + } + + void testSendIQ_WithFrom() { + IQRouter testling(channel_); + testling.setFrom(JID("foo@bar.com/baz")); + + testling.sendIQ(std::make_shared<IQ>()); + + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), channel_->iqs_[0]->getFrom()); + } + + void testSendIQ_WithoutFrom() { + IQRouter testling(channel_); - testling.sendIQ(boost::make_shared<IQ>()); + testling.sendIQ(std::make_shared<IQ>()); - CPPUNIT_ASSERT_EQUAL(JID(), channel_->iqs_[0]->getFrom()); - } + CPPUNIT_ASSERT_EQUAL(JID(), channel_->iqs_[0]->getFrom()); + } - void testHandleIQ_WithFrom() { - IQRouter testling(channel_); - testling.setFrom(JID("foo@bar.com/baz")); - DummyIQHandler handler(false, &testling); + void testHandleIQ_WithFrom() { + IQRouter testling(channel_); + testling.setFrom(JID("foo@bar.com/baz")); + DummyIQHandler handler(false, &testling); - channel_->onIQReceived(boost::make_shared<IQ>()); + channel_->onIQReceived(std::make_shared<IQ>()); - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), channel_->iqs_[0]->getFrom()); - } + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), channel_->iqs_[0]->getFrom()); + } - private: - struct DummyIQHandler : public IQHandler { - DummyIQHandler(bool handle, IQRouter* router) : handle(handle), router(router), called(0) { - router->addHandler(this); - } + private: + struct DummyIQHandler : public IQHandler { + DummyIQHandler(bool handle, IQRouter* router) : handle(handle), router(router), called(0) { + router->addHandler(this); + } - ~DummyIQHandler() { - router->removeHandler(this); - } + ~DummyIQHandler() { + router->removeHandler(this); + } - virtual bool handleIQ(boost::shared_ptr<IQ>) { - called++; - return handle; - } - bool handle; - IQRouter* router; - int called; - }; + virtual bool handleIQ(std::shared_ptr<IQ>) { + called++; + return handle; + } + bool handle; + IQRouter* router; + int called; + }; - struct RemovingIQHandler : public IQHandler { - RemovingIQHandler(IQRouter* router) : router(router), called(0) { - router->addHandler(this); - } + struct RemovingIQHandler : public IQHandler { + RemovingIQHandler(IQRouter* router) : router(router), called(0) { + router->addHandler(this); + } - virtual bool handleIQ(boost::shared_ptr<IQ>) { - called++; - router->removeHandler(this); - return false; - } - IQRouter* router; - int called; - }; + virtual bool handleIQ(std::shared_ptr<IQ>) { + called++; + router->removeHandler(this); + return false; + } + IQRouter* router; + int called; + }; - DummyIQChannel* channel_; + DummyIQChannel* channel_; }; CPPUNIT_TEST_SUITE_REGISTRATION(IQRouterTest); diff --git a/Swiften/Queries/UnitTest/RequestTest.cpp b/Swiften/Queries/UnitTest/RequestTest.cpp index 6c2a805..b46f1d4 100644 --- a/Swiften/Queries/UnitTest/RequestTest.cpp +++ b/Swiften/Queries/UnitTest/RequestTest.cpp @@ -1,366 +1,367 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> -#include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Queries/GenericRequest.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Queries/DummyIQChannel.h> #include <Swiften/Elements/Payload.h> #include <Swiften/Elements/RawXMLPayload.h> +#include <Swiften/Queries/DummyIQChannel.h> +#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Queries/IQRouter.h> using namespace Swift; class RequestTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(RequestTest); - CPPUNIT_TEST(testSendGet); - CPPUNIT_TEST(testSendSet); - CPPUNIT_TEST(testHandleIQ); - CPPUNIT_TEST(testHandleIQ_InvalidID); - CPPUNIT_TEST(testHandleIQ_Error); - CPPUNIT_TEST(testHandleIQ_ErrorWithoutPayload); - CPPUNIT_TEST(testHandleIQ_BeforeSend); - CPPUNIT_TEST(testHandleIQ_DifferentPayload); - CPPUNIT_TEST(testHandleIQ_RawXMLPayload); - CPPUNIT_TEST(testHandleIQ_GetWithSameID); - CPPUNIT_TEST(testHandleIQ_SetWithSameID); - CPPUNIT_TEST(testHandleIQ_IncorrectSender); - CPPUNIT_TEST(testHandleIQ_IncorrectSenderForServerQuery); - CPPUNIT_TEST(testHandleIQ_IncorrectOtherResourceSenderForServerQuery); - CPPUNIT_TEST(testHandleIQ_ServerRespondsWithDomain); - CPPUNIT_TEST(testHandleIQ_ServerRespondsWithBareJID); - CPPUNIT_TEST(testHandleIQ_ServerRespondsWithoutFrom); - CPPUNIT_TEST(testHandleIQ_ServerRespondsWithFullJID); - CPPUNIT_TEST_SUITE_END(); - - public: - class MyPayload : public Payload { - public: - MyPayload(const std::string& s = "") : text_(s) {} - std::string text_; - }; - - struct MyOtherPayload : public Payload { - }; - - class MyRequest : public Request { - public: - MyRequest( - IQ::Type type, - const JID& receiver, - boost::shared_ptr<Payload> payload, - IQRouter* router) : - Request(type, receiver, payload, router) { - } - - virtual void handleResponse(boost::shared_ptr<Payload> payload, ErrorPayload::ref error) { - onResponse(payload, error); - } - - public: - boost::signal<void (boost::shared_ptr<Payload>, ErrorPayload::ref)> onResponse; - }; - - public: - void setUp() { - channel_ = new DummyIQChannel(); - router_ = new IQRouter(channel_); - payload_ = boost::shared_ptr<Payload>(new MyPayload("foo")); - responsePayload_ = boost::shared_ptr<Payload>(new MyPayload("bar")); - responsesReceived_ = 0; - } - - void tearDown() { - delete router_; - delete channel_; - } - - void testSendSet() { - MyRequest testling(IQ::Set, JID("foo@bar.com/baz"), payload_, router_); - testling.send(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), channel_->iqs_[0]->getTo()); - CPPUNIT_ASSERT_EQUAL(IQ::Set, channel_->iqs_[0]->getType()); - CPPUNIT_ASSERT_EQUAL(std::string("test-id"), channel_->iqs_[0]->getID()); - } - - void testSendGet() { - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - testling.send(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - CPPUNIT_ASSERT_EQUAL(IQ::Get, channel_->iqs_[0]->getType()); - } - - void testHandleIQ() { - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); - - CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - // FIXME: Doesn't test that it didn't handle the payload - void testHandleIQ_InvalidID() { - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"different-id")); - - CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_Error() { - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - boost::shared_ptr<IQ> error = createError(JID("foo@bar.com/baz"),"test-id"); - boost::shared_ptr<Payload> errorPayload = boost::make_shared<ErrorPayload>(ErrorPayload::InternalServerError); - error->addPayload(errorPayload); - channel_->onIQReceived(error); - - CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - CPPUNIT_ASSERT_EQUAL(ErrorPayload::InternalServerError, receivedErrors[0].getCondition()); - } - - void testHandleIQ_ErrorWithoutPayload() { - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - channel_->onIQReceived(createError(JID("foo@bar.com/baz"),"test-id")); - - CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - CPPUNIT_ASSERT_EQUAL(ErrorPayload::UndefinedCondition, receivedErrors[0].getCondition()); - } - - void testHandleIQ_BeforeSend() { - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); - - CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_DifferentPayload() { - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - testling.onResponse.connect(boost::bind(&RequestTest::handleDifferentResponse, this, _1, _2)); - testling.send(); - - responsePayload_ = boost::make_shared<MyOtherPayload>(); - channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); - - CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_RawXMLPayload() { - payload_ = boost::make_shared<RawXMLPayload>("<bla/>"); - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - testling.onResponse.connect(boost::bind(&RequestTest::handleRawXMLResponse, this, _1, _2)); - testling.send(); - - responsePayload_ = boost::make_shared<MyOtherPayload>(); - channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); - - CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_GetWithSameID() { - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - boost::shared_ptr<IQ> response = createResponse(JID("foo@bar.com/baz"),"test-id"); - response->setType(IQ::Get); - channel_->onIQReceived(response); - - CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_SetWithSameID() { - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - boost::shared_ptr<IQ> response = createResponse(JID("foo@bar.com/baz"), "test-id"); - response->setType(IQ::Set); - channel_->onIQReceived(response); - - CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_IncorrectSender() { - MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); - router_->setJID("alice@wonderland.lit/TeaParty"); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - channel_->onIQReceived(createResponse(JID("anotherfoo@bar.com/baz"), "test-id")); - - CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_IncorrectSenderForServerQuery() { - MyRequest testling(IQ::Get, JID(), payload_, router_); - router_->setJID("alice@wonderland.lit/TeaParty"); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"), "test-id")); - - CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_IncorrectOtherResourceSenderForServerQuery() { - MyRequest testling(IQ::Get, JID(), payload_, router_); - router_->setJID("alice@wonderland.lit/TeaParty"); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - channel_->onIQReceived(createResponse(JID("alice@wonderland.lit/RabbitHole"), "test-id")); - - CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_ServerRespondsWithDomain() { - MyRequest testling(IQ::Get, JID(), payload_, router_); - router_->setJID("alice@wonderland.lit/TeaParty"); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - channel_->onIQReceived(createResponse(JID("wonderland.lit"),"test-id")); - - CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_ServerRespondsWithBareJID() { - MyRequest testling(IQ::Get, JID(), payload_, router_); - router_->setJID("alice@wonderland.lit/TeaParty"); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - channel_->onIQReceived(createResponse(JID("alice@wonderland.lit"),"test-id")); - - CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - // This tests a bug in ejabberd servers (2.0.5) - void testHandleIQ_ServerRespondsWithFullJID() { - MyRequest testling(IQ::Get, JID(), payload_, router_); - router_->setJID("alice@wonderland.lit/TeaParty"); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - channel_->onIQReceived(createResponse(JID("alice@wonderland.lit/TeaParty"),"test-id")); - - CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - void testHandleIQ_ServerRespondsWithoutFrom() { - MyRequest testling(IQ::Get, JID(), payload_, router_); - router_->setJID("alice@wonderland.lit/TeaParty"); - testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); - testling.send(); - - channel_->onIQReceived(createResponse(JID(),"test-id")); - - CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - } - - - - private: - void handleResponse(boost::shared_ptr<Payload> p, ErrorPayload::ref e) { - if (e) { - receivedErrors.push_back(*e); - } - else { - boost::shared_ptr<MyPayload> payload(boost::dynamic_pointer_cast<MyPayload>(p)); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT_EQUAL(std::string("bar"), payload->text_); - ++responsesReceived_; - } - } - - void handleDifferentResponse(boost::shared_ptr<Payload> p, ErrorPayload::ref e) { - CPPUNIT_ASSERT(!e); - CPPUNIT_ASSERT(!p); - ++responsesReceived_; - } - - void handleRawXMLResponse(boost::shared_ptr<Payload> p, ErrorPayload::ref e) { - CPPUNIT_ASSERT(!e); - CPPUNIT_ASSERT(p); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<MyOtherPayload>(p)); - ++responsesReceived_; - } - - boost::shared_ptr<IQ> createResponse(const JID& from, const std::string& id) { - boost::shared_ptr<IQ> iq(new IQ(IQ::Result)); - iq->setFrom(from); - iq->addPayload(responsePayload_); - iq->setID(id); - return iq; - } - - boost::shared_ptr<IQ> createError(const JID& from, const std::string& id) { - boost::shared_ptr<IQ> iq(new IQ(IQ::Error)); - iq->setFrom(from); - iq->setID(id); - return iq; - } - - private: - IQRouter* router_; - DummyIQChannel* channel_; - boost::shared_ptr<Payload> payload_; - boost::shared_ptr<Payload> responsePayload_; - int responsesReceived_; - std::vector<ErrorPayload> receivedErrors; + CPPUNIT_TEST_SUITE(RequestTest); + CPPUNIT_TEST(testSendGet); + CPPUNIT_TEST(testSendSet); + CPPUNIT_TEST(testHandleIQ); + CPPUNIT_TEST(testHandleIQ_InvalidID); + CPPUNIT_TEST(testHandleIQ_Error); + CPPUNIT_TEST(testHandleIQ_ErrorWithoutPayload); + CPPUNIT_TEST(testHandleIQ_BeforeSend); + CPPUNIT_TEST(testHandleIQ_DifferentPayload); + CPPUNIT_TEST(testHandleIQ_RawXMLPayload); + CPPUNIT_TEST(testHandleIQ_GetWithSameID); + CPPUNIT_TEST(testHandleIQ_SetWithSameID); + CPPUNIT_TEST(testHandleIQ_IncorrectSender); + CPPUNIT_TEST(testHandleIQ_IncorrectSenderForServerQuery); + CPPUNIT_TEST(testHandleIQ_IncorrectOtherResourceSenderForServerQuery); + CPPUNIT_TEST(testHandleIQ_ServerRespondsWithDomain); + CPPUNIT_TEST(testHandleIQ_ServerRespondsWithBareJID); + CPPUNIT_TEST(testHandleIQ_ServerRespondsWithoutFrom); + CPPUNIT_TEST(testHandleIQ_ServerRespondsWithFullJID); + CPPUNIT_TEST_SUITE_END(); + + public: + class MyPayload : public Payload { + public: + MyPayload(const std::string& s = "") : text_(s) {} + std::string text_; + }; + + struct MyOtherPayload : public Payload { + }; + + class MyRequest : public Request { + public: + MyRequest( + IQ::Type type, + const JID& receiver, + std::shared_ptr<Payload> payload, + IQRouter* router) : + Request(type, receiver, payload, router) { + } + + virtual void handleResponse(std::shared_ptr<Payload> payload, ErrorPayload::ref error) { + onResponse(payload, error); + } + + public: + boost::signals2::signal<void (std::shared_ptr<Payload>, ErrorPayload::ref)> onResponse; + }; + + public: + void setUp() { + channel_ = new DummyIQChannel(); + router_ = new IQRouter(channel_); + payload_ = std::make_shared<MyPayload>("foo"); + responsePayload_ = std::make_shared<MyPayload>("bar"); + responsesReceived_ = 0; + } + + void tearDown() { + delete router_; + delete channel_; + } + + void testSendSet() { + MyRequest testling(IQ::Set, JID("foo@bar.com/baz"), payload_, router_); + testling.send(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), channel_->iqs_[0]->getTo()); + CPPUNIT_ASSERT_EQUAL(IQ::Set, channel_->iqs_[0]->getType()); + CPPUNIT_ASSERT_EQUAL(std::string("test-id"), channel_->iqs_[0]->getID()); + } + + void testSendGet() { + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + testling.send(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + CPPUNIT_ASSERT_EQUAL(IQ::Get, channel_->iqs_[0]->getType()); + } + + void testHandleIQ() { + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); + + CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + // FIXME: Doesn't test that it didn't handle the payload + void testHandleIQ_InvalidID() { + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"different-id")); + + CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_Error() { + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + std::shared_ptr<IQ> error = createError(JID("foo@bar.com/baz"),"test-id"); + std::shared_ptr<Payload> errorPayload = std::make_shared<ErrorPayload>(ErrorPayload::InternalServerError); + error->addPayload(errorPayload); + channel_->onIQReceived(error); + + CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + CPPUNIT_ASSERT_EQUAL(ErrorPayload::InternalServerError, receivedErrors[0].getCondition()); + } + + void testHandleIQ_ErrorWithoutPayload() { + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + channel_->onIQReceived(createError(JID("foo@bar.com/baz"),"test-id")); + + CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + CPPUNIT_ASSERT_EQUAL(ErrorPayload::UndefinedCondition, receivedErrors[0].getCondition()); + } + + void testHandleIQ_BeforeSend() { + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); + + CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_DifferentPayload() { + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + testling.onResponse.connect(boost::bind(&RequestTest::handleDifferentResponse, this, _1, _2)); + testling.send(); + + responsePayload_ = std::make_shared<MyOtherPayload>(); + channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); + + CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_RawXMLPayload() { + payload_ = std::make_shared<RawXMLPayload>("<bla/>"); + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + testling.onResponse.connect(boost::bind(&RequestTest::handleRawXMLResponse, this, _1, _2)); + testling.send(); + + responsePayload_ = std::make_shared<MyOtherPayload>(); + channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"),"test-id")); + + CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_GetWithSameID() { + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + std::shared_ptr<IQ> response = createResponse(JID("foo@bar.com/baz"),"test-id"); + response->setType(IQ::Get); + channel_->onIQReceived(response); + + CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_SetWithSameID() { + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + std::shared_ptr<IQ> response = createResponse(JID("foo@bar.com/baz"), "test-id"); + response->setType(IQ::Set); + channel_->onIQReceived(response); + + CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_IncorrectSender() { + MyRequest testling(IQ::Get, JID("foo@bar.com/baz"), payload_, router_); + router_->setJID("alice@wonderland.lit/TeaParty"); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + channel_->onIQReceived(createResponse(JID("anotherfoo@bar.com/baz"), "test-id")); + + CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_IncorrectSenderForServerQuery() { + MyRequest testling(IQ::Get, JID(), payload_, router_); + router_->setJID("alice@wonderland.lit/TeaParty"); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + channel_->onIQReceived(createResponse(JID("foo@bar.com/baz"), "test-id")); + + CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_IncorrectOtherResourceSenderForServerQuery() { + MyRequest testling(IQ::Get, JID(), payload_, router_); + router_->setJID("alice@wonderland.lit/TeaParty"); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + channel_->onIQReceived(createResponse(JID("alice@wonderland.lit/RabbitHole"), "test-id")); + + CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_ServerRespondsWithDomain() { + MyRequest testling(IQ::Get, JID(), payload_, router_); + router_->setJID("alice@wonderland.lit/TeaParty"); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + channel_->onIQReceived(createResponse(JID("wonderland.lit"),"test-id")); + + CPPUNIT_ASSERT_EQUAL(0, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_ServerRespondsWithBareJID() { + MyRequest testling(IQ::Get, JID(), payload_, router_); + router_->setJID("alice@wonderland.lit/TeaParty"); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + channel_->onIQReceived(createResponse(JID("alice@wonderland.lit"),"test-id")); + + CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + // This tests a bug in ejabberd servers (2.0.5) + void testHandleIQ_ServerRespondsWithFullJID() { + MyRequest testling(IQ::Get, JID(), payload_, router_); + router_->setJID("alice@wonderland.lit/TeaParty"); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + channel_->onIQReceived(createResponse(JID("alice@wonderland.lit/TeaParty"),"test-id")); + + CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + void testHandleIQ_ServerRespondsWithoutFrom() { + MyRequest testling(IQ::Get, JID(), payload_, router_); + router_->setJID("alice@wonderland.lit/TeaParty"); + testling.onResponse.connect(boost::bind(&RequestTest::handleResponse, this, _1, _2)); + testling.send(); + + channel_->onIQReceived(createResponse(JID(),"test-id")); + + CPPUNIT_ASSERT_EQUAL(1, responsesReceived_); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedErrors.size())); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + } + + + + private: + void handleResponse(std::shared_ptr<Payload> p, ErrorPayload::ref e) { + if (e) { + receivedErrors.push_back(*e); + } + else { + std::shared_ptr<MyPayload> payload(std::dynamic_pointer_cast<MyPayload>(p)); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), payload->text_); + ++responsesReceived_; + } + } + + void handleDifferentResponse(std::shared_ptr<Payload> p, ErrorPayload::ref e) { + CPPUNIT_ASSERT(!e); + CPPUNIT_ASSERT(!p); + ++responsesReceived_; + } + + void handleRawXMLResponse(std::shared_ptr<Payload> p, ErrorPayload::ref e) { + CPPUNIT_ASSERT(!e); + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT(std::dynamic_pointer_cast<MyOtherPayload>(p)); + ++responsesReceived_; + } + + std::shared_ptr<IQ> createResponse(const JID& from, const std::string& id) { + std::shared_ptr<IQ> iq(new IQ(IQ::Result)); + iq->setFrom(from); + iq->addPayload(responsePayload_); + iq->setID(id); + return iq; + } + + std::shared_ptr<IQ> createError(const JID& from, const std::string& id) { + std::shared_ptr<IQ> iq(new IQ(IQ::Error)); + iq->setFrom(from); + iq->setID(id); + return iq; + } + + private: + IQRouter* router_; + DummyIQChannel* channel_; + std::shared_ptr<Payload> payload_; + std::shared_ptr<Payload> responsePayload_; + int responsesReceived_; + std::vector<ErrorPayload> receivedErrors; }; CPPUNIT_TEST_SUITE_REGISTRATION(RequestTest); diff --git a/Swiften/Queries/UnitTest/ResponderTest.cpp b/Swiften/Queries/UnitTest/ResponderTest.cpp index 6d40b6c..fa5072b 100644 --- a/Swiften/Queries/UnitTest/ResponderTest.cpp +++ b/Swiften/Queries/UnitTest/ResponderTest.cpp @@ -1,157 +1,157 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/bind.hpp> -#include <Swiften/Queries/Responder.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Queries/DummyIQChannel.h> #include <Swiften/Elements/SoftwareVersion.h> +#include <Swiften/Queries/DummyIQChannel.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Queries/Responder.h> using namespace Swift; class ResponderTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ResponderTest); - CPPUNIT_TEST(testConstructor); - CPPUNIT_TEST(testStart); - CPPUNIT_TEST(testStop); - CPPUNIT_TEST(testHandleIQ_Set); - CPPUNIT_TEST(testHandleIQ_Get); - CPPUNIT_TEST(testHandleIQ_Error); - CPPUNIT_TEST(testHandleIQ_Result); - CPPUNIT_TEST(testHandleIQ_NoPayload); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(ResponderTest); + CPPUNIT_TEST(testConstructor); + CPPUNIT_TEST(testStart); + CPPUNIT_TEST(testStop); + CPPUNIT_TEST(testHandleIQ_Set); + CPPUNIT_TEST(testHandleIQ_Get); + CPPUNIT_TEST(testHandleIQ_Error); + CPPUNIT_TEST(testHandleIQ_Result); + CPPUNIT_TEST(testHandleIQ_NoPayload); + CPPUNIT_TEST_SUITE_END(); - public: - void setUp() { - channel_ = new DummyIQChannel(); - router_ = new IQRouter(channel_); - payload_ = boost::make_shared<SoftwareVersion>("foo"); - } + public: + void setUp() { + channel_ = std::make_unique<DummyIQChannel>(); + router_ = std::make_unique<IQRouter>(channel_.get()); + payload_ = std::make_shared<SoftwareVersion>("foo"); + } - void tearDown() { - delete router_; - delete channel_; - } - - void testConstructor() { - MyResponder testling(router_); - - channel_->onIQReceived(createRequest(IQ::Set)); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); - } - - void testStart() { - MyResponder testling(router_); - - testling.start(); - channel_->onIQReceived(createRequest(IQ::Set)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling.setPayloads_.size())); - } - - void testStop() { - MyResponder testling(router_); - - testling.start(); - testling.stop(); - channel_->onIQReceived(createRequest(IQ::Set)); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); - } - - void testHandleIQ_Set() { - MyResponder testling(router_); - - CPPUNIT_ASSERT(dynamic_cast<IQHandler*>(&testling)->handleIQ(createRequest(IQ::Set))); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling.setPayloads_.size())); - CPPUNIT_ASSERT(payload_ == testling.setPayloads_[0]); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.getPayloads_.size())); - } - - void testHandleIQ_Get() { - MyResponder testling(router_); - - CPPUNIT_ASSERT(dynamic_cast<IQHandler*>(&testling)->handleIQ(createRequest(IQ::Get))); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling.getPayloads_.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); - CPPUNIT_ASSERT(payload_ == testling.getPayloads_[0]); - } - - void testHandleIQ_Error() { - MyResponder testling(router_); - - CPPUNIT_ASSERT(!dynamic_cast<IQHandler*>(&testling)->handleIQ(createRequest(IQ::Error))); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.getPayloads_.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); - } - - void testHandleIQ_Result() { - MyResponder testling(router_); - - CPPUNIT_ASSERT(!dynamic_cast<IQHandler*>(&testling)->handleIQ(createRequest(IQ::Result))); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.getPayloads_.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); - } - - void testHandleIQ_NoPayload() { - MyResponder testling(router_); - - CPPUNIT_ASSERT(!dynamic_cast<IQHandler*>(&testling)->handleIQ(boost::make_shared<IQ>(IQ::Get))); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.getPayloads_.size())); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); - } - - private: - boost::shared_ptr<IQ> createRequest(IQ::Type type) { - boost::shared_ptr<IQ> iq(new IQ(type)); - iq->addPayload(payload_); - iq->setID("myid"); - iq->setFrom(JID("foo@bar.com/baz")); - return iq; - } - - private: - class MyResponder : public Responder<SoftwareVersion> { - public: - MyResponder(IQRouter* router) : Responder<SoftwareVersion>(router), getRequestResponse_(true), setRequestResponse_(true) {} + void tearDown() { + router_.reset(); + } + + void testConstructor() { + MyResponder testling(router_.get()); + + channel_->onIQReceived(createRequest(IQ::Set)); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); + } + + void testStart() { + MyResponder testling(router_.get()); + + testling.start(); + channel_->onIQReceived(createRequest(IQ::Set)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling.setPayloads_.size())); + } + + void testStop() { + MyResponder testling(router_.get()); + + testling.start(); + testling.stop(); + channel_->onIQReceived(createRequest(IQ::Set)); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); + } + + void testHandleIQ_Set() { + MyResponder testling(router_.get()); + + CPPUNIT_ASSERT(dynamic_cast<IQHandler*>(&testling)->handleIQ(createRequest(IQ::Set))); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling.setPayloads_.size())); + CPPUNIT_ASSERT(payload_ == testling.setPayloads_[0]); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.getPayloads_.size())); + } + + void testHandleIQ_Get() { + MyResponder testling(router_.get()); + + CPPUNIT_ASSERT(dynamic_cast<IQHandler*>(&testling)->handleIQ(createRequest(IQ::Get))); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(testling.getPayloads_.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); + CPPUNIT_ASSERT(payload_ == testling.getPayloads_[0]); + } + + void testHandleIQ_Error() { + MyResponder testling(router_.get()); + + CPPUNIT_ASSERT(!dynamic_cast<IQHandler*>(&testling)->handleIQ(createRequest(IQ::Error))); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.getPayloads_.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); + } + + void testHandleIQ_Result() { + MyResponder testling(router_.get()); + + CPPUNIT_ASSERT(!dynamic_cast<IQHandler*>(&testling)->handleIQ(createRequest(IQ::Result))); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.getPayloads_.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); + } + + void testHandleIQ_NoPayload() { + MyResponder testling(router_.get()); + + CPPUNIT_ASSERT(!dynamic_cast<IQHandler*>(&testling)->handleIQ(std::make_shared<IQ>(IQ::Get))); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.getPayloads_.size())); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling.setPayloads_.size())); + } + + private: + std::shared_ptr<IQ> createRequest(IQ::Type type) { + std::shared_ptr<IQ> iq(new IQ(type)); + iq->addPayload(payload_); + iq->setID("myid"); + iq->setFrom(JID("foo@bar.com/baz")); + return iq; + } + + private: + class MyResponder : public Responder<SoftwareVersion> { + public: + MyResponder(IQRouter* router) : Responder<SoftwareVersion>(router), getRequestResponse_(true), setRequestResponse_(true) {} - virtual bool handleGetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<SoftwareVersion> payload) { - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), from); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), id); - getPayloads_.push_back(payload); - return getRequestResponse_; - } - virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<SoftwareVersion> payload) { - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), from); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), id); - setPayloads_.push_back(payload); - return setRequestResponse_; - } + virtual bool handleGetRequest(const JID& from, const JID&, const std::string& id, std::shared_ptr<SoftwareVersion> payload) { + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), from); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), id); + getPayloads_.push_back(payload); + return getRequestResponse_; + } + virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, std::shared_ptr<SoftwareVersion> payload) { + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), from); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), id); + setPayloads_.push_back(payload); + return setRequestResponse_; + } - bool getRequestResponse_; - bool setRequestResponse_; - std::vector<boost::shared_ptr<SoftwareVersion> > getPayloads_; - std::vector<boost::shared_ptr<SoftwareVersion> > setPayloads_; - }; + bool getRequestResponse_; + bool setRequestResponse_; + std::vector<std::shared_ptr<SoftwareVersion> > getPayloads_; + std::vector<std::shared_ptr<SoftwareVersion> > setPayloads_; + }; - private: - IQRouter* router_; - DummyIQChannel* channel_; - boost::shared_ptr<SoftwareVersion> payload_; + private: + std::unique_ptr<IQRouter> router_; + std::unique_ptr<DummyIQChannel> channel_; + std::shared_ptr<SoftwareVersion> payload_; }; CPPUNIT_TEST_SUITE_REGISTRATION(ResponderTest); diff --git a/Swiften/Roster/GetRosterRequest.h b/Swiften/Roster/GetRosterRequest.h index e7146d2..1a0499f 100644 --- a/Swiften/Roster/GetRosterRequest.h +++ b/Swiften/Roster/GetRosterRequest.h @@ -1,33 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/RosterPayload.h> - +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class GetRosterRequest : public GenericRequest<RosterPayload> { - public: - typedef boost::shared_ptr<GetRosterRequest> ref; + class SWIFTEN_API GetRosterRequest : public GenericRequest<RosterPayload> { + public: + typedef std::shared_ptr<GetRosterRequest> ref; - static ref create(IQRouter* router) { - return ref(new GetRosterRequest(router)); - } + static ref create(IQRouter* router) { + return ref(new GetRosterRequest(router)); + } - static ref create(IQRouter* router, const std::string& version) { - ref result(new GetRosterRequest(router)); - result->getPayloadGeneric()->setVersion(version); - return result; - } + static ref create(IQRouter* router, const std::string& version) { + ref result(new GetRosterRequest(router)); + result->getPayloadGeneric()->setVersion(version); + return result; + } - private: - GetRosterRequest(IQRouter* router) : - GenericRequest<RosterPayload>(IQ::Get, JID(), boost::shared_ptr<Payload>(new RosterPayload()), router) { - } - }; + private: + GetRosterRequest(IQRouter* router) : + GenericRequest<RosterPayload>(IQ::Get, JID(), std::make_shared<RosterPayload>(), router) { + } + }; } diff --git a/Swiften/Roster/RosterMemoryStorage.cpp b/Swiften/Roster/RosterMemoryStorage.cpp index cbf4563..1b72a85 100644 --- a/Swiften/Roster/RosterMemoryStorage.cpp +++ b/Swiften/Roster/RosterMemoryStorage.cpp @@ -1,23 +1,23 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Roster/RosterMemoryStorage.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> namespace Swift { RosterMemoryStorage::RosterMemoryStorage() { } -void RosterMemoryStorage::setRoster(boost::shared_ptr<RosterPayload> r) { - roster.reset(); - if (r) { - roster = boost::make_shared<RosterPayload>(*r); - } +void RosterMemoryStorage::setRoster(std::shared_ptr<RosterPayload> r) { + roster.reset(); + if (r) { + roster = std::make_shared<RosterPayload>(*r); + } } } diff --git a/Swiften/Roster/RosterMemoryStorage.h b/Swiften/Roster/RosterMemoryStorage.h index c9312db..19e7802 100644 --- a/Swiften/Roster/RosterMemoryStorage.h +++ b/Swiften/Roster/RosterMemoryStorage.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,17 +10,17 @@ #include <Swiften/Roster/RosterStorage.h> namespace Swift { - class SWIFTEN_API RosterMemoryStorage : public RosterStorage { - public: - RosterMemoryStorage(); + class SWIFTEN_API RosterMemoryStorage : public RosterStorage { + public: + RosterMemoryStorage(); - virtual boost::shared_ptr<RosterPayload> getRoster() const { - return roster; - } + virtual std::shared_ptr<RosterPayload> getRoster() const { + return roster; + } - virtual void setRoster(boost::shared_ptr<RosterPayload>); + virtual void setRoster(std::shared_ptr<RosterPayload>); - private: - boost::shared_ptr<RosterPayload> roster; - }; + private: + std::shared_ptr<RosterPayload> roster; + }; } diff --git a/Swiften/Roster/RosterPushResponder.h b/Swiften/Roster/RosterPushResponder.h index 74d300c..00411df 100644 --- a/Swiften/Roster/RosterPushResponder.h +++ b/Swiften/Roster/RosterPushResponder.h @@ -1,34 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> -#include <Swiften/Queries/SetResponder.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/RosterPayload.h> +#include <Swiften/Queries/SetResponder.h> namespace Swift { - class RosterPushResponder : public SetResponder<RosterPayload> { - public: - RosterPushResponder(IQRouter* router) : SetResponder<RosterPayload>(router) {} + class SWIFTEN_API RosterPushResponder : public SetResponder<RosterPayload> { + public: + RosterPushResponder(IQRouter* router) : SetResponder<RosterPayload>(router) {} - public: - boost::signal<void (boost::shared_ptr<RosterPayload>)> onRosterReceived; + public: + boost::signals2::signal<void (std::shared_ptr<RosterPayload>)> onRosterReceived; - private: - virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<RosterPayload> payload) { - if (getIQRouter()->isAccountJID(from)) { - onRosterReceived(payload); - sendResponse(from, id, boost::shared_ptr<RosterPayload>()); - } - else { - sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); - } - return true; - } - }; + private: + virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, std::shared_ptr<RosterPayload> payload) { + if (getIQRouter()->isAccountJID(from)) { + onRosterReceived(payload); + sendResponse(from, id, std::shared_ptr<RosterPayload>()); + } + else { + sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); + } + return true; + } + }; } diff --git a/Swiften/Roster/RosterStorage.cpp b/Swiften/Roster/RosterStorage.cpp index 6bf58de..63dee70 100644 --- a/Swiften/Roster/RosterStorage.cpp +++ b/Swiften/Roster/RosterStorage.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Roster/RosterStorage.h> diff --git a/Swiften/Roster/RosterStorage.h b/Swiften/Roster/RosterStorage.h index 7f0f20b..1c1461d 100644 --- a/Swiften/Roster/RosterStorage.h +++ b/Swiften/Roster/RosterStorage.h @@ -1,22 +1,22 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Elements/RosterPayload.h> namespace Swift { - class SWIFTEN_API RosterStorage { - public: - virtual ~RosterStorage(); + class SWIFTEN_API RosterStorage { + public: + virtual ~RosterStorage(); - virtual boost::shared_ptr<RosterPayload> getRoster() const = 0; - virtual void setRoster(boost::shared_ptr<RosterPayload>) = 0; - }; + virtual std::shared_ptr<RosterPayload> getRoster() const = 0; + virtual void setRoster(std::shared_ptr<RosterPayload>) = 0; + }; } diff --git a/Swiften/Roster/SetRosterRequest.h b/Swiften/Roster/SetRosterRequest.h index 6f4d79d..0f71ab7 100644 --- a/Swiften/Roster/SetRosterRequest.h +++ b/Swiften/Roster/SetRosterRequest.h @@ -1,40 +1,41 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Queries/Request.h> -#include <Swiften/Elements/RosterPayload.h> +#include <boost/signals2.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/RosterPayload.h> +#include <Swiften/Queries/Request.h> namespace Swift { - class SetRosterRequest : public Request { - public: - typedef boost::shared_ptr<SetRosterRequest> ref; + class SWIFTEN_API SetRosterRequest : public Request { + public: + typedef std::shared_ptr<SetRosterRequest> ref; - static ref create(RosterPayload::ref payload, IQRouter* router) { - return ref(new SetRosterRequest(JID(), payload, router)); - } + static ref create(RosterPayload::ref payload, IQRouter* router) { + return ref(new SetRosterRequest(JID(), payload, router)); + } - static ref create(RosterPayload::ref payload, const JID& to, IQRouter* router) { - return ref(new SetRosterRequest(to, payload, router)); - } + static ref create(RosterPayload::ref payload, const JID& to, IQRouter* router) { + return ref(new SetRosterRequest(to, payload, router)); + } - private: - SetRosterRequest(const JID& to, boost::shared_ptr<RosterPayload> payload, IQRouter* router) : Request(IQ::Set, to, boost::shared_ptr<RosterPayload>(payload), router) { - } + private: + SetRosterRequest(const JID& to, std::shared_ptr<RosterPayload> payload, IQRouter* router) : Request(IQ::Set, to, std::shared_ptr<RosterPayload>(payload), router) { + } - virtual void handleResponse(boost::shared_ptr<Payload> /*payload*/, ErrorPayload::ref error) { - onResponse(error); - } + virtual void handleResponse(std::shared_ptr<Payload> /*payload*/, ErrorPayload::ref error) { + onResponse(error); + } - public: - boost::signal<void (ErrorPayload::ref)> onResponse; - }; + public: + boost::signals2::signal<void (ErrorPayload::ref)> onResponse; + }; } diff --git a/Swiften/Roster/UnitTest/XMPPRosterControllerTest.cpp b/Swiften/Roster/UnitTest/XMPPRosterControllerTest.cpp index f1bdf86..b646aba 100644 --- a/Swiften/Roster/UnitTest/XMPPRosterControllerTest.cpp +++ b/Swiften/Roster/UnitTest/XMPPRosterControllerTest.cpp @@ -1,360 +1,361 @@ /* - * Copyright (c) 2010-2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h> -#include <Swiften/Roster/XMPPRosterController.h> +#include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Elements/Payload.h> #include <Swiften/Elements/RosterItemPayload.h> #include <Swiften/Elements/RosterPayload.h> -#include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Roster/XMPPRosterImpl.h> #include <Swiften/Roster/RosterMemoryStorage.h> +#include <Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h> +#include <Swiften/Roster/XMPPRosterController.h> +#include <Swiften/Roster/XMPPRosterImpl.h> using namespace Swift; class XMPPRosterControllerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(XMPPRosterControllerTest); - CPPUNIT_TEST(testGet_Response); - CPPUNIT_TEST(testGet_EmptyResponse); - CPPUNIT_TEST(testGet_NoRosterInStorage); - CPPUNIT_TEST(testGet_NoVersionInStorage); - CPPUNIT_TEST(testGet_VersionInStorage); - CPPUNIT_TEST(testGet_ServerDoesNotSupportVersion); - CPPUNIT_TEST(testGet_ResponseWithoutNewVersion); - CPPUNIT_TEST(testGet_ResponseWithNewVersion); - CPPUNIT_TEST(testAdd); - CPPUNIT_TEST(testAddFromNonAccount); - CPPUNIT_TEST(testModify); - CPPUNIT_TEST(testRemove); - CPPUNIT_TEST(testRemove_RosterStorageUpdated); - CPPUNIT_TEST(testMany); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - channel_ = new DummyStanzaChannel(); - router_ = new IQRouter(channel_); - router_->setJID("me@bla.com"); - xmppRoster_ = new XMPPRosterImpl(); - handler_ = new XMPPRosterSignalHandler(xmppRoster_); - rosterStorage_ = new RosterMemoryStorage(); - jid1_ = JID("foo@bar.com"); - jid2_ = JID("alice@wonderland.lit"); - jid3_ = JID("jane@austen.lit"); - } - - void tearDown() { - delete rosterStorage_; - delete handler_; - delete xmppRoster_; - delete router_; - delete channel_; - } - - void testGet_Response() { - boost::shared_ptr<XMPPRosterController> testling(createController()); - - testling->requestRoster(); - boost::shared_ptr<RosterPayload> payload = boost::make_shared<RosterPayload>(); - payload->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); - payload->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both)); - channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), payload)); - - CPPUNIT_ASSERT_EQUAL(2, handler_->getEventCount()); - CPPUNIT_ASSERT(xmppRoster_->getItem(jid1_)); - CPPUNIT_ASSERT(xmppRoster_->getItem(jid2_)); - } - - void testGet_EmptyResponse() { - XMPPRosterController controller(router_, xmppRoster_, rosterStorage_); - - controller.requestRoster(); - - channel_->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), channel_->sentStanzas[0]->getID(), boost::shared_ptr<RosterPayload>())); - } - - void testAdd() { - XMPPRosterController controller(router_, xmppRoster_, rosterStorage_); - - boost::shared_ptr<RosterPayload> payload(new RosterPayload()); - payload->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "eou", payload)); - - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), xmppRoster_->getGroupsForJID(jid1_).size()); - CPPUNIT_ASSERT(xmppRoster_->containsJID(jid1_)); - CPPUNIT_ASSERT_EQUAL(std::string("Bob"), xmppRoster_->getNameForJID(jid1_)); - } - - void testGet_NoRosterInStorage() { - boost::shared_ptr<XMPPRosterController> testling(createController()); - testling->setUseVersioning(true); - - testling->requestRoster(); - - boost::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>(); - CPPUNIT_ASSERT(roster->getVersion()); - CPPUNIT_ASSERT_EQUAL(std::string(""), *roster->getVersion()); - } - - void testGet_NoVersionInStorage() { - boost::shared_ptr<XMPPRosterController> testling(createController()); - testling->setUseVersioning(true); - rosterStorage_->setRoster(boost::make_shared<RosterPayload>()); - - testling->requestRoster(); - - boost::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>(); - CPPUNIT_ASSERT(roster->getVersion()); - CPPUNIT_ASSERT_EQUAL(std::string(""), *roster->getVersion()); - } - - void testGet_VersionInStorage() { - boost::shared_ptr<XMPPRosterController> testling(createController()); - testling->setUseVersioning(true); - boost::shared_ptr<RosterPayload> payload(new RosterPayload()); - payload->setVersion("foover"); - rosterStorage_->setRoster(payload); - - testling->requestRoster(); - - boost::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>(); - CPPUNIT_ASSERT(roster->getVersion()); - CPPUNIT_ASSERT_EQUAL(std::string("foover"), *roster->getVersion()); - } - - void testGet_ServerDoesNotSupportVersion() { - boost::shared_ptr<XMPPRosterController> testling(createController()); - boost::shared_ptr<RosterPayload> payload(new RosterPayload()); - payload->setVersion("foover"); - rosterStorage_->setRoster(payload); - - testling->requestRoster(); - - boost::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>(); - CPPUNIT_ASSERT(!roster->getVersion()); - } - - void testGet_ResponseWithoutNewVersion() { - boost::shared_ptr<XMPPRosterController> testling(createController()); - testling->setUseVersioning(true); - boost::shared_ptr<RosterPayload> storedRoster(new RosterPayload()); - storedRoster->setVersion("version10"); - storedRoster->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); - storedRoster->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both)); - rosterStorage_->setRoster(storedRoster); - testling->requestRoster(); - - channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), boost::shared_ptr<RosterPayload>())); - - CPPUNIT_ASSERT_EQUAL(2, handler_->getEventCount()); - CPPUNIT_ASSERT(xmppRoster_->getItem(jid1_)); - CPPUNIT_ASSERT(xmppRoster_->getItem(jid2_)); - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID()); - CPPUNIT_ASSERT(rosterStorage_->getRoster()); - CPPUNIT_ASSERT(rosterStorage_->getRoster()->getVersion()); - CPPUNIT_ASSERT_EQUAL(std::string("version10"), *rosterStorage_->getRoster()->getVersion()); - CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid1_)); - CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid2_)); - } - - void testGet_ResponseWithNewVersion() { - boost::shared_ptr<XMPPRosterController> testling(createController()); - testling->setUseVersioning(true); - boost::shared_ptr<RosterPayload> storedRoster(new RosterPayload()); - storedRoster->setVersion("version10"); - storedRoster->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); - rosterStorage_->setRoster(storedRoster); - testling->requestRoster(); - - boost::shared_ptr<RosterPayload> serverRoster(new RosterPayload()); - serverRoster->setVersion("version12"); - serverRoster->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both)); - std::vector<std::string> groups; - groups.push_back("foo"); - groups.push_back("bar"); - serverRoster->addItem(RosterItemPayload(jid3_, "Rabbit", RosterItemPayload::Both, groups)); - channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), serverRoster)); - - - CPPUNIT_ASSERT_EQUAL(2, handler_->getEventCount()); - CPPUNIT_ASSERT(!xmppRoster_->getItem(jid1_)); - CPPUNIT_ASSERT(xmppRoster_->getItem(jid2_)); - CPPUNIT_ASSERT(xmppRoster_->getItem(jid3_)); - CPPUNIT_ASSERT_EQUAL(jid3_, handler_->getLastJID()); - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT(rosterStorage_->getRoster()); - CPPUNIT_ASSERT(rosterStorage_->getRoster()->getVersion()); - CPPUNIT_ASSERT_EQUAL(std::string("version12"), *rosterStorage_->getRoster()->getVersion()); - CPPUNIT_ASSERT(!rosterStorage_->getRoster()->getItem(jid1_)); - CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid2_)); - CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid3_)); - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(rosterStorage_->getRoster()->getItem(jid3_)->getGroups().size())); - } - - void testAddFromNonAccount() { - boost::shared_ptr<XMPPRosterController> testling(createController()); - - boost::shared_ptr<RosterPayload> payload(new RosterPayload()); - payload->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); - IQ::ref request = IQ::createRequest(IQ::Set, JID(), "eou", payload); - request->setFrom(jid2_); - channel_->onIQReceived(request); - - CPPUNIT_ASSERT_EQUAL(None, handler_->getLastEvent()); - } - - void testModify() { - XMPPRosterController controller(router_, xmppRoster_, rosterStorage_); - boost::shared_ptr<RosterPayload> payload1(new RosterPayload()); - payload1->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id1", payload1)); - - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - handler_->reset(); - - boost::shared_ptr<RosterPayload> payload2(new RosterPayload()); - payload2->addItem(RosterItemPayload(jid1_, "Bob2", RosterItemPayload::Both)); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id2", payload2)); - - CPPUNIT_ASSERT_EQUAL(Update, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - - CPPUNIT_ASSERT_EQUAL(std::string("Bob2"), xmppRoster_->getNameForJID(jid1_)); - } - - void testRemove() { - XMPPRosterController controller(router_, xmppRoster_, rosterStorage_); - boost::shared_ptr<RosterPayload> payload1(new RosterPayload()); - payload1->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id1", payload1)); - - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - handler_->reset(); - - boost::shared_ptr<RosterPayload> payload2(new RosterPayload()); - payload2->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Remove)); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id2", payload2)); - CPPUNIT_ASSERT(!xmppRoster_->containsJID(jid1_)); - CPPUNIT_ASSERT_EQUAL(Remove, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - - } - - void testRemove_RosterStorageUpdated() { - boost::shared_ptr<XMPPRosterController> testling(createController()); - testling->setUseVersioning(true); - boost::shared_ptr<RosterPayload> storedRoster(new RosterPayload()); - storedRoster->setVersion("version10"); - storedRoster->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); - storedRoster->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both)); - rosterStorage_->setRoster(storedRoster); - testling->requestRoster(); - channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), boost::shared_ptr<RosterPayload>())); - - boost::shared_ptr<RosterPayload> payload2(new RosterPayload()); - payload2->setVersion("version15"); - payload2->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Remove)); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id2", payload2)); - - CPPUNIT_ASSERT(rosterStorage_->getRoster()); - CPPUNIT_ASSERT(rosterStorage_->getRoster()->getVersion()); - CPPUNIT_ASSERT_EQUAL(std::string("version15"), *rosterStorage_->getRoster()->getVersion()); - CPPUNIT_ASSERT(!rosterStorage_->getRoster()->getItem(jid1_)); - CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid2_)); - } - - void testMany() { - XMPPRosterController controller(router_, xmppRoster_, rosterStorage_); - boost::shared_ptr<RosterPayload> payload1(new RosterPayload()); - payload1->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id1", payload1)); - - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - handler_->reset(); - - boost::shared_ptr<RosterPayload> payload2(new RosterPayload()); - payload2->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both)); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id2", payload2)); - - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID()); - handler_->reset(); - - boost::shared_ptr<RosterPayload> payload3(new RosterPayload()); - payload3->addItem(RosterItemPayload(jid1_, "Ernie", RosterItemPayload::Both)); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id3", payload3)); - - CPPUNIT_ASSERT_EQUAL(Update, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - handler_->reset(); - - boost::shared_ptr<RosterPayload> payload4(new RosterPayload()); - RosterItemPayload item(jid3_, "Jane", RosterItemPayload::Both); - std::string janesGroup("Jane's Group"); - item.addGroup(janesGroup); - payload4->addItem(item); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id4", payload4)); - - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid3_, handler_->getLastJID()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), xmppRoster_->getGroupsForJID(jid3_).size()); - CPPUNIT_ASSERT_EQUAL(janesGroup, xmppRoster_->getGroupsForJID(jid3_)[0]); - handler_->reset(); - - boost::shared_ptr<RosterPayload> payload5(new RosterPayload()); - payload5->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Remove)); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id5", payload5)); - CPPUNIT_ASSERT(!xmppRoster_->containsJID(jid1_)); - CPPUNIT_ASSERT_EQUAL(Remove, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - handler_->reset(); - - boost::shared_ptr<RosterPayload> payload6(new RosterPayload()); - RosterItemPayload item2(jid2_, "Little Alice", RosterItemPayload::Both); - std::string alicesGroup("Alice's Group"); - item2.addGroup(alicesGroup); - payload6->addItem(item2); - channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id6", payload6)); - CPPUNIT_ASSERT_EQUAL(Update, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID()); - CPPUNIT_ASSERT_EQUAL(std::string("Little Alice"), xmppRoster_->getNameForJID(jid2_)); - CPPUNIT_ASSERT_EQUAL(std::string("Jane"), xmppRoster_->getNameForJID(jid3_)); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), xmppRoster_->getGroupsForJID(jid2_).size()); - CPPUNIT_ASSERT_EQUAL(alicesGroup, xmppRoster_->getGroupsForJID(jid2_)[0]); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), xmppRoster_->getGroupsForJID(jid3_).size()); - CPPUNIT_ASSERT_EQUAL(janesGroup, xmppRoster_->getGroupsForJID(jid3_)[0]); - handler_->reset(); - - } - - private: - XMPPRosterController* createController() { - return new XMPPRosterController(router_, xmppRoster_, rosterStorage_); - } - - private: - DummyStanzaChannel* channel_; - IQRouter* router_; - XMPPRosterImpl* xmppRoster_; - XMPPRosterSignalHandler* handler_; - RosterMemoryStorage* rosterStorage_; - JID jid1_; - JID jid2_; - JID jid3_; + CPPUNIT_TEST_SUITE(XMPPRosterControllerTest); + CPPUNIT_TEST(testGet_Response); + CPPUNIT_TEST(testGet_EmptyResponse); + CPPUNIT_TEST(testGet_NoRosterInStorage); + CPPUNIT_TEST(testGet_NoVersionInStorage); + CPPUNIT_TEST(testGet_VersionInStorage); + CPPUNIT_TEST(testGet_ServerDoesNotSupportVersion); + CPPUNIT_TEST(testGet_ResponseWithoutNewVersion); + CPPUNIT_TEST(testGet_ResponseWithNewVersion); + CPPUNIT_TEST(testAdd); + CPPUNIT_TEST(testAddFromNonAccount); + CPPUNIT_TEST(testModify); + CPPUNIT_TEST(testRemove); + CPPUNIT_TEST(testRemove_RosterStorageUpdated); + CPPUNIT_TEST(testMany); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + channel_ = new DummyStanzaChannel(); + router_ = new IQRouter(channel_); + router_->setJID("me@bla.com"); + xmppRoster_ = new XMPPRosterImpl(); + handler_ = new XMPPRosterSignalHandler(xmppRoster_); + rosterStorage_ = new RosterMemoryStorage(); + jid1_ = JID("foo@bar.com"); + jid2_ = JID("alice@wonderland.lit"); + jid3_ = JID("jane@austen.lit"); + } + + void tearDown() { + delete rosterStorage_; + delete handler_; + delete xmppRoster_; + delete router_; + delete channel_; + } + + void testGet_Response() { + std::shared_ptr<XMPPRosterController> testling(createController()); + + testling->requestRoster(); + std::shared_ptr<RosterPayload> payload = std::make_shared<RosterPayload>(); + payload->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); + payload->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both)); + channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), payload)); + + CPPUNIT_ASSERT_EQUAL(2, handler_->getEventCount()); + CPPUNIT_ASSERT(xmppRoster_->getItem(jid1_)); + CPPUNIT_ASSERT(xmppRoster_->getItem(jid2_)); + } + + void testGet_EmptyResponse() { + XMPPRosterController controller(router_, xmppRoster_, rosterStorage_); + + controller.requestRoster(); + + channel_->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), channel_->sentStanzas[0]->getID(), std::shared_ptr<RosterPayload>())); + } + + void testAdd() { + XMPPRosterController controller(router_, xmppRoster_, rosterStorage_); + + std::shared_ptr<RosterPayload> payload(new RosterPayload()); + payload->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "eou", payload)); + + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), xmppRoster_->getGroupsForJID(jid1_).size()); + CPPUNIT_ASSERT(xmppRoster_->containsJID(jid1_)); + CPPUNIT_ASSERT_EQUAL(std::string("Bob"), xmppRoster_->getNameForJID(jid1_)); + } + + void testGet_NoRosterInStorage() { + std::shared_ptr<XMPPRosterController> testling(createController()); + testling->setUseVersioning(true); + + testling->requestRoster(); + + std::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>(); + CPPUNIT_ASSERT(roster->getVersion()); + CPPUNIT_ASSERT_EQUAL(std::string(""), *roster->getVersion()); + } + + void testGet_NoVersionInStorage() { + std::shared_ptr<XMPPRosterController> testling(createController()); + testling->setUseVersioning(true); + rosterStorage_->setRoster(std::make_shared<RosterPayload>()); + + testling->requestRoster(); + + std::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>(); + CPPUNIT_ASSERT(roster->getVersion()); + CPPUNIT_ASSERT_EQUAL(std::string(""), *roster->getVersion()); + } + + void testGet_VersionInStorage() { + std::shared_ptr<XMPPRosterController> testling(createController()); + testling->setUseVersioning(true); + std::shared_ptr<RosterPayload> payload(new RosterPayload()); + payload->setVersion("foover"); + rosterStorage_->setRoster(payload); + + testling->requestRoster(); + + std::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>(); + CPPUNIT_ASSERT(roster->getVersion()); + CPPUNIT_ASSERT_EQUAL(std::string("foover"), *roster->getVersion()); + } + + void testGet_ServerDoesNotSupportVersion() { + std::shared_ptr<XMPPRosterController> testling(createController()); + std::shared_ptr<RosterPayload> payload(new RosterPayload()); + payload->setVersion("foover"); + rosterStorage_->setRoster(payload); + + testling->requestRoster(); + + std::shared_ptr<RosterPayload> roster = channel_->sentStanzas[0]->getPayload<RosterPayload>(); + CPPUNIT_ASSERT(!roster->getVersion()); + } + + void testGet_ResponseWithoutNewVersion() { + std::shared_ptr<XMPPRosterController> testling(createController()); + testling->setUseVersioning(true); + std::shared_ptr<RosterPayload> storedRoster(new RosterPayload()); + storedRoster->setVersion("version10"); + storedRoster->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); + storedRoster->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both)); + rosterStorage_->setRoster(storedRoster); + testling->requestRoster(); + + channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), std::shared_ptr<RosterPayload>())); + + CPPUNIT_ASSERT_EQUAL(2, handler_->getEventCount()); + CPPUNIT_ASSERT(xmppRoster_->getItem(jid1_)); + CPPUNIT_ASSERT(xmppRoster_->getItem(jid2_)); + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID()); + CPPUNIT_ASSERT(rosterStorage_->getRoster()); + CPPUNIT_ASSERT(rosterStorage_->getRoster()->getVersion()); + CPPUNIT_ASSERT_EQUAL(std::string("version10"), *rosterStorage_->getRoster()->getVersion()); + CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid1_)); + CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid2_)); + } + + void testGet_ResponseWithNewVersion() { + std::shared_ptr<XMPPRosterController> testling(createController()); + testling->setUseVersioning(true); + std::shared_ptr<RosterPayload> storedRoster(new RosterPayload()); + storedRoster->setVersion("version10"); + storedRoster->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); + rosterStorage_->setRoster(storedRoster); + testling->requestRoster(); + + std::shared_ptr<RosterPayload> serverRoster(new RosterPayload()); + serverRoster->setVersion("version12"); + serverRoster->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both)); + std::vector<std::string> groups; + groups.push_back("foo"); + groups.push_back("bar"); + serverRoster->addItem(RosterItemPayload(jid3_, "Rabbit", RosterItemPayload::Both, groups)); + channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), serverRoster)); + + + CPPUNIT_ASSERT_EQUAL(2, handler_->getEventCount()); + CPPUNIT_ASSERT(!xmppRoster_->getItem(jid1_)); + CPPUNIT_ASSERT(xmppRoster_->getItem(jid2_)); + CPPUNIT_ASSERT(xmppRoster_->getItem(jid3_)); + CPPUNIT_ASSERT_EQUAL(jid3_, handler_->getLastJID()); + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT(rosterStorage_->getRoster()); + CPPUNIT_ASSERT(rosterStorage_->getRoster()->getVersion()); + CPPUNIT_ASSERT_EQUAL(std::string("version12"), *rosterStorage_->getRoster()->getVersion()); + CPPUNIT_ASSERT(!rosterStorage_->getRoster()->getItem(jid1_)); + CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid2_)); + CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid3_)); + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(rosterStorage_->getRoster()->getItem(jid3_)->getGroups().size())); + } + + void testAddFromNonAccount() { + std::shared_ptr<XMPPRosterController> testling(createController()); + + std::shared_ptr<RosterPayload> payload(new RosterPayload()); + payload->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); + IQ::ref request = IQ::createRequest(IQ::Set, JID(), "eou", payload); + request->setFrom(jid2_); + channel_->onIQReceived(request); + + CPPUNIT_ASSERT_EQUAL(None, handler_->getLastEvent()); + } + + void testModify() { + XMPPRosterController controller(router_, xmppRoster_, rosterStorage_); + std::shared_ptr<RosterPayload> payload1(new RosterPayload()); + payload1->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id1", payload1)); + + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + handler_->reset(); + + std::shared_ptr<RosterPayload> payload2(new RosterPayload()); + payload2->addItem(RosterItemPayload(jid1_, "Bob2", RosterItemPayload::Both)); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id2", payload2)); + + CPPUNIT_ASSERT_EQUAL(Update, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + + CPPUNIT_ASSERT_EQUAL(std::string("Bob2"), xmppRoster_->getNameForJID(jid1_)); + } + + void testRemove() { + XMPPRosterController controller(router_, xmppRoster_, rosterStorage_); + std::shared_ptr<RosterPayload> payload1(new RosterPayload()); + payload1->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id1", payload1)); + + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + handler_->reset(); + + std::shared_ptr<RosterPayload> payload2(new RosterPayload()); + payload2->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Remove)); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id2", payload2)); + CPPUNIT_ASSERT(!xmppRoster_->containsJID(jid1_)); + CPPUNIT_ASSERT_EQUAL(Remove, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + + } + + void testRemove_RosterStorageUpdated() { + std::shared_ptr<XMPPRosterController> testling(createController()); + testling->setUseVersioning(true); + std::shared_ptr<RosterPayload> storedRoster(new RosterPayload()); + storedRoster->setVersion("version10"); + storedRoster->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); + storedRoster->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both)); + rosterStorage_->setRoster(storedRoster); + testling->requestRoster(); + channel_->onIQReceived(IQ::createResult("foo@bar.com", channel_->sentStanzas[0]->getID(), std::shared_ptr<RosterPayload>())); + + std::shared_ptr<RosterPayload> payload2(new RosterPayload()); + payload2->setVersion("version15"); + payload2->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Remove)); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id2", payload2)); + + CPPUNIT_ASSERT(rosterStorage_->getRoster()); + CPPUNIT_ASSERT(rosterStorage_->getRoster()->getVersion()); + CPPUNIT_ASSERT_EQUAL(std::string("version15"), *rosterStorage_->getRoster()->getVersion()); + CPPUNIT_ASSERT(!rosterStorage_->getRoster()->getItem(jid1_)); + CPPUNIT_ASSERT(rosterStorage_->getRoster()->getItem(jid2_)); + } + + void testMany() { + XMPPRosterController controller(router_, xmppRoster_, rosterStorage_); + std::shared_ptr<RosterPayload> payload1(new RosterPayload()); + payload1->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Both)); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id1", payload1)); + + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + handler_->reset(); + + std::shared_ptr<RosterPayload> payload2(new RosterPayload()); + payload2->addItem(RosterItemPayload(jid2_, "Alice", RosterItemPayload::Both)); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id2", payload2)); + + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID()); + handler_->reset(); + + std::shared_ptr<RosterPayload> payload3(new RosterPayload()); + payload3->addItem(RosterItemPayload(jid1_, "Ernie", RosterItemPayload::Both)); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id3", payload3)); + + CPPUNIT_ASSERT_EQUAL(Update, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + handler_->reset(); + + std::shared_ptr<RosterPayload> payload4(new RosterPayload()); + RosterItemPayload item(jid3_, "Jane", RosterItemPayload::Both); + std::string janesGroup("Jane's Group"); + item.addGroup(janesGroup); + payload4->addItem(item); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id4", payload4)); + + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid3_, handler_->getLastJID()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), xmppRoster_->getGroupsForJID(jid3_).size()); + CPPUNIT_ASSERT_EQUAL(janesGroup, xmppRoster_->getGroupsForJID(jid3_)[0]); + handler_->reset(); + + std::shared_ptr<RosterPayload> payload5(new RosterPayload()); + payload5->addItem(RosterItemPayload(jid1_, "Bob", RosterItemPayload::Remove)); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id5", payload5)); + CPPUNIT_ASSERT(!xmppRoster_->containsJID(jid1_)); + CPPUNIT_ASSERT_EQUAL(Remove, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + handler_->reset(); + + std::shared_ptr<RosterPayload> payload6(new RosterPayload()); + RosterItemPayload item2(jid2_, "Little Alice", RosterItemPayload::Both); + std::string alicesGroup("Alice's Group"); + item2.addGroup(alicesGroup); + payload6->addItem(item2); + channel_->onIQReceived(IQ::createRequest(IQ::Set, JID(), "id6", payload6)); + CPPUNIT_ASSERT_EQUAL(Update, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID()); + CPPUNIT_ASSERT_EQUAL(std::string("Little Alice"), xmppRoster_->getNameForJID(jid2_)); + CPPUNIT_ASSERT_EQUAL(std::string("Jane"), xmppRoster_->getNameForJID(jid3_)); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), xmppRoster_->getGroupsForJID(jid2_).size()); + CPPUNIT_ASSERT_EQUAL(alicesGroup, xmppRoster_->getGroupsForJID(jid2_)[0]); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), xmppRoster_->getGroupsForJID(jid3_).size()); + CPPUNIT_ASSERT_EQUAL(janesGroup, xmppRoster_->getGroupsForJID(jid3_)[0]); + handler_->reset(); + + } + + private: + XMPPRosterController* createController() { + return new XMPPRosterController(router_, xmppRoster_, rosterStorage_); + } + + private: + DummyStanzaChannel* channel_; + IQRouter* router_; + XMPPRosterImpl* xmppRoster_; + XMPPRosterSignalHandler* handler_; + RosterMemoryStorage* rosterStorage_; + JID jid1_; + JID jid2_; + JID jid3_; }; CPPUNIT_TEST_SUITE_REGISTRATION(XMPPRosterControllerTest); diff --git a/Swiften/Roster/UnitTest/XMPPRosterImplTest.cpp b/Swiften/Roster/UnitTest/XMPPRosterImplTest.cpp index 692779f..4137ebf 100644 --- a/Swiften/Roster/UnitTest/XMPPRosterImplTest.cpp +++ b/Swiften/Roster/UnitTest/XMPPRosterImplTest.cpp @@ -1,112 +1,108 @@ /* - * Copyright (c) 2010-2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/shared_ptr.hpp> -#include <boost/bind.hpp> #include <Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h> #include <Swiften/Roster/XMPPRosterImpl.h> - using namespace Swift; class XMPPRosterImplTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(XMPPRosterImplTest); - CPPUNIT_TEST(testJIDAdded); - CPPUNIT_TEST(testJIDRemoved); - CPPUNIT_TEST(testJIDUpdated); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - jid1_ = JID("a@b.c"); - jid2_ = JID("b@c.d"); - jid3_ = JID("c@d.e"); - roster_ = new XMPPRosterImpl(); - handler_ = new XMPPRosterSignalHandler(roster_); - groups1_.push_back("bobs"); - groups1_.push_back("berts"); - groups2_.push_back("ernies"); - } + CPPUNIT_TEST_SUITE(XMPPRosterImplTest); + CPPUNIT_TEST(testJIDAdded); + CPPUNIT_TEST(testJIDRemoved); + CPPUNIT_TEST(testJIDUpdated); + CPPUNIT_TEST_SUITE_END(); - void tearDown() { - delete handler_; - delete roster_; - } + public: + void setUp() { + jid1_ = JID("a@b.c"); + jid2_ = JID("b@c.d"); + jid3_ = JID("c@d.e"); + roster_ = std::make_unique<XMPPRosterImpl>(); + handler_ = std::make_unique<XMPPRosterSignalHandler>(roster_.get()); + groups1_.push_back("bobs"); + groups1_.push_back("berts"); + groups2_.push_back("ernies"); + } - void testJIDAdded() { - roster_->addContact(jid1_, "NewName", groups1_, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - CPPUNIT_ASSERT_EQUAL(std::string("NewName"), roster_->getNameForJID(jid1_)); - CPPUNIT_ASSERT(groups1_ == roster_->getGroupsForJID(jid1_)); - handler_->reset(); - roster_->addContact(jid2_, "NameTwo", groups1_, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID()); - CPPUNIT_ASSERT_EQUAL(std::string("NameTwo"), roster_->getNameForJID(jid2_)); - CPPUNIT_ASSERT_EQUAL(std::string("NewName"), roster_->getNameForJID(jid1_)); - CPPUNIT_ASSERT(groups1_ == roster_->getGroupsForJID(jid2_)); - CPPUNIT_ASSERT(groups1_ == roster_->getGroupsForJID(jid1_)); - handler_->reset(); - roster_->addContact(jid3_, "NewName", groups2_, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid3_, handler_->getLastJID()); - CPPUNIT_ASSERT_EQUAL(std::string("NewName"), roster_->getNameForJID(jid3_)); - CPPUNIT_ASSERT(groups2_ == roster_->getGroupsForJID(jid3_)); - } + void testJIDAdded() { + roster_->addContact(jid1_, "NewName", groups1_, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + CPPUNIT_ASSERT_EQUAL(std::string("NewName"), roster_->getNameForJID(jid1_)); + CPPUNIT_ASSERT(groups1_ == roster_->getGroupsForJID(jid1_)); + handler_->reset(); + roster_->addContact(jid2_, "NameTwo", groups1_, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID()); + CPPUNIT_ASSERT_EQUAL(std::string("NameTwo"), roster_->getNameForJID(jid2_)); + CPPUNIT_ASSERT_EQUAL(std::string("NewName"), roster_->getNameForJID(jid1_)); + CPPUNIT_ASSERT(groups1_ == roster_->getGroupsForJID(jid2_)); + CPPUNIT_ASSERT(groups1_ == roster_->getGroupsForJID(jid1_)); + handler_->reset(); + roster_->addContact(jid3_, "NewName", groups2_, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid3_, handler_->getLastJID()); + CPPUNIT_ASSERT_EQUAL(std::string("NewName"), roster_->getNameForJID(jid3_)); + CPPUNIT_ASSERT(groups2_ == roster_->getGroupsForJID(jid3_)); + } - void testJIDRemoved() { - roster_->addContact(jid1_, "NewName", groups1_, RosterItemPayload::Both); - handler_->reset(); - roster_->removeContact(jid1_); - CPPUNIT_ASSERT_EQUAL(Remove, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - handler_->reset(); - roster_->addContact(jid1_, "NewName2", groups1_, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - CPPUNIT_ASSERT_EQUAL(std::string("NewName2"), roster_->getNameForJID(jid1_)); - roster_->addContact(jid2_, "NewName3", groups1_, RosterItemPayload::Both); - handler_->reset(); - roster_->removeContact(jid2_); - CPPUNIT_ASSERT_EQUAL(Remove, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID()); - handler_->reset(); - roster_->removeContact(jid1_); - CPPUNIT_ASSERT_EQUAL(Remove, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - } + void testJIDRemoved() { + roster_->addContact(jid1_, "NewName", groups1_, RosterItemPayload::Both); + handler_->reset(); + roster_->removeContact(jid1_); + CPPUNIT_ASSERT_EQUAL(Remove, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + handler_->reset(); + roster_->addContact(jid1_, "NewName2", groups1_, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + CPPUNIT_ASSERT_EQUAL(std::string("NewName2"), roster_->getNameForJID(jid1_)); + roster_->addContact(jid2_, "NewName3", groups1_, RosterItemPayload::Both); + handler_->reset(); + roster_->removeContact(jid2_); + CPPUNIT_ASSERT_EQUAL(Remove, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid2_, handler_->getLastJID()); + handler_->reset(); + roster_->removeContact(jid1_); + CPPUNIT_ASSERT_EQUAL(Remove, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + } - void testJIDUpdated() { - roster_->addContact(jid1_, "NewName", groups1_, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - CPPUNIT_ASSERT_EQUAL(std::string("NewName"), roster_->getNameForJID(jid1_)); - CPPUNIT_ASSERT(groups1_ == roster_->getGroupsForJID(jid1_)); - handler_->reset(); - roster_->addContact(jid1_, "NameTwo", groups2_, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(Update, handler_->getLastEvent()); - CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); - CPPUNIT_ASSERT_EQUAL(std::string("NameTwo"), roster_->getNameForJID(jid1_)); - CPPUNIT_ASSERT(groups2_ == roster_->getGroupsForJID(jid1_)); - } + void testJIDUpdated() { + roster_->addContact(jid1_, "NewName", groups1_, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(Add, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + CPPUNIT_ASSERT_EQUAL(std::string("NewName"), roster_->getNameForJID(jid1_)); + CPPUNIT_ASSERT(groups1_ == roster_->getGroupsForJID(jid1_)); + handler_->reset(); + roster_->addContact(jid1_, "NameTwo", groups2_, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(Update, handler_->getLastEvent()); + CPPUNIT_ASSERT_EQUAL(jid1_, handler_->getLastJID()); + CPPUNIT_ASSERT_EQUAL(std::string("NameTwo"), roster_->getNameForJID(jid1_)); + CPPUNIT_ASSERT(groups2_ == roster_->getGroupsForJID(jid1_)); + } - private: - XMPPRosterImpl* roster_; - XMPPRosterSignalHandler* handler_; - JID jid1_; - JID jid2_; - JID jid3_; - std::vector<std::string> groups1_; - std::vector<std::string> groups2_; + private: + std::unique_ptr<XMPPRosterImpl> roster_; + std::unique_ptr<XMPPRosterSignalHandler> handler_; + JID jid1_; + JID jid2_; + JID jid3_; + std::vector<std::string> groups1_; + std::vector<std::string> groups2_; }; CPPUNIT_TEST_SUITE_REGISTRATION(XMPPRosterImplTest); diff --git a/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.cpp b/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.cpp index d89644a..add34a0 100644 --- a/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.cpp +++ b/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.cpp @@ -1,28 +1,29 @@ /* - * Copyright (c) 2010-2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h> -#include <boost/bind.hpp> #include <cassert> +#include <boost/bind.hpp> + using namespace Swift; XMPPRosterSignalHandler::XMPPRosterSignalHandler(Swift::XMPPRoster* roster) : eventCount(0) { - lastEvent_ = None; - roster->onJIDAdded.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDAdded, this, _1)); - roster->onJIDRemoved.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDRemoved, this, _1)); - roster->onJIDUpdated.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDUpdated, this, _1, _2, _3)); + lastEvent_ = None; + roster->onJIDAdded.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDAdded, this, _1)); + roster->onJIDRemoved.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDRemoved, this, _1)); + roster->onJIDUpdated.connect(boost::bind(&XMPPRosterSignalHandler::handleJIDUpdated, this, _1, _2, _3)); } void XMPPRosterSignalHandler::handleJIDUpdated(const Swift::JID& jid, const std::string& oldName, const std::vector<std::string>& oldGroups) { - assert(lastEvent_ == None); - lastJID_ = jid; - lastOldName_ = oldName; - lastOldGroups_ = oldGroups; - lastEvent_ = Update; - eventCount++; + assert(lastEvent_ == None); + lastJID_ = jid; + lastOldName_ = oldName; + lastOldGroups_ = oldGroups; + lastEvent_ = Update; + eventCount++; } diff --git a/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h b/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h index 5c51ec3..0535578 100644 --- a/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h +++ b/Swiften/Roster/UnitTest/XMPPRosterSignalHandler.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2010-2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <vector> #include <Swiften/Roster/XMPPRosterImpl.h> @@ -15,50 +15,50 @@ enum XMPPRosterEvents {None, Add, Remove, Update}; class XMPPRosterSignalHandler { public: - XMPPRosterSignalHandler(Swift::XMPPRoster* roster); + XMPPRosterSignalHandler(Swift::XMPPRoster* roster); - XMPPRosterEvents getLastEvent() { - return lastEvent_; - } + XMPPRosterEvents getLastEvent() { + return lastEvent_; + } - Swift::JID getLastJID() { - return lastJID_; - } + Swift::JID getLastJID() { + return lastJID_; + } - std::string getLastOldName() { - return lastOldName_; - } + std::string getLastOldName() { + return lastOldName_; + } - std::vector<std::string> getLastOldGroups() { - return lastOldGroups_; - } + std::vector<std::string> getLastOldGroups() { + return lastOldGroups_; + } - void reset() { - lastEvent_ = None; - } + void reset() { + lastEvent_ = None; + } - int getEventCount() const { - return eventCount; - } + int getEventCount() const { + return eventCount; + } private: - void handleJIDAdded(const Swift::JID& jid) { - lastJID_ = jid; - lastEvent_ = Add; - eventCount++; - } + void handleJIDAdded(const Swift::JID& jid) { + lastJID_ = jid; + lastEvent_ = Add; + eventCount++; + } - void handleJIDRemoved(const Swift::JID& jid) { - lastJID_ = jid; - lastEvent_ = Remove; - eventCount++; - } + void handleJIDRemoved(const Swift::JID& jid) { + lastJID_ = jid; + lastEvent_ = Remove; + eventCount++; + } - void handleJIDUpdated(const Swift::JID& jid, const std::string& oldName, const std::vector<std::string>& oldGroups); + void handleJIDUpdated(const Swift::JID& jid, const std::string& oldName, const std::vector<std::string>& oldGroups); - XMPPRosterEvents lastEvent_; - Swift::JID lastJID_; - std::string lastOldName_; - std::vector<std::string> lastOldGroups_; - int eventCount; + XMPPRosterEvents lastEvent_; + Swift::JID lastJID_; + std::string lastOldName_; + std::vector<std::string> lastOldGroups_; + int eventCount; }; diff --git a/Swiften/Roster/XMPPRoster.cpp b/Swiften/Roster/XMPPRoster.cpp index 730569d..d5b4960 100644 --- a/Swiften/Roster/XMPPRoster.cpp +++ b/Swiften/Roster/XMPPRoster.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Roster/XMPPRoster.h> diff --git a/Swiften/Roster/XMPPRoster.h b/Swiften/Roster/XMPPRoster.h index 4b18940..ae2dbc7 100644 --- a/Swiften/Roster/XMPPRoster.h +++ b/Swiften/Roster/XMPPRoster.h @@ -1,96 +1,98 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/optional.hpp> -#include <vector> #include <set> -#include <Swiften/Base/boost_bsignals.h> - #include <string> -#include <Swiften/JID/JID.h> +#include <vector> + +#include <boost/optional.hpp> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/RosterItemPayload.h> +#include <Swiften/JID/JID.h> #include <Swiften/Roster/XMPPRosterItem.h> namespace Swift { - /** - * This class represents the roster of an account, as stored on the XMPP server. - * - * Changes to the roster (either due to subscription requests or by going online/offline) are - * emitted through signals. - */ - class XMPPRoster { - public: - XMPPRoster(); - virtual ~XMPPRoster(); - - /** - * Checks whether the bare jid of the given jid is in the roster. - */ - virtual bool containsJID(const JID& jid) = 0; - - /** - * Retrieves the subscription state for the given jid. - */ - virtual RosterItemPayload::Subscription getSubscriptionStateForJID(const JID& jid) = 0; - - /** - * Retrieves the stored roster name for the given jid. - */ - virtual std::string getNameForJID(const JID& jid) const = 0; - - /** - * Returns the list of groups for the given JID. - */ - virtual std::vector<std::string> getGroupsForJID(const JID& jid) = 0; - - /** - * Retrieve the items in the roster. - */ - virtual std::vector<XMPPRosterItem> getItems() const = 0; - - /** - * Retrieve the item with the given JID. - */ - virtual boost::optional<XMPPRosterItem> getItem(const JID&) const = 0; - - /** - * Retrieve the list of (existing) groups. - */ - virtual std::set<std::string> getGroups() const = 0; - - public: - /** - * Emitted when the given JID is added to the roster. - */ - boost::signal<void (const JID&)> onJIDAdded; - - /** - * Emitted when the given JID is removed from the roster. - */ - boost::signal<void (const JID&)> onJIDRemoved; - - /** - * Emitted when the name or the groups of the roster item with the - * given JID changes. - */ - boost::signal<void (const JID&, const std::string&, const std::vector<std::string>&)> onJIDUpdated; - - /** - * Emitted when the roster is reset (e.g. due to logging in/logging out). - * After this signal is emitted, the roster is empty. It will be repopulated through - * onJIDAdded and onJIDRemoved events. - */ - boost::signal<void ()> onRosterCleared; - - /** - * Emitted after the last contact of the initial roster request response - * was added. - */ - boost::signal<void ()> onInitialRosterPopulated; - }; + /** + * This class represents the roster of an account, as stored on the XMPP server. + * + * Changes to the roster (either due to subscription requests or by going online/offline) are + * emitted through signals. + */ + class SWIFTEN_API XMPPRoster { + public: + XMPPRoster(); + virtual ~XMPPRoster(); + + /** + * Checks whether the bare jid of the given jid is in the roster. + */ + virtual bool containsJID(const JID& jid) = 0; + + /** + * Retrieves the subscription state for the given jid. + */ + virtual RosterItemPayload::Subscription getSubscriptionStateForJID(const JID& jid) = 0; + + /** + * Retrieves the stored roster name for the given jid. + */ + virtual std::string getNameForJID(const JID& jid) const = 0; + + /** + * Returns the list of groups for the given JID. + */ + virtual std::vector<std::string> getGroupsForJID(const JID& jid) = 0; + + /** + * Retrieve the items in the roster. + */ + virtual std::vector<XMPPRosterItem> getItems() const = 0; + + /** + * Retrieve the item with the given JID. + */ + virtual boost::optional<XMPPRosterItem> getItem(const JID&) const = 0; + + /** + * Retrieve the list of (existing) groups. + */ + virtual std::set<std::string> getGroups() const = 0; + + public: + /** + * Emitted when the given JID is added to the roster. + */ + boost::signals2::signal<void (const JID&)> onJIDAdded; + + /** + * Emitted when the given JID is removed from the roster. + */ + boost::signals2::signal<void (const JID&)> onJIDRemoved; + + /** + * Emitted when the name or the groups of the roster item with the + * given JID changes. + */ + boost::signals2::signal<void (const JID&, const std::string&, const std::vector<std::string>&)> onJIDUpdated; + + /** + * Emitted when the roster is reset (e.g. due to logging in/logging out). + * After this signal is emitted, the roster is empty. It will be repopulated through + * onJIDAdded and onJIDRemoved events. + */ + boost::signals2::signal<void ()> onRosterCleared; + + /** + * Emitted after the last contact of the initial roster request response + * was added. + */ + boost::signals2::signal<void ()> onInitialRosterPopulated; + }; } diff --git a/Swiften/Roster/XMPPRosterController.cpp b/Swiften/Roster/XMPPRosterController.cpp index c34c6ec..2b98b53 100644 --- a/Swiften/Roster/XMPPRosterController.cpp +++ b/Swiften/Roster/XMPPRosterController.cpp @@ -1,92 +1,91 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Roster/XMPPRosterController.h> #include <boost/bind.hpp> -#include <iostream> -#include <Swiften/Base/foreach.h> +#include <Swiften/Base/Log.h> #include <Swiften/Elements/RosterItemPayload.h> #include <Swiften/Queries/IQRouter.h> #include <Swiften/Roster/GetRosterRequest.h> -#include <Swiften/Roster/XMPPRosterImpl.h> #include <Swiften/Roster/RosterStorage.h> +#include <Swiften/Roster/XMPPRosterImpl.h> namespace Swift { - + /** * The controller does not gain ownership of these parameters. */ XMPPRosterController::XMPPRosterController(IQRouter* iqRouter, XMPPRosterImpl* xmppRoster, RosterStorage* rosterStorage) : iqRouter_(iqRouter), rosterPushResponder_(iqRouter), xmppRoster_(xmppRoster), rosterStorage_(rosterStorage), useVersioning(false) { - rosterPushResponder_.onRosterReceived.connect(boost::bind(&XMPPRosterController::handleRosterReceived, this, _1, false, boost::shared_ptr<RosterPayload>())); - rosterPushResponder_.start(); + rosterPushResponder_.onRosterReceived.connect(boost::bind(&XMPPRosterController::handleRosterReceived, this, _1, false, std::shared_ptr<RosterPayload>())); + rosterPushResponder_.start(); } XMPPRosterController::~XMPPRosterController() { - rosterPushResponder_.stop(); + rosterPushResponder_.stop(); } void XMPPRosterController::requestRoster() { - xmppRoster_->clear(); + xmppRoster_->clear(); - boost::shared_ptr<RosterPayload> storedRoster = rosterStorage_->getRoster(); - GetRosterRequest::ref rosterRequest; - if (useVersioning) { - std::string version = ""; - if (storedRoster && storedRoster->getVersion()) { - version = *storedRoster->getVersion(); - } - rosterRequest = GetRosterRequest::create(iqRouter_, version); - } - else { - rosterRequest = GetRosterRequest::create(iqRouter_); - } - rosterRequest->onResponse.connect(boost::bind(&XMPPRosterController::handleRosterReceived, this, _1, true, storedRoster)); - rosterRequest->send(); + std::shared_ptr<RosterPayload> storedRoster = rosterStorage_->getRoster(); + GetRosterRequest::ref rosterRequest; + if (useVersioning) { + std::string version = ""; + if (storedRoster && storedRoster->getVersion()) { + version = *storedRoster->getVersion(); + } + rosterRequest = GetRosterRequest::create(iqRouter_, version); + } + else { + rosterRequest = GetRosterRequest::create(iqRouter_); + } + rosterRequest->onResponse.connect(boost::bind(&XMPPRosterController::handleRosterReceived, this, _1, true, storedRoster)); + rosterRequest->send(); } -void XMPPRosterController::handleRosterReceived(boost::shared_ptr<RosterPayload> rosterPayload, bool initial, boost::shared_ptr<RosterPayload> previousRoster) { - if (rosterPayload) { - foreach(const RosterItemPayload& item, rosterPayload->getItems()) { - //Don't worry about the updated case, the XMPPRoster sorts that out. - if (item.getSubscription() == RosterItemPayload::Remove) { - xmppRoster_->removeContact(item.getJID()); - } else { - xmppRoster_->addContact(item.getJID(), item.getName(), item.getGroups(), item.getSubscription()); - } - } - } - else if (previousRoster) { - // The cached version hasn't changed; emit all items - foreach(const RosterItemPayload& item, previousRoster->getItems()) { - if (item.getSubscription() != RosterItemPayload::Remove) { - xmppRoster_->addContact(item.getJID(), item.getName(), item.getGroups(), item.getSubscription()); - } - else { - std::cerr << "ERROR: Stored invalid roster item" << std::endl; - } - } - } - if (initial) { - xmppRoster_->onInitialRosterPopulated(); - } - if (rosterPayload && rosterPayload->getVersion() && useVersioning) { - saveRoster(*rosterPayload->getVersion()); - } +void XMPPRosterController::handleRosterReceived(std::shared_ptr<RosterPayload> rosterPayload, bool initial, std::shared_ptr<RosterPayload> previousRoster) { + if (rosterPayload) { + for (const auto& item : rosterPayload->getItems()) { + //Don't worry about the updated case, the XMPPRoster sorts that out. + if (item.getSubscription() == RosterItemPayload::Remove) { + xmppRoster_->removeContact(item.getJID()); + } else { + xmppRoster_->addContact(item.getJID(), item.getName(), item.getGroups(), item.getSubscription()); + } + } + } + else if (previousRoster) { + // The cached version hasn't changed; emit all items + for (const auto& item : previousRoster->getItems()) { + if (item.getSubscription() != RosterItemPayload::Remove) { + xmppRoster_->addContact(item.getJID(), item.getName(), item.getGroups(), item.getSubscription()); + } + else { + SWIFT_LOG(error) << "Stored invalid roster item"; + } + } + } + if (initial) { + xmppRoster_->onInitialRosterPopulated(); + } + if (rosterPayload && rosterPayload->getVersion() && useVersioning) { + saveRoster(*rosterPayload->getVersion()); + } } void XMPPRosterController::saveRoster(const std::string& version) { - std::vector<XMPPRosterItem> items = xmppRoster_->getItems(); - boost::shared_ptr<RosterPayload> roster(new RosterPayload()); - roster->setVersion(version); - foreach(const XMPPRosterItem& item, items) { - roster->addItem(RosterItemPayload(item.getJID(), item.getName(), item.getSubscription(), item.getGroups())); - } - rosterStorage_->setRoster(roster); + std::vector<XMPPRosterItem> items = xmppRoster_->getItems(); + std::shared_ptr<RosterPayload> roster(new RosterPayload()); + roster->setVersion(version); + for (const auto& item : items) { + roster->addItem(RosterItemPayload(item.getJID(), item.getName(), item.getSubscription(), item.getGroups())); + } + rosterStorage_->setRoster(roster); } } diff --git a/Swiften/Roster/XMPPRosterController.h b/Swiften/Roster/XMPPRosterController.h index 603f350..f952c60 100644 --- a/Swiften/Roster/XMPPRosterController.h +++ b/Swiften/Roster/XMPPRosterController.h @@ -1,47 +1,48 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/JID/JID.h> -#include <string> #include <Swiften/Elements/IQ.h> #include <Swiften/Elements/RosterPayload.h> +#include <Swiften/JID/JID.h> #include <Swiften/Roster/RosterPushResponder.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class IQRouter; - class XMPPRosterImpl; - class RosterStorage; - - class SWIFTEN_API XMPPRosterController { - public: - XMPPRosterController(IQRouter *iqRouter, XMPPRosterImpl* xmppRoster, RosterStorage* storage); - ~XMPPRosterController(); - - void requestRoster(); - - void setUseVersioning(bool b) { - useVersioning = b; - } - - private: - void handleRosterReceived(boost::shared_ptr<RosterPayload> rosterPayload, bool initial, boost::shared_ptr<RosterPayload> previousRoster); - void saveRoster(const std::string& version); - - private: - IQRouter* iqRouter_; - RosterPushResponder rosterPushResponder_; - XMPPRosterImpl* xmppRoster_; - RosterStorage* rosterStorage_; - bool useVersioning; - }; + class IQRouter; + class XMPPRosterImpl; + class RosterStorage; + + class SWIFTEN_API XMPPRosterController { + public: + XMPPRosterController(IQRouter *iqRouter, XMPPRosterImpl* xmppRoster, RosterStorage* storage); + ~XMPPRosterController(); + + void requestRoster(); + + void setUseVersioning(bool b) { + useVersioning = b; + } + + private: + void handleRosterReceived(std::shared_ptr<RosterPayload> rosterPayload, bool initial, std::shared_ptr<RosterPayload> previousRoster); + void saveRoster(const std::string& version); + + private: + IQRouter* iqRouter_; + RosterPushResponder rosterPushResponder_; + XMPPRosterImpl* xmppRoster_; + RosterStorage* rosterStorage_; + bool useVersioning; + }; } diff --git a/Swiften/Roster/XMPPRosterImpl.cpp b/Swiften/Roster/XMPPRosterImpl.cpp index 8086806..74f634f 100644 --- a/Swiften/Roster/XMPPRosterImpl.cpp +++ b/Swiften/Roster/XMPPRosterImpl.cpp @@ -1,101 +1,104 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Roster/XMPPRosterImpl.h> -#include <Swiften/Base/foreach.h> namespace Swift { XMPPRosterImpl::XMPPRosterImpl() { } +XMPPRosterImpl::~XMPPRosterImpl() { + +} + void XMPPRosterImpl::addContact(const JID& jid, const std::string& name, const std::vector<std::string>& groups, RosterItemPayload::Subscription subscription) { - JID bareJID(jid.toBare()); - std::map<JID, XMPPRosterItem>::iterator i = entries_.find(bareJID); - if (i != entries_.end()) { - std::string oldName = i->second.getName(); - std::vector<std::string> oldGroups = i->second.getGroups(); - i->second = XMPPRosterItem(jid, name, groups, subscription); - onJIDUpdated(bareJID, oldName, oldGroups); - } - else { - entries_.insert(std::make_pair(bareJID, XMPPRosterItem(jid, name, groups, subscription))); - onJIDAdded(bareJID); - } + JID bareJID(jid.toBare()); + std::map<JID, XMPPRosterItem>::iterator i = entries_.find(bareJID); + if (i != entries_.end()) { + std::string oldName = i->second.getName(); + std::vector<std::string> oldGroups = i->second.getGroups(); + i->second = XMPPRosterItem(jid, name, groups, subscription); + onJIDUpdated(bareJID, oldName, oldGroups); + } + else { + entries_.insert(std::make_pair(bareJID, XMPPRosterItem(jid, name, groups, subscription))); + onJIDAdded(bareJID); + } } void XMPPRosterImpl::removeContact(const JID& jid) { - entries_.erase(JID(jid.toBare())); - onJIDRemoved(jid); + entries_.erase(JID(jid.toBare())); + onJIDRemoved(jid); } void XMPPRosterImpl::clear() { - entries_.clear(); - onRosterCleared(); + entries_.clear(); + onRosterCleared(); } bool XMPPRosterImpl::containsJID(const JID& jid) { - return entries_.find(JID(jid.toBare())) != entries_.end(); + return entries_.find(JID(jid.toBare())) != entries_.end(); } std::string XMPPRosterImpl::getNameForJID(const JID& jid) const { - std::map<JID, XMPPRosterItem>::const_iterator i = entries_.find(jid.toBare()); - if (i != entries_.end()) { - return i->second.getName(); - } - else { - return ""; - } + std::map<JID, XMPPRosterItem>::const_iterator i = entries_.find(jid.toBare()); + if (i != entries_.end()) { + return i->second.getName(); + } + else { + return ""; + } } std::vector<std::string> XMPPRosterImpl::getGroupsForJID(const JID& jid) { - std::map<JID, XMPPRosterItem>::iterator i = entries_.find(jid.toBare()); - if (i != entries_.end()) { - return i->second.getGroups(); - } - else { - return std::vector<std::string>(); - } + std::map<JID, XMPPRosterItem>::iterator i = entries_.find(jid.toBare()); + if (i != entries_.end()) { + return i->second.getGroups(); + } + else { + return std::vector<std::string>(); + } } RosterItemPayload::Subscription XMPPRosterImpl::getSubscriptionStateForJID(const JID& jid) { - std::map<JID, XMPPRosterItem>::iterator i = entries_.find(jid.toBare()); - if (i != entries_.end()) { - return i->second.getSubscription(); - } - else { - return RosterItemPayload::None; - } + std::map<JID, XMPPRosterItem>::iterator i = entries_.find(jid.toBare()); + if (i != entries_.end()) { + return i->second.getSubscription(); + } + else { + return RosterItemPayload::None; + } } std::vector<XMPPRosterItem> XMPPRosterImpl::getItems() const { - std::vector<XMPPRosterItem> result; - foreach(const RosterMap::value_type& entry, entries_) { - result.push_back(entry.second); - } - return result; + std::vector<XMPPRosterItem> result; + for (const auto& entry : entries_) { + result.push_back(entry.second); + } + return result; } boost::optional<XMPPRosterItem> XMPPRosterImpl::getItem(const JID& jid) const { - std::map<JID, XMPPRosterItem>::const_iterator i = entries_.find(jid.toBare()); - if (i != entries_.end()) { - return i->second; - } - else { - return boost::optional<XMPPRosterItem>(); - } + std::map<JID, XMPPRosterItem>::const_iterator i = entries_.find(jid.toBare()); + if (i != entries_.end()) { + return i->second; + } + else { + return boost::optional<XMPPRosterItem>(); + } } std::set<std::string> XMPPRosterImpl::getGroups() const { - std::set<std::string> result; - foreach(const RosterMap::value_type& entry, entries_) { - std::vector<std::string> groups = entry.second.getGroups(); - result.insert(groups.begin(), groups.end()); - } - return result; + std::set<std::string> result; + for (const auto& entry : entries_) { + std::vector<std::string> groups = entry.second.getGroups(); + result.insert(groups.begin(), groups.end()); + } + return result; } } diff --git a/Swiften/Roster/XMPPRosterImpl.h b/Swiften/Roster/XMPPRosterImpl.h index 8c8cf3e..28e3919 100644 --- a/Swiften/Roster/XMPPRosterImpl.h +++ b/Swiften/Roster/XMPPRosterImpl.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -13,25 +13,26 @@ #include <Swiften/Roster/XMPPRoster.h> namespace Swift { - class SWIFTEN_API XMPPRosterImpl : public XMPPRoster { - public: - XMPPRosterImpl(); - - void addContact(const JID& jid, const std::string& name, const std::vector<std::string>& groups, const RosterItemPayload::Subscription subscription); - void removeContact(const JID& jid); - void clear(); - - bool containsJID(const JID& jid); - RosterItemPayload::Subscription getSubscriptionStateForJID(const JID& jid); - std::string getNameForJID(const JID& jid) const; - std::vector<std::string> getGroupsForJID(const JID& jid); - - virtual std::vector<XMPPRosterItem> getItems() const; - virtual boost::optional<XMPPRosterItem> getItem(const JID&) const; - virtual std::set<std::string> getGroups() const; - - private: - typedef std::map<JID, XMPPRosterItem> RosterMap; - RosterMap entries_; - }; + class SWIFTEN_API XMPPRosterImpl : public XMPPRoster { + public: + XMPPRosterImpl(); + virtual ~XMPPRosterImpl(); + + void addContact(const JID& jid, const std::string& name, const std::vector<std::string>& groups, RosterItemPayload::Subscription subscription); + void removeContact(const JID& jid); + void clear(); + + bool containsJID(const JID& jid); + RosterItemPayload::Subscription getSubscriptionStateForJID(const JID& jid); + std::string getNameForJID(const JID& jid) const; + std::vector<std::string> getGroupsForJID(const JID& jid); + + virtual std::vector<XMPPRosterItem> getItems() const; + virtual boost::optional<XMPPRosterItem> getItem(const JID&) const; + virtual std::set<std::string> getGroups() const; + + private: + typedef std::map<JID, XMPPRosterItem> RosterMap; + RosterMap entries_; + }; } diff --git a/Swiften/Roster/XMPPRosterItem.h b/Swiften/Roster/XMPPRosterItem.h index c821cbf..53b3781 100644 --- a/Swiften/Roster/XMPPRosterItem.h +++ b/Swiften/Roster/XMPPRosterItem.h @@ -1,53 +1,53 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once - +#include <string> #include <vector> -#include <string> -#include <Swiften/JID/JID.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/RosterItemPayload.h> +#include <Swiften/JID/JID.h> namespace Swift { - class XMPPRosterItem { - public: - XMPPRosterItem(const JID& jid, const std::string& name, const std::vector<std::string>& groups, RosterItemPayload::Subscription subscription) : jid(jid), name(name), groups(groups), subscription(subscription) { - } - - const JID& getJID() const { - return jid; - } - - const std::string& getName() const { - return name; - } - - void setName(const std::string& name) { - this->name = name; - } - - const std::vector<std::string>& getGroups() const { - return groups; - } - - void setGroups(const std::vector<std::string>& groups) { - this->groups = groups; - } - - RosterItemPayload::Subscription getSubscription() const { - return subscription; - } - - private: - JID jid; - std::string name; - std::vector<std::string> groups; - RosterItemPayload::Subscription subscription; - }; + class SWIFTEN_API XMPPRosterItem { + public: + XMPPRosterItem(const JID& jid, const std::string& name, const std::vector<std::string>& groups, RosterItemPayload::Subscription subscription) : jid(jid), name(name), groups(groups), subscription(subscription) { + } + + const JID& getJID() const { + return jid; + } + + const std::string& getName() const { + return name; + } + + void setName(const std::string& name) { + this->name = name; + } + + const std::vector<std::string>& getGroups() const { + return groups; + } + + void setGroups(const std::vector<std::string>& groups) { + this->groups = groups; + } + + RosterItemPayload::Subscription getSubscription() const { + return subscription; + } + + private: + JID jid; + std::string name; + std::vector<std::string> groups; + RosterItemPayload::Subscription subscription; + }; } diff --git a/Swiften/SASL/ClientAuthenticator.cpp b/Swiften/SASL/ClientAuthenticator.cpp index e0900a3..9ad1d9b 100644 --- a/Swiften/SASL/ClientAuthenticator.cpp +++ b/Swiften/SASL/ClientAuthenticator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/SASL/ClientAuthenticator.h> diff --git a/Swiften/SASL/ClientAuthenticator.h b/Swiften/SASL/ClientAuthenticator.h index bc5b4f1..b22a81d 100644 --- a/Swiften/SASL/ClientAuthenticator.h +++ b/Swiften/SASL/ClientAuthenticator.h @@ -1,54 +1,55 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/optional.hpp> #include <string> #include <vector> +#include <boost/optional.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/SafeByteArray.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/SafeByteArray.h> namespace Swift { - class SWIFTEN_API ClientAuthenticator { - public: - ClientAuthenticator(const std::string& name); - virtual ~ClientAuthenticator(); - - const std::string& getName() const { - return name; - } - - void setCredentials(const std::string& authcid, const SafeByteArray& password, const std::string& authzid = std::string()) { - this->authcid = authcid; - this->password = password; - this->authzid = authzid; - } - - virtual boost::optional<SafeByteArray> getResponse() const = 0; - virtual bool setChallenge(const boost::optional<ByteArray>&) = 0; - - const std::string& getAuthenticationID() const { - return authcid; - } - - const std::string& getAuthorizationID() const { - return authzid; - } - - const SafeByteArray& getPassword() const { - return password; - } - - private: - std::string name; - std::string authcid; - SafeByteArray password; - std::string authzid; - }; + class SWIFTEN_API ClientAuthenticator { + public: + ClientAuthenticator(const std::string& name); + virtual ~ClientAuthenticator(); + + const std::string& getName() const { + return name; + } + + void setCredentials(const std::string& authcid, const SafeByteArray& password, const std::string& authzid = std::string()) { + this->authcid = authcid; + this->password = password; + this->authzid = authzid; + } + + virtual boost::optional<SafeByteArray> getResponse() const = 0; + virtual bool setChallenge(const boost::optional<ByteArray>&) = 0; + + const std::string& getAuthenticationID() const { + return authcid; + } + + const std::string& getAuthorizationID() const { + return authzid; + } + + const SafeByteArray& getPassword() const { + return password; + } + + private: + std::string name; + std::string authcid; + SafeByteArray password; + std::string authzid; + }; } diff --git a/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp b/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp index 74cdb85..a736a77 100644 --- a/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp +++ b/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp @@ -1,17 +1,17 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/SASL/DIGESTMD5ClientAuthenticator.h> #include <cassert> -#include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/Base/Concat.h> #include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/Concat.h> #include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/StringCodecs/Hexify.h> namespace Swift { @@ -19,78 +19,78 @@ DIGESTMD5ClientAuthenticator::DIGESTMD5ClientAuthenticator(const std::string& ho } boost::optional<SafeByteArray> DIGESTMD5ClientAuthenticator::getResponse() const { - if (step == Initial) { - return boost::optional<SafeByteArray>(); - } - else if (step == Response) { - std::string realm; - if (challenge.getValue("realm")) { - realm = *challenge.getValue("realm"); - } - std::string qop = "auth"; - std::string digestURI = "xmpp/" + host; - std::string nc = "00000001"; + if (step == Initial) { + return boost::optional<SafeByteArray>(); + } + else if (step == Response) { + std::string realm; + if (challenge.getValue("realm")) { + realm = *challenge.getValue("realm"); + } + std::string qop = "auth"; + std::string digestURI = "xmpp/" + host; + std::string nc = "00000001"; - // Compute the response value - ByteArray A1 = concat( - crypto->getMD5Hash( - concat(createSafeByteArray(getAuthenticationID().c_str()), createSafeByteArray(":"), createSafeByteArray(realm.c_str()), createSafeByteArray(":"), getPassword())), - createByteArray(":"), createByteArray(*challenge.getValue("nonce")), createByteArray(":"), createByteArray(cnonce)); - if (!getAuthorizationID().empty()) { - append(A1, createByteArray(":" + getAuthenticationID())); - } - ByteArray A2 = createByteArray("AUTHENTICATE:" + digestURI); + // Compute the response value + ByteArray A1 = concat( + crypto->getMD5Hash( + concat(createSafeByteArray(getAuthenticationID().c_str()), createSafeByteArray(":"), createSafeByteArray(realm.c_str()), createSafeByteArray(":"), getPassword())), + createByteArray(":"), createByteArray(*challenge.getValue("nonce")), createByteArray(":"), createByteArray(cnonce)); + if (!getAuthorizationID().empty()) { + append(A1, createByteArray(":" + getAuthenticationID())); + } + ByteArray A2 = createByteArray("AUTHENTICATE:" + digestURI); - std::string responseValue = Hexify::hexify(crypto->getMD5Hash(createByteArray( - Hexify::hexify(crypto->getMD5Hash(A1)) + ":" - + *challenge.getValue("nonce") + ":" + nc + ":" + cnonce + ":" + qop + ":" - + Hexify::hexify(crypto->getMD5Hash(A2))))); + std::string responseValue = Hexify::hexify(crypto->getMD5Hash(createByteArray( + Hexify::hexify(crypto->getMD5Hash(A1)) + ":" + + *challenge.getValue("nonce") + ":" + nc + ":" + cnonce + ":" + qop + ":" + + Hexify::hexify(crypto->getMD5Hash(A2))))); - DIGESTMD5Properties response; - response.setValue("username", getAuthenticationID()); - if (!realm.empty()) { - response.setValue("realm", realm); - } - response.setValue("nonce", *challenge.getValue("nonce")); - response.setValue("cnonce", cnonce); - response.setValue("nc", "00000001"); - response.setValue("qop", qop); - response.setValue("digest-uri", digestURI); - response.setValue("charset", "utf-8"); - response.setValue("response", responseValue); - if (!getAuthorizationID().empty()) { - response.setValue("authzid", getAuthorizationID()); - } - return createSafeByteArray(response.serialize()); - } - else { - return boost::optional<SafeByteArray>(); - } + DIGESTMD5Properties response; + response.setValue("username", getAuthenticationID()); + if (!realm.empty()) { + response.setValue("realm", realm); + } + response.setValue("nonce", *challenge.getValue("nonce")); + response.setValue("cnonce", cnonce); + response.setValue("nc", "00000001"); + response.setValue("qop", qop); + response.setValue("digest-uri", digestURI); + response.setValue("charset", "utf-8"); + response.setValue("response", responseValue); + if (!getAuthorizationID().empty()) { + response.setValue("authzid", getAuthorizationID()); + } + return createSafeByteArray(response.serialize()); + } + else { + return boost::optional<SafeByteArray>(); + } } bool DIGESTMD5ClientAuthenticator::setChallenge(const boost::optional<ByteArray>& challengeData) { - if (step == Initial) { - if (!challengeData) { - return false; - } - challenge = DIGESTMD5Properties::parse(*challengeData); + if (step == Initial) { + if (!challengeData) { + return false; + } + challenge = DIGESTMD5Properties::parse(*challengeData); - // Sanity checks - if (!challenge.getValue("nonce")) { - return false; - } - if (!challenge.getValue("charset") || *challenge.getValue("charset") != "utf-8") { - return false; - } - step = Response; - return true; - } - else { - step = Final; - // TODO: Check RSPAuth - return true; - } + // Sanity checks + if (!challenge.getValue("nonce")) { + return false; + } + if (!challenge.getValue("charset") || *challenge.getValue("charset") != "utf-8") { + return false; + } + step = Response; + return true; + } + else { + step = Final; + // TODO: Check RSPAuth + return true; + } } } diff --git a/Swiften/SASL/DIGESTMD5ClientAuthenticator.h b/Swiften/SASL/DIGESTMD5ClientAuthenticator.h index d141401..4a857d3 100644 --- a/Swiften/SASL/DIGESTMD5ClientAuthenticator.h +++ b/Swiften/SASL/DIGESTMD5ClientAuthenticator.h @@ -1,39 +1,39 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <map> - #include <string> #include <vector> + #include <Swiften/Base/API.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/SASL/ClientAuthenticator.h> #include <Swiften/SASL/DIGESTMD5Properties.h> -#include <Swiften/Base/SafeByteArray.h> namespace Swift { - class CryptoProvider; + class CryptoProvider; + + class SWIFTEN_API DIGESTMD5ClientAuthenticator : public ClientAuthenticator { + public: + DIGESTMD5ClientAuthenticator(const std::string& host, const std::string& nonce, CryptoProvider*); - class SWIFTEN_API DIGESTMD5ClientAuthenticator : public ClientAuthenticator { - public: - DIGESTMD5ClientAuthenticator(const std::string& host, const std::string& nonce, CryptoProvider*); - - virtual boost::optional<SafeByteArray> getResponse() const; - virtual bool setChallenge(const boost::optional<std::vector<unsigned char> >&); + virtual boost::optional<SafeByteArray> getResponse() const; + virtual bool setChallenge(const boost::optional<std::vector<unsigned char> >&); - private: - enum Step { - Initial, - Response, - Final - } step; - std::string host; - std::string cnonce; - CryptoProvider* crypto; - DIGESTMD5Properties challenge; - }; + private: + enum Step { + Initial, + Response, + Final + } step; + std::string host; + std::string cnonce; + CryptoProvider* crypto; + DIGESTMD5Properties challenge; + }; } diff --git a/Swiften/SASL/DIGESTMD5Properties.cpp b/Swiften/SASL/DIGESTMD5Properties.cpp index 23a3476..1f33c8f 100644 --- a/Swiften/SASL/DIGESTMD5Properties.cpp +++ b/Swiften/SASL/DIGESTMD5Properties.cpp @@ -1,130 +1,131 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/SASL/DIGESTMD5Properties.h> + #include <Swiften/Base/Algorithm.h> namespace Swift { namespace { - bool insideQuotes(const ByteArray& v) { - if (v.empty()) { - return false; - } - else if (v.size() == 1) { - return v[0] == '"'; - } - else if (v[0] == '"') { - return v[v.size() - 1] != '"'; - } - else { - return false; - } - } + bool insideQuotes(const ByteArray& v) { + if (v.empty()) { + return false; + } + else if (v.size() == 1) { + return v[0] == '"'; + } + else if (v[0] == '"') { + return v[v.size() - 1] != '"'; + } + else { + return false; + } + } - ByteArray stripQuotes(const ByteArray& v) { - const char* data = reinterpret_cast<const char*>(vecptr(v)); - size_t size = v.size(); - if (v[0] == '"') { - data++; - size--; - } - if (v[v.size() - 1] == '"') { - size--; - } - return createByteArray(data, size); - } + ByteArray stripQuotes(const ByteArray& v) { + const char* data = reinterpret_cast<const char*>(vecptr(v)); + size_t size = v.size(); + if (v[0] == '"') { + data++; + size--; + } + if (v[v.size() - 1] == '"') { + size--; + } + return createByteArray(data, size); + } } DIGESTMD5Properties::DIGESTMD5Properties() { } DIGESTMD5Properties DIGESTMD5Properties::parse(const ByteArray& data) { - DIGESTMD5Properties result; - bool inKey = true; - ByteArray currentKey; - ByteArray currentValue; - for (size_t i = 0; i < data.size(); ++i) { - char c = static_cast<char>(data[i]); - if (inKey) { - if (c == '=') { - inKey = false; - } - else { - currentKey.push_back(static_cast<unsigned char>(c)); - } - } - else { - if (c == ',' && !insideQuotes(currentValue)) { - std::string key = byteArrayToString(currentKey); - if (isQuoted(key)) { - result.setValue(key, byteArrayToString(stripQuotes(currentValue))); - } - else { - result.setValue(key, byteArrayToString(currentValue)); - } - inKey = true; - currentKey = ByteArray(); - currentValue = ByteArray(); - } - else { - currentValue.push_back(static_cast<unsigned char>(c)); - } - } - } + DIGESTMD5Properties result; + bool inKey = true; + ByteArray currentKey; + ByteArray currentValue; + for (unsigned char i : data) { + char c = static_cast<char>(i); + if (inKey) { + if (c == '=') { + inKey = false; + } + else { + currentKey.push_back(static_cast<unsigned char>(c)); + } + } + else { + if (c == ',' && !insideQuotes(currentValue)) { + std::string key = byteArrayToString(currentKey); + if (isQuoted(key)) { + result.setValue(key, byteArrayToString(stripQuotes(currentValue))); + } + else { + result.setValue(key, byteArrayToString(currentValue)); + } + inKey = true; + currentKey = ByteArray(); + currentValue = ByteArray(); + } + else { + currentValue.push_back(static_cast<unsigned char>(c)); + } + } + } - if (!currentKey.empty()) { - std::string key = byteArrayToString(currentKey); - if (isQuoted(key)) { - result.setValue(key, byteArrayToString(stripQuotes(currentValue))); - } - else { - result.setValue(key, byteArrayToString(currentValue)); - } - } + if (!currentKey.empty()) { + std::string key = byteArrayToString(currentKey); + if (isQuoted(key)) { + result.setValue(key, byteArrayToString(stripQuotes(currentValue))); + } + else { + result.setValue(key, byteArrayToString(currentValue)); + } + } - return result; + return result; } ByteArray DIGESTMD5Properties::serialize() const { - ByteArray result; - for(DIGESTMD5PropertiesMap::const_iterator i = properties.begin(); i != properties.end(); ++i) { - if (i != properties.begin()) { - result.push_back(','); - } - append(result, createByteArray(i->first)); - result.push_back('='); - if (isQuoted(i->first)) { - append(result, createByteArray("\"")); - append(result, i->second); - append(result, createByteArray("\"")); - } - else { - append(result, i->second); - } - } - return result; + ByteArray result; + for(DIGESTMD5PropertiesMap::const_iterator i = properties.begin(); i != properties.end(); ++i) { + if (i != properties.begin()) { + result.push_back(','); + } + append(result, createByteArray(i->first)); + result.push_back('='); + if (isQuoted(i->first)) { + append(result, createByteArray("\"")); + append(result, i->second); + append(result, createByteArray("\"")); + } + else { + append(result, i->second); + } + } + return result; } boost::optional<std::string> DIGESTMD5Properties::getValue(const std::string& key) const { - DIGESTMD5PropertiesMap::const_iterator i = properties.find(key); - if (i != properties.end()) { - return byteArrayToString(i->second); - } - else { - return boost::optional<std::string>(); - } + DIGESTMD5PropertiesMap::const_iterator i = properties.find(key); + if (i != properties.end()) { + return byteArrayToString(i->second); + } + else { + return boost::optional<std::string>(); + } } void DIGESTMD5Properties::setValue(const std::string& key, const std::string& value) { - properties.insert(DIGESTMD5PropertiesMap::value_type(key, createByteArray(value))); + properties.insert(DIGESTMD5PropertiesMap::value_type(key, createByteArray(value))); } bool DIGESTMD5Properties::isQuoted(const std::string& p) { - return p == "authzid" || p == "cnonce" || p == "digest-uri" || p == "nonce" || p == "realm" || p == "username"; + return p == "authzid" || p == "cnonce" || p == "digest-uri" || p == "nonce" || p == "realm" || p == "username"; } } diff --git a/Swiften/SASL/DIGESTMD5Properties.h b/Swiften/SASL/DIGESTMD5Properties.h index 654208d..a4d2d65 100644 --- a/Swiften/SASL/DIGESTMD5Properties.h +++ b/Swiften/SASL/DIGESTMD5Properties.h @@ -1,36 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <map> +#include <string> + #include <boost/optional.hpp> -#include <string> #include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> namespace Swift { - class SWIFTEN_API DIGESTMD5Properties { - public: - DIGESTMD5Properties(); - - boost::optional<std::string> getValue(const std::string& key) const; + class SWIFTEN_API DIGESTMD5Properties { + public: + DIGESTMD5Properties(); + + boost::optional<std::string> getValue(const std::string& key) const; - void setValue(const std::string& key, const std::string& value); + void setValue(const std::string& key, const std::string& value); - ByteArray serialize() const; + ByteArray serialize() const; - static DIGESTMD5Properties parse(const ByteArray&); + static DIGESTMD5Properties parse(const ByteArray&); - private: - static bool isQuoted(const std::string& property); + private: + static bool isQuoted(const std::string& property); - private: - typedef std::multimap<std::string, ByteArray> DIGESTMD5PropertiesMap; - DIGESTMD5PropertiesMap properties; - }; + private: + typedef std::multimap<std::string, ByteArray> DIGESTMD5PropertiesMap; + DIGESTMD5PropertiesMap properties; + }; } diff --git a/Swiften/SASL/EXTERNALClientAuthenticator.cpp b/Swiften/SASL/EXTERNALClientAuthenticator.cpp index a3016d1..027bc89 100644 --- a/Swiften/SASL/EXTERNALClientAuthenticator.cpp +++ b/Swiften/SASL/EXTERNALClientAuthenticator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/SASL/EXTERNALClientAuthenticator.h> @@ -12,15 +12,21 @@ EXTERNALClientAuthenticator::EXTERNALClientAuthenticator() : ClientAuthenticator } boost::optional<SafeByteArray> EXTERNALClientAuthenticator::getResponse() const { - return boost::optional<SafeByteArray>(); + const std::string& authorizationID = getAuthorizationID(); + + if (authorizationID.empty()) { + return boost::optional<SafeByteArray>(); + } else { + return createSafeByteArray(authorizationID); + } } bool EXTERNALClientAuthenticator::setChallenge(const boost::optional<ByteArray>&) { - if (finished) { - return false; - } - finished = true; - return true; + if (finished) { + return false; + } + finished = true; + return true; } } diff --git a/Swiften/SASL/EXTERNALClientAuthenticator.h b/Swiften/SASL/EXTERNALClientAuthenticator.h index b986295..e42e3fd 100644 --- a/Swiften/SASL/EXTERNALClientAuthenticator.h +++ b/Swiften/SASL/EXTERNALClientAuthenticator.h @@ -1,23 +1,24 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/SASL/ClientAuthenticator.h> +#include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/SASL/ClientAuthenticator.h> namespace Swift { - class EXTERNALClientAuthenticator : public ClientAuthenticator { - public: - EXTERNALClientAuthenticator(); + class SWIFTEN_API EXTERNALClientAuthenticator : public ClientAuthenticator { + public: + EXTERNALClientAuthenticator(); - virtual boost::optional<SafeByteArray> getResponse() const; - virtual bool setChallenge(const boost::optional<ByteArray>&); + virtual boost::optional<SafeByteArray> getResponse() const; + virtual bool setChallenge(const boost::optional<ByteArray>&); - private: - bool finished; - }; + private: + bool finished; + }; } diff --git a/Swiften/SASL/PLAINClientAuthenticator.cpp b/Swiften/SASL/PLAINClientAuthenticator.cpp index 7872174..11bd14c 100644 --- a/Swiften/SASL/PLAINClientAuthenticator.cpp +++ b/Swiften/SASL/PLAINClientAuthenticator.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/SASL/PLAINClientAuthenticator.h> + #include <Swiften/Base/Concat.h> namespace Swift { @@ -13,11 +14,11 @@ PLAINClientAuthenticator::PLAINClientAuthenticator() : ClientAuthenticator("PLAI } boost::optional<SafeByteArray> PLAINClientAuthenticator::getResponse() const { - return concat(createSafeByteArray(getAuthorizationID()), createSafeByteArray('\0'), createSafeByteArray(getAuthenticationID()), createSafeByteArray('\0'), getPassword()); + return concat(createSafeByteArray(getAuthorizationID()), createSafeByteArray('\0'), createSafeByteArray(getAuthenticationID()), createSafeByteArray('\0'), getPassword()); } bool PLAINClientAuthenticator::setChallenge(const boost::optional<ByteArray>&) { - return true; + return true; } } diff --git a/Swiften/SASL/PLAINClientAuthenticator.h b/Swiften/SASL/PLAINClientAuthenticator.h index ad3a695..64ef741 100644 --- a/Swiften/SASL/PLAINClientAuthenticator.h +++ b/Swiften/SASL/PLAINClientAuthenticator.h @@ -1,21 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/SASL/ClientAuthenticator.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/SASL/ClientAuthenticator.h> namespace Swift { - class SWIFTEN_API PLAINClientAuthenticator : public ClientAuthenticator { - public: - PLAINClientAuthenticator(); + class SWIFTEN_API PLAINClientAuthenticator : public ClientAuthenticator { + public: + PLAINClientAuthenticator(); - virtual boost::optional<SafeByteArray> getResponse() const; - virtual bool setChallenge(const boost::optional<ByteArray>&); - }; + virtual boost::optional<SafeByteArray> getResponse() const; + virtual bool setChallenge(const boost::optional<ByteArray>&); + }; } diff --git a/Swiften/SASL/PLAINMessage.cpp b/Swiften/SASL/PLAINMessage.cpp index c43b446..a55f604 100644 --- a/Swiften/SASL/PLAINMessage.cpp +++ b/Swiften/SASL/PLAINMessage.cpp @@ -1,10 +1,11 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/SASL/PLAINMessage.h> + #include <Swiften/Base/Concat.h> namespace Swift { @@ -13,32 +14,32 @@ PLAINMessage::PLAINMessage(const std::string& authcid, const SafeByteArray& pass } PLAINMessage::PLAINMessage(const SafeByteArray& value) { - size_t i = 0; - while (i < value.size() && value[i] != '\0') { - authzid += static_cast<char>(value[i]); - ++i; - } - if (i == value.size()) { - return; - } - ++i; - while (i < value.size() && value[i] != '\0') { - authcid += static_cast<char>(value[i]); - ++i; - } - if (i == value.size()) { - authcid = ""; - return; - } - ++i; - while (i < value.size()) { - password.push_back(value[i]); - ++i; - } + size_t i = 0; + while (i < value.size() && value[i] != '\0') { + authzid += static_cast<char>(value[i]); + ++i; + } + if (i == value.size()) { + return; + } + ++i; + while (i < value.size() && value[i] != '\0') { + authcid += static_cast<char>(value[i]); + ++i; + } + if (i == value.size()) { + authcid = ""; + return; + } + ++i; + while (i < value.size()) { + password.push_back(value[i]); + ++i; + } } SafeByteArray PLAINMessage::getValue() const { - return concat(createSafeByteArray(authzid), createSafeByteArray('\0'), createSafeByteArray(authcid), createSafeByteArray('\0'), password); + return concat(createSafeByteArray(authzid), createSafeByteArray('\0'), createSafeByteArray(authcid), createSafeByteArray('\0'), password); } } diff --git a/Swiften/SASL/PLAINMessage.h b/Swiften/SASL/PLAINMessage.h index 3811b31..80479f9 100644 --- a/Swiften/SASL/PLAINMessage.h +++ b/Swiften/SASL/PLAINMessage.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ // TODO: Get rid of this @@ -14,28 +14,28 @@ #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class SWIFTEN_API PLAINMessage { - public: - PLAINMessage(const std::string& authcid, const SafeByteArray& password, const std::string& authzid = ""); - PLAINMessage(const SafeByteArray& value); - - SafeByteArray getValue() const; - - const std::string& getAuthenticationID() const { - return authcid; - } - - const SafeByteArray& getPassword() const { - return password; - } - - const std::string& getAuthorizationID() const { - return authzid; - } - - private: - std::string authcid; - std::string authzid; - SafeByteArray password; - }; + class SWIFTEN_API PLAINMessage { + public: + PLAINMessage(const std::string& authcid, const SafeByteArray& password, const std::string& authzid = ""); + PLAINMessage(const SafeByteArray& value); + + SafeByteArray getValue() const; + + const std::string& getAuthenticationID() const { + return authcid; + } + + const SafeByteArray& getPassword() const { + return password; + } + + const std::string& getAuthorizationID() const { + return authzid; + } + + private: + std::string authcid; + std::string authzid; + SafeByteArray password; + }; } diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp index 44fef76..3c00402 100644 --- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp +++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/SASL/SCRAMSHA1ClientAuthenticator.h> #include <cassert> #include <map> + #include <boost/lexical_cast.hpp> +#include <Swiften/Base/Concat.h> #include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/IDN/IDNConverter.h> #include <Swiften/StringCodecs/Base64.h> #include <Swiften/StringCodecs/PBKDF2.h> -#include <Swiften/IDN/IDNConverter.h> -#include <Swiften/Base/Concat.h> namespace Swift { static std::string escape(const std::string& s) { - std::string result; - for (size_t i = 0; i < s.size(); ++i) { - if (s[i] == ',') { - result += "=2C"; - } - else if (s[i] == '=') { - result += "=3D"; - } - else { - result += s[i]; - } - } - return result; + std::string result; + for (char i : s) { + if (i == ',') { + result += "=2C"; + } + else if (i == '=') { + result += "=3D"; + } + else { + result += i; + } + } + return result; } @@ -39,144 +40,144 @@ SCRAMSHA1ClientAuthenticator::SCRAMSHA1ClientAuthenticator(const std::string& no } boost::optional<SafeByteArray> SCRAMSHA1ClientAuthenticator::getResponse() const { - if (step == Initial) { - return createSafeByteArray(concat(getGS2Header(), getInitialBareClientMessage())); - } - else if (step == Proof) { - ByteArray clientKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Client Key")); - ByteArray storedKey = crypto->getSHA1Hash(clientKey); - ByteArray clientSignature = crypto->getHMACSHA1(createSafeByteArray(storedKey), authMessage); - ByteArray clientProof = clientKey; - for (unsigned int i = 0; i < clientProof.size(); ++i) { - clientProof[i] ^= clientSignature[i]; - } - ByteArray result = concat(getFinalMessageWithoutProof(), createByteArray(",p="), createByteArray(Base64::encode(clientProof))); - return createSafeByteArray(result); - } - else { - return boost::optional<SafeByteArray>(); - } + if (step == Initial) { + return createSafeByteArray(concat(getGS2Header(), getInitialBareClientMessage())); + } + else if (step == Proof) { + ByteArray clientKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Client Key")); + ByteArray storedKey = crypto->getSHA1Hash(clientKey); + ByteArray clientSignature = crypto->getHMACSHA1(createSafeByteArray(storedKey), authMessage); + ByteArray clientProof = clientKey; + for (unsigned int i = 0; i < clientProof.size(); ++i) { + clientProof[i] ^= clientSignature[i]; + } + ByteArray result = concat(getFinalMessageWithoutProof(), createByteArray(",p="), createByteArray(Base64::encode(clientProof))); + return createSafeByteArray(result); + } + else { + return boost::optional<SafeByteArray>(); + } } bool SCRAMSHA1ClientAuthenticator::setChallenge(const boost::optional<ByteArray>& challenge) { - if (step == Initial) { - if (!challenge) { - return false; - } - initialServerMessage = *challenge; - - std::map<char, std::string> keys = parseMap(byteArrayToString(initialServerMessage)); - - // Extract the salt - ByteArray salt = Base64::decode(keys['s']); - - // Extract the server nonce - std::string clientServerNonce = keys['r']; - if (clientServerNonce.size() <= clientnonce.size()) { - return false; - } - std::string receivedClientNonce = clientServerNonce.substr(0, clientnonce.size()); - if (receivedClientNonce != clientnonce) { - return false; - } - serverNonce = createByteArray(clientServerNonce.substr(clientnonce.size(), clientServerNonce.npos)); - - // Extract the number of iterations - int iterations = 0; - try { - iterations = boost::lexical_cast<int>(keys['i']); - } - catch (const boost::bad_lexical_cast&) { - return false; - } - if (iterations <= 0) { - return false; - } - - // Compute all the values needed for the server signature - try { - saltedPassword = PBKDF2::encode(idnConverter->getStringPrepared(getPassword(), IDNConverter::SASLPrep), salt, iterations, crypto); - } - catch (const std::exception&) { - } - authMessage = concat(getInitialBareClientMessage(), createByteArray(","), initialServerMessage, createByteArray(","), getFinalMessageWithoutProof()); - ByteArray serverKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Server Key")); - serverSignature = crypto->getHMACSHA1(serverKey, authMessage); - - step = Proof; - return true; - } - else if (step == Proof) { - ByteArray result = concat(createByteArray("v="), createByteArray(Base64::encode(serverSignature))); - step = Final; - return challenge && challenge == result; - } - else { - return true; - } + if (step == Initial) { + if (!challenge) { + return false; + } + initialServerMessage = *challenge; + + std::map<char, std::string> keys = parseMap(byteArrayToString(initialServerMessage)); + + // Extract the salt + ByteArray salt = Base64::decode(keys['s']); + + // Extract the server nonce + std::string clientServerNonce = keys['r']; + if (clientServerNonce.size() <= clientnonce.size()) { + return false; + } + std::string receivedClientNonce = clientServerNonce.substr(0, clientnonce.size()); + if (receivedClientNonce != clientnonce) { + return false; + } + serverNonce = createByteArray(clientServerNonce.substr(clientnonce.size(), clientServerNonce.npos)); + + // Extract the number of iterations + int iterations = 0; + try { + iterations = boost::lexical_cast<int>(keys['i']); + } + catch (const boost::bad_lexical_cast&) { + return false; + } + if (iterations <= 0) { + return false; + } + + // Compute all the values needed for the server signature + try { + saltedPassword = PBKDF2::encode(idnConverter->getStringPrepared(getPassword(), IDNConverter::SASLPrep), salt, iterations, crypto); + } + catch (const std::exception&) { + } + authMessage = concat(getInitialBareClientMessage(), createByteArray(","), initialServerMessage, createByteArray(","), getFinalMessageWithoutProof()); + ByteArray serverKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Server Key")); + serverSignature = crypto->getHMACSHA1(serverKey, authMessage); + + step = Proof; + return true; + } + else if (step == Proof) { + ByteArray result = concat(createByteArray("v="), createByteArray(Base64::encode(serverSignature))); + step = Final; + return challenge && challenge == result; + } + else { + return true; + } } std::map<char, std::string> SCRAMSHA1ClientAuthenticator::parseMap(const std::string& s) { - std::map<char, std::string> result; - if (s.size() > 0) { - char key = 0; - std::string value; - size_t i = 0; - bool expectKey = true; - while (i < s.size()) { - if (expectKey) { - key = s[i]; - expectKey = false; - i++; - } - else if (s[i] == ',') { - result[key] = value; - value = ""; - expectKey = true; - } - else { - value += s[i]; - } - i++; - } - result[key] = value; - } - return result; + std::map<char, std::string> result; + if (s.size() > 0) { + char key = 0; + std::string value; + size_t i = 0; + bool expectKey = true; + while (i < s.size()) { + if (expectKey) { + key = s[i]; + expectKey = false; + i++; + } + else if (s[i] == ',') { + result[key] = value; + value = ""; + expectKey = true; + } + else { + value += s[i]; + } + i++; + } + result[key] = value; + } + return result; } ByteArray SCRAMSHA1ClientAuthenticator::getInitialBareClientMessage() const { - std::string authenticationID; - try { - authenticationID = idnConverter->getStringPrepared(getAuthenticationID(), IDNConverter::SASLPrep); - } - catch (const std::exception&) { - } - return createByteArray(std::string("n=" + escape(authenticationID) + ",r=" + clientnonce)); + std::string authenticationID; + try { + authenticationID = idnConverter->getStringPrepared(getAuthenticationID(), IDNConverter::SASLPrep); + } + catch (const std::exception&) { + } + return createByteArray(std::string("n=" + escape(authenticationID) + ",r=" + clientnonce)); } ByteArray SCRAMSHA1ClientAuthenticator::getGS2Header() const { - ByteArray channelBindingHeader(createByteArray("n")); - if (tlsChannelBindingData) { - if (useChannelBinding) { - channelBindingHeader = createByteArray("p=tls-unique"); - } - else { - channelBindingHeader = createByteArray("y"); - } - } - return concat(channelBindingHeader, createByteArray(","), (getAuthorizationID().empty() ? ByteArray() : createByteArray("a=" + escape(getAuthorizationID()))), createByteArray(",")); + ByteArray channelBindingHeader(createByteArray("n")); + if (tlsChannelBindingData) { + if (useChannelBinding) { + channelBindingHeader = createByteArray("p=tls-unique"); + } + else { + channelBindingHeader = createByteArray("y"); + } + } + return concat(channelBindingHeader, createByteArray(","), (getAuthorizationID().empty() ? ByteArray() : createByteArray("a=" + escape(getAuthorizationID()))), createByteArray(",")); } void SCRAMSHA1ClientAuthenticator::setTLSChannelBindingData(const ByteArray& channelBindingData) { - this->tlsChannelBindingData = channelBindingData; + this->tlsChannelBindingData = channelBindingData; } ByteArray SCRAMSHA1ClientAuthenticator::getFinalMessageWithoutProof() const { - ByteArray channelBindData; - if (useChannelBinding && tlsChannelBindingData) { - channelBindData = *tlsChannelBindingData; - } - return concat(createByteArray("c=" + Base64::encode(concat(getGS2Header(), channelBindData)) + ",r=" + clientnonce), serverNonce); + ByteArray channelBindData; + if (useChannelBinding && tlsChannelBindingData) { + channelBindData = *tlsChannelBindingData; + } + return concat(createByteArray("c=" + Base64::encode(concat(getGS2Header(), channelBindData)) + ",r=" + clientnonce), serverNonce); } diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h index b713f9f..5dc169a 100644 --- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h +++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h @@ -1,54 +1,55 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <map> +#include <string> + #include <boost/optional.hpp> -#include <string> +#include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/SASL/ClientAuthenticator.h> -#include <Swiften/Base/API.h> namespace Swift { - class IDNConverter; - class CryptoProvider; - - class SWIFTEN_API SCRAMSHA1ClientAuthenticator : public ClientAuthenticator { - public: - SCRAMSHA1ClientAuthenticator(const std::string& nonce, bool useChannelBinding, IDNConverter*, CryptoProvider*); - - void setTLSChannelBindingData(const ByteArray& channelBindingData); - - virtual boost::optional<SafeByteArray> getResponse() const; - virtual bool setChallenge(const boost::optional<ByteArray>&); - - private: - ByteArray getInitialBareClientMessage() const; - ByteArray getGS2Header() const; - ByteArray getFinalMessageWithoutProof() const; - - static std::map<char, std::string> parseMap(const std::string&); - - private: - enum Step { - Initial, - Proof, - Final - } step; - std::string clientnonce; - ByteArray initialServerMessage; - ByteArray serverNonce; - ByteArray authMessage; - ByteArray saltedPassword; - ByteArray serverSignature; - bool useChannelBinding; - IDNConverter* idnConverter; - CryptoProvider* crypto; - boost::optional<ByteArray> tlsChannelBindingData; - }; + class IDNConverter; + class CryptoProvider; + + class SWIFTEN_API SCRAMSHA1ClientAuthenticator : public ClientAuthenticator { + public: + SCRAMSHA1ClientAuthenticator(const std::string& nonce, bool useChannelBinding, IDNConverter*, CryptoProvider*); + + void setTLSChannelBindingData(const ByteArray& channelBindingData); + + virtual boost::optional<SafeByteArray> getResponse() const; + virtual bool setChallenge(const boost::optional<ByteArray>&); + + private: + ByteArray getInitialBareClientMessage() const; + ByteArray getGS2Header() const; + ByteArray getFinalMessageWithoutProof() const; + + static std::map<char, std::string> parseMap(const std::string&); + + private: + enum Step { + Initial, + Proof, + Final + } step; + std::string clientnonce; + ByteArray initialServerMessage; + ByteArray serverNonce; + ByteArray authMessage; + ByteArray saltedPassword; + ByteArray serverSignature; + bool useChannelBinding; + IDNConverter* idnConverter; + CryptoProvider* crypto; + boost::optional<ByteArray> tlsChannelBindingData; + }; } diff --git a/Swiften/SASL/SConscript b/Swiften/SASL/SConscript index 6509547..8a248cc 100644 --- a/Swiften/SASL/SConscript +++ b/Swiften/SASL/SConscript @@ -3,20 +3,32 @@ Import("swiften_env", "env") myenv = swiften_env.Clone() objects = myenv.SwiftenObject([ - "ClientAuthenticator.cpp", - "EXTERNALClientAuthenticator.cpp", - "PLAINClientAuthenticator.cpp", - "PLAINMessage.cpp", - "SCRAMSHA1ClientAuthenticator.cpp", - "DIGESTMD5Properties.cpp", - "DIGESTMD5ClientAuthenticator.cpp", - ]) + "ClientAuthenticator.cpp", + "EXTERNALClientAuthenticator.cpp", + "PLAINClientAuthenticator.cpp", + "PLAINMessage.cpp", + "SCRAMSHA1ClientAuthenticator.cpp", + "DIGESTMD5Properties.cpp", + "DIGESTMD5ClientAuthenticator.cpp", + ]) +if myenv["PLATFORM"] == "win32" : + objects += myenv.SwiftenObject([ + "WindowsServicePrincipalName.cpp", + "WindowsAuthentication.cpp", + "WindowsGSSAPIClientAuthenticator.cpp" + ]) + swiften_env.Append(SWIFTEN_OBJECTS = [objects]) env.Append(UNITTEST_SOURCES = [ - File("UnitTest/PLAINMessageTest.cpp"), - File("UnitTest/PLAINClientAuthenticatorTest.cpp"), - File("UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp"), - File("UnitTest/DIGESTMD5PropertiesTest.cpp"), - File("UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp"), - ]) + File("UnitTest/PLAINMessageTest.cpp"), + File("UnitTest/PLAINClientAuthenticatorTest.cpp"), + File("UnitTest/EXTERNALClientAuthenticatorTest.cpp"), + File("UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp"), + File("UnitTest/DIGESTMD5PropertiesTest.cpp"), + File("UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp"), + ]) +if myenv["PLATFORM"] == "win32" : + env.Append(UNITTEST_SOURCES = [ + File("UnitTest/WindowsServicePrincipalNameTest.cpp"), + ]) diff --git a/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp b/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp index 94bcd0a..d29af59 100644 --- a/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp +++ b/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <QA/Checker/IO.h> @@ -9,63 +9,62 @@ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/SASL/DIGESTMD5ClientAuthenticator.h> #include <Swiften/Base/ByteArray.h> - #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/SASL/DIGESTMD5ClientAuthenticator.h> using namespace Swift; class DIGESTMD5ClientAuthenticatorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DIGESTMD5ClientAuthenticatorTest); - CPPUNIT_TEST(testGetInitialResponse); - CPPUNIT_TEST(testGetResponse); - CPPUNIT_TEST(testGetResponse_WithAuthorizationID); - //CPPUNIT_TEST(testSetChallenge); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - } - - void testGetInitialResponse() { - DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get()); - - CPPUNIT_ASSERT(!testling.getResponse()); - } - - void testGetResponse() { - DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get()); - - testling.setCredentials("user", createSafeByteArray("pass"), ""); - testling.setChallenge(createByteArray( - "realm=\"example.com\"," - "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," - "qop=auth,charset=utf-8,algorithm=md5-sess")); - - SafeByteArray response = *testling.getResponse(); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("charset=utf-8,cnonce=\"abcdefgh\",digest-uri=\"xmpp/xmpp.example.com\",nc=00000001,nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\",qop=auth,realm=\"example.com\",response=088891c800ecff1b842159ad6459104a,username=\"user\""), response); - } - - void testGetResponse_WithAuthorizationID() { - DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get()); - - testling.setCredentials("user", createSafeByteArray("pass"), "myauthzid"); - testling.setChallenge(createByteArray( - "realm=\"example.com\"," - "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," - "qop=auth,charset=utf-8,algorithm=md5-sess")); - - SafeByteArray response = *testling.getResponse(); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("authzid=\"myauthzid\",charset=utf-8,cnonce=\"abcdefgh\",digest-uri=\"xmpp/xmpp.example.com\",nc=00000001,nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\",qop=auth,realm=\"example.com\",response=4293834432b6e7889a2dee7e8fe7dd06,username=\"user\""), response); - } - - private: - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(DIGESTMD5ClientAuthenticatorTest); + CPPUNIT_TEST(testGetInitialResponse); + CPPUNIT_TEST(testGetResponse); + CPPUNIT_TEST(testGetResponse_WithAuthorizationID); + //CPPUNIT_TEST(testSetChallenge); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } + + void testGetInitialResponse() { + DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get()); + + CPPUNIT_ASSERT(!testling.getResponse()); + } + + void testGetResponse() { + DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get()); + + testling.setCredentials("user", createSafeByteArray("pass"), ""); + testling.setChallenge(createByteArray( + "realm=\"example.com\"," + "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," + "qop=auth,charset=utf-8,algorithm=md5-sess")); + + SafeByteArray response = *testling.getResponse(); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("charset=utf-8,cnonce=\"abcdefgh\",digest-uri=\"xmpp/xmpp.example.com\",nc=00000001,nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\",qop=auth,realm=\"example.com\",response=088891c800ecff1b842159ad6459104a,username=\"user\""), response); + } + + void testGetResponse_WithAuthorizationID() { + DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get()); + + testling.setCredentials("user", createSafeByteArray("pass"), "myauthzid"); + testling.setChallenge(createByteArray( + "realm=\"example.com\"," + "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," + "qop=auth,charset=utf-8,algorithm=md5-sess")); + + SafeByteArray response = *testling.getResponse(); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("authzid=\"myauthzid\",charset=utf-8,cnonce=\"abcdefgh\",digest-uri=\"xmpp/xmpp.example.com\",nc=00000001,nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\",qop=auth,realm=\"example.com\",response=4293834432b6e7889a2dee7e8fe7dd06,username=\"user\""), response); + } + + private: + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(DIGESTMD5ClientAuthenticatorTest); diff --git a/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp b/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp index d664f14..841f580 100644 --- a/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp +++ b/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -12,44 +12,44 @@ using namespace Swift; class DIGESTMD5PropertiesTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DIGESTMD5PropertiesTest); - CPPUNIT_TEST(testParse); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); - - public: - void testParse() { - DIGESTMD5Properties properties = DIGESTMD5Properties::parse(createByteArray( - "realm=\"myrealm1\",realm=\"myrealm2\",nonce=\"mynonce\"," - "algorithm=md5-sess,charset=utf-8")); - - CPPUNIT_ASSERT(properties.getValue("realm")); - CPPUNIT_ASSERT_EQUAL(std::string("myrealm1"), *properties.getValue("realm")); - CPPUNIT_ASSERT(properties.getValue("nonce")); - CPPUNIT_ASSERT_EQUAL(std::string("mynonce"), *properties.getValue("nonce")); - CPPUNIT_ASSERT(properties.getValue("algorithm")); - CPPUNIT_ASSERT_EQUAL(std::string("md5-sess"), *properties.getValue("algorithm")); - CPPUNIT_ASSERT(properties.getValue("charset")); - CPPUNIT_ASSERT_EQUAL(std::string("utf-8"), *properties.getValue("charset")); - } - - void testSerialize() { - DIGESTMD5Properties properties; - properties.setValue("authzid", "myauthzid"); - properties.setValue("charset", "utf-8"); - properties.setValue("cnonce", "mycnonce"); - properties.setValue("digest-uri", "mydigesturi"); - properties.setValue("nc", "1"); - properties.setValue("nonce", "mynonce"); - properties.setValue("qop", "auth"); - properties.setValue("realm", "myrealm"); - properties.setValue("response", "myresponse"); - properties.setValue("username", "myuser"); - - ByteArray result = properties.serialize(); - ByteArray expected(createByteArray("authzid=\"myauthzid\",charset=utf-8,cnonce=\"mycnonce\",digest-uri=\"mydigesturi\",nc=1,nonce=\"mynonce\",qop=auth,realm=\"myrealm\",response=myresponse,username=\"myuser\"")); - CPPUNIT_ASSERT_EQUAL(byteArrayToString(expected), byteArrayToString(result)); - } + CPPUNIT_TEST_SUITE(DIGESTMD5PropertiesTest); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); + + public: + void testParse() { + DIGESTMD5Properties properties = DIGESTMD5Properties::parse(createByteArray( + "realm=\"myrealm1\",realm=\"myrealm2\",nonce=\"mynonce\"," + "algorithm=md5-sess,charset=utf-8")); + + CPPUNIT_ASSERT(properties.getValue("realm")); + CPPUNIT_ASSERT_EQUAL(std::string("myrealm1"), *properties.getValue("realm")); + CPPUNIT_ASSERT(properties.getValue("nonce")); + CPPUNIT_ASSERT_EQUAL(std::string("mynonce"), *properties.getValue("nonce")); + CPPUNIT_ASSERT(properties.getValue("algorithm")); + CPPUNIT_ASSERT_EQUAL(std::string("md5-sess"), *properties.getValue("algorithm")); + CPPUNIT_ASSERT(properties.getValue("charset")); + CPPUNIT_ASSERT_EQUAL(std::string("utf-8"), *properties.getValue("charset")); + } + + void testSerialize() { + DIGESTMD5Properties properties; + properties.setValue("authzid", "myauthzid"); + properties.setValue("charset", "utf-8"); + properties.setValue("cnonce", "mycnonce"); + properties.setValue("digest-uri", "mydigesturi"); + properties.setValue("nc", "1"); + properties.setValue("nonce", "mynonce"); + properties.setValue("qop", "auth"); + properties.setValue("realm", "myrealm"); + properties.setValue("response", "myresponse"); + properties.setValue("username", "myuser"); + + ByteArray result = properties.serialize(); + ByteArray expected(createByteArray("authzid=\"myauthzid\",charset=utf-8,cnonce=\"mycnonce\",digest-uri=\"mydigesturi\",nc=1,nonce=\"mynonce\",qop=auth,realm=\"myrealm\",response=myresponse,username=\"myuser\"")); + CPPUNIT_ASSERT_EQUAL(byteArrayToString(expected), byteArrayToString(result)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(DIGESTMD5PropertiesTest); diff --git a/Swiften/SASL/UnitTest/EXTERNALClientAuthenticatorTest.cpp b/Swiften/SASL/UnitTest/EXTERNALClientAuthenticatorTest.cpp new file mode 100644 index 0000000..728eed6 --- /dev/null +++ b/Swiften/SASL/UnitTest/EXTERNALClientAuthenticatorTest.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <QA/Checker/IO.h> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/SASL/EXTERNALClientAuthenticator.h> + +using namespace Swift; + +class EXTERNALClientAuthenticatorTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(EXTERNALClientAuthenticatorTest); + CPPUNIT_TEST(testGetResponse_WithoutAuthzID); + CPPUNIT_TEST(testGetResponse_WithAuthzID); + CPPUNIT_TEST_SUITE_END(); + + public: + void testGetResponse_WithoutAuthzID() { + EXTERNALClientAuthenticator testling; + + // Authcid and password are not used (ignored) + testling.setCredentials("user", createSafeByteArray("pass")); + + boost::optional<SafeByteArray> response = testling.getResponse(); + + // No data should have been returned + bool result = !response; + + CPPUNIT_ASSERT(result); + } + + void testGetResponse_WithAuthzID() { + EXTERNALClientAuthenticator testling; + + // Authcid and password are not used (ignored) + testling.setCredentials("user", createSafeByteArray("pass"), "authz"); + + CPPUNIT_ASSERT_EQUAL(*testling.getResponse(), createSafeByteArray("authz", 5)); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(EXTERNALClientAuthenticatorTest); diff --git a/Swiften/SASL/UnitTest/PLAINClientAuthenticatorTest.cpp b/Swiften/SASL/UnitTest/PLAINClientAuthenticatorTest.cpp index 3416923..070b4d9 100644 --- a/Swiften/SASL/UnitTest/PLAINClientAuthenticatorTest.cpp +++ b/Swiften/SASL/UnitTest/PLAINClientAuthenticatorTest.cpp @@ -1,39 +1,40 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/SASL/PLAINClientAuthenticator.h> - #include <QA/Checker/IO.h> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <Swiften/SASL/PLAINClientAuthenticator.h> + using namespace Swift; class PLAINClientAuthenticatorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PLAINClientAuthenticatorTest); - CPPUNIT_TEST(testGetResponse_WithoutAuthzID); - CPPUNIT_TEST(testGetResponse_WithAuthzID); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(PLAINClientAuthenticatorTest); + CPPUNIT_TEST(testGetResponse_WithoutAuthzID); + CPPUNIT_TEST(testGetResponse_WithAuthzID); + CPPUNIT_TEST_SUITE_END(); - public: - void testGetResponse_WithoutAuthzID() { - PLAINClientAuthenticator testling; + public: + void testGetResponse_WithoutAuthzID() { + PLAINClientAuthenticator testling; - testling.setCredentials("user", createSafeByteArray("pass")); + testling.setCredentials("user", createSafeByteArray("pass")); - CPPUNIT_ASSERT_EQUAL(*testling.getResponse(), createSafeByteArray("\0user\0pass", 10)); - } + CPPUNIT_ASSERT_EQUAL(*testling.getResponse(), createSafeByteArray("\0user\0pass", 10)); + } - void testGetResponse_WithAuthzID() { - PLAINClientAuthenticator testling; + void testGetResponse_WithAuthzID() { + PLAINClientAuthenticator testling; - testling.setCredentials("user", createSafeByteArray("pass"), "authz"); + testling.setCredentials("user", createSafeByteArray("pass"), "authz"); - CPPUNIT_ASSERT_EQUAL(*testling.getResponse(), createSafeByteArray("authz\0user\0pass", 15)); - } + CPPUNIT_ASSERT_EQUAL(*testling.getResponse(), createSafeByteArray("authz\0user\0pass", 15)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(PLAINClientAuthenticatorTest); diff --git a/Swiften/SASL/UnitTest/PLAINMessageTest.cpp b/Swiften/SASL/UnitTest/PLAINMessageTest.cpp index e917af5..271b827 100644 --- a/Swiften/SASL/UnitTest/PLAINMessageTest.cpp +++ b/Swiften/SASL/UnitTest/PLAINMessageTest.cpp @@ -1,70 +1,70 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/SASL/PLAINMessage.h> using namespace Swift; class PLAINMessageTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PLAINMessageTest); - CPPUNIT_TEST(testGetValue_WithoutAuthzID); - CPPUNIT_TEST(testGetValue_WithAuthzID); - CPPUNIT_TEST(testConstructor_WithoutAuthzID); - CPPUNIT_TEST(testConstructor_WithAuthzID); - CPPUNIT_TEST(testConstructor_NoAuthcid); - CPPUNIT_TEST(testConstructor_NoPassword); - CPPUNIT_TEST_SUITE_END(); - - public: - PLAINMessageTest() {} - - void testGetValue_WithoutAuthzID() { - PLAINMessage message("user", createSafeByteArray("pass")); - CPPUNIT_ASSERT_EQUAL(message.getValue(), createSafeByteArray("\0user\0pass", 10)); - } - - void testGetValue_WithAuthzID() { - PLAINMessage message("user", createSafeByteArray("pass"), "authz"); - CPPUNIT_ASSERT_EQUAL(message.getValue(), createSafeByteArray("authz\0user\0pass", 15)); - } - - void testConstructor_WithoutAuthzID() { - PLAINMessage message(createSafeByteArray("\0user\0pass", 10)); - - CPPUNIT_ASSERT_EQUAL(std::string(""), message.getAuthorizationID()); - CPPUNIT_ASSERT_EQUAL(std::string("user"), message.getAuthenticationID()); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("pass"), message.getPassword()); - } - - void testConstructor_WithAuthzID() { - PLAINMessage message(createSafeByteArray("authz\0user\0pass", 15)); - - CPPUNIT_ASSERT_EQUAL(std::string("authz"), message.getAuthorizationID()); - CPPUNIT_ASSERT_EQUAL(std::string("user"), message.getAuthenticationID()); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("pass"), message.getPassword()); - } - - void testConstructor_NoAuthcid() { - PLAINMessage message(createSafeByteArray("authzid", 7)); - - CPPUNIT_ASSERT_EQUAL(std::string(""), message.getAuthenticationID()); - } - - void testConstructor_NoPassword() { - PLAINMessage message(createSafeByteArray("authzid\0authcid", 15)); - - CPPUNIT_ASSERT_EQUAL(std::string(""), message.getAuthenticationID()); - } + CPPUNIT_TEST_SUITE(PLAINMessageTest); + CPPUNIT_TEST(testGetValue_WithoutAuthzID); + CPPUNIT_TEST(testGetValue_WithAuthzID); + CPPUNIT_TEST(testConstructor_WithoutAuthzID); + CPPUNIT_TEST(testConstructor_WithAuthzID); + CPPUNIT_TEST(testConstructor_NoAuthcid); + CPPUNIT_TEST(testConstructor_NoPassword); + CPPUNIT_TEST_SUITE_END(); + + public: + PLAINMessageTest() {} + + void testGetValue_WithoutAuthzID() { + PLAINMessage message("user", createSafeByteArray("pass")); + CPPUNIT_ASSERT_EQUAL(message.getValue(), createSafeByteArray("\0user\0pass", 10)); + } + + void testGetValue_WithAuthzID() { + PLAINMessage message("user", createSafeByteArray("pass"), "authz"); + CPPUNIT_ASSERT_EQUAL(message.getValue(), createSafeByteArray("authz\0user\0pass", 15)); + } + + void testConstructor_WithoutAuthzID() { + PLAINMessage message(createSafeByteArray("\0user\0pass", 10)); + + CPPUNIT_ASSERT_EQUAL(std::string(""), message.getAuthorizationID()); + CPPUNIT_ASSERT_EQUAL(std::string("user"), message.getAuthenticationID()); + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("pass"), message.getPassword()); + } + + void testConstructor_WithAuthzID() { + PLAINMessage message(createSafeByteArray("authz\0user\0pass", 15)); + + CPPUNIT_ASSERT_EQUAL(std::string("authz"), message.getAuthorizationID()); + CPPUNIT_ASSERT_EQUAL(std::string("user"), message.getAuthenticationID()); + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("pass"), message.getPassword()); + } + + void testConstructor_NoAuthcid() { + PLAINMessage message(createSafeByteArray("authzid", 7)); + + CPPUNIT_ASSERT_EQUAL(std::string(""), message.getAuthenticationID()); + } + + void testConstructor_NoPassword() { + PLAINMessage message(createSafeByteArray("authzid\0authcid", 15)); + + CPPUNIT_ASSERT_EQUAL(std::string(""), message.getAuthenticationID()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(PLAINMessageTest); diff --git a/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp b/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp index 3341ad8..7f408c6 100644 --- a/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp +++ b/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <QA/Checker/IO.h> @@ -9,225 +9,225 @@ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/SASL/SCRAMSHA1ClientAuthenticator.h> #include <Swiften/Base/ByteArray.h> -#include <Swiften/IDN/IDNConverter.h> -#include <Swiften/IDN/PlatformIDNConverter.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/IDN/IDNConverter.h> +#include <Swiften/IDN/PlatformIDNConverter.h> +#include <Swiften/SASL/SCRAMSHA1ClientAuthenticator.h> using namespace Swift; class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SCRAMSHA1ClientAuthenticatorTest); - CPPUNIT_TEST(testGetInitialResponse); - CPPUNIT_TEST(testGetInitialResponse_UsernameHasSpecialChars); - CPPUNIT_TEST(testGetInitialResponse_WithAuthorizationID); - CPPUNIT_TEST(testGetInitialResponse_WithAuthorizationIDWithSpecialChars); - CPPUNIT_TEST(testGetInitialResponse_WithoutChannelBindingWithTLSChannelBindingData); - CPPUNIT_TEST(testGetInitialResponse_WithChannelBindingWithTLSChannelBindingData); - CPPUNIT_TEST(testGetFinalResponse); - CPPUNIT_TEST(testGetFinalResponse_WithoutChannelBindingWithTLSChannelBindingData); - CPPUNIT_TEST(testGetFinalResponse_WithChannelBindingWithTLSChannelBindingData); - CPPUNIT_TEST(testSetChallenge); - CPPUNIT_TEST(testSetChallenge_InvalidClientNonce); - CPPUNIT_TEST(testSetChallenge_OnlyClientNonce); - CPPUNIT_TEST(testSetChallenge_InvalidIterations); - CPPUNIT_TEST(testSetChallenge_ZeroIterations); - CPPUNIT_TEST(testSetChallenge_NegativeIterations); - CPPUNIT_TEST(testSetChallenge_MissingIterations); - CPPUNIT_TEST(testSetFinalChallenge); - CPPUNIT_TEST(testSetFinalChallenge_InvalidChallenge); - CPPUNIT_TEST(testGetResponseAfterFinalChallenge); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(SCRAMSHA1ClientAuthenticatorTest); + CPPUNIT_TEST(testGetInitialResponse); + CPPUNIT_TEST(testGetInitialResponse_UsernameHasSpecialChars); + CPPUNIT_TEST(testGetInitialResponse_WithAuthorizationID); + CPPUNIT_TEST(testGetInitialResponse_WithAuthorizationIDWithSpecialChars); + CPPUNIT_TEST(testGetInitialResponse_WithoutChannelBindingWithTLSChannelBindingData); + CPPUNIT_TEST(testGetInitialResponse_WithChannelBindingWithTLSChannelBindingData); + CPPUNIT_TEST(testGetFinalResponse); + CPPUNIT_TEST(testGetFinalResponse_WithoutChannelBindingWithTLSChannelBindingData); + CPPUNIT_TEST(testGetFinalResponse_WithChannelBindingWithTLSChannelBindingData); + CPPUNIT_TEST(testSetChallenge); + CPPUNIT_TEST(testSetChallenge_InvalidClientNonce); + CPPUNIT_TEST(testSetChallenge_OnlyClientNonce); + CPPUNIT_TEST(testSetChallenge_InvalidIterations); + CPPUNIT_TEST(testSetChallenge_ZeroIterations); + CPPUNIT_TEST(testSetChallenge_NegativeIterations); + CPPUNIT_TEST(testSetChallenge_MissingIterations); + CPPUNIT_TEST(testSetFinalChallenge); + CPPUNIT_TEST(testSetFinalChallenge_InvalidChallenge); + CPPUNIT_TEST(testGetResponseAfterFinalChallenge); + CPPUNIT_TEST_SUITE_END(); - public: - void setUp() { - idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - } + public: + void setUp() { + idnConverter = std::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } - void testGetInitialResponse() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); + void testGetInitialResponse() { + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); - SafeByteArray response = *testling.getResponse(); + SafeByteArray response = *testling.getResponse(); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("n,,n=user,r=abcdefghABCDEFGH"), response); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("n,,n=user,r=abcdefghABCDEFGH"), response); + } - void testGetInitialResponse_UsernameHasSpecialChars() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); - testling.setCredentials(",us=,er=", createSafeByteArray("pass"), ""); + void testGetInitialResponse_UsernameHasSpecialChars() { + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); + testling.setCredentials(",us=,er=", createSafeByteArray("pass"), ""); - SafeByteArray response = *testling.getResponse(); + SafeByteArray response = *testling.getResponse(); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("n,,n==2Cus=3D=2Cer=3D,r=abcdefghABCDEFGH"), response); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("n,,n==2Cus=3D=2Cer=3D,r=abcdefghABCDEFGH"), response); + } - void testGetInitialResponse_WithAuthorizationID() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), "auth"); + void testGetInitialResponse_WithAuthorizationID() { + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), "auth"); - SafeByteArray response = *testling.getResponse(); + SafeByteArray response = *testling.getResponse(); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("n,a=auth,n=user,r=abcdefghABCDEFGH"), response); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("n,a=auth,n=user,r=abcdefghABCDEFGH"), response); + } - void testGetInitialResponse_WithAuthorizationIDWithSpecialChars() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), "a=u,th"); + void testGetInitialResponse_WithAuthorizationIDWithSpecialChars() { + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), "a=u,th"); - SafeByteArray response = *testling.getResponse(); + SafeByteArray response = *testling.getResponse(); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("n,a=a=3Du=2Cth,n=user,r=abcdefghABCDEFGH"), response); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("n,a=a=3Du=2Cth,n=user,r=abcdefghABCDEFGH"), response); + } - void testGetInitialResponse_WithoutChannelBindingWithTLSChannelBindingData() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); - testling.setTLSChannelBindingData(createByteArray("xyza")); - testling.setCredentials("user", createSafeByteArray("pass"), ""); + void testGetInitialResponse_WithoutChannelBindingWithTLSChannelBindingData() { + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); + testling.setTLSChannelBindingData(createByteArray("xyza")); + testling.setCredentials("user", createSafeByteArray("pass"), ""); - SafeByteArray response = *testling.getResponse(); + SafeByteArray response = *testling.getResponse(); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("y,,n=user,r=abcdefghABCDEFGH"), response); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("y,,n=user,r=abcdefghABCDEFGH"), response); + } - void testGetInitialResponse_WithChannelBindingWithTLSChannelBindingData() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", true, idnConverter.get(), crypto.get()); - testling.setTLSChannelBindingData(createByteArray("xyza")); - testling.setCredentials("user", createSafeByteArray("pass"), ""); + void testGetInitialResponse_WithChannelBindingWithTLSChannelBindingData() { + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", true, idnConverter.get(), crypto.get()); + testling.setTLSChannelBindingData(createByteArray("xyza")); + testling.setCredentials("user", createSafeByteArray("pass"), ""); - SafeByteArray response = *testling.getResponse(); + SafeByteArray response = *testling.getResponse(); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("p=tls-unique,,n=user,r=abcdefghABCDEFGH"), response); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("p=tls-unique,,n=user,r=abcdefghABCDEFGH"), response); + } - void testGetFinalResponse() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); - testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); + void testGetFinalResponse() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); + testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); - SafeByteArray response = *testling.getResponse(); + SafeByteArray response = *testling.getResponse(); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("c=biws,r=abcdefghABCDEFGH,p=CZbjGDpIteIJwQNBgO0P8pKkMGY="), response); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("c=biws,r=abcdefghABCDEFGH,p=CZbjGDpIteIJwQNBgO0P8pKkMGY="), response); + } - void testGetFinalResponse_WithoutChannelBindingWithTLSChannelBindingData() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); - testling.setTLSChannelBindingData(createByteArray("xyza")); - testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); + void testGetFinalResponse_WithoutChannelBindingWithTLSChannelBindingData() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); + testling.setTLSChannelBindingData(createByteArray("xyza")); + testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); - SafeByteArray response = *testling.getResponse(); + SafeByteArray response = *testling.getResponse(); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("c=eSws,r=abcdefghABCDEFGH,p=JNpsiFEcxZvNZ1+FFBBqrYvYxMk="), response); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("c=eSws,r=abcdefghABCDEFGH,p=JNpsiFEcxZvNZ1+FFBBqrYvYxMk="), response); + } - void testGetFinalResponse_WithChannelBindingWithTLSChannelBindingData() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", true, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); - testling.setTLSChannelBindingData(createByteArray("xyza")); - testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); + void testGetFinalResponse_WithChannelBindingWithTLSChannelBindingData() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", true, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); + testling.setTLSChannelBindingData(createByteArray("xyza")); + testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); - SafeByteArray response = *testling.getResponse(); + SafeByteArray response = *testling.getResponse(); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("c=cD10bHMtdW5pcXVlLCx4eXph,r=abcdefghABCDEFGH,p=i6Rghite81P1ype8XxaVAa5l7v0="), response); - } + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("c=cD10bHMtdW5pcXVlLCx4eXph,r=abcdefghABCDEFGH,p=i6Rghite81P1ype8XxaVAa5l7v0="), response); + } - void testSetFinalChallenge() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); - testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); + void testSetFinalChallenge() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); + testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); - bool result = testling.setChallenge(createByteArray("v=Dd+Q20knZs9jeeK0pi1Mx1Se+yo=")); + bool result = testling.setChallenge(createByteArray("v=Dd+Q20knZs9jeeK0pi1Mx1Se+yo=")); - CPPUNIT_ASSERT(result); - } + CPPUNIT_ASSERT(result); + } - void testSetChallenge() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); + void testSetChallenge() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); - bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); + bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); - CPPUNIT_ASSERT(result); - } + CPPUNIT_ASSERT(result); + } - void testSetChallenge_InvalidClientNonce() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); + void testSetChallenge_InvalidClientNonce() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); - bool result = testling.setChallenge(createByteArray("r=abcdefgiABCDEFGH,s=MTIzNDU2NzgK,i=4096")); + bool result = testling.setChallenge(createByteArray("r=abcdefgiABCDEFGH,s=MTIzNDU2NzgK,i=4096")); - CPPUNIT_ASSERT(!result); - } + CPPUNIT_ASSERT(!result); + } - void testSetChallenge_OnlyClientNonce() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); + void testSetChallenge_OnlyClientNonce() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); - bool result = testling.setChallenge(createByteArray("r=abcdefgh,s=MTIzNDU2NzgK,i=4096")); + bool result = testling.setChallenge(createByteArray("r=abcdefgh,s=MTIzNDU2NzgK,i=4096")); - CPPUNIT_ASSERT(!result); - } + CPPUNIT_ASSERT(!result); + } - void testSetChallenge_InvalidIterations() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); + void testSetChallenge_InvalidIterations() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); - bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=bla")); + bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=bla")); - CPPUNIT_ASSERT(!result); - } + CPPUNIT_ASSERT(!result); + } - void testSetChallenge_MissingIterations() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); + void testSetChallenge_MissingIterations() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); - bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK")); + bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK")); - CPPUNIT_ASSERT(!result); - } + CPPUNIT_ASSERT(!result); + } - void testSetChallenge_ZeroIterations() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); + void testSetChallenge_ZeroIterations() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); - bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=0")); + bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=0")); - CPPUNIT_ASSERT(!result); - } + CPPUNIT_ASSERT(!result); + } - void testSetChallenge_NegativeIterations() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); + void testSetChallenge_NegativeIterations() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); - bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=-1")); + bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=-1")); - CPPUNIT_ASSERT(!result); - } + CPPUNIT_ASSERT(!result); + } - void testSetFinalChallenge_InvalidChallenge() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); - testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); - bool result = testling.setChallenge(createByteArray("v=e26kI69ICb6zosapLLxrER/631A=")); + void testSetFinalChallenge_InvalidChallenge() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); + testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); + bool result = testling.setChallenge(createByteArray("v=e26kI69ICb6zosapLLxrER/631A=")); - CPPUNIT_ASSERT(!result); - } + CPPUNIT_ASSERT(!result); + } - void testGetResponseAfterFinalChallenge() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); - testling.setCredentials("user", createSafeByteArray("pass"), ""); - testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); - testling.setChallenge(createByteArray("v=Dd+Q20knZs9jeeK0pi1Mx1Se+yo=")); + void testGetResponseAfterFinalChallenge() { + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); + testling.setCredentials("user", createSafeByteArray("pass"), ""); + testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); + testling.setChallenge(createByteArray("v=Dd+Q20knZs9jeeK0pi1Mx1Se+yo=")); - CPPUNIT_ASSERT(!testling.getResponse()); - } + CPPUNIT_ASSERT(!testling.getResponse()); + } - boost::shared_ptr<IDNConverter> idnConverter; - boost::shared_ptr<CryptoProvider> crypto; + std::shared_ptr<IDNConverter> idnConverter; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(SCRAMSHA1ClientAuthenticatorTest); diff --git a/Swiften/SASL/UnitTest/WindowsServicePrincipalNameTest.cpp b/Swiften/SASL/UnitTest/WindowsServicePrincipalNameTest.cpp new file mode 100644 index 0000000..ef3a9b3 --- /dev/null +++ b/Swiften/SASL/UnitTest/WindowsServicePrincipalNameTest.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> + +#include <Swiften/SASL/WindowsServicePrincipalName.h> + +using namespace Swift; + +class WindowsServicePrincipalNameTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(WindowsServicePrincipalNameTest); + CPPUNIT_TEST(testServiceClass); + CPPUNIT_TEST(testServiceName); + CPPUNIT_TEST(testInstanceName); + CPPUNIT_TEST(testInstancePort); + CPPUNIT_TEST(testReferrer); + CPPUNIT_TEST_SUITE_END(); + + public: + void testServiceClass() { + WindowsServicePrincipalName spn("mlink.adlon.isode.net"); + + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("xmpp/mlink.adlon.isode.net")); + + spn.setServiceClass("ldap"); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("ldap/mlink.adlon.isode.net")); + + spn.setServiceClass("中文"); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("中文/mlink.adlon.isode.net")); + + try { + spn.setServiceClass(""); + spn.toString(); + CPPUNIT_ASSERT(false); + } catch (std::runtime_error) { + /* expected */ + } + + try { + spn.setServiceClass("xm/pp"); /* Foward slash not allowed */ + spn.toString(); + CPPUNIT_ASSERT(false); + } catch (std::runtime_error) { + /* expected */ + } + } + + void testServiceName() { + try { + WindowsServicePrincipalName spn(""); + spn.toString(); + CPPUNIT_ASSERT(false); + } catch (std::runtime_error) { + /* expected */ + } + + try { + WindowsServicePrincipalName spn2("mlink/adlon.isode.net"); /* Foward slash not allowed */ + spn2.toString(); + CPPUNIT_ASSERT(false); + } catch (std::runtime_error) { + /* expected */ + } + + WindowsServicePrincipalName spn3("mlinkÄ.adlon.isode.net"); + CPPUNIT_ASSERT_EQUAL(spn3.toString(), std::string("xmpp/mlinkÄ.adlon.isode.net")); + } + + void testInstanceName() { + WindowsServicePrincipalName spn("adlon.isode.net"); + + spn.setInstanceName("mlink.adlon.isode.net"); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("xmpp/mlink.adlon.isode.net/adlon.isode.net")); + + spn.setInstanceName("127.0.0.1"); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("xmpp/127.0.0.1/adlon.isode.net")); + + spn.setInstanceName(""); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("xmpp/adlon.isode.net")); + + spn.setInstanceName("cañón.adlon.isode.net"); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("xmpp/cañón.adlon.isode.net/adlon.isode.net")); + + try { + spn.setInstanceName("mlink/adlon.isode.net"); /* Foward slash not allowed */ + spn.toString(); + CPPUNIT_ASSERT(false); + } catch (std::runtime_error) { + /* expected */ + } + } + + void testInstancePort() { + WindowsServicePrincipalName spn("adlon.isode.net"); + + spn.setInstanceName("mlink.adlon.isode.net"); + spn.setInstancePort(55222); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("xmpp/mlink.adlon.isode.net:55222/adlon.isode.net")); + + spn.setInstancePort(0); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("xmpp/mlink.adlon.isode.net/adlon.isode.net")); + + WindowsServicePrincipalName spn2("mlink.adlon.isode.net"); + + spn2.setInstancePort(55222); + CPPUNIT_ASSERT_EQUAL(spn2.toString(), std::string("xmpp/mlink.adlon.isode.net:55222")); + + spn2.setInstancePort(0); + CPPUNIT_ASSERT_EQUAL(spn2.toString(), std::string("xmpp/mlink.adlon.isode.net")); + } + + void testReferrer() { + WindowsServicePrincipalName spn("127.0.0.1"); + + spn.setReferrer("referrer.net"); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("xmpp/127.0.0.1/referrer.net")); + + spn.setInstancePort(6222); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("xmpp/127.0.0.1:6222/referrer.net")); + + spn.setReferrer("हिन्दी.net"); + CPPUNIT_ASSERT_EQUAL(spn.toString(), std::string("xmpp/127.0.0.1:6222/हिन्दी.net")); + + try { + spn.setReferrer("referrer/net"); /* Foward slash not allowed */ + spn.toString(); + CPPUNIT_ASSERT(false); + } catch (std::runtime_error) { + /* expected */ + } + + try { + spn.setReferrer(""); /* seems like you must have referrer with an IP */ + spn.toString(); + CPPUNIT_ASSERT(false); + } catch (std::runtime_error) { + /* expected */ + } + + WindowsServicePrincipalName spn2("mlink.adlon.isode.net"); + + spn2.setReferrer("referrer.net"); /* Referrer ignored if service name is not IP */ + CPPUNIT_ASSERT_EQUAL(spn2.toString(), std::string("xmpp/mlink.adlon.isode.net")); + + spn2.setReferrer("referrer/net"); /* Referrer ignored if service name is not IP */ + CPPUNIT_ASSERT_EQUAL(spn2.toString(), std::string("xmpp/mlink.adlon.isode.net")); + + WindowsServicePrincipalName spn3("adlon.isode.net"); + + spn3.setInstanceName("mlink.adlon.isode.net"); + spn3.setInstancePort(6222); + spn3.setReferrer("referrer.net"); /* Referrer ignored if service name is not IP */ + CPPUNIT_ASSERT_EQUAL(spn3.toString(), std::string("xmpp/mlink.adlon.isode.net:6222/adlon.isode.net")); + + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(WindowsServicePrincipalNameTest); diff --git a/Swiften/SASL/WindowsAuthentication.cpp b/Swiften/SASL/WindowsAuthentication.cpp new file mode 100644 index 0000000..f951fac --- /dev/null +++ b/Swiften/SASL/WindowsAuthentication.cpp @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/SASL/WindowsAuthentication.h> + +#include <iomanip> + +#include <Secext.h> + +#include <Swiften/Base/Log.h> +#include <Swiften/Base/String.h> + +#define ASSIGN_ERROR(status, errorCode) \ +{ \ + errorCode = std::make_shared<boost::system::error_code>(status, boost::system::system_category()); \ + SWIFT_LOG(debug) << std::hex << "status: 0x" << status << ": " << errorCode->message(); \ +} + +#define ASSIGN_SEC_ERROR(status, errorCode) \ +{ \ + if (status == SEC_E_OK) \ + { \ + SWIFT_LOG(debug) << "success"; \ + } \ + else { \ + ASSIGN_ERROR(status, errorCode); \ + } \ +} + +namespace Swift { + +std::shared_ptr<boost::system::error_code> getUserNameEx(std::string& userName, std::string& clientName, std::string& serverName) { + ULONG length = 512; + DWORD status = ERROR_MORE_DATA; + bool firstCall = true; + std::shared_ptr<boost::system::error_code> errorCode; + + while (status == ERROR_MORE_DATA) { + std::vector<wchar_t> value(length); + + /* length after this call will contain the required length if current length is not enough - so the next call should succeed */ + if (GetUserNameExW(NameSamCompatible, vecptr(value), &length)) { + std::size_t position; + + userName = convertWStringToString(std::wstring(vecptr(value), length)); + SWIFT_LOG(debug) << "User Name: " << userName; + + position = userName.find("\\"); + clientName = userName.substr(position + 1); + SWIFT_LOG(debug) << "Client name: " << clientName; + + serverName = userName.substr(0, position); + SWIFT_LOG(debug) << "Server name: " << serverName; + + break; + } + + status = GetLastError(); + if ((firstCall == false) || (status != ERROR_MORE_DATA)) { + ASSIGN_ERROR(status, errorCode); + break; + } + + firstCall = false; + } + + return errorCode; +} + +std::shared_ptr<boost::system::error_code> acquireCredentialsHandle(PCredHandle credentialsHandle) { + SECURITY_STATUS status; + std::shared_ptr<boost::system::error_code> errorCode; + TimeStamp validity; + + status = AcquireCredentialsHandle( + NULL, /* NULL indicates credentials of the user under whose security context it is executing */ + "Kerberos", + SECPKG_CRED_OUTBOUND, /* client credential */ + NULL, + NULL, /* use default credentials */ + NULL, /* not used */ + NULL, /* not used */ + credentialsHandle, + &validity); + ASSIGN_SEC_ERROR(status, errorCode); + + return errorCode; +} + +std::shared_ptr<boost::system::error_code> freeCredentialsHandle(PCredHandle credentialsHandle) { + SECURITY_STATUS status; + std::shared_ptr<boost::system::error_code> errorCode; + + status = FreeCredentialsHandle(credentialsHandle); + ASSIGN_SEC_ERROR(status, errorCode); + + return errorCode; +} + +std::shared_ptr<boost::system::error_code> initializeSecurityContext(const boost::optional<ByteArray>& inputToken, const std::string& servicePrincipalNameString, const PCredHandle credentialsHandle, bool haveContextHandle, PCtxtHandle contextHandle, ULONG contextRequested, ULONG* contextSupported, bool* haveCompleteContext, SafeByteArray& outputToken) { + SECURITY_STATUS status; + std::shared_ptr<boost::system::error_code> errorCode; + SecBufferDesc input; + SecBufferDesc output; + SecBuffer inputTokenBuffer; + SecBuffer outputTokenBuffer; + TimeStamp validity; + + *haveCompleteContext = false; + + input.ulVersion = 0; + input.cBuffers = 1; + input.pBuffers = &inputTokenBuffer; + + inputTokenBuffer.BufferType = SECBUFFER_TOKEN; + inputTokenBuffer.cbBuffer = 0; + inputTokenBuffer.pvBuffer = NULL; + if (inputToken && inputToken->size()) { + inputTokenBuffer.cbBuffer = inputToken->size(); + inputTokenBuffer.pvBuffer = (void *) vecptr(*inputToken); + } + + output.ulVersion = 0; + output.cBuffers = 1; + output.pBuffers = &outputTokenBuffer; + + outputTokenBuffer.BufferType = SECBUFFER_TOKEN; + outputTokenBuffer.cbBuffer = 0; + outputTokenBuffer.pvBuffer = NULL; + + status = InitializeSecurityContext( + credentialsHandle, /* previously acquired handle */ + haveContextHandle ? contextHandle : NULL, /* use partial context on subsequent calls */ + const_cast<char *>(servicePrincipalNameString.c_str()), + contextRequested | ISC_REQ_ALLOCATE_MEMORY, + 0, /* not used */ + SECURITY_NETWORK_DREP, + haveContextHandle ? &input : NULL, + 0, /* not used */ + contextHandle, + &output, + contextSupported, + &validity); + ASSIGN_SEC_ERROR(status, errorCode); /* errorCode set here will only be returned to caller if there was a non-success status */ + if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED)) { + /* The Windows documentation suggests that this function is used only for Digest and only on the server side, but still asks to call this function for Kerberos clients. Most likely this function will never be called, but including it for compliance with documentation. */ + errorCode = completeAuthToken(contextHandle, &output); + if (!errorCode) { + /* success, move on */ + } + else { + freeContextBuffer(outputTokenBuffer.pvBuffer); + return errorCode; + } + } + if ((status == SEC_E_OK) || (status == SEC_I_COMPLETE_NEEDED)) { + *haveCompleteContext = true; + } + if ((status == SEC_E_OK) || (status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_I_CONTINUE_NEEDED)) { + outputToken = createSafeByteArray (static_cast<unsigned char *>(outputTokenBuffer.pvBuffer), outputTokenBuffer.cbBuffer); + SWIFT_LOG(debug) << "outputToken.size(): " << outputToken.size(); + freeContextBuffer(outputTokenBuffer.pvBuffer); + + return std::shared_ptr<boost::system::error_code>(); /* success */ + } + + return errorCode; +} + +std::shared_ptr<boost::system::error_code> deleteSecurityContext(PCtxtHandle contextHandle) { + SECURITY_STATUS status; + std::shared_ptr<boost::system::error_code> errorCode; + + status = DeleteSecurityContext(contextHandle); + ASSIGN_SEC_ERROR(status, errorCode); + + return errorCode; +} + +std::shared_ptr<boost::system::error_code> completeAuthToken(const PCtxtHandle contextHandle, PSecBufferDesc token) { + SECURITY_STATUS status; + std::shared_ptr<boost::system::error_code> errorCode; + + status = CompleteAuthToken( + contextHandle, /* partial context */ + token); + ASSIGN_SEC_ERROR(status, errorCode); + + return errorCode; +} + +std::shared_ptr<boost::system::error_code> freeContextBuffer(PVOID contextBuffer) { + SECURITY_STATUS status; + std::shared_ptr<boost::system::error_code> errorCode; + + if (contextBuffer == NULL) { + return errorCode; + } + + status = FreeContextBuffer(contextBuffer); + ASSIGN_SEC_ERROR(status, errorCode); + + return errorCode; +} + +std::shared_ptr<boost::system::error_code> decryptMessage(const PCtxtHandle contextHandle, const ByteArray& message, SafeByteArray& decrypted) { + /* Following https://msdn.microsoft.com/en-us/library/windows/desktop/aa380496%28v=vs.85%29.aspx */ + + SECURITY_STATUS status; + std::shared_ptr<boost::system::error_code> errorCode; + SecBufferDesc inOut; + SecBuffer messageBuffer[2]; + SafeByteArray inputMessage; + ULONG qualityOfProtection; + + inOut.ulVersion = SECBUFFER_VERSION; + inOut.cBuffers = 2; + inOut.pBuffers = messageBuffer; + + inputMessage = createSafeByteArray (message); /* Make a copy as DecryptMessage decrypts the input in place, overwriting it */ + messageBuffer[0].BufferType = SECBUFFER_STREAM; + messageBuffer[0].cbBuffer = inputMessage.size(); + messageBuffer[0].pvBuffer = static_cast<void *>(vecptr(inputMessage)); + + messageBuffer[1].BufferType = SECBUFFER_DATA; + messageBuffer[1].cbBuffer = 0; + messageBuffer[1].pvBuffer = NULL; + + SWIFT_LOG(debug) << "inputMessage.size(): " << inputMessage.size(); + + status = DecryptMessage( + contextHandle, + &inOut, + 0, /* Don't maintain sequence numbers */ + &qualityOfProtection); + ASSIGN_SEC_ERROR(status, errorCode); + if (status == SEC_E_OK) { + if (qualityOfProtection == SECQOP_WRAP_NO_ENCRYPT) { + SWIFT_LOG(debug) << "Message was signed only"; + } + else { + SWIFT_LOG(debug) << "Message was encrypted"; + } + + SWIFT_LOG(debug) << "messageBuffer[1].cbBuffer: " << messageBuffer[1].cbBuffer; + + decrypted = createSafeByteArray (static_cast<unsigned char *>(messageBuffer[1].pvBuffer), messageBuffer[1].cbBuffer); + } + + return errorCode; +} + +std::shared_ptr<boost::system::error_code> encryptMessage(const PCtxtHandle contextHandle, const SecPkgContext_Sizes& sizes, const SafeByteArray& message, SafeByteArray& output) { + /* Following https://msdn.microsoft.com/en-us/library/windows/desktop/aa380496%28v=vs.85%29.aspx */ + + SECURITY_STATUS status; + std::shared_ptr<boost::system::error_code> errorCode; + SecBufferDesc inOut; + SecBuffer messageBuffer[3]; + SafeByteArray securityTrailer(sizes.cbSecurityTrailer); + SafeByteArray blockSize(sizes.cbBlockSize); + SafeByteArray inputMessage; + + inOut.ulVersion = SECBUFFER_VERSION; + inOut.cBuffers = 3; + inOut.pBuffers = messageBuffer; + + messageBuffer[0].BufferType = SECBUFFER_TOKEN; + messageBuffer[0].cbBuffer = sizes.cbSecurityTrailer; + messageBuffer[0].pvBuffer = vecptr(securityTrailer); + + inputMessage = createSafeByteArray (vecptr(message), message.size()); /* Make a copy as EncryptMessage encrypts the input in place, overwriting it */ + messageBuffer[1].BufferType = SECBUFFER_DATA; + messageBuffer[1].cbBuffer = inputMessage.size(); + messageBuffer[1].pvBuffer = (void *) vecptr(inputMessage); + + messageBuffer[2].BufferType = SECBUFFER_PADDING; + messageBuffer[2].cbBuffer = sizes.cbBlockSize; + messageBuffer[2].pvBuffer = vecptr(blockSize); + + SWIFT_LOG(debug) << "sizes.cbSecurityTrailer: " << sizes.cbSecurityTrailer; + SWIFT_LOG(debug) << "inputMessage.size(): " << inputMessage.size(); + SWIFT_LOG(debug) << "sizes.cbBlockSize: " << sizes.cbBlockSize; + + status = EncryptMessage( + contextHandle, + SECQOP_WRAP_NO_ENCRYPT, + &inOut, + 0); /* Don't maintain sequence numbers */ + ASSIGN_SEC_ERROR(status, errorCode); + if (status == SEC_E_OK) { + unsigned char* pointer; + + SWIFT_LOG(debug) << "messageBuffer[0].cbBuffer: " << messageBuffer[0].cbBuffer; + SWIFT_LOG(debug) << "messageBuffer[1].cbBuffer: " << messageBuffer[1].cbBuffer; + SWIFT_LOG(debug) << "messageBuffer[2].cbBuffer: " << messageBuffer[2].cbBuffer; + + output.resize(messageBuffer[0].cbBuffer + messageBuffer[1].cbBuffer + messageBuffer[2].cbBuffer); + pointer = vecptr(output); + for (size_t i = 0; i < inOut.cBuffers; i++) { + if (messageBuffer[i].cbBuffer) { + memcpy(pointer, messageBuffer[i].pvBuffer, messageBuffer[i].cbBuffer); + pointer += messageBuffer[i].cbBuffer; + } + } + } + + return errorCode; +} + +std::shared_ptr<boost::system::error_code> queryContextAttributes(const PCtxtHandle contextHandle, ULONG attribute, PVOID buffer) { + SECURITY_STATUS status; + std::shared_ptr<boost::system::error_code> errorCode; + + status = QueryContextAttributes( + contextHandle, + attribute, + buffer); + ASSIGN_SEC_ERROR(status, errorCode); + + return errorCode; +} + +} diff --git a/Swiften/SASL/WindowsAuthentication.h b/Swiften/SASL/WindowsAuthentication.h new file mode 100644 index 0000000..311c4c1 --- /dev/null +++ b/Swiften/SASL/WindowsAuthentication.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#define SECURITY_WIN32 +#include <Windows.h> +#include <Sspi.h> + +#include <Swiften/Base/API.h> +#include <boost/signals2.hpp> +#include <Swiften/Base/SafeByteArray.h> + +namespace Swift { + /** + * Retrieves the names & Windows server domain of the user associated + * with the calling thread. + * + * @param userName Will return the user name in the form "DOMAIN\user" + * @param clientName Will return the client name in the form "user" + * @param serverName Will return the server name in the form "DOMAIN" + * + * @return NULL for success, otherwise the error code returned by + * Windows. + */ + SWIFTEN_API std::shared_ptr<boost::system::error_code> getUserNameEx(std::string& userName, std::string& clientName, std::string& serverName); + + /** + * Retrieves the handle to preexisting client credentials for the + * Kerberos security package that were established through a system + * logon. + * freeCredentialsHandle() should be called if this function is + * successful and when credentials are no longer needed. + * + * @param credentialsHandle Pointer to the returned credentials handle. + * + * @return NULL for success, otherwise the error code returned by + * Windows. + */ + SWIFTEN_API std::shared_ptr<boost::system::error_code> acquireCredentialsHandle(PCredHandle credentialsHandle); + + /** + * Releases the credentials handle obtained by the + * acquireCredentialsHandle() function. + * freeCredentialsHandle() should be called when credentials are no + * longer needed. + * + * @param credentialsHandle Pointer to the credentials handle. + * + * @return NULL for success, otherwise the error code returned by + * Windows. + */ + SWIFTEN_API std::shared_ptr<boost::system::error_code> freeCredentialsHandle(PCredHandle credentialsHandle); + + /** + * Builds the security context between the client and remote peer. + * Kerberos security package that were established through a system + * logon. + * + * @param inputToken NULL or empty on the first call, otherwise the + * token returned by the server. + * @param servicePrincipalNameString Service principal name of the + * server. + * @param credentialsHandle Pointer to the credentials handle acquired + * before. + * @param haveContextHandle False on the first call to this function, + * true otherwise. + * @param contextHandle Pointer to the context handle returned on the + * first call and passed on subsequent calls. + * @param contextRequested Context related requests by the caller. See + * the Windows API InitializeSecurityContext for allowed values. + * @param contextSupported Pointer to context related attributes + * returned when context is completely established (when + * haveCompleteContext contains true). See the Windows API + * InitializeSecurityContext for allowed values. + * @param haveCompleteContext Pointer to boolean - this will only be + * true on return when the context is completely established and + * there is no need to call this function again. + * @param outputToken Returned security token to be sent to the server, + * may be empty. + * + * @return NULL for success, otherwise the error code returned by + * Windows. + */ + SWIFTEN_API std::shared_ptr<boost::system::error_code> initializeSecurityContext(const boost::optional<ByteArray>& inputToken, const std::string& servicePrincipalNameString, const PCredHandle credentialsHandle, bool haveContextHandle, PCtxtHandle contextHandle, ULONG contextRequested, ULONG* contextSupported, bool* haveCompleteContext, SafeByteArray& outputToken); + + /** + * Releases the context handle obtained by the + * initializeSecurityContext() function. + * deleteSecurityContext() should be called when the context is no + * longer needed. + * + * @param contextHandle Pointer to the context handle. + * + * @return NULL for success, otherwise the error code returned by + * Windows. + */ + SWIFTEN_API std::shared_ptr<boost::system::error_code> deleteSecurityContext(PCtxtHandle contextHandle); + + /** + * Completes an authentication token for a partial security context. + * + * @param contextHandle Pointer to the context handle. + * @param token authentication token. + * + * @return NULL for success, otherwise the error code returned by + * Windows. + */ + SWIFTEN_API std::shared_ptr<boost::system::error_code> completeAuthToken(const PCtxtHandle contextHandle, PSecBufferDesc token); + + /** + * Frees a memory buffer allocated by the security package. + * + * @param contextBuffer Pointer to buffer to be freed. + * + * @return NULL for success, otherwise the error code returned by + * Windows. + */ + SWIFTEN_API std::shared_ptr<boost::system::error_code> freeContextBuffer(PVOID contextBuffer); + + /** + * Decrypt message (assumes that sequence numbers are not maintained). + * + * @param contextHandle Pointer to the context handle. + * @param message Message to decrypt. + * @param decrypted Returned decrypted message. + * + * @return NULL for success, otherwise the error code returned by + * Windows. + */ + SWIFTEN_API std::shared_ptr<boost::system::error_code> decryptMessage(const PCtxtHandle contextHandle, const ByteArray& message, SafeByteArray& decrypted); + + /** + * Produces a header or trailer for the message but does not encrypt it + * (also assumes that sequence numbers are not maintained). + * + * @param contextHandle Pointer to the context handle. + * @param sizes SecPkgContext_Sizes obtained for the context. + * @param message Input message. + * @param output Returned output message. + * + * @return NULL for success, otherwise the error code returned by + * Windows. + */ + SWIFTEN_API std::shared_ptr<boost::system::error_code> encryptMessage(const PCtxtHandle contextHandle, const SecPkgContext_Sizes& sizes, const SafeByteArray& message, SafeByteArray& output); + + /** + * Queries the security package for attributes of the security context. + * + * @param contextHandle Pointer to the context handle. + * @param attribute Attribute to query. See the Windows API + * QueryContextAttributes for allowed values. + * @param buffer Pointer to a structure that receives the output. + * The type of structure depends on the queried attribute and + * memory for it must be allocated by caller. If the SSP allocates + * any memory required to hold some members, that memory should be + * freed using the function freeContextBuffer(). See the Windows + * API QueryContextAttributes for details. + * + * @return NULL for success, otherwise the error code returned by + * Windows. + */ + SWIFTEN_API std::shared_ptr<boost::system::error_code> queryContextAttributes(const PCtxtHandle contextHandle, ULONG attribute, PVOID buffer); + +} diff --git a/Swiften/SASL/WindowsGSSAPIClientAuthenticator.cpp b/Swiften/SASL/WindowsGSSAPIClientAuthenticator.cpp new file mode 100644 index 0000000..10e8c89 --- /dev/null +++ b/Swiften/SASL/WindowsGSSAPIClientAuthenticator.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/SASL/WindowsGSSAPIClientAuthenticator.h> + +#include <Swiften/Base/Log.h> +#include <Swiften/SASL/WindowsAuthentication.h> +#include <Swiften/SASL/WindowsServicePrincipalName.h> + +#define SECURITY_LAYER_NONE 1 + +namespace Swift { + +WindowsGSSAPIClientAuthenticator::WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname, int port) : ClientAuthenticator("GSSAPI"), step_(BuildingSecurityContext), error_(false), haveCredentialsHandle_(false), haveContextHandle_(false), haveCompleteContext_(false) { + WindowsServicePrincipalName servicePrincipalName(domainname); + servicePrincipalName.setInstanceName(hostname); + if ((port != -1) && (port != 5222)) { + servicePrincipalName.setInstancePort(port); + } + servicePrincipalNameString_ = servicePrincipalName.toString(); + + errorCode_ = acquireCredentialsHandle(&credentialsHandle_); + if (isError()) { + return; + } + else { + haveCredentialsHandle_ = true; + } + + buildSecurityContext(boost::optional<ByteArray>()); +} + +WindowsGSSAPIClientAuthenticator::~WindowsGSSAPIClientAuthenticator() { + if (haveContextHandle_) { + deleteSecurityContext(&contextHandle_); + } + + if (haveCredentialsHandle_) { + freeCredentialsHandle(&credentialsHandle_); + } +} + +boost::optional<SafeByteArray> WindowsGSSAPIClientAuthenticator::getResponse() const { + SWIFT_LOG(debug) << "response_.size(): " << response_.size(); + return response_; +} + +bool WindowsGSSAPIClientAuthenticator::setChallenge(const boost::optional<ByteArray>& challengeData) { + /* Following http://tools.ietf.org/html/rfc4752, https://msdn.microsoft.com/en-us/library/windows/desktop/aa380496%28v=vs.85%29.aspx */ + + if (step_ == BuildingSecurityContext) { + buildSecurityContext(challengeData); + } + else if (step_ == SecurityLayerNegotiation) { + if (!challengeData) { + SWIFT_LOG(debug) << "Empty message received from the server"; + error_ = true; + return false; + } + + SafeByteArray challenge; + errorCode_ = decryptMessage(&contextHandle_, challengeData.get(), challenge); + if (isError()) { + return false; + } + + if (challenge.size() != 4) { + SWIFT_LOG(debug) << "Token received from the server of incorrect length: " << challenge.size(); + error_ = true; + return false; + } + + unsigned char* challengePointer = vecptr(challenge); + + unsigned char serverSecurityLayer = challengePointer[0]; + if (serverSecurityLayer == 0) { + SWIFT_LOG(debug) << "Server supports unknown security layer, assuming no security layer"; + serverSecurityLayer = SECURITY_LAYER_NONE; + } + else if (serverSecurityLayer == SECURITY_LAYER_NONE) { + SWIFT_LOG(debug) << "Server supports no security layer"; + } + else { + SWIFT_LOG(debug) << "Server supports security layer"; + } + + unsigned int serverMaximumBuffer = (challengePointer[1] << 16) | + (challengePointer[2] << 8) | + (challengePointer[3] << 0); + + if ((serverSecurityLayer == SECURITY_LAYER_NONE) && (serverMaximumBuffer != 0)) { + SWIFT_LOG(debug) << "Server supports no security layer but has maximum buffer size" << serverMaximumBuffer; + error_ = true; + return false; + } + + SafeByteArray message(4); + + /* Commenting this out as streamSizes was not obtained before + if (message.size() > streamSizes_.cbMaximumMessage) { + error_ = true; + return false; + } */ + + unsigned char* messagePointer = vecptr(message); + messagePointer[0] = SECURITY_LAYER_NONE; + + /* The next 3 bytes indicate the client's maximum size buffer which is set to 0 as we do not support a security layer */ + messagePointer[1] = 0; + messagePointer[2] = 0; + messagePointer[3] = 0; + + /* The authorization identity is omitted as it is the same as the authentication identity */ + + errorCode_ = encryptMessage(&contextHandle_, sizes_, message, response_); + if (isError()) { + return false; + } + + step_ = ServerAuthenticated; + } + + if (isError()) { + return false; + } + + return true; +} + +bool WindowsGSSAPIClientAuthenticator::isError() { + if (error_) { + return true; + } + + if (!errorCode_) { + return false; + } + + return true; +} + +void WindowsGSSAPIClientAuthenticator::buildSecurityContext(const boost::optional<ByteArray>& inputToken) { + ULONG contextSupported; + + /* An XMPP server may not support Kerberos encryption or SASL security layer so not requesting integrity or confidentiality */ + errorCode_ = initializeSecurityContext(inputToken, servicePrincipalNameString_, &credentialsHandle_, haveContextHandle_, &contextHandle_, ISC_REQ_MUTUAL_AUTH, &contextSupported, &haveCompleteContext_, response_); + if (isError()) { + return; + } + + haveContextHandle_ = true; + + if (!haveCompleteContext_) { + return; + } + + if (contextSupported & ISC_REQ_MUTUAL_AUTH == 0) { + SWIFT_LOG(debug) << "Mutual authentication not supported"; + error_ = true; + return; + } + + errorCode_ = queryContextAttributes(&contextHandle_, SECPKG_ATTR_SIZES, &sizes_); + if (isError()) { + return; + } + + /* Commenting this out as it gives the error code 0x80090302: The function requested is not supported + errorCode_ = queryContextAttributes(&contextHandle_, SECPKG_ATTR_STREAM_SIZES, &streamSizes_); + if (isError()) { + return; + }*/ + + SecPkgContext_Names names; + errorCode_ = queryContextAttributes(&contextHandle_, SECPKG_ATTR_NAMES, &names); + if (isError()) { + return; + } + + userName_ = names.sUserName; + SWIFT_LOG(debug) << "User name: " << userName_; + + std::size_t position = userName_.find("\\"); + clientName_ = userName_.substr(position + 1); + SWIFT_LOG(debug) << "Client name: " << clientName_; + + serverName_ = userName_.substr(0, position); + SWIFT_LOG(debug) << "Server name: " << serverName_; + + freeContextBuffer(names.sUserName); + step_ = SecurityLayerNegotiation; +} + +} diff --git a/Swiften/SASL/WindowsGSSAPIClientAuthenticator.h b/Swiften/SASL/WindowsGSSAPIClientAuthenticator.h new file mode 100644 index 0000000..72616ed --- /dev/null +++ b/Swiften/SASL/WindowsGSSAPIClientAuthenticator.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> +#include <vector> + +#define SECURITY_WIN32 +#include <Windows.h> +#include <Sspi.h> + +#include <Swiften/Base/API.h> +#include <Swiften/Base/SafeByteArray.h> +#include <Swiften/SASL/ClientAuthenticator.h> + +namespace Swift { + class SWIFTEN_API WindowsGSSAPIClientAuthenticator : public ClientAuthenticator { + public: + WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname, int port); + + virtual ~WindowsGSSAPIClientAuthenticator(); + + virtual boost::optional<SafeByteArray> getResponse() const; + virtual bool setChallenge(const boost::optional<std::vector<unsigned char> >&); + + /** + * Returns whether the authenticator has the complete + * security context. It could be true before any + * message exchanges with the server or after some + * messages have been exchanged. + * + * @return True if security context is complete. + */ + bool isCompleteContext() { + return haveCompleteContext_; + } + + /** + * Retrieves the user name associated with the + * security context. It will only be set when + * isCompleteContext() returns true. + * + * @return User name in the form "EXAMPLE.COM\user". + */ + const std::string& getUserName() { + return userName_; + } + + /** + * Retrieves the client part of the user name + * associated with the security context. It will only + * be set when isCompleteContext() returns true. + * + * @return Client name in the form "user" when the user + * name is "EXAMPLE.COM\user". + */ + const std::string& getClientName() { + return clientName_; + } + + /** + * Retrieves the server name associated with the + * security context. It will only be set when + * isCompleteContext() returns true. + * + * @return Server name in the form "EXAMPLE.COM". + */ + const std::string& getServerName() { + return serverName_; + } + + /** + * Returns whether an error has occurred at any point, + * including in the constructor. + * + * @return True if an error has occured. + */ + bool isError(); + + /** + * Returns error details if isError() returns true. + * May be empty if there are no details to be provided + * for the error. + * + * @return Error details. + */ + std::shared_ptr<boost::system::error_code> getErrorCode() { + return errorCode_; + } + + private: + void buildSecurityContext(const boost::optional<ByteArray>& inputToken); + + private: + enum Step { + BuildingSecurityContext, + SecurityLayerNegotiation, + ServerAuthenticated + } step_; + bool error_; + std::shared_ptr<boost::system::error_code> errorCode_; + std::string servicePrincipalNameString_; + bool haveCredentialsHandle_; + bool haveContextHandle_; + bool haveCompleteContext_; + CredHandle credentialsHandle_; + CtxtHandle contextHandle_; + SecPkgContext_Sizes sizes_; + SecPkgContext_StreamSizes streamSizes_; + std::string userName_; + std::string clientName_; + std::string serverName_; + SafeByteArray response_; + }; +} diff --git a/Swiften/SASL/WindowsServicePrincipalName.cpp b/Swiften/SASL/WindowsServicePrincipalName.cpp new file mode 100644 index 0000000..6c87925 --- /dev/null +++ b/Swiften/SASL/WindowsServicePrincipalName.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/SASL/WindowsServicePrincipalName.h> + +#include <vector> + +#include <Ntdsapi.h> + +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Log.h> +#include <Swiften/Base/String.h> + +namespace Swift { + +WindowsServicePrincipalName::WindowsServicePrincipalName(const std::string& serviceName) : serviceClass_(L"xmpp"), instancePort_(0) { + serviceName_ = convertStringToWString(serviceName); +} + +WindowsServicePrincipalName::~WindowsServicePrincipalName() { +} + +void WindowsServicePrincipalName::setServiceClass(const std::string& serviceClass) { + serviceClass_ = convertStringToWString(serviceClass); +} + +void WindowsServicePrincipalName::setInstanceName(const std::string& instanceName) { + instanceName_ = convertStringToWString(instanceName); +} + +void WindowsServicePrincipalName::setReferrer(const std::string& referrer) { + referrer_ = convertStringToWString(referrer); +} + +std::string WindowsServicePrincipalName::toString() { + DWORD length = 512; + DWORD status = ERROR_BUFFER_OVERFLOW; + bool firstCall = true; + std::string str; + + while (status == ERROR_BUFFER_OVERFLOW) { + std::vector<wchar_t> value(length); + + /* length after this call will contain the required length if current length is not enough - so the next call should succeed */ + status = dsMakeSpn(&length, vecptr(value)); + if (status == ERROR_SUCCESS) { + str = convertWStringToString(std::wstring(vecptr(value), length-1 /* trailing 0 character */)); + break; + } + + if ((firstCall == false) || (status != ERROR_BUFFER_OVERFLOW)) { + std::stringstream errorString; + boost::system::error_code errorCode(status, boost::system::system_category()); + + errorString << "Error creating Service Principal Name: status: 0x" << std::hex << status << ": " << errorCode.message(); + + /* Any other error will be a programming error */ + throw std::runtime_error(errorString.str()); + } + + firstCall = false; + } + + SWIFT_LOG(debug) << "SPN: " << str; + return str; +} + +DWORD WindowsServicePrincipalName::dsMakeSpn(DWORD* length, wchar_t* value) { + DWORD status; + +#ifdef UNICODE + SWIFT_LOG(debug) << "UNICODE is defined"; +#else + SWIFT_LOG(debug) << "UNICODE is not defined"; +#endif + + SWIFT_LOG(debug) << "serviceClass_: " << convertWStringToString(serviceClass_.c_str()); + SWIFT_LOG(debug) << "serviceName_: " << convertWStringToString(serviceName_.c_str()); + SWIFT_LOG(debug) << "instanceName_: " << convertWStringToString(instanceName_.c_str()); + SWIFT_LOG(debug) << "referrer_: " << convertWStringToString(referrer_.c_str()); + SWIFT_LOG(debug) << "instancePort_: " << instancePort_; + SWIFT_LOG(debug) << "length: " << *length; + + /* Call the Unicode function because that is recommended: +https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407%28v=vs.85%29.aspx */ + status = DsMakeSpnW( + serviceClass_.c_str(), + serviceName_.c_str(), + instanceName_.empty() ? NULL : instanceName_.c_str(), + instancePort_, + referrer_.empty() ? NULL : referrer_.c_str(), + length, + value); + if (status != ERROR_SUCCESS) { + boost::system::error_code errorCode(status, boost::system::system_category()); + + SWIFT_LOG(debug) << std::hex << "status: 0x" << status << ": " << errorCode.message(); + } + + return status; +} + +} diff --git a/Swiften/SASL/WindowsServicePrincipalName.h b/Swiften/SASL/WindowsServicePrincipalName.h new file mode 100644 index 0000000..2e4e5c4 --- /dev/null +++ b/Swiften/SASL/WindowsServicePrincipalName.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <Windows.h> + +#include <Swiften/Base/API.h> + +namespace Swift { + /* + * This represents the SPN used on Windows to identify a service + * instance. + */ + class SWIFTEN_API WindowsServicePrincipalName { + public: + /* + * This assigns the provided service name, + * "xmpp" service class, no instance name or referrer, + * and default port. All of these (except the service + * name) can be set to other values using the provided + * methods. + * If the constructor is called with the service name + * "hostname.example.com" and the provided methods are + * not used to change the defaults, then toString() + * will return the SPN "xmpp/hostname.example.com". + */ + WindowsServicePrincipalName(const std::string& serviceName); + + ~WindowsServicePrincipalName(); + + void setServiceClass(const std::string& serviceClass); + + void setInstanceName(const std::string& instanceName); + + void setReferrer(const std::string& referrer); + + /* + * This sets a non-default port for the service. Note + * that the default value is 0 which indicates the + * default port for the service. So if the XMPP service + * is using the default port of 5222 for client + * connections, then do not set the port to 5222 but let + * it remain 0 to indicate that the default port is + * used. + */ + void setInstancePort(unsigned short instancePort) { instancePort_ = instancePort; } + + /* + * This follows the rules of SPN creation on Windows and + * returns the SPN string constructed from the set + * values. + */ + std::string toString(); + + private: + DWORD dsMakeSpn(DWORD* length, wchar_t* value); + + private: + std::wstring serviceClass_; + std::wstring serviceName_; + std::wstring instanceName_; + USHORT instancePort_; + std::wstring referrer_; + }; +} diff --git a/Swiften/SConscript b/Swiften/SConscript index a8daac5..7ea7355 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -1,4 +1,4 @@ -import os, re, Version, os.path, time +import os, re, Version, os.path, time, urllib Import("env") @@ -10,518 +10,645 @@ swiften_dep_modules = ["BOOST", "GCONF", "ICU", "LIBIDN", "ZLIB", "LDNS", "UNBOU external_swiften_dep_modules = ["BOOST"] if env["SCONS_STAGE"] == "flags" : - env["SWIFTEN_DLL"] = env["swiften_dll"] - env["SWIFTEN_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "swift") - version_match = re.match("(\d+)\.(\d+).*", env["SWIFTEN_VERSION"]) - if version_match : - env["SWIFTEN_VERSION_MAJOR"] = int(version_match.group(1)) - env["SWIFTEN_VERSION_MINOR"] = int(version_match.group(2)) - else : - env["SWIFTEN_VERSION_MAJOR"] = 0 - env["SWIFTEN_VERSION_MINOR"] = 0 - env["SWIFTEN_VERSION_PATCH"] = 0 - env["SWIFTEN_LIBRARY"] = "Swiften" - env["SWIFTEN_LIBRARY_FILE"] = "Swiften" - env["SWIFTEN_LIBRARY_ALIASES"] = [] - - if env["SWIFTEN_DLL"] : - if env["PLATFORM"] == "win32" : - env["SWIFTEN_LIBRARY"] = env.subst("Swiften${SWIFTEN_VERSION_MAJOR}") - env["SWIFTEN_LIBRARY_FILE"] = env.subst("${SWIFTEN_LIBRARY}.dll") - elif env["PLATFORM"] == "darwin" : - env["SWIFTEN_LIBRARY_FILE"] = env.subst("Swiften.${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}") - env["SWIFTEN_LIBRARY_ALIASES"] = ["libSwiften.dylib", env.subst("libSwiften.${SWIFTEN_VERSION_MAJOR}.dylib")] - else : - env["SWIFTEN_LIBRARY_FILE"] = env.subst("libSwiften.so.${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}") - env["SWIFTEN_LIBRARY_ALIASES"] = ["libSwiften.so", env.subst("libSwiften.so.${SWIFTEN_VERSION_MAJOR}")] + env["SWIFTEN_DLL"] = env["swiften_dll"] + env["SWIFTEN_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "swift") + version_match = re.match(r"(\d+)\.(\d+).*", env["SWIFTEN_VERSION"]) + if version_match : + env["SWIFTEN_VERSION_MAJOR"] = int(version_match.group(1)) + env["SWIFTEN_VERSION_MINOR"] = int(version_match.group(2)) + else : + env["SWIFTEN_VERSION_MAJOR"] = 0 + env["SWIFTEN_VERSION_MINOR"] = 0 + env["SWIFTEN_VERSION_PATCH"] = 0 + env["SWIFTEN_LIBRARY"] = "Swiften" + env["SWIFTEN_LIBRARY_FILE"] = "Swiften" + env["SWIFTEN_LIBRARY_ALIASES"] = [] - if env["SWIFTEN_DLL"] : - env.AddMethod(lambda e,s : e.SharedObject(s), "SwiftenObject") - else : - env.AddMethod(lambda e,s : e.StaticObject(s), "SwiftenObject") + if env["SWIFTEN_DLL"] : + if env["PLATFORM"] == "win32" : + env["SWIFTEN_LIBRARY"] = env.subst("Swiften${SWIFTEN_VERSION_MAJOR}") + env["SWIFTEN_LIBRARY_FILE"] = env.subst("${SWIFTEN_LIBRARY}.dll") + elif env["PLATFORM"] == "darwin" : + env["SWIFTEN_LIBRARY_FILE"] = env.subst("Swiften.${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}") + env["SWIFTEN_LIBRARY_ALIASES"] = ["libSwiften.dylib", env.subst("libSwiften.${SWIFTEN_VERSION_MAJOR}.dylib")] + else : + env["SWIFTEN_LIBRARY_FILE"] = env.subst("libSwiften.so.${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}") + env["SWIFTEN_LIBRARY_ALIASES"] = ["libSwiften.so", env.subst("libSwiften.so.${SWIFTEN_VERSION_MAJOR}")] - swiften_env = env.Clone() - swiften_env["LIBPATH"] = [Dir(".")] - swiften_env["LIBRUNPATH"] = [Dir(".")] - swiften_env["LIBS"] = [swiften_env["SWIFTEN_LIBRARY"]] - if not env["SWIFTEN_DLL"] : - swiften_env.Append(CPPDEFINES = ["SWIFTEN_STATIC"]) - dep_env = env.Clone() - for module in swiften_dep_modules : - module_flags = env.get(module + "_FLAGS", {}) - if env.get(module + "_BUNDLED", False) : - if module in external_swiften_dep_modules : - swiften_env.UseFlags(module_flags) - else : - if module in external_swiften_dep_modules : - dep_env.UseFlags(module_flags) - else : - # Expose only libraries - dep_env.Append(LIBPATH = module_flags.get("LIBPATH", [])) - dep_env.Append(LIBS = module_flags.get("LIBS", [])) - dep_env.Append(FRAMEWORKS = module_flags.get("FRAMEWORKS", [])) - dep_env.UseFlags(dep_env["PLATFORM_FLAGS"]) + if env["SWIFTEN_DLL"] : + env.AddMethod(lambda e,s : e.SharedObject(s), "SwiftenObject") + else : + env.AddMethod(lambda e,s : e.StaticObject(s), "SwiftenObject") - if env.get("HAVE_SCHANNEL", 0) : - dep_env.Append(LIBS = ["Winscard"]) + swiften_env = env.Clone() + swiften_env["LIBPATH"] = [Dir(".")] + swiften_env["LIBRUNPATH"] = [Dir(".")] + swiften_env["LIBS"] = [swiften_env["SWIFTEN_LIBRARY"]] + if not env["SWIFTEN_DLL"] : + swiften_env.Append(CPPDEFINES = ["SWIFTEN_STATIC"]) + dep_env = env.Clone() + for module in swiften_dep_modules : + module_flags = env.get(module + "_FLAGS", {}) + if env.get(module + "_BUNDLED", False) : + if module in external_swiften_dep_modules : + swiften_env.UseFlags(module_flags) + else : + if module in external_swiften_dep_modules : + dep_env.UseFlags(module_flags) + else : + # Expose only libraries + dep_env.Append(LIBPATH = module_flags.get("LIBPATH", [])) + dep_env.Append(LIBS = module_flags.get("LIBS", [])) + dep_env.Append(FRAMEWORKS = module_flags.get("FRAMEWORKS", [])) + dep_env.UseFlags(dep_env["PLATFORM_FLAGS"]) - for var, e in [("SWIFTEN_FLAGS", swiften_env), ("SWIFTEN_DEP_FLAGS", dep_env)] : - env[var] = { - "CPPDEFINES": e.get("CPPDEFINES", []), - "CPPPATH": e.get("CPPPATH", []), - "CPPFLAGS": e.get("CPPFLAGS", []), - "LIBPATH": e.get("LIBPATH", []), - "LIBRUNPATH": e.get("LIBRUNPATH", []), - "LIBS": e.get("LIBS", []), - "FRAMEWORKS": e.get("FRAMEWORKS", []), - } + if env.get("HAVE_SCHANNEL", 0) : + dep_env.Append(LIBS = ["Winscard"]) + + for var, e in [("SWIFTEN_FLAGS", swiften_env), ("SWIFTEN_DEP_FLAGS", dep_env)] : + env[var] = { + "CPPDEFINES": e.get("CPPDEFINES", []), + "CPPPATH": e.get("CPPPATH", []), + "CPPFLAGS": e.get("CPPFLAGS", []), + "LIBPATH": e.get("LIBPATH", []), + "LIBRUNPATH": e.get("LIBRUNPATH", []), + "LIBS": e.get("LIBS", []), + "FRAMEWORKS": e.get("FRAMEWORKS", []), + } + + if env["PLATFORM"] == "win32" : + # 0x0600 = _WIN32_WINNT_VISTA, 0x06000000 = NTDDI_VISTA + env.Append(CPPDEFINES = [("_WIN32_WINNT","0x0600") , ("NTDDI_VERSION","0x06000000")]) ################################################################################ # Build ################################################################################ if env["SCONS_STAGE"] == "build" : - swiften_env = env.Clone() - swiften_env.Append(CPPDEFINES = ["SWIFTEN_BUILDING"]) - for module in swiften_dep_modules : - swiften_env.UseFlags(swiften_env.get(module + "_FLAGS", {})) - if env.get(module + "_BUNDLED", False) : - swiften_env.Append(SWIFTEN_OBJECTS = env.get(module + "_OBJECTS", [])) - swiften_env.UseFlags(swiften_env["PLATFORM_FLAGS"]) - - if swiften_env["SWIFTEN_DLL"] : - swiften_env.AddMethod(lambda e,l,o : e.SharedLibrary(l,o), "SwiftenLibrary") - else : - swiften_env.Append(CPPDEFINES = ["SWIFTEN_STATIC"]) - swiften_env.AddMethod(lambda e,l,o : e.StaticLibrary(l,o), "SwiftenLibrary") - Export("swiften_env") + swiften_env = env.Clone() + swiften_env.Append(CPPDEFINES = ["SWIFTEN_BUILDING"]) + for module in swiften_dep_modules : + swiften_env.UseFlags(swiften_env.get(module + "_FLAGS", {})) + if env.get(module + "_BUNDLED", False) : + swiften_env.Append(SWIFTEN_OBJECTS = env.get(module + "_OBJECTS", [])) + swiften_env.UseFlags(swiften_env["PLATFORM_FLAGS"]) + + if swiften_env["SWIFTEN_DLL"] : + swiften_env.AddMethod(lambda e,l,o : e.SharedLibrary(l,o), "SwiftenLibrary") + else : + swiften_env.Append(CPPDEFINES = ["SWIFTEN_STATIC"]) + swiften_env.AddMethod(lambda e,l,o : e.StaticLibrary(l,o), "SwiftenLibrary") + Export("swiften_env") # TODO: Move all this to a submodule SConscript - sources = [ - "Chat/ChatStateTracker.cpp", - "Chat/ChatStateNotifier.cpp", - "Client/ClientSessionStanzaChannel.cpp", - "Client/CoreClient.cpp", - "Client/Client.cpp", - "Client/ClientXMLTracer.cpp", - "Client/ClientSession.cpp", - "Client/BlockList.cpp", - "Client/BlockListImpl.cpp", - "Client/ClientBlockListManager.cpp", - "Client/MemoryStorages.cpp", - "Client/NickResolver.cpp", - "Client/NickManager.cpp", - "Client/NickManagerImpl.cpp", - "Client/Storages.cpp", - "Client/XMLBeautifier.cpp", - "Compress/ZLibCodecompressor.cpp", - "Compress/ZLibDecompressor.cpp", - "Compress/ZLibCompressor.cpp", - "Elements/DiscoInfo.cpp", - "Elements/Presence.cpp", - "Elements/Form.cpp", - "Elements/FormField.cpp", - "Elements/StreamFeatures.cpp", - "Elements/Element.cpp", - "Elements/IQ.cpp", - "Elements/Payload.cpp", - "Elements/PubSubPayload.cpp", - "Elements/PubSubOwnerPayload.cpp", - "Elements/PubSubEventPayload.cpp", - "Elements/RosterItemExchangePayload.cpp", - "Elements/RosterPayload.cpp", - "Elements/Stanza.cpp", - "Elements/StanzaAck.cpp", - "Elements/StatusShow.cpp", - "Elements/StreamManagementEnabled.cpp", - "Elements/StreamResume.cpp", - "Elements/StreamResumed.cpp", - "Elements/UserLocation.cpp", - "Elements/VCard.cpp", - "Elements/MUCOccupant.cpp", - "Entity/Entity.cpp", - "Entity/PayloadPersister.cpp", - "MUC/MUC.cpp", - "MUC/MUCManager.cpp", - "MUC/MUCRegistry.cpp", - "MUC/MUCBookmarkManager.cpp", - "PubSub/PubSubManager.cpp", - "PubSub/PubSubManagerImpl.cpp", - "Queries/IQChannel.cpp", - "Queries/IQHandler.cpp", - "Queries/IQRouter.cpp", - "Queries/Request.cpp", - "Queries/Requests/GetInBandRegistrationFormRequest.cpp", - "Queries/Requests/SubmitInBandRegistrationFormRequest.cpp", - "Queries/Responders/SoftwareVersionResponder.cpp", - "Roster/RosterStorage.cpp", - "Roster/RosterMemoryStorage.cpp", - "Roster/XMPPRoster.cpp", - "Roster/XMPPRosterImpl.cpp", - "Roster/XMPPRosterController.cpp", - "Serializer/AuthRequestSerializer.cpp", - "Serializer/AuthSuccessSerializer.cpp", - "Serializer/AuthChallengeSerializer.cpp", - "Serializer/AuthResponseSerializer.cpp", - "Serializer/CompressRequestSerializer.cpp", - "Serializer/ElementSerializer.cpp", - "Serializer/MessageSerializer.cpp", - "Serializer/StreamManagementEnabledSerializer.cpp", - "Serializer/StreamResumeSerializer.cpp", - "Serializer/StreamResumedSerializer.cpp", - "Serializer/ComponentHandshakeSerializer.cpp", - "Serializer/PayloadSerializer.cpp", - "Serializer/PayloadSerializerCollection.cpp", - "Serializer/PayloadSerializers/IBBSerializer.cpp", - "Serializer/PayloadSerializers/CapsInfoSerializer.cpp", - "Serializer/PayloadSerializers/ChatStateSerializer.cpp", - "Serializer/PayloadSerializers/DiscoInfoSerializer.cpp", - "Serializer/PayloadSerializers/DiscoItemsSerializer.cpp", - "Serializer/PayloadSerializers/ErrorSerializer.cpp", - "Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp", - "Serializer/PayloadSerializers/MUCPayloadSerializer.cpp", - "Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp", - "Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp", - "Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.cpp", - "Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.cpp", - "Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp", - "Serializer/PayloadSerializers/ResourceBindSerializer.cpp", - "Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp", - "Serializer/PayloadSerializers/RosterSerializer.cpp", - "Serializer/PayloadSerializers/SecurityLabelSerializer.cpp", - "Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.cpp", - "Serializer/PayloadSerializers/SoftwareVersionSerializer.cpp", - "Serializer/PayloadSerializers/StreamInitiationSerializer.cpp", - "Serializer/PayloadSerializers/BytestreamsSerializer.cpp", - "Serializer/PayloadSerializers/VCardSerializer.cpp", - "Serializer/PayloadSerializers/VCardUpdateSerializer.cpp", - "Serializer/PayloadSerializers/StorageSerializer.cpp", - "Serializer/PayloadSerializers/PrivateStorageSerializer.cpp", - "Serializer/PayloadSerializers/DelaySerializer.cpp", - "Serializer/PayloadSerializers/CommandSerializer.cpp", - "Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp", - "Serializer/PayloadSerializers/SearchPayloadSerializer.cpp", - "Serializer/PayloadSerializers/FormSerializer.cpp", - "Serializer/PayloadSerializers/NicknameSerializer.cpp", - "Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp", - "Serializer/PayloadSerializers/JinglePayloadSerializer.cpp", - "Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp", - "Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp", - "Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.cpp", - "Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp", - "Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.cpp", - "Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.cpp", - "Serializer/PayloadSerializers/DeliveryReceiptSerializer.cpp", - "Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp", - "Serializer/PayloadSerializers/UserLocationSerializer.cpp", - "Serializer/PayloadSerializers/WhiteboardSerializer.cpp", - "Serializer/PresenceSerializer.cpp", - "Serializer/StanzaSerializer.cpp", - "Serializer/StreamErrorSerializer.cpp", - "Serializer/StreamFeaturesSerializer.cpp", - "Serializer/XML/XMLElement.cpp", - "Serializer/XML/XMLNode.cpp", - "Serializer/XMPPSerializer.cpp", - "Session/Session.cpp", - "Session/SessionTracer.cpp", - "Session/SessionStream.cpp", - "Session/BasicSessionStream.cpp", - "Session/BOSHSessionStream.cpp", - "StringCodecs/Base64.cpp", - "StringCodecs/Hexify.cpp", - "Whiteboard/WhiteboardResponder.cpp", - "Whiteboard/WhiteboardSession.cpp", - "Whiteboard/IncomingWhiteboardSession.cpp", - "Whiteboard/OutgoingWhiteboardSession.cpp", - "Whiteboard/WhiteboardSessionManager.cpp", - "Whiteboard/WhiteboardServer.cpp", - "Whiteboard/WhiteboardClient.cpp", - "Elements/Whiteboard/WhiteboardColor.cpp", - "Whiteboard/WhiteboardTransformer.cpp", - ] - - elements = [ - "PubSub", "PubSubAffiliations", "PubSubAffiliation", "PubSubConfigure", "PubSubCreate", "PubSubDefault", - "PubSubItems", "PubSubItem", "PubSubOptions", "PubSubPublish", "PubSubRetract", "PubSubSubscribeOptions", - "PubSubSubscribe", "PubSubSubscriptions", "PubSubSubscription", "PubSubUnsubscribe", + sources = [ + "Base/Debug.cpp", + "Chat/ChatStateTracker.cpp", + "Chat/ChatStateNotifier.cpp", + "Client/ClientSessionStanzaChannel.cpp", + "Client/CoreClient.cpp", + "Client/Client.cpp", + "Client/ClientXMLTracer.cpp", + "Client/ClientSession.cpp", + "Client/BlockList.cpp", + "Client/BlockListImpl.cpp", + "Client/ClientBlockListManager.cpp", + "Client/MemoryStorages.cpp", + "Client/NickResolver.cpp", + "Client/NickManager.cpp", + "Client/NickManagerImpl.cpp", + "Client/Storages.cpp", + "Client/XMLBeautifier.cpp", + "Compress/ZLibCodecompressor.cpp", + "Compress/ZLibDecompressor.cpp", + "Compress/ZLibCompressor.cpp", + "Elements/CarbonsEnable.cpp", + "Elements/CarbonsDisable.cpp", + "Elements/CarbonsPrivate.cpp", + "Elements/CarbonsReceived.cpp", + "Elements/CarbonsSent.cpp", + "Elements/DiscoInfo.cpp", + "Elements/Presence.cpp", + "Elements/Form.cpp", + "Elements/FormField.cpp", + "Elements/FormPage.cpp", + "Elements/FormSection.cpp", + "Elements/FormText.cpp", + "Elements/StreamFeatures.cpp", + "Elements/Element.cpp", + "Elements/ToplevelElement.cpp", + "Elements/IQ.cpp", + "Elements/Payload.cpp", + "Elements/PubSubPayload.cpp", + "Elements/PubSubOwnerPayload.cpp", + "Elements/PubSubEventPayload.cpp", + "Elements/ReferencePayload.cpp", + "Elements/RosterItemExchangePayload.cpp", + "Elements/RosterPayload.cpp", + "Elements/SecurityLabel.cpp", + "Elements/Stanza.cpp", + "Elements/StanzaAck.cpp", + "Elements/StatusShow.cpp", + "Elements/StreamManagementEnabled.cpp", + "Elements/StreamResume.cpp", + "Elements/StreamResumed.cpp", + "Elements/UserLocation.cpp", + "Elements/UserTune.cpp", + "Elements/VCard.cpp", + "Elements/MUCOccupant.cpp", + "Elements/ResultSet.cpp", + "Elements/Forwarded.cpp", + "Elements/MAMResult.cpp", + "Elements/MAMQuery.cpp", + "Elements/MAMFin.cpp", + "Elements/Thread.cpp", + "Elements/IsodeIQDelegation.cpp", + "Entity/Entity.cpp", + "Entity/PayloadPersister.cpp", + "MIX/MIX.cpp", + "MIX/MIXImpl.cpp", + "MUC/MUC.cpp", + "MUC/MUCImpl.cpp", + "MUC/MUCManager.cpp", + "MUC/MUCRegistry.cpp", + "MUC/MUCBookmarkManager.cpp", + "PubSub/PubSubManager.cpp", + "PubSub/PubSubManagerImpl.cpp", + "Queries/IQChannel.cpp", + "Queries/IQHandler.cpp", + "Queries/IQRouter.cpp", + "Queries/Request.cpp", + "Queries/Responders/SoftwareVersionResponder.cpp", + "Roster/RosterStorage.cpp", + "Roster/RosterMemoryStorage.cpp", + "Roster/XMPPRoster.cpp", + "Roster/XMPPRosterImpl.cpp", + "Roster/XMPPRosterController.cpp", + "Serializer/AuthRequestSerializer.cpp", + "Serializer/AuthSuccessSerializer.cpp", + "Serializer/AuthChallengeSerializer.cpp", + "Serializer/AuthResponseSerializer.cpp", + "Serializer/CompressRequestSerializer.cpp", + "Serializer/ElementSerializer.cpp", + "Serializer/MessageSerializer.cpp", + "Serializer/StreamManagementEnabledSerializer.cpp", + "Serializer/StreamResumeSerializer.cpp", + "Serializer/StreamResumedSerializer.cpp", + "Serializer/ComponentHandshakeSerializer.cpp", + "Serializer/PayloadSerializer.cpp", + "Serializer/PayloadSerializerCollection.cpp", + "Serializer/PayloadSerializers/IBBSerializer.cpp", + "Serializer/PayloadSerializers/CapsInfoSerializer.cpp", + "Serializer/PayloadSerializers/CarbonsDisableSerializer.cpp", + "Serializer/PayloadSerializers/CarbonsEnableSerializer.cpp", + "Serializer/PayloadSerializers/CarbonsPrivateSerializer.cpp", + "Serializer/PayloadSerializers/CarbonsSentSerializer.cpp", + "Serializer/PayloadSerializers/CarbonsReceivedSerializer.cpp", + "Serializer/PayloadSerializers/ChatStateSerializer.cpp", + "Serializer/PayloadSerializers/ClientStateSerializer.cpp", + "Serializer/PayloadSerializers/DiscoInfoSerializer.cpp", + "Serializer/PayloadSerializers/DiscoItemsSerializer.cpp", + "Serializer/PayloadSerializers/ErrorSerializer.cpp", + "Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp", + "Serializer/PayloadSerializers/MIXParticipantSerializer.cpp", + "Serializer/PayloadSerializers/MIXSetNickSerializer.cpp", + "Serializer/PayloadSerializers/MIXRegisterNickSerializer.cpp", + "Serializer/PayloadSerializers/MIXDestroySerializer.cpp", + "Serializer/PayloadSerializers/MIXCreateSerializer.cpp", + "Serializer/PayloadSerializers/MIXPayloadSerializer.cpp", + "Serializer/PayloadSerializers/MIXUserPreferenceSerializer.cpp", + "Serializer/PayloadSerializers/MIXLeaveSerializer.cpp", + "Serializer/PayloadSerializers/MIXJoinSerializer.cpp", + "Serializer/PayloadSerializers/MIXUpdateSubscriptionSerializer.cpp", + "Serializer/PayloadSerializers/MUCPayloadSerializer.cpp", + "Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp", + "Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp", + "Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.cpp", + "Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.cpp", + "Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp", + "Serializer/PayloadSerializers/ReferencePayloadSerializer.cpp", + "Serializer/PayloadSerializers/ResourceBindSerializer.cpp", + "Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp", + "Serializer/PayloadSerializers/RosterSerializer.cpp", + "Serializer/PayloadSerializers/SecurityLabelSerializer.cpp", + "Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.cpp", + "Serializer/PayloadSerializers/SoftwareVersionSerializer.cpp", + "Serializer/PayloadSerializers/StreamInitiationSerializer.cpp", + "Serializer/PayloadSerializers/BytestreamsSerializer.cpp", + "Serializer/PayloadSerializers/VCardSerializer.cpp", + "Serializer/PayloadSerializers/VCardUpdateSerializer.cpp", + "Serializer/PayloadSerializers/StorageSerializer.cpp", + "Serializer/PayloadSerializers/PrivateStorageSerializer.cpp", + "Serializer/PayloadSerializers/DelaySerializer.cpp", + "Serializer/PayloadSerializers/CommandSerializer.cpp", + "Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp", + "Serializer/PayloadSerializers/SearchPayloadSerializer.cpp", + "Serializer/PayloadSerializers/FormSerializer.cpp", + "Serializer/PayloadSerializers/NicknameSerializer.cpp", + "Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp", + "Serializer/PayloadSerializers/JinglePayloadSerializer.cpp", + "Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp", + "Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp", + "Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp", + "Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.cpp", + "Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.cpp", + "Serializer/PayloadSerializers/DeliveryReceiptSerializer.cpp", + "Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp", + "Serializer/PayloadSerializers/UserLocationSerializer.cpp", + "Serializer/PayloadSerializers/UserTuneSerializer.cpp", + "Serializer/PayloadSerializers/WhiteboardSerializer.cpp", + "Serializer/PayloadSerializers/ResultSetSerializer.cpp", + "Serializer/PayloadSerializers/ForwardedSerializer.cpp", + "Serializer/PayloadSerializers/MAMFinSerializer.cpp", + "Serializer/PayloadSerializers/MAMResultSerializer.cpp", + "Serializer/PayloadSerializers/MAMQuerySerializer.cpp", + "Serializer/PayloadSerializers/IsodeIQDelegationSerializer.cpp", + "Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp", + "Serializer/PayloadSerializers/ThreadSerializer.cpp", + "Serializer/PresenceSerializer.cpp", + "Serializer/StanzaSerializer.cpp", + "Serializer/StreamErrorSerializer.cpp", + "Serializer/StreamFeaturesSerializer.cpp", + "Serializer/XML/XMLElement.cpp", + "Serializer/XML/XMLNode.cpp", + "Serializer/XMPPSerializer.cpp", + "Session/Session.cpp", + "Session/SessionTracer.cpp", + "Session/SessionStream.cpp", + "Session/BasicSessionStream.cpp", + "Session/BOSHSessionStream.cpp", + "StringCodecs/Base64.cpp", + "StringCodecs/Hexify.cpp", + "Whiteboard/WhiteboardResponder.cpp", + "Whiteboard/WhiteboardSession.cpp", + "Whiteboard/IncomingWhiteboardSession.cpp", + "Whiteboard/OutgoingWhiteboardSession.cpp", + "Whiteboard/WhiteboardSessionManager.cpp", + "Whiteboard/WhiteboardServer.cpp", + "Whiteboard/WhiteboardClient.cpp", + "Elements/Whiteboard/WhiteboardColor.cpp", + "Whiteboard/WhiteboardTransformer.cpp", + ] + + elements = [ + "PubSub", "PubSubAffiliations", "PubSubAffiliation", "PubSubConfigure", "PubSubCreate", "PubSubDefault", + "PubSubItems", "PubSubItem", "PubSubOptions", "PubSubPublish", "PubSubRetract", "PubSubSubscribeOptions", + "PubSubSubscribe", "PubSubSubscriptions", "PubSubSubscription", "PubSubUnsubscribe", + + "PubSubEvent", "PubSubEventAssociate", "PubSubEventCollection", "PubSubEventConfiguration", "PubSubEventDelete", + "PubSubEventDisassociate", "PubSubEventItem", "PubSubEventItems", "PubSubEventPurge", "PubSubEventRedirect", + "PubSubEventRetract", "PubSubEventSubscription", + + "PubSubOwnerAffiliation", "PubSubOwnerAffiliations", "PubSubOwnerConfigure", "PubSubOwnerDefault", + "PubSubOwnerDelete", "PubSubOwnerPubSub", "PubSubOwnerPurge", "PubSubOwnerRedirect", + "PubSubOwnerSubscription", "PubSubOwnerSubscriptions", - "PubSubEvent", "PubSubEventAssociate", "PubSubEventCollection", "PubSubEventConfiguration", "PubSubEventDelete", - "PubSubEventDisassociate", "PubSubEventItem", "PubSubEventItems", "PubSubEventPurge", "PubSubEventRedirect", - "PubSubEventRetract", "PubSubEventSubscription", + "PubSubError", + ] + for element in elements : + sources += [ + "Elements/" + element + ".cpp", + "Serializer/PayloadSerializers/" + element + "Serializer.cpp", + "Parser/PayloadParsers/" + element + "Parser.cpp", + ] - "PubSubOwnerAffiliation", "PubSubOwnerAffiliations", "PubSubOwnerConfigure", "PubSubOwnerDefault", - "PubSubOwnerDelete", "PubSubOwnerPubSub", "PubSubOwnerPurge", "PubSubOwnerRedirect", - "PubSubOwnerSubscription", "PubSubOwnerSubscriptions", + SConscript(dirs = [ + "Avatars", + "Base", + "IDN", + "SASL", + "TLS", + "Crypto", + "EventLoop", + "Parser", + "JID", + "Jingle", + "Disco", + "VCards", + "Network", + "Presence", + "FileTransfer", + "History", + "StreamStack", + "LinkLocal", + "StreamManagement", + "Component", + "AdHoc" + ]) + if env["build_examples"] : + SConscript(dirs = [ + "Config", + "Examples" + ]) + env.SConscript(test_only = True, dirs = [ + "QA", + ]) - "PubSubError", - ] - for element in elements : - sources += [ - "Elements/" + element + ".cpp", - "Serializer/PayloadSerializers/" + element + "Serializer.cpp", - "Parser/PayloadParsers/" + element + "Parser.cpp", - ] + myenv = swiften_env.Clone() + if myenv["PLATFORM"] != "darwin" and myenv["PLATFORM"] != "win32" and myenv.get("HAVE_GCONF", 0) : + env.MergeFlags(env["GCONF_FLAGS"]) - SConscript(dirs = [ - "Avatars", - "Base", - "IDN", - "SASL", - "TLS", - "Crypto", - "EventLoop", - "Parser", - "JID", - "Jingle", - "Disco", - "VCards", - "Network", - "Presence", - "FileTransfer", - "History", - "StreamStack", - "LinkLocal", - "StreamManagement", - "Component", - "AdHoc" - ]) - if env["build_examples"] : - SConscript(dirs = [ - "Config", - "Examples" - ]) - env.SConscript(test_only = True, dirs = [ - "QA", - ]) + if myenv["SWIFTEN_DLL"] : + if myenv["PLATFORM"] == "posix" : + myenv.Append(LINKFLAGS = ["-Wl,-soname,libSwiften.so.$SWIFTEN_VERSION_MAJOR"]) + myenv["SHLIBSUFFIX"] = "" + elif myenv["PLATFORM"] == "darwin" : + myenv.Append(LINKFLAGS = ["-Wl,-install_name,${SHLIBPREFIX}Swiften.${SWIFTEN_VERSION_MAJOR}${SHLIBSUFFIX}", "-Wl,-compatibility_version,${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}", "-Wl,-current_version,${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}"]) + elif myenv["PLATFORM"] == "win32" : + res_env = myenv.Clone() + res_env.Append(CPPDEFINES = [ + ("SWIFTEN_LIBRARY_FILE", "\"\\\"${SWIFTEN_LIBRARY_FILE}\\\"\""), + ("SWIFTEN_COPYRIGHT_YEAR", "\"\\\"2010-%s\\\"\"" % str(time.localtime()[0])), + ("SWIFTEN_VERSION_MAJOR", "${SWIFTEN_VERSION_MAJOR}"), + ("SWIFTEN_VERSION_MINOR", "${SWIFTEN_VERSION_MINOR}"), + ("SWIFTEN_VERSION_PATCH", "${SWIFTEN_VERSION_PATCH}"), + ]) + res = res_env.RES("Swiften.rc") + # For some reason, SCons isn't picking up the dependency correctly + # Adding it explicitly until i figure out why + res_env.Depends(res, "Version.h") + sources += res - myenv = swiften_env.Clone() - if myenv["PLATFORM"] != "darwin" and myenv["PLATFORM"] != "win32" and myenv.get("HAVE_GCONF", 0) : - env.MergeFlags(env["GCONF_FLAGS"]) + swiften_lib = myenv.SwiftenLibrary(swiften_env["SWIFTEN_LIBRARY_FILE"], sources + swiften_env["SWIFTEN_OBJECTS"]) + def symlink(env, target, source) : + if os.path.exists(str(target[0])) : + os.unlink(str(target[0])) + os.symlink(source[0].get_contents(), str(target[0])) + for alias in myenv["SWIFTEN_LIBRARY_ALIASES"] : + myenv.Command(myenv.File(alias), [myenv.Value(swiften_lib[0].name), swiften_lib[0]], symlink) - if myenv["SWIFTEN_DLL"] : - if myenv["PLATFORM"] == "posix" : - myenv.Append(LINKFLAGS = ["-Wl,-soname,libSwiften.so.$SWIFTEN_VERSION_MAJOR"]) - myenv["SHLIBSUFFIX"] = "" - elif myenv["PLATFORM"] == "darwin" : - myenv.Append(LINKFLAGS = ["-Wl,-install_name,${SHLIBPREFIX}Swiften.${SWIFTEN_VERSION_MAJOR}${SHLIBSUFFIX}", "-Wl,-compatibility_version,${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}", "-Wl,-current_version,${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}"]) - elif myenv["PLATFORM"] == "win32" : - res_env = myenv.Clone() - res_env.Append(CPPDEFINES = [ - ("SWIFTEN_LIBRARY_FILE", "\"\\\"${SWIFTEN_LIBRARY_FILE}\\\"\""), - ("SWIFTEN_COPYRIGHT_YEAR", "\"\\\"2010-%s\\\"\"" % str(time.localtime()[0])), - ("SWIFTEN_VERSION_MAJOR", "${SWIFTEN_VERSION_MAJOR}"), - ("SWIFTEN_VERSION_MINOR", "${SWIFTEN_VERSION_MINOR}"), - ("SWIFTEN_VERSION_PATCH", "${SWIFTEN_VERSION_PATCH}"), - ]) - res = res_env.RES("Swiften.rc") - # For some reason, SCons isn't picking up the dependency correctly - # Adding it explicitly until i figure out why - res_env.Depends(res, "Version.h") - sources += res + env.Append(UNITTEST_SOURCES = [ + File("Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp"), + File("Avatars/UnitTest/VCardAvatarManagerTest.cpp"), + File("Avatars/UnitTest/CombinedAvatarProviderTest.cpp"), + File("Avatars/UnitTest/AvatarManagerImplTest.cpp"), + File("Base/UnitTest/IDGeneratorTest.cpp"), + File("Base/UnitTest/LogTest.cpp"), + File("Base/UnitTest/LRUCacheTest.cpp"), + File("Base/UnitTest/SimpleIDGeneratorTest.cpp"), + File("Base/UnitTest/StringTest.cpp"), + File("Base/UnitTest/DateTimeTest.cpp"), + File("Base/UnitTest/ByteArrayTest.cpp"), + File("Base/UnitTest/URLTest.cpp"), + File("Base/UnitTest/PathTest.cpp"), + File("Chat/UnitTest/ChatStateNotifierTest.cpp"), +# File("Chat/UnitTest/ChatStateTrackerTest.cpp"), + File("Client/UnitTest/ClientSessionTest.cpp"), + File("Client/UnitTest/NickResolverTest.cpp"), + File("Client/UnitTest/ClientBlockListManagerTest.cpp"), + File("Client/UnitTest/BlockListImplTest.cpp"), + File("Client/UnitTest/XMLBeautifierTest.cpp"), + File("Compress/UnitTest/ZLibCompressorTest.cpp"), + File("Compress/UnitTest/ZLibDecompressorTest.cpp"), + File("Component/UnitTest/ComponentHandshakeGeneratorTest.cpp"), + File("Component/UnitTest/ComponentConnectorTest.cpp"), + File("Component/UnitTest/ComponentSessionTest.cpp"), + File("Disco/UnitTest/CapsInfoGeneratorTest.cpp"), + File("Disco/UnitTest/CapsManagerTest.cpp"), + File("Disco/UnitTest/DiscoInfoResponderTest.cpp"), + File("Disco/UnitTest/EntityCapsManagerTest.cpp"), + File("Disco/UnitTest/FeatureOracleTest.cpp"), + File("Disco/UnitTest/JIDDiscoInfoResponderTest.cpp"), + File("Elements/UnitTest/IQTest.cpp"), + File("Elements/UnitTest/StanzaTest.cpp"), + File("Elements/UnitTest/FormTest.cpp"), + File("EventLoop/UnitTest/EventLoopTest.cpp"), + File("EventLoop/UnitTest/SimpleEventLoopTest.cpp"), +# File("History/UnitTest/SQLiteHistoryManagerTest.cpp"), + File("JID/UnitTest/JIDTest.cpp"), + File("LinkLocal/UnitTest/LinkLocalConnectorTest.cpp"), + File("LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp"), + File("LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp"), + File("LinkLocal/UnitTest/LinkLocalServiceTest.cpp"), + File("MIX/UnitTest/MIXImplTest.cpp"), + File("MUC/UnitTest/MUCTest.cpp"), + File("MUC/UnitTest/MockMUC.cpp"), + File("Network/UnitTest/HostAddressTest.cpp"), + File("Network/UnitTest/ConnectorTest.cpp"), + File("Network/UnitTest/ChainedConnectorTest.cpp"), + File("Network/UnitTest/DomainNameServiceQueryTest.cpp"), + File("Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp"), + File("Network/UnitTest/BOSHConnectionTest.cpp"), + File("Network/UnitTest/BOSHConnectionPoolTest.cpp"), + File("Parser/PayloadParsers/UnitTest/BlockParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/BodyParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/ClientStateParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/DiscoItemsParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/FormParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/CommandParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/PriorityParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/RawXMLPayloadParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/ReferencePayloadParserTest.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/InBandRegistrationPayloadParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/JingleParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MIXParticipantParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MIXPayloadParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MIXUpdateSubscriptionParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MIXRegisterNickParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MIXSetNickParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MIXDestroyParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MIXLeaveParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MIXCreateParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MIXUserPreferenceParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/StatusParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/StreamInitiationParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/VCardParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/StorageParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/ReplaceTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp"), + 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/MIXJoinParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MAMFinParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MAMResultParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/MAMQueryParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/CarbonsParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/UserTuneParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/UserLocationParserTest.cpp"), + File("Parser/PayloadParsers/UnitTest/PubSubRetractParserTest.cpp"), + File("Parser/UnitTest/BOSHBodyExtractorTest.cpp"), + File("Parser/UnitTest/AttributeMapTest.cpp"), + File("Parser/UnitTest/EnumParserTest.cpp"), + File("Parser/UnitTest/IQParserTest.cpp"), + File("Parser/UnitTest/GenericPayloadTreeParserTest.cpp"), + File("Parser/UnitTest/MessageParserTest.cpp"), + File("Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp"), + File("Parser/UnitTest/PresenceParserTest.cpp"), + File("Parser/UnitTest/StanzaAckParserTest.cpp"), + File("Parser/UnitTest/SerializingParserTest.cpp"), + File("Parser/UnitTest/StanzaParserTest.cpp"), + File("Parser/UnitTest/StreamFeaturesParserTest.cpp"), + File("Parser/UnitTest/StreamManagementEnabledParserTest.cpp"), + File("Parser/UnitTest/XMLParserTest.cpp"), + File("Parser/UnitTest/XMPPParserTest.cpp"), + File("Presence/UnitTest/PresenceOracleTest.cpp"), + File("Presence/UnitTest/DirectedPresenceSenderTest.cpp"), + File("Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp"), + File("Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp"), + File("Queries/UnitTest/IQRouterTest.cpp"), + File("Queries/UnitTest/RequestTest.cpp"), + File("Queries/UnitTest/ResponderTest.cpp"), + File("Roster/UnitTest/XMPPRosterImplTest.cpp"), + File("Roster/UnitTest/XMPPRosterControllerTest.cpp"), + File("Roster/UnitTest/XMPPRosterSignalHandler.cpp"), + File("Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.cpp"), + File("Serializer/PayloadSerializers/UnitTest/BlockSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/CarbonsSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/CapsInfoSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/ChatStateSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/ClientStateSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/DiscoInfoSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/ErrorSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/IBBSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/PrioritySerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/ReferencePayloadSerializerTest.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"), + File("Serializer/PayloadSerializers/UnitTest/SecurityLabelsCatalogSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/SoftwareVersionSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/StatusSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/StatusShowSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/IsodeIQDelegationSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/VCardUpdateSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/StorageSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/ReplaceSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MIXParticipantSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MIXSetNickSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MIXUpdateSubscriptionSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MIXRegisterNickSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MIXDestroySerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MIXCreateSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MIXPayloadSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MIXUserPreferenceSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MIXLeaveSerializerTest.cpp"), + 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/MIXJoinSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MAMFinSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MAMResultSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/MAMQuerySerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/PubSubItemSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/PubSubItemsSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/PubSubRetractSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/UserTuneSerializerTest.cpp"), + File("Serializer/PayloadSerializers/UnitTest/UserLocationSerializerTest.cpp"), + File("Serializer/UnitTest/StreamFeaturesSerializerTest.cpp"), + File("Serializer/UnitTest/AuthSuccessSerializerTest.cpp"), + File("Serializer/UnitTest/AuthChallengeSerializerTest.cpp"), + File("Serializer/UnitTest/AuthRequestSerializerTest.cpp"), + File("Serializer/UnitTest/AuthResponseSerializerTest.cpp"), + File("Serializer/UnitTest/XMPPSerializerTest.cpp"), + File("Serializer/XML/UnitTest/XMLElementTest.cpp"), + File("StreamManagement/UnitTest/StanzaAckRequesterTest.cpp"), + File("StreamManagement/UnitTest/StanzaAckResponderTest.cpp"), + File("StreamStack/UnitTest/StreamStackTest.cpp"), + File("StreamStack/UnitTest/XMPPLayerTest.cpp"), + File("StringCodecs/UnitTest/Base64Test.cpp"), + File("StringCodecs/UnitTest/HexifyTest.cpp"), + File("StringCodecs/UnitTest/PBKDF2Test.cpp"), + File("TLS/UnitTest/ServerIdentityVerifierTest.cpp"), + File("TLS/UnitTest/CertificateTest.cpp"), + File("VCards/UnitTest/VCardManagerTest.cpp"), + File("Whiteboard/UnitTest/WhiteboardServerTest.cpp"), + File("Whiteboard/UnitTest/WhiteboardClientTest.cpp"), + ]) + if env.get("HAVE_OPENSSL", 0) : + env.Append(UNITTEST_SOURCES = [ + File("TLS/UnitTest/ClientServerTest.cpp"), + ]) - swiften_lib = myenv.SwiftenLibrary(swiften_env["SWIFTEN_LIBRARY_FILE"], sources + swiften_env["SWIFTEN_OBJECTS"]) - def symlink(env, target, source) : - if os.path.exists(str(target[0])) : - os.unlink(str(target[0])) - os.symlink(source[0].get_contents(), str(target[0])) - for alias in myenv["SWIFTEN_LIBRARY_ALIASES"] : - myenv.Command(myenv.File(alias), [myenv.Value(swiften_lib[0].name), swiften_lib[0]], symlink) + # Generate the Swiften header + def relpath(path, start) : + i = len(os.path.commonprefix([path, start])) + return path[i+1:] + swiften_header = "#pragma once\n" + swiften_includes = [] + swiften_public_includes = [] + top_path = env.Dir("..").abspath + for root, dirs, files in os.walk(env.Dir(".").abspath) : + dirs.sort() + files.sort() + if root.endswith("UnitTest") : + continue + for file in files : + if not file.endswith(".h") : + continue + include = relpath(os.path.join(root, file), top_path) + if swiften_env["PLATFORM"] == "win32" : + include = include.replace("\\", "/") + swiften_includes.append(include) + # Private modules + if root.endswith("Config") : + continue - env.Append(UNITTEST_SOURCES = [ - File("Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp"), - File("Avatars/UnitTest/VCardAvatarManagerTest.cpp"), - File("Avatars/UnitTest/CombinedAvatarProviderTest.cpp"), - File("Base/UnitTest/IDGeneratorTest.cpp"), - File("Base/UnitTest/SimpleIDGeneratorTest.cpp"), - File("Base/UnitTest/StringTest.cpp"), - File("Base/UnitTest/DateTimeTest.cpp"), - File("Base/UnitTest/ByteArrayTest.cpp"), - File("Base/UnitTest/URLTest.cpp"), - File("Base/UnitTest/PathTest.cpp"), - File("Chat/UnitTest/ChatStateNotifierTest.cpp"), -# File("Chat/UnitTest/ChatStateTrackerTest.cpp"), - File("Client/UnitTest/ClientSessionTest.cpp"), - File("Client/UnitTest/NickResolverTest.cpp"), - File("Client/UnitTest/ClientBlockListManagerTest.cpp"), - File("Compress/UnitTest/ZLibCompressorTest.cpp"), - File("Compress/UnitTest/ZLibDecompressorTest.cpp"), - File("Component/UnitTest/ComponentHandshakeGeneratorTest.cpp"), - File("Component/UnitTest/ComponentConnectorTest.cpp"), - File("Component/UnitTest/ComponentSessionTest.cpp"), - File("Disco/UnitTest/CapsInfoGeneratorTest.cpp"), - File("Disco/UnitTest/CapsManagerTest.cpp"), - File("Disco/UnitTest/EntityCapsManagerTest.cpp"), - File("Disco/UnitTest/JIDDiscoInfoResponderTest.cpp"), - File("Disco/UnitTest/DiscoInfoResponderTest.cpp"), - File("Elements/UnitTest/IQTest.cpp"), - File("Elements/UnitTest/StanzaTest.cpp"), - File("Elements/UnitTest/FormTest.cpp"), - File("EventLoop/UnitTest/EventLoopTest.cpp"), - File("EventLoop/UnitTest/SimpleEventLoopTest.cpp"), -# File("History/UnitTest/SQLiteHistoryManagerTest.cpp"), - File("JID/UnitTest/JIDTest.cpp"), - File("LinkLocal/UnitTest/LinkLocalConnectorTest.cpp"), - File("LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp"), - File("LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp"), - File("LinkLocal/UnitTest/LinkLocalServiceTest.cpp"), - File("MUC/UnitTest/MUCTest.cpp"), - File("Network/UnitTest/HostAddressTest.cpp"), - File("Network/UnitTest/ConnectorTest.cpp"), - File("Network/UnitTest/ChainedConnectorTest.cpp"), - File("Network/UnitTest/DomainNameServiceQueryTest.cpp"), - File("Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp"), - File("Network/UnitTest/BOSHConnectionTest.cpp"), - File("Network/UnitTest/BOSHConnectionPoolTest.cpp"), - File("Parser/PayloadParsers/UnitTest/BlockParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/BodyParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/DiscoInfoParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/DiscoItemsParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/ErrorParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/FormParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/CommandParserTest.cpp"), - 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/JingleParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/SecurityLabelParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/SecurityLabelsCatalogParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/StatusParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/StreamInitiationParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/VCardParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/StorageParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/ReplaceTest.cpp"), - File("Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/DeliveryReceiptParserTest.cpp"), - File("Parser/PayloadParsers/UnitTest/IdleParserTest.cpp"), - File("Parser/UnitTest/BOSHBodyExtractorTest.cpp"), - File("Parser/UnitTest/AttributeMapTest.cpp"), - File("Parser/UnitTest/EnumParserTest.cpp"), - File("Parser/UnitTest/IQParserTest.cpp"), - File("Parser/UnitTest/GenericPayloadTreeParserTest.cpp"), - File("Parser/UnitTest/MessageParserTest.cpp"), - File("Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp"), - File("Parser/UnitTest/PresenceParserTest.cpp"), - File("Parser/UnitTest/StanzaAckParserTest.cpp"), - File("Parser/UnitTest/SerializingParserTest.cpp"), - File("Parser/UnitTest/StanzaParserTest.cpp"), - File("Parser/UnitTest/StreamFeaturesParserTest.cpp"), - File("Parser/UnitTest/StreamManagementEnabledParserTest.cpp"), - File("Parser/UnitTest/XMLParserTest.cpp"), - File("Parser/UnitTest/XMPPParserTest.cpp"), - File("Presence/UnitTest/PresenceOracleTest.cpp"), - File("Presence/UnitTest/DirectedPresenceSenderTest.cpp"), - File("Presence/UnitTest/PayloadAddingPresenceSenderTest.cpp"), - File("Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp"), - File("Queries/UnitTest/IQRouterTest.cpp"), - File("Queries/UnitTest/RequestTest.cpp"), - File("Queries/UnitTest/ResponderTest.cpp"), - File("Roster/UnitTest/XMPPRosterImplTest.cpp"), - File("Roster/UnitTest/XMPPRosterControllerTest.cpp"), - File("Roster/UnitTest/XMPPRosterSignalHandler.cpp"), - File("Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.cpp"), - File("Serializer/PayloadSerializers/UnitTest/BlockSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/CapsInfoSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/DiscoInfoSerializerTest.cpp"), - 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"), - File("Serializer/PayloadSerializers/UnitTest/SecurityLabelsCatalogSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/SoftwareVersionSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/StatusSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/StatusShowSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/VCardUpdateSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/StorageSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/ReplaceSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/DeliveryReceiptSerializerTest.cpp"), - File("Serializer/PayloadSerializers/UnitTest/IdleSerializerTest.cpp"), - File("Serializer/UnitTest/StreamFeaturesSerializerTest.cpp"), - File("Serializer/UnitTest/AuthSuccessSerializerTest.cpp"), - File("Serializer/UnitTest/AuthChallengeSerializerTest.cpp"), - File("Serializer/UnitTest/AuthRequestSerializerTest.cpp"), - File("Serializer/UnitTest/AuthResponseSerializerTest.cpp"), - File("Serializer/UnitTest/XMPPSerializerTest.cpp"), - File("Serializer/XML/UnitTest/XMLElementTest.cpp"), - File("StreamManagement/UnitTest/StanzaAckRequesterTest.cpp"), - File("StreamManagement/UnitTest/StanzaAckResponderTest.cpp"), - File("StreamStack/UnitTest/StreamStackTest.cpp"), - File("StreamStack/UnitTest/XMPPLayerTest.cpp"), - File("StringCodecs/UnitTest/Base64Test.cpp"), - File("StringCodecs/UnitTest/HexifyTest.cpp"), - File("StringCodecs/UnitTest/PBKDF2Test.cpp"), - File("TLS/UnitTest/ServerIdentityVerifierTest.cpp"), - File("TLS/UnitTest/CertificateTest.cpp"), - File("VCards/UnitTest/VCardManagerTest.cpp"), - File("Whiteboard/UnitTest/WhiteboardServerTest.cpp"), - File("Whiteboard/UnitTest/WhiteboardClientTest.cpp"), - ]) - - # Generate the Swiften header - def relpath(path, start) : - i = len(os.path.commonprefix([path, start])) - return path[i+1:] - swiften_header = "#pragma once\n" - swiften_includes = [] - top_path = env.Dir("..").abspath - for root, dirs, files in os.walk(env.Dir(".").abspath) : - if root.endswith("UnitTest") : - continue - for file in files : - if not file.endswith(".h") : - continue - include = relpath(os.path.join(root, file), top_path) - if swiften_env["PLATFORM"] == "win32" : - include = include.replace("\\", "/") - swiften_includes.append(include) - # Private modules - if root.endswith("Config") : - continue + # Library-specfifc private modules + if root.endswith("OpenSSL") or root.endswith("Cocoa") or root.endswith("Qt") or root.endswith("Avahi") or root.endswith("Bonjour") : + continue - # Library-specfifc private modules - if root.endswith("OpenSSL") or root.endswith("Cocoa") or root.endswith("Qt") or root.endswith("Avahi") or root.endswith("Bonjour") : - continue + # Library-specific files + if file.endswith("_Private.h") or file.startswith("Schannel") or file.startswith("CAPI") or file.startswith("MacOSX") or file.startswith("SecureTransport") or file.startswith("Windows") or file.endswith("_Windows.h") or file.startswith("SQLite") or file == "ICUConverter.h" or file == "UnboundDomainNameResolver.h" : + continue - # Library-specific files - if file.endswith("_Private.h") or file.startswith("Schannel") or file.startswith("CAPI") or file.startswith("MacOSX") or file.startswith("Windows") or file.endswith("_Windows.h") or file.startswith("SQLite") or file == "ICUConverter.h" or file == "UnboundDomainNameResolver.h" : - continue + # Specific headers we don't want to globally include + if file == "Swiften.h" or file == "foreach.h" or file == "Log.h" or file == "format.h" : + continue + swiften_header += "#include <" + include + ">\n" + swiften_public_includes.append(include) + swiften_includes.append(include) + swiften_env.WriteVal("Swiften.h", swiften_env.Value(swiften_header)) + swiften_includes.append("Swiften/Swiften.h") - # Specific headers we don't want to globally include - if file == "Swiften.h" or file == "foreach.h" or file == "Log.h" or file == "format.h" : - continue - swiften_header += "#include <" + include + ">\n" - swiften_includes.append(include) - swiften_env.WriteVal("Swiften.h", swiften_env.Value(swiften_header)) - swiften_includes.append("Swiften/Swiften.h") + version_header = "#pragma once\n\n" + version_header += "#define SWIFTEN_VERSION 0x%02X%02X%02X\n" % (swiften_env["SWIFTEN_VERSION_MAJOR"], swiften_env["SWIFTEN_VERSION_MINOR"], swiften_env["SWIFTEN_VERSION_PATCH"]) + version_header += "#define SWIFTEN_VERSION_STRING \"%s\"\n" % swiften_env["SWIFTEN_VERSION"] + swiften_env.WriteVal("Version.h", swiften_env.Value(version_header)) + swiften_includes.append("Swiften/Version.h") - version_header = "#pragma once\n\n" - version_header += "#define SWIFTEN_VERSION 0x%02X%02X%02X\n" % (swiften_env["SWIFTEN_VERSION_MAJOR"], swiften_env["SWIFTEN_VERSION_MINOR"], swiften_env["SWIFTEN_VERSION_PATCH"]) - version_header += "#define SWIFTEN_VERSION_STRING \"%s\"\n" % swiften_env["SWIFTEN_VERSION"] - swiften_env.WriteVal("Version.h", swiften_env.Value(version_header)) - swiften_includes.append("Swiften/Version.h") + # Check headers + if env["check_headers"] : + test_env = swiften_env.Clone() + for header in swiften_public_includes: + program_text = "#include <%s>\n" % (header) + filename = Dir('#/.sconf_temp').abspath + ("/%s.cpp" % (urllib.quote(header, '') )) + text_file = open(filename, "w") + text_file.write(program_text) + text_file.close() + test_obj = test_env.Object(File("#/.sconf_temp/%s.cpp" % (urllib.quote(header, '') ))) + test_env.Default(test_obj) - # Install swiften - if swiften_env.get("SWIFTEN_INSTALLDIR", "") : - swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "lib"), swiften_lib) - for alias in myenv["SWIFTEN_LIBRARY_ALIASES"] : - myenv.Command(myenv.File(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "lib", alias)), [env.Value(swiften_lib[0].name), swiften_lib[0]], symlink) - for include in swiften_includes : - swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "include", os.path.dirname(include)), "#/" + include) + # Install swiften + if swiften_env.get("SWIFTEN_INSTALLDIR", "") : + swiften_libdir = swiften_env.get("SWIFTEN_LIBDIR", "lib") + swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], swiften_libdir), swiften_lib) + for alias in myenv["SWIFTEN_LIBRARY_ALIASES"] : + myenv.Command(myenv.File(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], swiften_libdir, alias)), [env.Value(swiften_lib[0].name), swiften_lib[0]], symlink) + for include in swiften_includes : + swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "include", os.path.dirname(include)), "#/" + include) diff --git a/Swiften/Serializer/AuthChallengeSerializer.cpp b/Swiften/Serializer/AuthChallengeSerializer.cpp index 1ddc165..8f963ff 100644 --- a/Swiften/Serializer/AuthChallengeSerializer.cpp +++ b/Swiften/Serializer/AuthChallengeSerializer.cpp @@ -1,33 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/AuthChallengeSerializer.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Elements/AuthChallenge.h> #include <Swiften/StringCodecs/Base64.h> -#include <Swiften/Base/ByteArray.h> namespace Swift { AuthChallengeSerializer::AuthChallengeSerializer() { } -SafeByteArray AuthChallengeSerializer::serialize(boost::shared_ptr<Element> element) const { - boost::shared_ptr<AuthChallenge> authChallenge(boost::dynamic_pointer_cast<AuthChallenge>(element)); - std::string value; - boost::optional<std::vector<unsigned char> > message = authChallenge->getValue(); - if (message) { - if ((*message).empty()) { - value = "="; - } - else { - value = Base64::encode(ByteArray(*message)); - } - } - return createSafeByteArray("<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + value + "</challenge>"); +SafeByteArray AuthChallengeSerializer::serialize(std::shared_ptr<ToplevelElement> element) const { + std::shared_ptr<AuthChallenge> authChallenge(std::dynamic_pointer_cast<AuthChallenge>(element)); + std::string value; + boost::optional<std::vector<unsigned char> > message = authChallenge->getValue(); + if (message) { + if ((*message).empty()) { + value = "="; + } + else { + value = Base64::encode(ByteArray(*message)); + } + } + return createSafeByteArray("<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + value + "</challenge>"); } } diff --git a/Swiften/Serializer/AuthChallengeSerializer.h b/Swiften/Serializer/AuthChallengeSerializer.h index 7d0b1b8..9bcf68b 100644 --- a/Swiften/Serializer/AuthChallengeSerializer.h +++ b/Swiften/Serializer/AuthChallengeSerializer.h @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Elements/AuthChallenge.h> #include <Swiften/Serializer/GenericElementSerializer.h> namespace Swift { - class SWIFTEN_API AuthChallengeSerializer : public GenericElementSerializer<AuthChallenge> { - public: - AuthChallengeSerializer(); + class SWIFTEN_API AuthChallengeSerializer : public GenericElementSerializer<AuthChallenge> { + public: + AuthChallengeSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const; + }; } diff --git a/Swiften/Serializer/AuthFailureSerializer.h b/Swiften/Serializer/AuthFailureSerializer.h index 090f0c4..a410e8c 100644 --- a/Swiften/Serializer/AuthFailureSerializer.h +++ b/Swiften/Serializer/AuthFailureSerializer.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/AuthFailure.h> #include <Swiften/Serializer/GenericElementSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class AuthFailureSerializer : public GenericElementSerializer<AuthFailure> { - public: - AuthFailureSerializer() : GenericElementSerializer<AuthFailure>() { - } + class SWIFTEN_API AuthFailureSerializer : public GenericElementSerializer<AuthFailure> { + public: + AuthFailureSerializer() : GenericElementSerializer<AuthFailure>() { + } - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const { - return createSafeByteArray(XMLElement("failure", "urn:ietf:params:xml:ns:xmpp-sasl").serialize()); - } - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const { + return createSafeByteArray(XMLElement("failure", "urn:ietf:params:xml:ns:xmpp-sasl").serialize()); + } + }; } diff --git a/Swiften/Serializer/AuthRequestSerializer.cpp b/Swiften/Serializer/AuthRequestSerializer.cpp index 7f25c93..2c9a4dd 100644 --- a/Swiften/Serializer/AuthRequestSerializer.cpp +++ b/Swiften/Serializer/AuthRequestSerializer.cpp @@ -1,34 +1,34 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/AuthRequestSerializer.h> +#include <Swiften/Base/Concat.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/Elements/AuthRequest.h> #include <Swiften/StringCodecs/Base64.h> -#include <Swiften/Base/SafeByteArray.h> -#include <Swiften/Base/Concat.h> namespace Swift { AuthRequestSerializer::AuthRequestSerializer() { } -SafeByteArray AuthRequestSerializer::serialize(boost::shared_ptr<Element> element) const { - boost::shared_ptr<AuthRequest> authRequest(boost::dynamic_pointer_cast<AuthRequest>(element)); - SafeByteArray value; - boost::optional<SafeByteArray> message = authRequest->getMessage(); - if (message) { - if ((*message).empty()) { - value = createSafeByteArray("="); - } - else { - value = Base64::encode(*message); - } - } - return concat(createSafeByteArray("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"" + authRequest->getMechanism() + "\">"), value, createSafeByteArray("</auth>")); +SafeByteArray AuthRequestSerializer::serialize(std::shared_ptr<ToplevelElement> element) const { + std::shared_ptr<AuthRequest> authRequest(std::dynamic_pointer_cast<AuthRequest>(element)); + SafeByteArray value; + boost::optional<SafeByteArray> message = authRequest->getMessage(); + if (message) { + if ((*message).empty()) { + value = createSafeByteArray("="); + } + else { + value = Base64::encode(*message); + } + } + return concat(createSafeByteArray("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"" + authRequest->getMechanism() + "\">"), value, createSafeByteArray("</auth>")); } } diff --git a/Swiften/Serializer/AuthRequestSerializer.h b/Swiften/Serializer/AuthRequestSerializer.h index 0b49384..ae85cf6 100644 --- a/Swiften/Serializer/AuthRequestSerializer.h +++ b/Swiften/Serializer/AuthRequestSerializer.h @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Elements/AuthRequest.h> #include <Swiften/Serializer/GenericElementSerializer.h> namespace Swift { - class SWIFTEN_API AuthRequestSerializer : public GenericElementSerializer<AuthRequest> { - public: - AuthRequestSerializer(); + class SWIFTEN_API AuthRequestSerializer : public GenericElementSerializer<AuthRequest> { + public: + AuthRequestSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const; + }; } diff --git a/Swiften/Serializer/AuthResponseSerializer.cpp b/Swiften/Serializer/AuthResponseSerializer.cpp index 86b7fbe..9d3e2e0 100644 --- a/Swiften/Serializer/AuthResponseSerializer.cpp +++ b/Swiften/Serializer/AuthResponseSerializer.cpp @@ -1,34 +1,34 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/AuthResponseSerializer.h> +#include <Swiften/Base/Concat.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/Elements/AuthResponse.h> #include <Swiften/StringCodecs/Base64.h> -#include <Swiften/Base/SafeByteArray.h> -#include <Swiften/Base/Concat.h> namespace Swift { AuthResponseSerializer::AuthResponseSerializer() { } -SafeByteArray AuthResponseSerializer::serialize(boost::shared_ptr<Element> element) const { - boost::shared_ptr<AuthResponse> authResponse(boost::dynamic_pointer_cast<AuthResponse>(element)); - SafeByteArray value; - boost::optional<SafeByteArray> message = authResponse->getValue(); - if (message) { - if ((*message).empty()) { - value = createSafeByteArray("="); - } - else { - value = Base64::encode(*message); - } - } - return concat(createSafeByteArray("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"), value, createSafeByteArray("</response>")); +SafeByteArray AuthResponseSerializer::serialize(std::shared_ptr<ToplevelElement> element) const { + std::shared_ptr<AuthResponse> authResponse(std::dynamic_pointer_cast<AuthResponse>(element)); + SafeByteArray value; + boost::optional<SafeByteArray> message = authResponse->getValue(); + if (message) { + if ((*message).empty()) { + value = createSafeByteArray(""); + } + else { + value = Base64::encode(*message); + } + } + return concat(createSafeByteArray("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"), value, createSafeByteArray("</response>")); } } diff --git a/Swiften/Serializer/AuthResponseSerializer.h b/Swiften/Serializer/AuthResponseSerializer.h index af71f59..25ffbbb 100644 --- a/Swiften/Serializer/AuthResponseSerializer.h +++ b/Swiften/Serializer/AuthResponseSerializer.h @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Elements/AuthResponse.h> #include <Swiften/Serializer/GenericElementSerializer.h> namespace Swift { - class SWIFTEN_API AuthResponseSerializer : public GenericElementSerializer<AuthResponse> { - public: - AuthResponseSerializer(); + class SWIFTEN_API AuthResponseSerializer : public GenericElementSerializer<AuthResponse> { + public: + AuthResponseSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const; + }; } diff --git a/Swiften/Serializer/AuthSuccessSerializer.cpp b/Swiften/Serializer/AuthSuccessSerializer.cpp index 26b58c3..48d512b 100644 --- a/Swiften/Serializer/AuthSuccessSerializer.cpp +++ b/Swiften/Serializer/AuthSuccessSerializer.cpp @@ -1,33 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/AuthSuccessSerializer.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Elements/AuthSuccess.h> #include <Swiften/StringCodecs/Base64.h> -#include <Swiften/Base/ByteArray.h> namespace Swift { AuthSuccessSerializer::AuthSuccessSerializer() { } -SafeByteArray AuthSuccessSerializer::serialize(boost::shared_ptr<Element> element) const { - boost::shared_ptr<AuthSuccess> authSuccess(boost::dynamic_pointer_cast<AuthSuccess>(element)); - std::string value; - boost::optional<std::vector<unsigned char> > message = authSuccess->getValue(); - if (message) { - if ((*message).empty()) { - value = "="; - } - else { - value = Base64::encode(ByteArray(*message)); - } - } - return createSafeByteArray("<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + value + "</success>"); +SafeByteArray AuthSuccessSerializer::serialize(std::shared_ptr<ToplevelElement> element) const { + std::shared_ptr<AuthSuccess> authSuccess(std::dynamic_pointer_cast<AuthSuccess>(element)); + std::string value; + boost::optional<std::vector<unsigned char> > message = authSuccess->getValue(); + if (message) { + if ((*message).empty()) { + value = "="; + } + else { + value = Base64::encode(ByteArray(*message)); + } + } + return createSafeByteArray("<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + value + "</success>"); } } diff --git a/Swiften/Serializer/AuthSuccessSerializer.h b/Swiften/Serializer/AuthSuccessSerializer.h index 370afaa..102e6a0 100644 --- a/Swiften/Serializer/AuthSuccessSerializer.h +++ b/Swiften/Serializer/AuthSuccessSerializer.h @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Elements/AuthSuccess.h> #include <Swiften/Serializer/GenericElementSerializer.h> namespace Swift { - class SWIFTEN_API AuthSuccessSerializer : public GenericElementSerializer<AuthSuccess> { - public: - AuthSuccessSerializer(); + class SWIFTEN_API AuthSuccessSerializer : public GenericElementSerializer<AuthSuccess> { + public: + AuthSuccessSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const; + }; } diff --git a/Swiften/Serializer/ComponentHandshakeSerializer.cpp b/Swiften/Serializer/ComponentHandshakeSerializer.cpp index e7837d3..0e94917 100644 --- a/Swiften/Serializer/ComponentHandshakeSerializer.cpp +++ b/Swiften/Serializer/ComponentHandshakeSerializer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/ComponentHandshakeSerializer.h> @@ -13,9 +13,9 @@ namespace Swift { ComponentHandshakeSerializer::ComponentHandshakeSerializer() { } -SafeByteArray ComponentHandshakeSerializer::serialize(boost::shared_ptr<Element> element) const { - boost::shared_ptr<ComponentHandshake> handshake(boost::dynamic_pointer_cast<ComponentHandshake>(element)); - return createSafeByteArray("<handshake>" + handshake->getData() + "</handshake>"); +SafeByteArray ComponentHandshakeSerializer::serialize(std::shared_ptr<ToplevelElement> element) const { + std::shared_ptr<ComponentHandshake> handshake(std::dynamic_pointer_cast<ComponentHandshake>(element)); + return createSafeByteArray("<handshake>" + handshake->getData() + "</handshake>"); } } diff --git a/Swiften/Serializer/ComponentHandshakeSerializer.h b/Swiften/Serializer/ComponentHandshakeSerializer.h index 1145ed9..d6ee156 100644 --- a/Swiften/Serializer/ComponentHandshakeSerializer.h +++ b/Swiften/Serializer/ComponentHandshakeSerializer.h @@ -1,21 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/ComponentHandshake.h> #include <Swiften/Serializer/GenericElementSerializer.h> namespace Swift { - class ComponentHandshakeSerializer : public GenericElementSerializer<ComponentHandshake> { - public: - ComponentHandshakeSerializer(); + class SWIFTEN_API ComponentHandshakeSerializer : public GenericElementSerializer<ComponentHandshake> { + public: + ComponentHandshakeSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const; + }; } diff --git a/Swiften/Serializer/CompressFailureSerializer.h b/Swiften/Serializer/CompressFailureSerializer.h index 27a638f..045c7d2 100644 --- a/Swiften/Serializer/CompressFailureSerializer.h +++ b/Swiften/Serializer/CompressFailureSerializer.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/CompressFailure.h> #include <Swiften/Serializer/GenericElementSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class CompressFailureSerializer : public GenericElementSerializer<CompressFailure> { - public: - CompressFailureSerializer() : GenericElementSerializer<CompressFailure>() { - } + class SWIFTEN_API CompressFailureSerializer : public GenericElementSerializer<CompressFailure> { + public: + CompressFailureSerializer() : GenericElementSerializer<CompressFailure>() { + } - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const { - return createSafeByteArray(XMLElement("failure", "http://jabber.org/protocol/compress").serialize()); - } - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const { + return createSafeByteArray(XMLElement("failure", "http://jabber.org/protocol/compress").serialize()); + } + }; } diff --git a/Swiften/Serializer/CompressRequestSerializer.cpp b/Swiften/Serializer/CompressRequestSerializer.cpp index af7f7db..9deb702 100644 --- a/Swiften/Serializer/CompressRequestSerializer.cpp +++ b/Swiften/Serializer/CompressRequestSerializer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/CompressRequestSerializer.h> @@ -13,13 +13,13 @@ namespace Swift { CompressRequestSerializer::CompressRequestSerializer() { } -SafeByteArray CompressRequestSerializer::serialize(boost::shared_ptr<Element> element) const { - boost::shared_ptr<CompressRequest> compressRequest(boost::dynamic_pointer_cast<CompressRequest>(element)); - return createSafeByteArray("<compress xmlns='http://jabber.org/protocol/compress'><method>" + compressRequest->getMethod() + "</method></compress>"); +SafeByteArray CompressRequestSerializer::serialize(std::shared_ptr<ToplevelElement> element) const { + std::shared_ptr<CompressRequest> compressRequest(std::dynamic_pointer_cast<CompressRequest>(element)); + return createSafeByteArray("<compress xmlns='http://jabber.org/protocol/compress'><method>" + compressRequest->getMethod() + "</method></compress>"); } -bool CompressRequestSerializer::canSerialize(boost::shared_ptr<Element> element) const { - return boost::dynamic_pointer_cast<CompressRequest>(element) != 0; +bool CompressRequestSerializer::canSerialize(std::shared_ptr<ToplevelElement> element) const { + return std::dynamic_pointer_cast<CompressRequest>(element) != nullptr; } } diff --git a/Swiften/Serializer/CompressRequestSerializer.h b/Swiften/Serializer/CompressRequestSerializer.h index 4d68c98..d768023 100644 --- a/Swiften/Serializer/CompressRequestSerializer.h +++ b/Swiften/Serializer/CompressRequestSerializer.h @@ -1,21 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Serializer/ElementSerializer.h> namespace Swift { - class CompressRequestSerializer : public ElementSerializer { - public: - CompressRequestSerializer(); + class SWIFTEN_API CompressRequestSerializer : public ElementSerializer { + public: + CompressRequestSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const; - virtual bool canSerialize(boost::shared_ptr<Element> element) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const; + virtual bool canSerialize(std::shared_ptr<ToplevelElement> element) const; + }; } diff --git a/Swiften/Serializer/ElementSerializer.cpp b/Swiften/Serializer/ElementSerializer.cpp index 8cfb294..42980d8 100644 --- a/Swiften/Serializer/ElementSerializer.cpp +++ b/Swiften/Serializer/ElementSerializer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/ElementSerializer.h> diff --git a/Swiften/Serializer/ElementSerializer.h b/Swiften/Serializer/ElementSerializer.h index ba59106..3bef58b 100644 --- a/Swiften/Serializer/ElementSerializer.h +++ b/Swiften/Serializer/ElementSerializer.h @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Elements/Element.h> #include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Elements/ToplevelElement.h> namespace Swift { - class ElementSerializer { - public: - virtual ~ElementSerializer(); + class ElementSerializer { + public: + virtual ~ElementSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const = 0; - virtual bool canSerialize(boost::shared_ptr<Element> element) const = 0; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const = 0; + virtual bool canSerialize(std::shared_ptr<ToplevelElement> element) const = 0; + }; } diff --git a/Swiften/Serializer/EnableStreamManagementSerializer.h b/Swiften/Serializer/EnableStreamManagementSerializer.h index 384753b..ba92843 100644 --- a/Swiften/Serializer/EnableStreamManagementSerializer.h +++ b/Swiften/Serializer/EnableStreamManagementSerializer.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/EnableStreamManagement.h> #include <Swiften/Serializer/GenericElementSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class EnableStreamManagementSerializer : public GenericElementSerializer<EnableStreamManagement> { - public: - EnableStreamManagementSerializer() : GenericElementSerializer<EnableStreamManagement>() { - } + class SWIFTEN_API EnableStreamManagementSerializer : public GenericElementSerializer<EnableStreamManagement> { + public: + EnableStreamManagementSerializer() : GenericElementSerializer<EnableStreamManagement>() { + } - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const { - return createSafeByteArray(XMLElement("enable", "urn:xmpp:sm:2").serialize()); - } - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const { + return createSafeByteArray(XMLElement("enable", "urn:xmpp:sm:2").serialize()); + } + }; } diff --git a/Swiften/Serializer/GenericElementSerializer.h b/Swiften/Serializer/GenericElementSerializer.h index e56f156..b5f4119 100644 --- a/Swiften/Serializer/GenericElementSerializer.h +++ b/Swiften/Serializer/GenericElementSerializer.h @@ -1,23 +1,24 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Serializer/ElementSerializer.h> namespace Swift { - template<typename T> - class GenericElementSerializer : public ElementSerializer { - public: - virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const = 0; + template<typename T> + class SWIFTEN_API GenericElementSerializer : public ElementSerializer { + public: + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const = 0; - virtual bool canSerialize(boost::shared_ptr<Element> element) const { - return boost::dynamic_pointer_cast<T>(element); - } - }; + virtual bool canSerialize(std::shared_ptr<ToplevelElement> element) const { + return !!std::dynamic_pointer_cast<T>(element); + } + }; } diff --git a/Swiften/Serializer/GenericPayloadSerializer.h b/Swiften/Serializer/GenericPayloadSerializer.h index b501613..804ccaf 100644 --- a/Swiften/Serializer/GenericPayloadSerializer.h +++ b/Swiften/Serializer/GenericPayloadSerializer.h @@ -1,27 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Serializer/PayloadSerializer.h> namespace Swift { - template<typename PAYLOAD_TYPE> - class GenericPayloadSerializer : public PayloadSerializer { - public: - virtual std::string serialize(boost::shared_ptr<Payload> element) const { - return serializePayload(boost::dynamic_pointer_cast<PAYLOAD_TYPE>(element)); - } + template<typename PAYLOAD_TYPE> + class GenericPayloadSerializer : public PayloadSerializer { + public: + virtual std::string serialize(std::shared_ptr<Payload> element) const { + return serializePayload(std::dynamic_pointer_cast<PAYLOAD_TYPE>(element)); + } - virtual bool canSerialize(boost::shared_ptr<Payload> element) const { - return boost::dynamic_pointer_cast<PAYLOAD_TYPE>(element); - } + virtual bool canSerialize(std::shared_ptr<Payload> element) const { + return !!std::dynamic_pointer_cast<PAYLOAD_TYPE>(element); + } - virtual std::string serializePayload(boost::shared_ptr<PAYLOAD_TYPE>) const = 0; - }; + virtual std::string serializePayload(std::shared_ptr<PAYLOAD_TYPE>) const = 0; + }; } diff --git a/Swiften/Serializer/GenericStanzaSerializer.h b/Swiften/Serializer/GenericStanzaSerializer.h index 4129ca8..badd55c 100644 --- a/Swiften/Serializer/GenericStanzaSerializer.h +++ b/Swiften/Serializer/GenericStanzaSerializer.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Serializer/StanzaSerializer.h> namespace Swift { - template<typename STANZA_TYPE> - class GenericStanzaSerializer : public StanzaSerializer { - public: - GenericStanzaSerializer(const std::string& tag, PayloadSerializerCollection* payloadSerializers) : StanzaSerializer(tag, payloadSerializers) {} + template<typename STANZA_TYPE> + class SWIFTEN_API GenericStanzaSerializer : public StanzaSerializer { + public: + GenericStanzaSerializer(const std::string& tag, PayloadSerializerCollection* payloadSerializers, const boost::optional<std::string>& explicitNS = boost::optional<std::string>()) : StanzaSerializer(tag, payloadSerializers, explicitNS) {} - virtual bool canSerialize(boost::shared_ptr<Element> element) const { - return dynamic_cast<STANZA_TYPE*>(element.get()) != 0; - } + virtual bool canSerialize(std::shared_ptr<ToplevelElement> element) const { + return dynamic_cast<STANZA_TYPE*>(element.get()) != nullptr; + } - virtual void setStanzaSpecificAttributes( - boost::shared_ptr<Element> stanza, - XMLElement& element) const { - setStanzaSpecificAttributesGeneric( - boost::dynamic_pointer_cast<STANZA_TYPE>(stanza), element); - } + virtual void setStanzaSpecificAttributes( + std::shared_ptr<ToplevelElement> stanza, + XMLElement& element) const { + setStanzaSpecificAttributesGeneric( + std::dynamic_pointer_cast<STANZA_TYPE>(stanza), element); + } - virtual void setStanzaSpecificAttributesGeneric( - boost::shared_ptr<STANZA_TYPE>, - XMLElement&) const = 0; - }; + virtual void setStanzaSpecificAttributesGeneric( + std::shared_ptr<STANZA_TYPE>, + XMLElement&) const = 0; + }; } diff --git a/Swiften/Serializer/IQSerializer.h b/Swiften/Serializer/IQSerializer.h index 76a9cb7..1bdbb07 100644 --- a/Swiften/Serializer/IQSerializer.h +++ b/Swiften/Serializer/IQSerializer.h @@ -1,31 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericStanzaSerializer.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/IQ.h> +#include <Swiften/Serializer/GenericStanzaSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class IQSerializer : public GenericStanzaSerializer<IQ> { - public: - IQSerializer(PayloadSerializerCollection* payloadSerializers) : - GenericStanzaSerializer<IQ>("iq", payloadSerializers) {} + class SWIFTEN_API IQSerializer : public GenericStanzaSerializer<IQ> { + public: + IQSerializer(PayloadSerializerCollection* payloadSerializers, const boost::optional<std::string>& explicitNS = boost::optional<std::string>()) : + GenericStanzaSerializer<IQ>("iq", payloadSerializers, explicitNS) { + } - private: - virtual void setStanzaSpecificAttributesGeneric( - boost::shared_ptr<IQ> iq, - XMLElement& element) const { - switch (iq->getType()) { - case IQ::Get: element.setAttribute("type","get"); break; - case IQ::Set: element.setAttribute("type","set"); break; - case IQ::Result: element.setAttribute("type","result"); break; - case IQ::Error: element.setAttribute("type","error"); break; - } - } - }; + private: + virtual void setStanzaSpecificAttributesGeneric( + std::shared_ptr<IQ> iq, + XMLElement& element) const { + switch (iq->getType()) { + case IQ::Get: element.setAttribute("type","get"); break; + case IQ::Set: element.setAttribute("type","set"); break; + case IQ::Result: element.setAttribute("type","result"); break; + case IQ::Error: element.setAttribute("type","error"); break; + } + } + }; } diff --git a/Swiften/Serializer/MessageSerializer.cpp b/Swiften/Serializer/MessageSerializer.cpp index c221680..774d9a3 100644 --- a/Swiften/Serializer/MessageSerializer.cpp +++ b/Swiften/Serializer/MessageSerializer.cpp @@ -1,33 +1,34 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/MessageSerializer.h> + #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { -MessageSerializer::MessageSerializer(PayloadSerializerCollection* payloadSerializers) : - GenericStanzaSerializer<Message>("message", payloadSerializers) { +MessageSerializer::MessageSerializer(PayloadSerializerCollection* payloadSerializers, const boost::optional<std::string>& explicitNS) : + GenericStanzaSerializer<Message>("message", payloadSerializers, explicitNS) { } void MessageSerializer::setStanzaSpecificAttributesGeneric( - boost::shared_ptr<Message> message, - XMLElement& element) const { - if (message->getType() == Message::Chat) { - element.setAttribute("type", "chat"); - } - else if (message->getType() == Message::Groupchat) { - element.setAttribute("type", "groupchat"); - } - else if (message->getType() == Message::Headline) { - element.setAttribute("type", "headline"); - } - else if (message->getType() == Message::Error) { - element.setAttribute("type", "error"); - } + std::shared_ptr<Message> message, + XMLElement& element) const { + if (message->getType() == Message::Chat) { + element.setAttribute("type", "chat"); + } + else if (message->getType() == Message::Groupchat) { + element.setAttribute("type", "groupchat"); + } + else if (message->getType() == Message::Headline) { + element.setAttribute("type", "headline"); + } + else if (message->getType() == Message::Error) { + element.setAttribute("type", "error"); + } } } diff --git a/Swiften/Serializer/MessageSerializer.h b/Swiften/Serializer/MessageSerializer.h index 8e9e941..812b647 100644 --- a/Swiften/Serializer/MessageSerializer.h +++ b/Swiften/Serializer/MessageSerializer.h @@ -1,24 +1,27 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericStanzaSerializer.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Message.h> +#include <Swiften/Serializer/GenericStanzaSerializer.h> namespace Swift { - class XMLElement; + class XMLElement; - class MessageSerializer : public GenericStanzaSerializer<Message> { - public: - MessageSerializer(PayloadSerializerCollection* payloadSerializers); + class SWIFTEN_API MessageSerializer : public GenericStanzaSerializer<Message> { + public: + MessageSerializer(PayloadSerializerCollection* payloadSerializers, const boost::optional<std::string>& explitNS = boost::optional<std::string>()); - private: - void setStanzaSpecificAttributesGeneric( - boost::shared_ptr<Message> message, - XMLElement& element) const; - }; + private: + void setStanzaSpecificAttributesGeneric( + std::shared_ptr<Message> message, + XMLElement& element) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializer.cpp index be73676..1c3e751 100644 --- a/Swiften/Serializer/PayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializer.h> diff --git a/Swiften/Serializer/PayloadSerializer.h b/Swiften/Serializer/PayloadSerializer.h index 46132fc..fe14e3d 100644 --- a/Swiften/Serializer/PayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializer.h @@ -1,24 +1,24 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <string> -#include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> namespace Swift { - class Payload; + class Payload; - class SWIFTEN_API PayloadSerializer { - public: - virtual ~PayloadSerializer(); + class SWIFTEN_API PayloadSerializer { + public: + virtual ~PayloadSerializer(); - virtual bool canSerialize(boost::shared_ptr<Payload>) const = 0; - virtual std::string serialize(boost::shared_ptr<Payload>) const = 0; - }; + virtual bool canSerialize(std::shared_ptr<Payload>) const = 0; + virtual std::string serialize(std::shared_ptr<Payload>) const = 0; + }; } diff --git a/Swiften/Serializer/PayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializerCollection.cpp index ab2b4f4..114512e 100644 --- a/Swiften/Serializer/PayloadSerializerCollection.cpp +++ b/Swiften/Serializer/PayloadSerializerCollection.cpp @@ -1,13 +1,15 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/bind.hpp> +#include <Swiften/Serializer/PayloadSerializerCollection.h> + #include <algorithm> -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <boost/bind.hpp> + #include <Swiften/Serializer/PayloadSerializer.h> namespace Swift { @@ -15,19 +17,22 @@ namespace Swift { PayloadSerializerCollection::PayloadSerializerCollection() { } +PayloadSerializerCollection::~PayloadSerializerCollection() { +} + void PayloadSerializerCollection::addSerializer(PayloadSerializer* serializer) { - serializers_.push_back(serializer); + serializers_.push_back(serializer); } void PayloadSerializerCollection::removeSerializer(PayloadSerializer* serializer) { - serializers_.erase(remove(serializers_.begin(), serializers_.end(), serializer), serializers_.end()); + serializers_.erase(std::remove(serializers_.begin(), serializers_.end(), serializer), serializers_.end()); } -PayloadSerializer* PayloadSerializerCollection::getPayloadSerializer(boost::shared_ptr<Payload> payload) const { - std::vector<PayloadSerializer*>::const_iterator i = std::find_if( - serializers_.begin(), serializers_.end(), - boost::bind(&PayloadSerializer::canSerialize, _1, payload)); - return (i != serializers_.end() ? *i : NULL); +PayloadSerializer* PayloadSerializerCollection::getPayloadSerializer(std::shared_ptr<Payload> payload) const { + std::vector<PayloadSerializer*>::const_iterator i = std::find_if( + serializers_.begin(), serializers_.end(), + boost::bind(&PayloadSerializer::canSerialize, _1, payload)); + return (i != serializers_.end() ? *i : nullptr); } } diff --git a/Swiften/Serializer/PayloadSerializerCollection.h b/Swiften/Serializer/PayloadSerializerCollection.h index 78f8808..53b3135 100644 --- a/Swiften/Serializer/PayloadSerializerCollection.h +++ b/Swiften/Serializer/PayloadSerializerCollection.h @@ -1,30 +1,30 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <vector> -#include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> namespace Swift { - class PayloadSerializer; - + class PayloadSerializer; - class SWIFTEN_API PayloadSerializerCollection { - public: - PayloadSerializerCollection(); + class SWIFTEN_API PayloadSerializerCollection { + public: + PayloadSerializerCollection(); + virtual ~PayloadSerializerCollection(); - void addSerializer(PayloadSerializer* factory); - void removeSerializer(PayloadSerializer* factory); - PayloadSerializer* getPayloadSerializer(boost::shared_ptr<Payload>) const; + void addSerializer(PayloadSerializer* factory); + void removeSerializer(PayloadSerializer* factory); + PayloadSerializer* getPayloadSerializer(std::shared_ptr<Payload>) const; - private: - std::vector<PayloadSerializer*> serializers_; - }; + private: + std::vector<PayloadSerializer*> serializers_; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/BlockSerializer.h b/Swiften/Serializer/PayloadSerializers/BlockSerializer.h index fc628c2..f034c46 100644 --- a/Swiften/Serializer/PayloadSerializers/BlockSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/BlockSerializer.h @@ -1,36 +1,37 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> #include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - template<typename BLOCK_ELEMENT> - class BlockSerializer : public GenericPayloadSerializer<BLOCK_ELEMENT> { - public: - BlockSerializer(std::string tag) : GenericPayloadSerializer<BLOCK_ELEMENT>(), tag(tag) { - } + template<typename BLOCK_ELEMENT> + class SWIFTEN_API BlockSerializer : public GenericPayloadSerializer<BLOCK_ELEMENT> { + public: + BlockSerializer(std::string tag) : GenericPayloadSerializer<BLOCK_ELEMENT>(), tag(tag) { + } - virtual std::string serializePayload(boost::shared_ptr<BLOCK_ELEMENT> payload) const { - XMLElement element(tag, "urn:xmpp:blocking"); - const std::vector<JID>& items = payload->getItems(); - for (std::vector<JID>::const_iterator i = items.begin(); i != items.end(); ++i) { - boost::shared_ptr<XMLElement> item = boost::make_shared<XMLElement>("item"); - item->setAttribute("jid", *i); - element.addNode(item); - } - return element.serialize(); - } + virtual std::string serializePayload(std::shared_ptr<BLOCK_ELEMENT> payload) const { + XMLElement element(tag, "urn:xmpp:blocking"); + const std::vector<JID>& items = payload->getItems(); + for (const auto& i : items) { + std::shared_ptr<XMLElement> item = std::make_shared<XMLElement>("item"); + item->setAttribute("jid", i); + element.addNode(item); + } + return element.serialize(); + } - private: - std::string tag; - }; + private: + std::string tag; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/BodySerializer.h b/Swiften/Serializer/PayloadSerializers/BodySerializer.h index 99df0f5..faad411 100644 --- a/Swiften/Serializer/PayloadSerializers/BodySerializer.h +++ b/Swiften/Serializer/PayloadSerializers/BodySerializer.h @@ -1,23 +1,24 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Body.h> #include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Elements/Body.h> namespace Swift { - class BodySerializer : public GenericPayloadSerializer<Body> { - public: - BodySerializer() : GenericPayloadSerializer<Body>() {} + class SWIFTEN_API BodySerializer : public GenericPayloadSerializer<Body> { + public: + BodySerializer() : GenericPayloadSerializer<Body>() {} - virtual std::string serializePayload(boost::shared_ptr<Body> body) const { - XMLTextNode textNode(body->getText()); - return "<body>" + textNode.serialize() + "</body>"; - } - }; + virtual std::string serializePayload(std::shared_ptr<Body> body) const { + XMLTextNode textNode(body->getText()); + return "<body>" + textNode.serialize() + "</body>"; + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.cpp index beb84dd..37a9c03 100644 --- a/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.cpp @@ -1,41 +1,40 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h> -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/lexical_cast.hpp> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/PayloadSerializerCollection.h> - +#include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { BytestreamsSerializer::BytestreamsSerializer() { } -std::string BytestreamsSerializer::serializePayload(boost::shared_ptr<Bytestreams> bytestreams) const { - XMLElement queryElement("query", "http://jabber.org/protocol/bytestreams"); - queryElement.setAttribute("sid", bytestreams->getStreamID()); - foreach(const Bytestreams::StreamHost& streamHost, bytestreams->getStreamHosts()) { - boost::shared_ptr<XMLElement> streamHostElement(new XMLElement("streamhost")); - streamHostElement->setAttribute("host", streamHost.host); - streamHostElement->setAttribute("jid", streamHost.jid.toString()); - streamHostElement->setAttribute("port", boost::lexical_cast<std::string>(streamHost.port)); - queryElement.addNode(streamHostElement); - } - - if (bytestreams->getUsedStreamHost()) { - boost::shared_ptr<XMLElement> streamHostElement(new XMLElement("streamhost-used")); - streamHostElement->setAttribute("jid", *bytestreams->getUsedStreamHost()); - queryElement.addNode(streamHostElement); - } - return queryElement.serialize(); +std::string BytestreamsSerializer::serializePayload(std::shared_ptr<Bytestreams> bytestreams) const { + XMLElement queryElement("query", "http://jabber.org/protocol/bytestreams"); + queryElement.setAttribute("sid", bytestreams->getStreamID()); + for (const auto& streamHost : bytestreams->getStreamHosts()) { + std::shared_ptr<XMLElement> streamHostElement(new XMLElement("streamhost")); + streamHostElement->setAttribute("host", streamHost.host); + streamHostElement->setAttribute("jid", streamHost.jid.toString()); + streamHostElement->setAttribute("port", std::to_string(streamHost.port)); + queryElement.addNode(streamHostElement); + } + + if (bytestreams->getUsedStreamHost()) { + std::shared_ptr<XMLElement> streamHostElement(new XMLElement("streamhost-used")); + streamHostElement->setAttribute("jid", *bytestreams->getUsedStreamHost()); + queryElement.addNode(streamHostElement); + } + return queryElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h b/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h index 0e58eb0..900d37a 100644 --- a/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h @@ -1,21 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Bytestreams.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class BytestreamsSerializer : public GenericPayloadSerializer<Bytestreams> { - public: - BytestreamsSerializer(); + class SWIFTEN_API BytestreamsSerializer : public GenericPayloadSerializer<Bytestreams> { + public: + BytestreamsSerializer(); - virtual std::string serializePayload(boost::shared_ptr<Bytestreams>) const; - }; + virtual std::string serializePayload(std::shared_ptr<Bytestreams>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.cpp b/Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.cpp index 2466958..19f8a27 100644 --- a/Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.h> -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Serializer/XML/XMLElement.h> @@ -15,12 +15,12 @@ namespace Swift { CapsInfoSerializer::CapsInfoSerializer() : GenericPayloadSerializer<CapsInfo>() { } -std::string CapsInfoSerializer::serializePayload(boost::shared_ptr<CapsInfo> capsInfo) const { - XMLElement capsElement("c", "http://jabber.org/protocol/caps"); - capsElement.setAttribute("node", capsInfo->getNode()); - capsElement.setAttribute("hash", capsInfo->getHash()); - capsElement.setAttribute("ver", capsInfo->getVersion()); - return capsElement.serialize(); +std::string CapsInfoSerializer::serializePayload(std::shared_ptr<CapsInfo> capsInfo) const { + XMLElement capsElement("c", "http://jabber.org/protocol/caps"); + capsElement.setAttribute("node", capsInfo->getNode()); + capsElement.setAttribute("hash", capsInfo->getHash()); + capsElement.setAttribute("ver", capsInfo->getVersion()); + return capsElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.h b/Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.h index b952a31..ac168e4 100644 --- a/Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/CapsInfo.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API CapsInfoSerializer : public GenericPayloadSerializer<CapsInfo> { - public: - CapsInfoSerializer(); + class SWIFTEN_API CapsInfoSerializer : public GenericPayloadSerializer<CapsInfo> { + public: + CapsInfoSerializer(); - virtual std::string serializePayload(boost::shared_ptr<CapsInfo>) const; - }; + virtual std::string serializePayload(std::shared_ptr<CapsInfo>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/CarbonsDisableSerializer.cpp b/Swiften/Serializer/PayloadSerializers/CarbonsDisableSerializer.cpp new file mode 100644 index 0000000..9938bd9 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/CarbonsDisableSerializer.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/CarbonsDisableSerializer.h> + +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { + CarbonsDisableSerializer::CarbonsDisableSerializer() : GenericPayloadSerializer<CarbonsDisable>() { + + } + + CarbonsDisableSerializer::~CarbonsDisableSerializer() { + + } + + std::string CarbonsDisableSerializer::serializePayload(std::shared_ptr<CarbonsDisable>) const { + XMLElement element("disable", "urn:xmpp:carbons:2"); + return element.serialize(); + } +} diff --git a/Swiften/Serializer/PayloadSerializers/CarbonsDisableSerializer.h b/Swiften/Serializer/PayloadSerializers/CarbonsDisableSerializer.h new file mode 100644 index 0000000..a6bf16f --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/CarbonsDisableSerializer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsDisable.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class SWIFTEN_API CarbonsDisableSerializer : public GenericPayloadSerializer<CarbonsDisable> { + public: + CarbonsDisableSerializer(); + virtual ~CarbonsDisableSerializer(); + + virtual std::string serializePayload(std::shared_ptr<CarbonsDisable>) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/CarbonsEnableSerializer.cpp b/Swiften/Serializer/PayloadSerializers/CarbonsEnableSerializer.cpp new file mode 100644 index 0000000..424c6fc --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/CarbonsEnableSerializer.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/CarbonsEnableSerializer.h> + +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { + CarbonsEnableSerializer::CarbonsEnableSerializer() : GenericPayloadSerializer<CarbonsEnable>() { + } + + CarbonsEnableSerializer::~CarbonsEnableSerializer() { + + } + + std::string CarbonsEnableSerializer::serializePayload(std::shared_ptr<CarbonsEnable>) const { + XMLElement element("enable", "urn:xmpp:carbons:2"); + return element.serialize(); + } +} diff --git a/Swiften/Serializer/PayloadSerializers/CarbonsEnableSerializer.h b/Swiften/Serializer/PayloadSerializers/CarbonsEnableSerializer.h new file mode 100644 index 0000000..eb0f6fa --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/CarbonsEnableSerializer.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsEnable.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { + class SWIFTEN_API CarbonsEnableSerializer : public GenericPayloadSerializer<CarbonsEnable> { + public: + CarbonsEnableSerializer(); + virtual ~CarbonsEnableSerializer(); + + virtual std::string serializePayload(std::shared_ptr<CarbonsEnable>) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/CarbonsPrivateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/CarbonsPrivateSerializer.cpp new file mode 100644 index 0000000..fb92017 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/CarbonsPrivateSerializer.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/CarbonsPrivateSerializer.h> + +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { + CarbonsPrivateSerializer::CarbonsPrivateSerializer() : GenericPayloadSerializer<CarbonsPrivate>() { + } + + CarbonsPrivateSerializer::~CarbonsPrivateSerializer() { + + } + + std::string CarbonsPrivateSerializer::serializePayload(std::shared_ptr<CarbonsPrivate>) const { + XMLElement element("private", "urn:xmpp:carbons:2"); + return element.serialize(); + } +} diff --git a/Swiften/Serializer/PayloadSerializers/CarbonsPrivateSerializer.h b/Swiften/Serializer/PayloadSerializers/CarbonsPrivateSerializer.h new file mode 100644 index 0000000..d148a26 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/CarbonsPrivateSerializer.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsPrivate.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { + class SWIFTEN_API CarbonsPrivateSerializer : public GenericPayloadSerializer<CarbonsPrivate> { + public: + CarbonsPrivateSerializer(); + virtual ~CarbonsPrivateSerializer(); + + virtual std::string serializePayload(std::shared_ptr<CarbonsPrivate>) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/CarbonsReceivedSerializer.cpp b/Swiften/Serializer/PayloadSerializers/CarbonsReceivedSerializer.cpp new file mode 100644 index 0000000..cc87929 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/CarbonsReceivedSerializer.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/CarbonsReceivedSerializer.h> + +#include <memory> + +namespace Swift { + CarbonsReceivedSerializer::CarbonsReceivedSerializer(PayloadSerializerCollection* serializers) : GenericPayloadSerializer<CarbonsReceived>(), serializers_(serializers) { + } + + CarbonsReceivedSerializer::~CarbonsReceivedSerializer() { + } + + std::string CarbonsReceivedSerializer::serializePayload(std::shared_ptr<CarbonsReceived> received) const { + XMLElement element("received", "urn:xmpp:carbons:2"); + if (received->getForwarded()) { + element.addNode(std::make_shared<XMLRawTextNode>(ForwardedSerializer(serializers_).serialize(received->getForwarded()))); + } + return element.serialize(); + } +} + diff --git a/Swiften/Serializer/PayloadSerializers/CarbonsReceivedSerializer.h b/Swiften/Serializer/PayloadSerializers/CarbonsReceivedSerializer.h new file mode 100644 index 0000000..017b187 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/CarbonsReceivedSerializer.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsReceived.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +namespace Swift { + class SWIFTEN_API CarbonsReceivedSerializer : public GenericPayloadSerializer<CarbonsReceived> { + public: + CarbonsReceivedSerializer(PayloadSerializerCollection* serializers); + virtual ~CarbonsReceivedSerializer(); + + virtual std::string serializePayload(std::shared_ptr<CarbonsReceived> received) const; + + private: + PayloadSerializerCollection* serializers_; + }; +} + diff --git a/Swiften/Serializer/PayloadSerializers/CarbonsSentSerializer.cpp b/Swiften/Serializer/PayloadSerializers/CarbonsSentSerializer.cpp new file mode 100644 index 0000000..986edcb --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/CarbonsSentSerializer.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/CarbonsSentSerializer.h> + +namespace Swift { + CarbonsSentSerializer::CarbonsSentSerializer(PayloadSerializerCollection* serializers) : GenericPayloadSerializer<CarbonsSent>(), serializers_(serializers) { + } + + CarbonsSentSerializer::~CarbonsSentSerializer() { + } + + std::string CarbonsSentSerializer::serializePayload(std::shared_ptr<CarbonsSent> sent) const { + XMLElement element("sent", "urn:xmpp:carbons:2"); + if (sent->getForwarded()) { + element.addNode(std::make_shared<XMLRawTextNode>(ForwardedSerializer(serializers_).serialize(sent->getForwarded()))); + } + return element.serialize(); + } +} + diff --git a/Swiften/Serializer/PayloadSerializers/CarbonsSentSerializer.h b/Swiften/Serializer/PayloadSerializers/CarbonsSentSerializer.h new file mode 100644 index 0000000..16db398 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/CarbonsSentSerializer.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/CarbonsSent.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +namespace Swift { + class SWIFTEN_API CarbonsSentSerializer : public GenericPayloadSerializer<CarbonsSent> { + public: + CarbonsSentSerializer(PayloadSerializerCollection* serializers); + virtual ~CarbonsSentSerializer(); + + virtual std::string serializePayload(std::shared_ptr<CarbonsSent> sent) const; + + private: + PayloadSerializerCollection* serializers_; + }; +} + diff --git a/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp index d23cad7..17f8be0 100644 --- a/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h> @@ -11,17 +11,17 @@ namespace Swift { ChatStateSerializer::ChatStateSerializer() : GenericPayloadSerializer<ChatState>() { } -std::string ChatStateSerializer::serializePayload(boost::shared_ptr<ChatState> chatState) const { - std::string result("<"); - switch (chatState->getChatState()) { - case ChatState::Active: result += "active"; break; - case ChatState::Composing: result += "composing"; break; - case ChatState::Paused: result += "paused"; break; - case ChatState::Inactive: result += "inactive"; break; - case ChatState::Gone: result += "gone"; break; - } - result += " xmlns=\"http://jabber.org/protocol/chatstates\"/>"; - return result; +std::string ChatStateSerializer::serializePayload(std::shared_ptr<ChatState> chatState) const { + std::string result("<"); + switch (chatState->getChatState()) { + case ChatState::Active: result += "active"; break; + case ChatState::Composing: result += "composing"; break; + case ChatState::Paused: result += "paused"; break; + case ChatState::Inactive: result += "inactive"; break; + case ChatState::Gone: result += "gone"; break; + } + result += " xmlns=\"http://jabber.org/protocol/chatstates\"/>"; + return result; } } diff --git a/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h b/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h index d71873d..3b9f315 100644 --- a/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h @@ -1,19 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/ChatState.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class ChatStateSerializer : public GenericPayloadSerializer<ChatState> { - public: - ChatStateSerializer(); + class SWIFTEN_API ChatStateSerializer : public GenericPayloadSerializer<ChatState> { + public: + ChatStateSerializer(); - virtual std::string serializePayload(boost::shared_ptr<ChatState> error) const; - }; + virtual std::string serializePayload(std::shared_ptr<ChatState> error) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/ClientStateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ClientStateSerializer.cpp new file mode 100644 index 0000000..1485dcb --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ClientStateSerializer.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/ClientStateSerializer.h> + +namespace Swift { + +ClientStateSerializer::ClientStateSerializer() : GenericPayloadSerializer<ClientState>() { +} + +std::string ClientStateSerializer::serializePayload(std::shared_ptr<ClientState> clientState) const { + std::string result("<"); + switch (clientState->getClientState()) { + case ClientState::ClientStateType::Active: result += "active"; break; + case ClientState::ClientStateType::Inactive: result += "inactive"; break; + } + result += " xmlns=\"urn:xmpp:csi:0\"/>"; + return result; +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/ClientStateSerializer.h b/Swiften/Serializer/PayloadSerializers/ClientStateSerializer.h new file mode 100644 index 0000000..1c4f977 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ClientStateSerializer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ClientState.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class SWIFTEN_API ClientStateSerializer : public GenericPayloadSerializer<ClientState> { + public: + ClientStateSerializer(); + + virtual std::string serializePayload(std::shared_ptr<ClientState> error) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp b/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp index 40acd8e..25a70f6 100644 --- a/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/CommandSerializer.cpp @@ -1,96 +1,94 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/CommandSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Serializer/XML/XMLTextNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> namespace Swift { CommandSerializer::CommandSerializer() { } -std::string CommandSerializer::serializePayload(boost::shared_ptr<Command> command) const { - XMLElement commandElement("command", "http://jabber.org/protocol/commands"); - commandElement.setAttribute("node", command->getNode()); +std::string CommandSerializer::serializePayload(std::shared_ptr<Command> command) const { + XMLElement commandElement("command", "http://jabber.org/protocol/commands"); + commandElement.setAttribute("node", command->getNode()); - if (!command->getSessionID().empty()) { - commandElement.setAttribute("sessionid", command->getSessionID()); - } + if (!command->getSessionID().empty()) { + commandElement.setAttribute("sessionid", command->getSessionID()); + } - std::string action = actionToString(command->getAction()); - if (!action.empty()) { - commandElement.setAttribute("action", action); - } + std::string action = actionToString(command->getAction()); + if (!action.empty()) { + commandElement.setAttribute("action", action); + } - std::string status; - switch (command->getStatus()) { - case Command::Executing: status = "executing";break; - case Command::Completed: status = "completed";break; - case Command::Canceled: status = "canceled";break; - case Command::NoStatus: break; - } - if (!status.empty()) { - commandElement.setAttribute("status", status); - } + std::string status; + switch (command->getStatus()) { + case Command::Executing: status = "executing";break; + case Command::Completed: status = "completed";break; + case Command::Canceled: status = "canceled";break; + case Command::NoStatus: break; + } + if (!status.empty()) { + commandElement.setAttribute("status", status); + } - if (command->getAvailableActions().size() > 0) { - std::string actions = "<actions"; - std::string executeAction = actionToString(command->getExecuteAction()); - if (!executeAction.empty()) { - actions += " execute='" + executeAction + "'"; - } - actions += ">"; - foreach (Command::Action action, command->getAvailableActions()) { - actions += "<" + actionToString(action) + "/>"; - } - actions += "</actions>"; - commandElement.addNode(boost::make_shared<XMLRawTextNode>(actions)); - } + if (command->getAvailableActions().size() > 0) { + std::string actions = "<actions"; + std::string executeAction = actionToString(command->getExecuteAction()); + if (!executeAction.empty()) { + actions += " execute='" + executeAction + "'"; + } + actions += ">"; + for (const auto& action : command->getAvailableActions()) { + actions += "<" + actionToString(action) + "/>"; + } + actions += "</actions>"; + commandElement.addNode(std::make_shared<XMLRawTextNode>(actions)); + } - foreach (Command::Note note, command->getNotes()) { - boost::shared_ptr<XMLElement> noteElement(new XMLElement("note")); - std::string type; - switch (note.type) { - case Command::Note::Info: type = "info"; break; - case Command::Note::Warn: type = "warn"; break; - case Command::Note::Error: type = "error"; break; - } - if (!type.empty()) { - noteElement->setAttribute("type", type); - } - noteElement->addNode(boost::make_shared<XMLTextNode>(note.note)); - commandElement.addNode(noteElement); - } + for (const auto& note : command->getNotes()) { + std::shared_ptr<XMLElement> noteElement(new XMLElement("note")); + std::string type; + switch (note.type) { + case Command::Note::Info: type = "info"; break; + case Command::Note::Warn: type = "warn"; break; + case Command::Note::Error: type = "error"; break; + } + if (!type.empty()) { + noteElement->setAttribute("type", type); + } + noteElement->addNode(std::make_shared<XMLTextNode>(note.note)); + commandElement.addNode(noteElement); + } - Form::ref form = command->getForm(); - if (form) { - commandElement.addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); - } - return commandElement.serialize(); + Form::ref form = command->getForm(); + if (form) { + commandElement.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); + } + return commandElement.serialize(); } std::string CommandSerializer::actionToString(Command::Action action) const { - std::string string; - switch (action) { - case Command::Cancel: string = "cancel"; break; - case Command::Execute: string = "execute"; break; - case Command::Complete: string = "complete"; break; - case Command::Prev: string = "prev"; break; - case Command::Next: string = "next"; break; - case Command::NoAction: break; - } - return string; + std::string string; + switch (action) { + case Command::Cancel: string = "cancel"; break; + case Command::Execute: string = "execute"; break; + case Command::Complete: string = "complete"; break; + case Command::Prev: string = "prev"; break; + case Command::Next: string = "next"; break; + case Command::NoAction: break; + } + return string; } } diff --git a/Swiften/Serializer/PayloadSerializers/CommandSerializer.h b/Swiften/Serializer/PayloadSerializers/CommandSerializer.h index 03b6aa0..e1f0b24 100644 --- a/Swiften/Serializer/PayloadSerializers/CommandSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/CommandSerializer.h @@ -1,22 +1,23 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Command.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class CommandSerializer : public GenericPayloadSerializer<Command> { - public: - CommandSerializer(); + class SWIFTEN_API CommandSerializer : public GenericPayloadSerializer<Command> { + public: + CommandSerializer(); - virtual std::string serializePayload(boost::shared_ptr<Command>) const; + virtual std::string serializePayload(std::shared_ptr<Command>) const; - private: - std::string actionToString(Command::Action action) const; - }; + private: + std::string actionToString(Command::Action action) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp b/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp index 6148632..b168fdc 100644 --- a/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp @@ -1,30 +1,31 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/DelaySerializer.h> -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/date_time/posix_time/posix_time.hpp> +#include <Swiften/Base/DateTime.h> #include <Swiften/Base/String.h> #include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Base/DateTime.h> namespace Swift { DelaySerializer::DelaySerializer() : GenericPayloadSerializer<Delay>() { } -std::string DelaySerializer::serializePayload(boost::shared_ptr<Delay> delay) const { - XMLElement delayElement("delay", "urn:xmpp:delay"); - if (delay->getFrom()) { - delayElement.setAttribute("from", delay->getFrom()->toString()); - } - delayElement.setAttribute("stamp", dateTimeToString(delay->getStamp())); - return delayElement.serialize(); +std::string DelaySerializer::serializePayload(std::shared_ptr<Delay> delay) const { + XMLElement delayElement("delay", "urn:xmpp:delay"); + if (delay->getFrom() && delay->getFrom()->isValid()) { + delayElement.setAttribute("from", delay->getFrom()->toString()); + } + delayElement.setAttribute("stamp", dateTimeToString(delay->getStamp())); + return delayElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/DelaySerializer.h b/Swiften/Serializer/PayloadSerializers/DelaySerializer.h index 06c7665..86fde42 100644 --- a/Swiften/Serializer/PayloadSerializers/DelaySerializer.h +++ b/Swiften/Serializer/PayloadSerializers/DelaySerializer.h @@ -1,21 +1,22 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Delay.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class DelaySerializer : public GenericPayloadSerializer<Delay> { - public: - DelaySerializer(); + class SWIFTEN_API DelaySerializer : public GenericPayloadSerializer<Delay> { + public: + DelaySerializer(); - virtual std::string serializePayload(boost::shared_ptr<Delay>) const; - }; + virtual std::string serializePayload(std::shared_ptr<Delay>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp b/Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp index eeb0d90..8183b7f 100644 --- a/Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp @@ -4,19 +4,25 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Base/Log.h> +#include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { DeliveryReceiptRequestSerializer::DeliveryReceiptRequestSerializer() : GenericPayloadSerializer<DeliveryReceiptRequest>() { } -std::string DeliveryReceiptRequestSerializer::serializePayload(boost::shared_ptr<DeliveryReceiptRequest> /* request*/) const { - XMLElement requestXML("request", "urn:xmpp:receipts"); - return requestXML.serialize(); +std::string DeliveryReceiptRequestSerializer::serializePayload(std::shared_ptr<DeliveryReceiptRequest> /* request*/) const { + XMLElement requestXML("request", "urn:xmpp:receipts"); + return requestXML.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.h b/Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.h index 784d9e1..a3e76eb 100644 --- a/Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.h @@ -4,17 +4,23 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> -#include <Swiften/Elements/DeliveryReceiptRequest.h> #include <Swiften/Base/API.h> +#include <Swiften/Elements/DeliveryReceiptRequest.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API DeliveryReceiptRequestSerializer : public GenericPayloadSerializer<DeliveryReceiptRequest> { - public: - DeliveryReceiptRequestSerializer(); + class SWIFTEN_API DeliveryReceiptRequestSerializer : public GenericPayloadSerializer<DeliveryReceiptRequest> { + public: + DeliveryReceiptRequestSerializer(); - virtual std::string serializePayload(boost::shared_ptr<DeliveryReceiptRequest> request) const; - }; + virtual std::string serializePayload(std::shared_ptr<DeliveryReceiptRequest> request) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.cpp b/Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.cpp index a9033b2..d392d17 100644 --- a/Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.cpp @@ -4,7 +4,14 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.h> + #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { @@ -12,10 +19,10 @@ namespace Swift { DeliveryReceiptSerializer::DeliveryReceiptSerializer() : GenericPayloadSerializer<DeliveryReceipt>() { } -std::string DeliveryReceiptSerializer::serializePayload(boost::shared_ptr<DeliveryReceipt> receipt) const { - XMLElement received("received", "urn:xmpp:receipts"); - received.setAttribute("id", receipt->getReceivedID()); - return received.serialize(); +std::string DeliveryReceiptSerializer::serializePayload(std::shared_ptr<DeliveryReceipt> receipt) const { + XMLElement received("received", "urn:xmpp:receipts"); + received.setAttribute("id", receipt->getReceivedID()); + return received.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.h b/Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.h index 92a531a..6153de1 100644 --- a/Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.h @@ -4,17 +4,23 @@ * See http://www.opensource.org/licenses/bsd-license.php for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/DeliveryReceipt.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API DeliveryReceiptSerializer : public GenericPayloadSerializer<DeliveryReceipt> { - public: - DeliveryReceiptSerializer(); + class SWIFTEN_API DeliveryReceiptSerializer : public GenericPayloadSerializer<DeliveryReceipt> { + public: + DeliveryReceiptSerializer(); - virtual std::string serializePayload(boost::shared_ptr<DeliveryReceipt> receipt) const; - }; + virtual std::string serializePayload(std::shared_ptr<DeliveryReceipt> receipt) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.cpp b/Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.cpp index 03b3eb2..06cad2b 100644 --- a/Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.cpp @@ -1,48 +1,46 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> namespace Swift { DiscoInfoSerializer::DiscoInfoSerializer() : GenericPayloadSerializer<DiscoInfo>() { } -std::string DiscoInfoSerializer::serializePayload(boost::shared_ptr<DiscoInfo> discoInfo) const { - XMLElement queryElement("query", "http://jabber.org/protocol/disco#info"); - if (!discoInfo->getNode().empty()) { - queryElement.setAttribute("node", discoInfo->getNode()); - } - foreach(const DiscoInfo::Identity& identity, discoInfo->getIdentities()) { - boost::shared_ptr<XMLElement> identityElement(new XMLElement("identity")); - if (!identity.getLanguage().empty()) { - identityElement->setAttribute("xml:lang", identity.getLanguage()); - } - identityElement->setAttribute("category", identity.getCategory()); - identityElement->setAttribute("name", identity.getName()); - identityElement->setAttribute("type", identity.getType()); - queryElement.addNode(identityElement); - } - foreach(const std::string& feature, discoInfo->getFeatures()) { - boost::shared_ptr<XMLElement> featureElement(new XMLElement("feature")); - featureElement->setAttribute("var", feature); - queryElement.addNode(featureElement); - } - foreach(const Form::ref extension, discoInfo->getExtensions()) { - queryElement.addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(extension))); - } - return queryElement.serialize(); +std::string DiscoInfoSerializer::serializePayload(std::shared_ptr<DiscoInfo> discoInfo) const { + XMLElement queryElement("query", "http://jabber.org/protocol/disco#info"); + if (!discoInfo->getNode().empty()) { + queryElement.setAttribute("node", discoInfo->getNode()); + } + for (const auto& identity : discoInfo->getIdentities()) { + std::shared_ptr<XMLElement> identityElement(new XMLElement("identity")); + if (!identity.getLanguage().empty()) { + identityElement->setAttribute("xml:lang", identity.getLanguage()); + } + identityElement->setAttribute("category", identity.getCategory()); + identityElement->setAttribute("name", identity.getName()); + identityElement->setAttribute("type", identity.getType()); + queryElement.addNode(identityElement); + } + for (const auto& feature : discoInfo->getFeatures()) { + std::shared_ptr<XMLElement> featureElement(new XMLElement("feature")); + featureElement->setAttribute("var", feature); + queryElement.addNode(featureElement); + } + for (const auto& extension : discoInfo->getExtensions()) { + queryElement.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(extension))); + } + return queryElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.h b/Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.h index 233d752..21648d6 100644 --- a/Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API DiscoInfoSerializer : public GenericPayloadSerializer<DiscoInfo> { - public: - DiscoInfoSerializer(); + class SWIFTEN_API DiscoInfoSerializer : public GenericPayloadSerializer<DiscoInfo> { + public: + DiscoInfoSerializer(); - virtual std::string serializePayload(boost::shared_ptr<DiscoInfo>) const; - }; + virtual std::string serializePayload(std::shared_ptr<DiscoInfo>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.cpp index dd52b70..a8eafef 100644 --- a/Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.cpp @@ -1,14 +1,13 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.h> -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { @@ -16,21 +15,21 @@ namespace Swift { DiscoItemsSerializer::DiscoItemsSerializer() : GenericPayloadSerializer<DiscoItems>() { } -std::string DiscoItemsSerializer::serializePayload(boost::shared_ptr<DiscoItems> discoItems) const { - XMLElement queryElement("query", "http://jabber.org/protocol/disco#items"); - if (!discoItems->getNode().empty()) { - queryElement.setAttribute("node", discoItems->getNode()); - } - foreach(const DiscoItems::Item& item, discoItems->getItems()) { - boost::shared_ptr<XMLElement> itemElement(new XMLElement("item")); - itemElement->setAttribute("name", item.getName()); - itemElement->setAttribute("jid", item.getJID()); - if (!item.getNode().empty()) { - itemElement->setAttribute("node", item.getNode()); - } - queryElement.addNode(itemElement); - } - return queryElement.serialize(); +std::string DiscoItemsSerializer::serializePayload(std::shared_ptr<DiscoItems> discoItems) const { + XMLElement queryElement("query", "http://jabber.org/protocol/disco#items"); + if (!discoItems->getNode().empty()) { + queryElement.setAttribute("node", discoItems->getNode()); + } + for (const auto& item : discoItems->getItems()) { + std::shared_ptr<XMLElement> itemElement(new XMLElement("item")); + itemElement->setAttribute("name", item.getName()); + itemElement->setAttribute("jid", item.getJID()); + if (!item.getNode().empty()) { + itemElement->setAttribute("node", item.getNode()); + } + queryElement.addNode(itemElement); + } + return queryElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.h b/Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.h index a8785c2..ca88cb0 100644 --- a/Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.h @@ -1,20 +1,21 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/DiscoItems.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class DiscoItemsSerializer : public GenericPayloadSerializer<DiscoItems> { - public: - DiscoItemsSerializer(); + class SWIFTEN_API DiscoItemsSerializer : public GenericPayloadSerializer<DiscoItems> { + public: + DiscoItemsSerializer(); - virtual std::string serializePayload(boost::shared_ptr<DiscoItems>) const; - }; + virtual std::string serializePayload(std::shared_ptr<DiscoItems>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/ErrorSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ErrorSerializer.cpp index 954b885..26686f0 100644 --- a/Swiften/Serializer/PayloadSerializers/ErrorSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/ErrorSerializer.cpp @@ -1,70 +1,71 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/ErrorSerializer.h> -#include <Swiften/Serializer/XML/XMLTextNode.h> + #include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> namespace Swift { ErrorSerializer::ErrorSerializer(PayloadSerializerCollection* serializers) : GenericPayloadSerializer<ErrorPayload>(), serializers(serializers) { } -std::string ErrorSerializer::serializePayload(boost::shared_ptr<ErrorPayload> error) const { - std::string result("<error type=\""); - switch (error->getType()) { - case ErrorPayload::Continue: result += "continue"; break; - case ErrorPayload::Modify: result += "modify"; break; - case ErrorPayload::Auth: result += "auth"; break; - case ErrorPayload::Wait: result += "wait"; break; - case ErrorPayload::Cancel: result += "cancel"; break; - } - result += "\">"; +std::string ErrorSerializer::serializePayload(std::shared_ptr<ErrorPayload> error) const { + std::string result("<error type=\""); + switch (error->getType()) { + case ErrorPayload::Continue: result += "continue"; break; + case ErrorPayload::Modify: result += "modify"; break; + case ErrorPayload::Auth: result += "auth"; break; + case ErrorPayload::Wait: result += "wait"; break; + case ErrorPayload::Cancel: result += "cancel"; break; + } + result += "\">"; - std::string conditionElement; - switch (error->getCondition()) { - case ErrorPayload::BadRequest: conditionElement = "bad-request"; break; - case ErrorPayload::Conflict: conditionElement = "conflict"; break; - case ErrorPayload::FeatureNotImplemented: conditionElement = "feature-not-implemented"; break; - case ErrorPayload::Forbidden: conditionElement = "forbidden"; break; - case ErrorPayload::Gone: conditionElement = "gone"; break; - case ErrorPayload::InternalServerError: conditionElement = "internal-server-error"; break; - case ErrorPayload::ItemNotFound: conditionElement = "item-not-found"; break; - case ErrorPayload::JIDMalformed: conditionElement = "jid-malformed"; break; - case ErrorPayload::NotAcceptable: conditionElement = "not-acceptable"; break; - case ErrorPayload::NotAllowed: conditionElement = "not-allowed"; break; - case ErrorPayload::NotAuthorized: conditionElement = "not-authorized"; break; - case ErrorPayload::PaymentRequired: conditionElement = "payment-required"; break; - case ErrorPayload::RecipientUnavailable: conditionElement = "recipient-unavailable"; break; - case ErrorPayload::Redirect: conditionElement = "redirect"; break; - case ErrorPayload::RegistrationRequired: conditionElement = "registration-required"; break; - case ErrorPayload::RemoteServerNotFound: conditionElement = "remote-server-not-found"; break; - case ErrorPayload::RemoteServerTimeout: conditionElement = "remote-server-timeout"; break; - case ErrorPayload::ResourceConstraint: conditionElement = "resource-constraint"; break; - case ErrorPayload::ServiceUnavailable: conditionElement = "service-unavailable"; break; - case ErrorPayload::SubscriptionRequired: conditionElement = "subscription-required"; break; - case ErrorPayload::UnexpectedRequest: conditionElement = "unexpected-request"; break; - case ErrorPayload::UndefinedCondition: conditionElement = "undefined-condition"; break; - } - result += "<" + conditionElement + " xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>"; + std::string conditionElement; + switch (error->getCondition()) { + case ErrorPayload::BadRequest: conditionElement = "bad-request"; break; + case ErrorPayload::Conflict: conditionElement = "conflict"; break; + case ErrorPayload::FeatureNotImplemented: conditionElement = "feature-not-implemented"; break; + case ErrorPayload::Forbidden: conditionElement = "forbidden"; break; + case ErrorPayload::Gone: conditionElement = "gone"; break; + case ErrorPayload::InternalServerError: conditionElement = "internal-server-error"; break; + case ErrorPayload::ItemNotFound: conditionElement = "item-not-found"; break; + case ErrorPayload::JIDMalformed: conditionElement = "jid-malformed"; break; + case ErrorPayload::NotAcceptable: conditionElement = "not-acceptable"; break; + case ErrorPayload::NotAllowed: conditionElement = "not-allowed"; break; + case ErrorPayload::NotAuthorized: conditionElement = "not-authorized"; break; + case ErrorPayload::PaymentRequired: conditionElement = "payment-required"; break; + case ErrorPayload::RecipientUnavailable: conditionElement = "recipient-unavailable"; break; + case ErrorPayload::Redirect: conditionElement = "redirect"; break; + case ErrorPayload::RegistrationRequired: conditionElement = "registration-required"; break; + case ErrorPayload::RemoteServerNotFound: conditionElement = "remote-server-not-found"; break; + case ErrorPayload::RemoteServerTimeout: conditionElement = "remote-server-timeout"; break; + case ErrorPayload::ResourceConstraint: conditionElement = "resource-constraint"; break; + case ErrorPayload::ServiceUnavailable: conditionElement = "service-unavailable"; break; + case ErrorPayload::SubscriptionRequired: conditionElement = "subscription-required"; break; + case ErrorPayload::UnexpectedRequest: conditionElement = "unexpected-request"; break; + case ErrorPayload::UndefinedCondition: conditionElement = "undefined-condition"; break; + } + result += "<" + conditionElement + " xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>"; - if (!error->getText().empty()) { - XMLTextNode textNode(error->getText()); - result += "<text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">" + textNode.serialize() + "</text>"; - } + if (!error->getText().empty()) { + XMLTextNode textNode(error->getText()); + result += "<text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">" + textNode.serialize() + "</text>"; + } - if (error->getPayload()) { - PayloadSerializer* serializer = serializers->getPayloadSerializer(error->getPayload()); - if (serializer) { - result += serializer->serialize(error->getPayload()); - } - } + if (error->getPayload()) { + PayloadSerializer* serializer = serializers->getPayloadSerializer(error->getPayload()); + if (serializer) { + result += serializer->serialize(error->getPayload()); + } + } - result += "</error>"; - return result; + result += "</error>"; + return result; } } diff --git a/Swiften/Serializer/PayloadSerializers/ErrorSerializer.h b/Swiften/Serializer/PayloadSerializers/ErrorSerializer.h index f41d585..df7791e 100644 --- a/Swiften/Serializer/PayloadSerializers/ErrorSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/ErrorSerializer.h @@ -1,25 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; + class PayloadSerializerCollection; - class SWIFTEN_API ErrorSerializer : public GenericPayloadSerializer<ErrorPayload> { - public: - ErrorSerializer(PayloadSerializerCollection* serializers); + class SWIFTEN_API ErrorSerializer : public GenericPayloadSerializer<ErrorPayload> { + public: + ErrorSerializer(PayloadSerializerCollection* serializers); - virtual std::string serializePayload(boost::shared_ptr<ErrorPayload> error) const; + virtual std::string serializePayload(std::shared_ptr<ErrorPayload> error) const; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp index cf0f4ea..f723ead 100644 --- a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp @@ -1,148 +1,209 @@ /* - * Copyright (c) 2010-2013 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <iostream> +#include <memory> #include <string> -#include <Swiften/Base/String.h> #include <Swiften/Base/Algorithm.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLTextNode.h> +#include <Swiften/Base/String.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> using namespace Swift; namespace { - template<typename T> void serializeValueAsString(boost::shared_ptr<FormField> field, boost::shared_ptr<XMLElement> parent) { - std::string value = boost::dynamic_pointer_cast<T>(field)->getValue(); - if (!value.empty()) { - boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); - valueElement->addNode(XMLTextNode::create(value)); - parent->addNode(valueElement); - } - } + template<typename T> void serializeValueAsString(std::shared_ptr<FormField> field, std::shared_ptr<XMLElement> parent) { + std::string value = std::dynamic_pointer_cast<T>(field)->getValue(); + if (!value.empty()) { + std::shared_ptr<XMLElement> valueElement(new XMLElement("value")); + valueElement->addNode(XMLTextNode::create(value)); + parent->addNode(valueElement); + } + } } - namespace Swift { -FormSerializer::FormSerializer() : GenericPayloadSerializer<Form>() { +FormSerializer::FormSerializer() : GenericPayloadSerializer<Form>() {} + +std::string FormSerializer::serializePayload(std::shared_ptr<Form> form) const { + if (!form) { + return ""; + } + + std::shared_ptr<XMLElement> formElement(new XMLElement("x", "jabber:x:data")); + std::string type; + switch (form->getType()) { + case Form::FormType: type = "form"; break; + case Form::SubmitType: type = "submit"; break; + case Form::CancelType: type = "cancel"; break; + case Form::ResultType: type = "result"; break; + } + formElement->setAttribute("type", type); + if (!form->getTitle().empty()) { + multiLineify(form->getTitle(), "title", formElement); + } + if (!form->getInstructions().empty()) { + multiLineify(form->getInstructions(), "instructions", formElement); + } + for (const auto& page : form->getPages()) { + formElement->addNode(pageToXML(page)); + } + for (const auto& field : form->getFields()) { + formElement->addNode(fieldToXML(field, true)); + } + if (!form->getReportedFields().empty()) { + std::shared_ptr<XMLElement> reportedElement(new XMLElement("reported")); + for (const auto& field : form->getReportedFields()) { + reportedElement->addNode(fieldToXML(field, true)); + } + formElement->addNode(reportedElement); + } + + for (const auto& item : form->getItems()) { + std::shared_ptr<XMLElement> itemElement(new XMLElement("item")); + for (const auto& field : item) { + itemElement->addNode(fieldToXML(field, false)); + } + formElement->addNode(itemElement); + } + + for (const auto& text : form->getTextElements()) { + formElement->addNode(textToXML(text)); + } + + for (const auto& field : fields_) { + formElement->addNode(fieldToXML(field,true)); + } + + return formElement->serialize(); } -std::string FormSerializer::serializePayload(boost::shared_ptr<Form> form) const { - if (!form) { - return ""; - } - - boost::shared_ptr<XMLElement> formElement(new XMLElement("x", "jabber:x:data")); - std::string type; - switch (form->getType()) { - case Form::FormType: type = "form"; break; - case Form::SubmitType: type = "submit"; break; - case Form::CancelType: type = "cancel"; break; - case Form::ResultType: type = "result"; break; - } - formElement->setAttribute("type", type); - if (!form->getTitle().empty()) { - multiLineify(form->getTitle(), "title", formElement); - } - if (!form->getInstructions().empty()) { - multiLineify(form->getInstructions(), "instructions", formElement); - } - foreach(boost::shared_ptr<FormField> field, form->getFields()) { - formElement->addNode(fieldToXML(field, true)); - } - if (!form->getReportedFields().empty()) { - boost::shared_ptr<XMLElement> reportedElement(new XMLElement("reported")); - foreach(FormField::ref field, form->getReportedFields()) { - reportedElement->addNode(fieldToXML(field, true)); - } - formElement->addNode(reportedElement); - } - foreach(Form::FormItem item, form->getItems()) { - boost::shared_ptr<XMLElement> itemElement(new XMLElement("item")); - foreach(FormField::ref field, item) { - itemElement->addNode(fieldToXML(field, false)); - } - formElement->addNode(itemElement); - } - - return formElement->serialize(); +std::shared_ptr<XMLElement> FormSerializer::textToXML(std::shared_ptr<FormText> text) const { + std::shared_ptr<XMLElement> textElement (new XMLElement("text")); + textElement->addNode(std::make_shared<XMLTextNode>(text->getTextString())); + return textElement; } -boost::shared_ptr<XMLElement> FormSerializer::fieldToXML(boost::shared_ptr<FormField> field, bool withTypeAttribute) const { - boost::shared_ptr<XMLElement> fieldElement(new XMLElement("field")); - if (!field->getName().empty()) { - fieldElement->setAttribute("var", field->getName()); - } - if (!field->getLabel().empty()) { - fieldElement->setAttribute("label", field->getLabel()); - } - if (field->getRequired()) { - fieldElement->addNode(boost::make_shared<XMLElement>("required")); - } - if (!field->getDescription().empty()) { - boost::shared_ptr<XMLElement> descriptionElement(new XMLElement("desc")); - descriptionElement->addNode(boost::make_shared<XMLTextNode>(field->getDescription())); - fieldElement->addNode(descriptionElement); - } - - // Set the value and type - std::string fieldType; - switch (field->getType()) { - case FormField::UnknownType: fieldType = ""; break; - case FormField::BooleanType: fieldType = "boolean"; break; - case FormField::FixedType: fieldType = "fixed"; break; - case FormField::HiddenType: fieldType = "hidden"; break; - case FormField::ListSingleType: fieldType = "list-single"; break; - case FormField::TextMultiType: fieldType = "text-multi"; break; - case FormField::TextPrivateType: fieldType = "text-private"; break; - case FormField::TextSingleType: fieldType = "text-single"; break; - case FormField::JIDSingleType: fieldType = "jid-single"; break; - case FormField::JIDMultiType: fieldType = "jid-multi"; break; - case FormField::ListMultiType: fieldType = "list-multi"; break; - } - if (!fieldType.empty() && withTypeAttribute) { - fieldElement->setAttribute("type", fieldType); - } - foreach (const std::string& value, field->getValues()) { - boost::shared_ptr<XMLElement> valueElement = boost::make_shared<XMLElement>("value"); - valueElement->addNode(boost::make_shared<XMLTextNode>(value)); - fieldElement->addNode(valueElement); - } - - foreach (const FormField::Option& option, field->getOptions()) { - boost::shared_ptr<XMLElement> optionElement(new XMLElement("option")); - if (!option.label.empty()) { - optionElement->setAttribute("label", option.label); - } - - boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); - valueElement->addNode(XMLTextNode::create(option.value)); - optionElement->addNode(valueElement); - - fieldElement->addNode(optionElement); - } - - return fieldElement; +std::shared_ptr<XMLElement> FormSerializer::fieldRefToXML(const std::string& ref) const { + std::shared_ptr<XMLElement> fieldRefElement(new XMLElement("fieldref")); + fieldRefElement->setAttribute("var", ref); + return fieldRefElement; } -void FormSerializer::multiLineify(const std::string& text, const std::string& elementName, boost::shared_ptr<XMLElement> element) const { - std::string unRdText(text); - erase(unRdText, '\r'); - std::vector<std::string> lines = String::split(unRdText, '\n'); - foreach (std::string line, lines) { - boost::shared_ptr<XMLElement> lineElement(new XMLElement(elementName)); - lineElement->addNode(boost::make_shared<XMLTextNode>(line)); - element->addNode(lineElement); - } +std::shared_ptr<XMLElement> FormSerializer::pageToXML(std::shared_ptr<FormPage> page) const { + std::shared_ptr<XMLElement> pageElement(new XMLElement("page")); + pageElement->setAttribute("xmlns", "http://jabber.org/protocol/xdata-layout"); + if (!page->getLabel().empty()) { + pageElement->setAttribute("label", page->getLabel()); + } + for (const auto& text : page->getTextElements()) { + pageElement->addNode(textToXML(text)); + } + for (const auto& field : page->getFields()) { + pageElement->addNode(fieldRefToXML(field->getName())); + fields_.push_back(field); + } + for (const auto& reportedRef: page->getReportedRefs()) { + (void)reportedRef; + pageElement->addNode(std::make_shared<XMLElement>("reportedref")); + } + for (const auto& section : page->getChildSections()) { + pageElement->addNode(sectionToXML(section)); + } + return pageElement; } +std::shared_ptr<XMLElement> FormSerializer::sectionToXML(std::shared_ptr<FormSection> section) const { + std::shared_ptr<XMLElement> sectionElement(new XMLElement("section")); + if (!section->getLabel().empty()) { + sectionElement->setAttribute("label", section->getLabel()); + } + for (const auto& text : section->getTextElements()) { + sectionElement->addNode(textToXML(text)); + } + for (const auto& field : section->getFields()) { + sectionElement->addNode(fieldRefToXML(field->getName())); + fields_.push_back(field); + } + for (const auto& reportedRef : section->getReportedRefs()) { + (void)reportedRef; + sectionElement->addNode(std::make_shared<XMLElement>("reportedref")); + } + for (const auto& childSection : section->getChildSections()) { + sectionElement->addNode(sectionToXML(childSection)); + } + return sectionElement; +} + +std::shared_ptr<XMLElement> FormSerializer::fieldToXML(std::shared_ptr<FormField> field, bool withTypeAttribute) const { + std::shared_ptr<XMLElement> fieldElement(new XMLElement("field")); + if (!field->getName().empty()) { + fieldElement->setAttribute("var", field->getName()); + } + if (!field->getLabel().empty()) { + fieldElement->setAttribute("label", field->getLabel()); + } + if (field->getRequired()) { + fieldElement->addNode(std::make_shared<XMLElement>("required")); + } + if (!field->getDescription().empty()) { + std::shared_ptr<XMLElement> descriptionElement(new XMLElement("desc")); + descriptionElement->addNode(std::make_shared<XMLTextNode>(field->getDescription())); + fieldElement->addNode(descriptionElement); + } + + // Set the value and type + std::string fieldType; + switch (field->getType()) { + case FormField::UnknownType: fieldType = ""; break; + case FormField::BooleanType: fieldType = "boolean"; break; + case FormField::FixedType: fieldType = "fixed"; break; + case FormField::HiddenType: fieldType = "hidden"; break; + case FormField::ListSingleType: fieldType = "list-single"; break; + case FormField::TextMultiType: fieldType = "text-multi"; break; + case FormField::TextPrivateType: fieldType = "text-private"; break; + case FormField::TextSingleType: fieldType = "text-single"; break; + case FormField::JIDSingleType: fieldType = "jid-single"; break; + case FormField::JIDMultiType: fieldType = "jid-multi"; break; + case FormField::ListMultiType: fieldType = "list-multi"; break; + } + if (!fieldType.empty() && withTypeAttribute) { + fieldElement->setAttribute("type", fieldType); + } + for (const auto& value : field->getValues()) { + std::shared_ptr<XMLElement> valueElement = std::make_shared<XMLElement>("value"); + valueElement->addNode(std::make_shared<XMLTextNode>(value)); + fieldElement->addNode(valueElement); + } + + for (const auto& option : field->getOptions()) { + std::shared_ptr<XMLElement> optionElement(new XMLElement("option")); + if (!option.label.empty()) { + optionElement->setAttribute("label", option.label); + } + + std::shared_ptr<XMLElement> valueElement(new XMLElement("value")); + valueElement->addNode(XMLTextNode::create(option.value)); + optionElement->addNode(valueElement); + fieldElement->addNode(optionElement); + } + return fieldElement; +} + +void FormSerializer::multiLineify(const std::string& text, const std::string& elementName, std::shared_ptr<XMLElement> element) const { + std::string unRdText(text); + erase(unRdText, '\r'); + std::vector<std::string> lines = String::split(unRdText, '\n'); + for (const auto& line : lines) { + std::shared_ptr<XMLElement> lineElement(new XMLElement(elementName)); + lineElement->addNode(std::make_shared<XMLTextNode>(line)); + element->addNode(lineElement); + } +} } diff --git a/Swiften/Serializer/PayloadSerializers/FormSerializer.h b/Swiften/Serializer/PayloadSerializers/FormSerializer.h index f0f365c..590fce4 100644 --- a/Swiften/Serializer/PayloadSerializers/FormSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/FormSerializer.h @@ -1,28 +1,33 @@ /* - * Copyright (c) 2010-2013 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/Form.h> #include <Swiften/Elements/FormField.h> +#include <Swiften/Elements/FormPage.h> +#include <Swiften/Elements/FormSection.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class SWIFTEN_API FormSerializer : public GenericPayloadSerializer<Form> { - public: - FormSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<Form>) const; + class SWIFTEN_API FormSerializer : public GenericPayloadSerializer<Form> { + public: + FormSerializer(); + virtual std::string serializePayload(std::shared_ptr<Form>) const; - private: - boost::shared_ptr<XMLElement> fieldToXML(boost::shared_ptr<FormField> field, bool withTypeAttribute) const; - void multiLineify(const std::string& text, const std::string& elementName, boost::shared_ptr<XMLElement> parent) const; - }; + private: + std::shared_ptr<XMLElement> textToXML(std::shared_ptr<FormText> textElement) const; + std::shared_ptr<XMLElement> fieldRefToXML(const std::string& ref) const; + std::shared_ptr<XMLElement> reportedRefToXML(std::shared_ptr<FormReportedRef> reportedRef) const; + std::shared_ptr<XMLElement> pageToXML(std::shared_ptr<FormPage> page) const; + std::shared_ptr<XMLElement> sectionToXML(std::shared_ptr<FormSection> section) const; + std::shared_ptr<XMLElement> fieldToXML(std::shared_ptr<FormField> field, bool withTypeAttribute) const; + void multiLineify(const std::string& text, const std::string& elementName, std::shared_ptr<XMLElement> parent) const; + mutable std::vector<std::shared_ptr<FormField> > fields_; + }; } - - diff --git a/Swiften/Serializer/PayloadSerializers/ForwardedSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ForwardedSerializer.cpp new file mode 100644 index 0000000..58660d7 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ForwardedSerializer.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h> + +#include <memory> + +#include <boost/lexical_cast.hpp> + +#include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.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/PresenceSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +ForwardedSerializer::ForwardedSerializer(PayloadSerializerCollection* serializers) : serializers_(serializers) { +} + +ForwardedSerializer::~ForwardedSerializer() { +} + +std::string ForwardedSerializer::serializePayload(std::shared_ptr<Forwarded> payload) const { + if (!payload) { + return ""; + } + + XMLElement element("forwarded", "urn:xmpp:forward:0"); + + if (payload->getDelay()) { + element.addNode(std::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*/ + std::shared_ptr<IQ> iq; + std::shared_ptr<Message> message; + std::shared_ptr<Presence> presence; + const std::string ns = "jabber:client"; + if ((iq = std::dynamic_pointer_cast<IQ>(payload->getStanza()))) { + element.addNode(std::make_shared<XMLRawTextNode>(safeByteArrayToString(IQSerializer(serializers_).serialize(iq, ns)))); + } else if ((message = std::dynamic_pointer_cast<Message>(payload->getStanza()))) { + element.addNode(std::make_shared<XMLRawTextNode>(safeByteArrayToString(MessageSerializer(serializers_).serialize(message, ns)))); + } else if ((presence = std::dynamic_pointer_cast<Presence>(payload->getStanza()))) { + element.addNode(std::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..439e684 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#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() override; + + virtual std::string serializePayload(std::shared_ptr<Forwarded>) const override; + + private: + PayloadSerializerCollection* serializers_; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp index a57a74e..31294f1 100644 --- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp +++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp @@ -1,152 +1,205 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> -#include <Swiften/Base/foreach.h> + +#include <Swiften/Elements/BlockListPayload.h> #include <Swiften/Elements/BlockPayload.h> #include <Swiften/Elements/UnblockPayload.h> -#include <Swiften/Elements/BlockListPayload.h> #include <Swiften/Serializer/PayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/IBBSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/BodySerializer.h> #include <Swiften/Serializer/PayloadSerializers/BlockSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/SubjectSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/BodySerializer.h> +#include <Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CarbonsDisableSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CarbonsEnableSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CarbonsPrivateSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CarbonsReceivedSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CarbonsSentSerializer.h> #include <Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PrioritySerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ClientStateSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CommandSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/DelaySerializer.h> +#include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.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/FormSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/IBBSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/IdleSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/IsodeIQDelegationSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/LastSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MAMFinSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MAMResultSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MIXJoinSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MIXDestroySerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MIXUpdateSubscriptionSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MIXParticipantSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MIXRegisterNickSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MIXCreateSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MIXPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MIXSetNickSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MIXUserPreferenceSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MIXLeaveSerializer.h> #include <Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.h> #include <Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.h> #include <Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/StatusSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/StatusShowSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/NicknameSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PrioritySerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/RawXMLPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ReferencePayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ReplaceSerializer.h> #include <Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/StartSessionSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/RosterSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/S5BProxyRequestSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.h> #include <Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.h> #include <Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/StartSessionSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/StatusSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/StatusShowSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/StorageSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h> #include <Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/SubjectSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ThreadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h> #include <Swiften/Serializer/PayloadSerializers/VCardSerializer.h> #include <Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/RawXMLPayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/StorageSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/DelaySerializer.h> -#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/CommandSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/NicknameSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/ReplaceSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/LastSerializer.h> #include <Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/IdleSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h> - -#include <Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/S5BProxyRequestSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.h> namespace Swift { FullPayloadSerializerCollection::FullPayloadSerializerCollection() { - serializers_.push_back(new IBBSerializer()); - serializers_.push_back(new BodySerializer()); - serializers_.push_back(new SubjectSerializer()); - serializers_.push_back(new ChatStateSerializer()); - serializers_.push_back(new PrioritySerializer()); - serializers_.push_back(new ErrorSerializer(this)); - serializers_.push_back(new RosterSerializer()); - serializers_.push_back(new RosterItemExchangeSerializer()); - serializers_.push_back(new MUCPayloadSerializer()); - serializers_.push_back(new MUCDestroyPayloadSerializer()); - serializers_.push_back(new MUCAdminPayloadSerializer()); - serializers_.push_back(new MUCInvitationPayloadSerializer()); - serializers_.push_back(new MUCOwnerPayloadSerializer(this)); - serializers_.push_back(new MUCUserPayloadSerializer(this)); - serializers_.push_back(new SoftwareVersionSerializer()); - serializers_.push_back(new StatusSerializer()); - serializers_.push_back(new StatusShowSerializer()); - serializers_.push_back(new DiscoInfoSerializer()); - serializers_.push_back(new DiscoItemsSerializer()); - serializers_.push_back(new CapsInfoSerializer()); - serializers_.push_back(new BlockSerializer<BlockPayload>("block")); - serializers_.push_back(new BlockSerializer<UnblockPayload>("unblock")); - serializers_.push_back(new BlockSerializer<BlockListPayload>("blocklist")); - serializers_.push_back(new ResourceBindSerializer()); - serializers_.push_back(new StartSessionSerializer()); - serializers_.push_back(new SecurityLabelSerializer()); - serializers_.push_back(new SecurityLabelsCatalogSerializer()); - serializers_.push_back(new StreamInitiationSerializer()); - serializers_.push_back(new BytestreamsSerializer()); - serializers_.push_back(new VCardSerializer()); - serializers_.push_back(new VCardUpdateSerializer()); - serializers_.push_back(new RawXMLPayloadSerializer()); - serializers_.push_back(new StorageSerializer()); - serializers_.push_back(new DelaySerializer()); - serializers_.push_back(new FormSerializer()); - serializers_.push_back(new PrivateStorageSerializer(this)); - serializers_.push_back(new CommandSerializer()); - serializers_.push_back(new InBandRegistrationPayloadSerializer()); - serializers_.push_back(new NicknameSerializer()); - serializers_.push_back(new SearchPayloadSerializer()); - serializers_.push_back(new ReplaceSerializer()); - serializers_.push_back(new LastSerializer()); - serializers_.push_back(new WhiteboardSerializer()); - serializers_.push_back(new UserLocationSerializer()); - serializers_.push_back(new IdleSerializer()); - - serializers_.push_back(new StreamInitiationFileInfoSerializer()); - serializers_.push_back(new JingleContentPayloadSerializer()); - serializers_.push_back(new JingleFileTransferDescriptionSerializer()); - serializers_.push_back(new JingleFileTransferHashSerializer()); - serializers_.push_back(new JingleFileTransferReceivedSerializer()); - serializers_.push_back(new JingleIBBTransportPayloadSerializer()); - serializers_.push_back(new JingleS5BTransportPayloadSerializer()); - serializers_.push_back(new JinglePayloadSerializer(this)); - serializers_.push_back(new S5BProxyRequestSerializer()); - serializers_.push_back(new DeliveryReceiptSerializer()); - serializers_.push_back(new DeliveryReceiptRequestSerializer()); + serializers_.push_back(new IBBSerializer()); + serializers_.push_back(new BodySerializer()); + serializers_.push_back(new SubjectSerializer()); + serializers_.push_back(new ThreadSerializer()); + serializers_.push_back(new ChatStateSerializer()); + serializers_.push_back(new ClientStateSerializer()); + serializers_.push_back(new PrioritySerializer()); + serializers_.push_back(new ErrorSerializer(this)); + serializers_.push_back(new RosterSerializer()); + serializers_.push_back(new RosterItemExchangeSerializer()); + serializers_.push_back(new MUCPayloadSerializer()); + serializers_.push_back(new MUCDestroyPayloadSerializer()); + serializers_.push_back(new MUCAdminPayloadSerializer()); + serializers_.push_back(new MUCInvitationPayloadSerializer()); + serializers_.push_back(new MUCOwnerPayloadSerializer(this)); + serializers_.push_back(new MUCUserPayloadSerializer(this)); + serializers_.push_back(new SoftwareVersionSerializer()); + serializers_.push_back(new StatusSerializer()); + serializers_.push_back(new StatusShowSerializer()); + serializers_.push_back(new DiscoInfoSerializer()); + serializers_.push_back(new DiscoItemsSerializer()); + serializers_.push_back(new CapsInfoSerializer()); + serializers_.push_back(new BlockSerializer<BlockPayload>("block")); + serializers_.push_back(new BlockSerializer<UnblockPayload>("unblock")); + serializers_.push_back(new BlockSerializer<BlockListPayload>("blocklist")); + serializers_.push_back(new ResourceBindSerializer()); + serializers_.push_back(new StartSessionSerializer()); + serializers_.push_back(new SecurityLabelSerializer()); + serializers_.push_back(new SecurityLabelsCatalogSerializer()); + serializers_.push_back(new StreamInitiationSerializer()); + serializers_.push_back(new BytestreamsSerializer()); + serializers_.push_back(new VCardSerializer()); + serializers_.push_back(new VCardUpdateSerializer()); + serializers_.push_back(new RawXMLPayloadSerializer()); + serializers_.push_back(new StorageSerializer()); + serializers_.push_back(new DelaySerializer()); + serializers_.push_back(new FormSerializer()); + serializers_.push_back(new PrivateStorageSerializer(this)); + serializers_.push_back(new CommandSerializer()); + serializers_.push_back(new InBandRegistrationPayloadSerializer()); + serializers_.push_back(new NicknameSerializer()); + serializers_.push_back(new SearchPayloadSerializer()); + serializers_.push_back(new ReplaceSerializer()); + serializers_.push_back(new LastSerializer()); + serializers_.push_back(new WhiteboardSerializer()); + serializers_.push_back(new UserLocationSerializer(this)); + serializers_.push_back(new UserTuneSerializer(this)); + serializers_.push_back(new IdleSerializer()); + + serializers_.push_back(new StreamInitiationFileInfoSerializer()); + serializers_.push_back(new JingleFileTransferFileInfoSerializer()); + serializers_.push_back(new JingleContentPayloadSerializer()); + serializers_.push_back(new JingleFileTransferDescriptionSerializer()); + serializers_.push_back(new JingleFileTransferHashSerializer()); + serializers_.push_back(new JingleIBBTransportPayloadSerializer()); + serializers_.push_back(new JingleS5BTransportPayloadSerializer()); + serializers_.push_back(new JinglePayloadSerializer(this)); + serializers_.push_back(new S5BProxyRequestSerializer()); + serializers_.push_back(new DeliveryReceiptSerializer()); + serializers_.push_back(new DeliveryReceiptRequestSerializer()); + + serializers_.push_back(new PubSubSerializer(this)); + serializers_.push_back(new PubSubEventSerializer(this)); + serializers_.push_back(new PubSubOwnerPubSubSerializer(this)); + serializers_.push_back(new PubSubErrorSerializer()); + + serializers_.push_back(new ResultSetSerializer()); + serializers_.push_back(new ForwardedSerializer(this)); + serializers_.push_back(new MIXParticipantSerializer()); + serializers_.push_back(new MIXCreateSerializer()); + serializers_.push_back(new MIXRegisterNickSerializer()); + serializers_.push_back(new MIXPayloadSerializer()); + serializers_.push_back(new MIXSetNickSerializer()); + serializers_.push_back(new MIXUserPreferenceSerializer()); + serializers_.push_back(new MIXLeaveSerializer()); + serializers_.push_back(new MIXJoinSerializer()); + serializers_.push_back(new MIXDestroySerializer()); + serializers_.push_back(new MIXUpdateSubscriptionSerializer()); + serializers_.push_back(new MAMResultSerializer(this)); + serializers_.push_back(new MAMQuerySerializer()); + serializers_.push_back(new MAMFinSerializer()); + + serializers_.push_back(new CarbonsDisableSerializer()); + serializers_.push_back(new CarbonsEnableSerializer()); + serializers_.push_back(new CarbonsPrivateSerializer()); + serializers_.push_back(new CarbonsReceivedSerializer(this)); + serializers_.push_back(new CarbonsSentSerializer(this)); + + serializers_.push_back(new IsodeIQDelegationSerializer(this)); + + serializers_.push_back(new ReferencePayloadSerializer(this)); - serializers_.push_back(new PubSubSerializer(this)); - serializers_.push_back(new PubSubEventSerializer(this)); - serializers_.push_back(new PubSubOwnerPubSubSerializer(this)); - serializers_.push_back(new PubSubErrorSerializer()); - - foreach(PayloadSerializer* serializer, serializers_) { - addSerializer(serializer); - } + for (auto serializer : serializers_) { + addSerializer(serializer); + } } FullPayloadSerializerCollection::~FullPayloadSerializerCollection() { - foreach(PayloadSerializer* serializer, serializers_) { - removeSerializer(serializer); - delete serializer; - } - serializers_.clear(); + for (auto serializer : serializers_) { + removeSerializer(serializer); + delete serializer; + } + serializers_.clear(); } } diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h index eaae742..59354ea 100644 --- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h +++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -12,12 +12,12 @@ #include <Swiften/Serializer/PayloadSerializerCollection.h> namespace Swift { - class SWIFTEN_API FullPayloadSerializerCollection : public PayloadSerializerCollection { - public: - FullPayloadSerializerCollection(); - ~FullPayloadSerializerCollection(); + class SWIFTEN_API FullPayloadSerializerCollection : public PayloadSerializerCollection { + public: + FullPayloadSerializerCollection(); + virtual ~FullPayloadSerializerCollection(); - private: - std::vector<PayloadSerializer*> serializers_; - }; + private: + std::vector<PayloadSerializer*> serializers_; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp b/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp index c83b293..74a8e7b 100644 --- a/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp @@ -1,17 +1,16 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/IBBSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <cassert> +#include <memory> + #include <boost/lexical_cast.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> #include <Swiften/StringCodecs/Base64.h> @@ -21,36 +20,36 @@ namespace Swift { IBBSerializer::IBBSerializer() { } -std::string IBBSerializer::serializePayload(boost::shared_ptr<IBB> ibb) const { - switch(ibb->getAction()) { - case IBB::Data: { - XMLElement ibbElement("data", "http://jabber.org/protocol/ibb"); - ibbElement.setAttribute("sid", ibb->getStreamID()); - if (ibb->getSequenceNumber() >= 0) { - ibbElement.setAttribute("seq", boost::lexical_cast<std::string>(ibb->getSequenceNumber())); - } - ibbElement.addNode(boost::make_shared<XMLTextNode>(Base64::encode(ibb->getData()))); - return ibbElement.serialize(); - } - case IBB::Open: { - XMLElement ibbElement("open", "http://jabber.org/protocol/ibb"); - ibbElement.setAttribute("sid", ibb->getStreamID()); - switch (ibb->getStanzaType()) { - case IBB::IQStanza: ibbElement.setAttribute("stanza", "iq"); break; - case IBB::MessageStanza: ibbElement.setAttribute("stanza", "message"); break; - } - assert(ibb->getBlockSize() > 0); - ibbElement.setAttribute("block-size", boost::lexical_cast<std::string>(ibb->getBlockSize())); - return ibbElement.serialize(); - } - case IBB::Close: { - XMLElement ibbElement("close", "http://jabber.org/protocol/ibb"); - ibbElement.setAttribute("sid", ibb->getStreamID()); - return ibbElement.serialize(); - } - } - assert(false); - return ""; +std::string IBBSerializer::serializePayload(std::shared_ptr<IBB> ibb) const { + switch(ibb->getAction()) { + case IBB::Data: { + XMLElement ibbElement("data", "http://jabber.org/protocol/ibb"); + ibbElement.setAttribute("sid", ibb->getStreamID()); + if (ibb->getSequenceNumber() >= 0) { + ibbElement.setAttribute("seq", std::to_string(ibb->getSequenceNumber())); + } + ibbElement.addNode(std::make_shared<XMLTextNode>(Base64::encode(ibb->getData()))); + return ibbElement.serialize(); + } + case IBB::Open: { + XMLElement ibbElement("open", "http://jabber.org/protocol/ibb"); + ibbElement.setAttribute("sid", ibb->getStreamID()); + switch (ibb->getStanzaType()) { + case IBB::IQStanza: ibbElement.setAttribute("stanza", "iq"); break; + case IBB::MessageStanza: ibbElement.setAttribute("stanza", "message"); break; + } + assert(ibb->getBlockSize() > 0); + ibbElement.setAttribute("block-size", std::to_string(ibb->getBlockSize())); + return ibbElement.serialize(); + } + case IBB::Close: { + XMLElement ibbElement("close", "http://jabber.org/protocol/ibb"); + ibbElement.setAttribute("sid", ibb->getStreamID()); + return ibbElement.serialize(); + } + } + assert(false); + return ""; } } diff --git a/Swiften/Serializer/PayloadSerializers/IBBSerializer.h b/Swiften/Serializer/PayloadSerializers/IBBSerializer.h index 229f131..0ef1680 100644 --- a/Swiften/Serializer/PayloadSerializers/IBBSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/IBBSerializer.h @@ -1,19 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/IBB.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class IBBSerializer : public GenericPayloadSerializer<IBB> { - public: - IBBSerializer(); + class SWIFTEN_API IBBSerializer : public GenericPayloadSerializer<IBB> { + public: + IBBSerializer(); - virtual std::string serializePayload(boost::shared_ptr<IBB>) const; - }; + virtual std::string serializePayload(std::shared_ptr<IBB>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/IdleSerializer.h b/Swiften/Serializer/PayloadSerializers/IdleSerializer.h index 45f9da4..4e1a953 100644 --- a/Swiften/Serializer/PayloadSerializers/IdleSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/IdleSerializer.h @@ -4,19 +4,26 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> -#include <Swiften/Elements/Idle.h> +#include <Swiften/Base/API.h> #include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/Idle.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class IdleSerializer : public GenericPayloadSerializer<Idle> { - public: - IdleSerializer() : GenericPayloadSerializer<Idle>() {} + class SWIFTEN_API IdleSerializer : public GenericPayloadSerializer<Idle> { + public: + IdleSerializer() : GenericPayloadSerializer<Idle>() {} - virtual std::string serializePayload(boost::shared_ptr<Idle> idle) const { - return "<idle xmlns='urn:xmpp:idle:1' since='" + dateTimeToString(idle->getSince()) + "'/>"; - } - }; + virtual std::string serializePayload(std::shared_ptr<Idle> idle) const { + return "<idle xmlns='urn:xmpp:idle:1' since='" + dateTimeToString(idle->getSince()) + "'/>"; + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp index 0db546e..04b7c56 100644 --- a/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp @@ -1,113 +1,111 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> namespace Swift { InBandRegistrationPayloadSerializer::InBandRegistrationPayloadSerializer() { } -std::string InBandRegistrationPayloadSerializer::serializePayload(boost::shared_ptr<InBandRegistrationPayload> registration) const { - XMLElement registerElement("query", "jabber:iq:register"); +std::string InBandRegistrationPayloadSerializer::serializePayload(std::shared_ptr<InBandRegistrationPayload> registration) const { + XMLElement registerElement("query", "jabber:iq:register"); - if (registration->isRegistered()) { - registerElement.addNode(XMLElement::ref(new XMLElement("registered"))); - } + if (registration->isRegistered()) { + registerElement.addNode(XMLElement::ref(new XMLElement("registered"))); + } - if (registration->isRemove()) { - registerElement.addNode(XMLElement::ref(new XMLElement("remove"))); - } + if (registration->isRemove()) { + registerElement.addNode(XMLElement::ref(new XMLElement("remove"))); + } - if (registration->getInstructions()) { - registerElement.addNode(XMLElement::ref(new XMLElement("instructions", "", *registration->getInstructions()))); - } + if (registration->getInstructions()) { + registerElement.addNode(XMLElement::ref(new XMLElement("instructions", "", *registration->getInstructions()))); + } - if (registration->getUsername()) { - registerElement.addNode(XMLElement::ref(new XMLElement("username", "", *registration->getUsername()))); - } + if (registration->getUsername()) { + registerElement.addNode(XMLElement::ref(new XMLElement("username", "", *registration->getUsername()))); + } - if (registration->getNick()) { - registerElement.addNode(XMLElement::ref(new XMLElement("nick", "", *registration->getNick()))); - } + if (registration->getNick()) { + registerElement.addNode(XMLElement::ref(new XMLElement("nick", "", *registration->getNick()))); + } - if (registration->getPassword()) { - registerElement.addNode(XMLElement::ref(new XMLElement("password", "", *registration->getPassword()))); - } + if (registration->getPassword()) { + registerElement.addNode(XMLElement::ref(new XMLElement("password", "", *registration->getPassword()))); + } - if (registration->getName()) { - registerElement.addNode(XMLElement::ref(new XMLElement("name", "", *registration->getName()))); - } + if (registration->getName()) { + registerElement.addNode(XMLElement::ref(new XMLElement("name", "", *registration->getName()))); + } - if (registration->getFirst()) { - registerElement.addNode(XMLElement::ref(new XMLElement("first", "", *registration->getFirst()))); - } + if (registration->getFirst()) { + registerElement.addNode(XMLElement::ref(new XMLElement("first", "", *registration->getFirst()))); + } - if (registration->getLast()) { - registerElement.addNode(XMLElement::ref(new XMLElement("last", "", *registration->getLast()))); - } + if (registration->getLast()) { + registerElement.addNode(XMLElement::ref(new XMLElement("last", "", *registration->getLast()))); + } - if (registration->getEMail()) { - registerElement.addNode(XMLElement::ref(new XMLElement("email", "", *registration->getEMail()))); - } + if (registration->getEMail()) { + registerElement.addNode(XMLElement::ref(new XMLElement("email", "", *registration->getEMail()))); + } - if (registration->getAddress()) { - registerElement.addNode(XMLElement::ref(new XMLElement("address", "", *registration->getAddress()))); - } + if (registration->getAddress()) { + registerElement.addNode(XMLElement::ref(new XMLElement("address", "", *registration->getAddress()))); + } - if (registration->getCity()) { - registerElement.addNode(XMLElement::ref(new XMLElement("city", "", *registration->getCity()))); - } + if (registration->getCity()) { + registerElement.addNode(XMLElement::ref(new XMLElement("city", "", *registration->getCity()))); + } - if (registration->getState()) { - registerElement.addNode(XMLElement::ref(new XMLElement("state", "", *registration->getState()))); - } + if (registration->getState()) { + registerElement.addNode(XMLElement::ref(new XMLElement("state", "", *registration->getState()))); + } - if (registration->getZip()) { - registerElement.addNode(XMLElement::ref(new XMLElement("zip", "", *registration->getZip()))); - } + if (registration->getZip()) { + registerElement.addNode(XMLElement::ref(new XMLElement("zip", "", *registration->getZip()))); + } - if (registration->getPhone()) { - registerElement.addNode(XMLElement::ref(new XMLElement("phone", "", *registration->getPhone()))); - } + if (registration->getPhone()) { + registerElement.addNode(XMLElement::ref(new XMLElement("phone", "", *registration->getPhone()))); + } - if (registration->getURL()) { - registerElement.addNode(XMLElement::ref(new XMLElement("url", "", *registration->getURL()))); - } + if (registration->getURL()) { + registerElement.addNode(XMLElement::ref(new XMLElement("url", "", *registration->getURL()))); + } - if (registration->getDate()) { - registerElement.addNode(XMLElement::ref(new XMLElement("date", "", *registration->getDate()))); - } + if (registration->getDate()) { + registerElement.addNode(XMLElement::ref(new XMLElement("date", "", *registration->getDate()))); + } - if (registration->getMisc()) { - registerElement.addNode(XMLElement::ref(new XMLElement("misc", "", *registration->getMisc()))); - } + if (registration->getMisc()) { + registerElement.addNode(XMLElement::ref(new XMLElement("misc", "", *registration->getMisc()))); + } - if (registration->getText()) { - registerElement.addNode(XMLElement::ref(new XMLElement("text", "", *registration->getText()))); - } + if (registration->getText()) { + registerElement.addNode(XMLElement::ref(new XMLElement("text", "", *registration->getText()))); + } - if (registration->getKey()) { - registerElement.addNode(XMLElement::ref(new XMLElement("key", "", *registration->getKey()))); - } + if (registration->getKey()) { + registerElement.addNode(XMLElement::ref(new XMLElement("key", "", *registration->getKey()))); + } - if (Form::ref form = registration->getForm()) { - registerElement.addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); - } + if (Form::ref form = registration->getForm()) { + registerElement.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); + } - return registerElement.serialize(); + return registerElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h index e71671c..d5f6cce 100644 --- a/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h @@ -1,21 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/InBandRegistrationPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API InBandRegistrationPayloadSerializer : public GenericPayloadSerializer<InBandRegistrationPayload> { - public: - InBandRegistrationPayloadSerializer(); + class SWIFTEN_API InBandRegistrationPayloadSerializer : public GenericPayloadSerializer<InBandRegistrationPayload> { + public: + InBandRegistrationPayloadSerializer(); - virtual std::string serializePayload(boost::shared_ptr<InBandRegistrationPayload>) const; - }; + virtual std::string serializePayload(std::shared_ptr<InBandRegistrationPayload>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/IsodeIQDelegationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/IsodeIQDelegationSerializer.cpp new file mode 100644 index 0000000..41c824f --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/IsodeIQDelegationSerializer.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + + + +#include <Swiften/Serializer/PayloadSerializers/IsodeIQDelegationSerializer.h> + +#include <memory> + +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +IsodeIQDelegationSerializer::IsodeIQDelegationSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +IsodeIQDelegationSerializer::~IsodeIQDelegationSerializer() { +} + +std::string IsodeIQDelegationSerializer::serializePayload(std::shared_ptr<IsodeIQDelegation> payload) const { + if (!payload) { + return ""; + } + XMLElement element("delegate", "http://isode.com/iq_delegation"); + element.addNode(std::make_shared<XMLRawTextNode>(serializers->getPayloadSerializer(payload->getForward())->serialize(payload->getForward()))); + return element.serialize(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/IsodeIQDelegationSerializer.h b/Swiften/Serializer/PayloadSerializers/IsodeIQDelegationSerializer.h new file mode 100644 index 0000000..419e2d5 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/IsodeIQDelegationSerializer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/IsodeIQDelegation.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API IsodeIQDelegationSerializer : public GenericPayloadSerializer<IsodeIQDelegation> { + public: + IsodeIQDelegationSerializer(PayloadSerializerCollection* serializers); + virtual ~IsodeIQDelegationSerializer() override; + + virtual std::string serializePayload(std::shared_ptr<IsodeIQDelegation>) const override; + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp index 0e21812..39eb149 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp @@ -4,75 +4,77 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include <Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.h> +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/smart_ptr/intrusive_ptr.hpp> +#include <Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLNode.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <memory> +#include <Swiften/Base/Log.h> #include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h> - #include <Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h> #include <Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLNode.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> namespace Swift { JingleContentPayloadSerializer::JingleContentPayloadSerializer() { } -std::string JingleContentPayloadSerializer::serializePayload(boost::shared_ptr<JingleContentPayload> payload) const { - XMLElement payloadXML("content"); - payloadXML.setAttribute("creator", creatorToString(payload->getCreator())); - payloadXML.setAttribute("name", payload->getName()); - - if (!payload->getDescriptions().empty()) { - // JingleFileTransferDescription - JingleFileTransferDescriptionSerializer ftSerializer; - JingleFileTransferDescription::ref filetransfer; - - foreach(JingleDescription::ref desc, payload->getDescriptions()) { - if ((filetransfer = boost::dynamic_pointer_cast<JingleFileTransferDescription>(desc))) { - payloadXML.addNode(boost::make_shared<XMLRawTextNode>(ftSerializer.serializePayload(filetransfer))); - } - } - } - - if (!payload->getTransports().empty()) { - // JingleIBBTransportPayload - JingleIBBTransportPayloadSerializer ibbSerializer; - JingleIBBTransportPayload::ref ibb; - - // JingleS5BTransportPayload - JingleS5BTransportPayloadSerializer s5bSerializer; - JingleS5BTransportPayload::ref s5b; +std::string JingleContentPayloadSerializer::serializePayload(std::shared_ptr<JingleContentPayload> payload) const { + XMLElement payloadXML("content"); + payloadXML.setAttribute("creator", creatorToString(payload->getCreator())); + payloadXML.setAttribute("name", payload->getName()); + + if (!payload->getDescriptions().empty()) { + // JingleFileTransferDescription + JingleFileTransferDescriptionSerializer ftSerializer; + JingleFileTransferDescription::ref filetransfer; + + for (auto&& desc : payload->getDescriptions()) { + if ((filetransfer = std::dynamic_pointer_cast<JingleFileTransferDescription>(desc))) { + payloadXML.addNode(std::make_shared<XMLRawTextNode>(ftSerializer.serializePayload(filetransfer))); + } + } + } + + if (!payload->getTransports().empty()) { + // JingleIBBTransportPayload + JingleIBBTransportPayloadSerializer ibbSerializer; + JingleIBBTransportPayload::ref ibb; + + // JingleS5BTransportPayload + JingleS5BTransportPayloadSerializer s5bSerializer; + JingleS5BTransportPayload::ref s5b; - foreach(JingleTransportPayload::ref transport, payload->getTransports()) { - if ((ibb = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transport))) { - payloadXML.addNode(boost::make_shared<XMLRawTextNode>(ibbSerializer.serializePayload(ibb))); - } else if ((s5b = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transport))) { - payloadXML.addNode(boost::make_shared<XMLRawTextNode>(s5bSerializer.serializePayload(s5b))); - } - } - } - return payloadXML.serialize(); + for (auto&& transport : payload->getTransports()) { + if ((ibb = std::dynamic_pointer_cast<JingleIBBTransportPayload>(transport))) { + payloadXML.addNode(std::make_shared<XMLRawTextNode>(ibbSerializer.serializePayload(ibb))); + } else if ((s5b = std::dynamic_pointer_cast<JingleS5BTransportPayload>(transport))) { + payloadXML.addNode(std::make_shared<XMLRawTextNode>(s5bSerializer.serializePayload(s5b))); + } + } + } + return payloadXML.serialize(); } std::string JingleContentPayloadSerializer::creatorToString(JingleContentPayload::Creator creator) const { - switch(creator) { - case JingleContentPayload::InitiatorCreator: - return "initiator"; - case JingleContentPayload::ResponderCreator: - return "responder"; - case JingleContentPayload::UnknownCreator: - std::cerr << "Serializing unknown creator value." << std::endl; - return "ERROR ERROR ERROR"; - } - assert(false); - return ""; + switch(creator) { + case JingleContentPayload::InitiatorCreator: + return "initiator"; + case JingleContentPayload::ResponderCreator: + return "responder"; + case JingleContentPayload::UnknownCreator: + SWIFT_LOG(error) << "Serializing unknown creator value."; + return "ERROR ERROR ERROR"; + } + assert(false); + return ""; } } diff --git a/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.h index 2de0064..93cf5b3 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.h @@ -4,22 +4,27 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleContentPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class JingleContentPayloadSerializer : public GenericPayloadSerializer<JingleContentPayload> { - public: - JingleContentPayloadSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<JingleContentPayload>) const; - - private: - std::string creatorToString(JingleContentPayload::Creator creator) const; - }; + class SWIFTEN_API JingleContentPayloadSerializer : public GenericPayloadSerializer<JingleContentPayload> { + public: + JingleContentPayloadSerializer(); + + virtual std::string serializePayload(std::shared_ptr<JingleContentPayload>) const; + + private: + std::string creatorToString(JingleContentPayload::Creator creator) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp index 16337ff..27e3b33 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp @@ -4,43 +4,37 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLNode.h> +#include <boost/lexical_cast.hpp> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> - -#include <Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h> +#include <Swiften/StringCodecs/Base64.h> namespace Swift { JingleFileTransferDescriptionSerializer::JingleFileTransferDescriptionSerializer() { } -std::string JingleFileTransferDescriptionSerializer::serializePayload(boost::shared_ptr<JingleFileTransferDescription> payload) const { - XMLElement description("description", "urn:xmpp:jingle:apps:file-transfer:3"); - StreamInitiationFileInfoSerializer fileInfoSerializer; - if (!payload->getOffers().empty()) { - boost::shared_ptr<XMLElement> offers = boost::make_shared<XMLElement>("offer"); - foreach(const StreamInitiationFileInfo &fileInfo, payload->getOffers()) { - boost::shared_ptr<XMLRawTextNode> fileInfoXML = boost::make_shared<XMLRawTextNode>(fileInfoSerializer.serialize(boost::make_shared<StreamInitiationFileInfo>(fileInfo))); - offers->addNode(fileInfoXML); - } - description.addNode(offers); - } - if (!payload->getRequests().empty()) { - boost::shared_ptr<XMLElement> requests = boost::make_shared<XMLElement>("request"); - foreach(const StreamInitiationFileInfo &fileInfo, payload->getRequests()) { - boost::shared_ptr<XMLRawTextNode> fileInfoXML = boost::make_shared<XMLRawTextNode>(fileInfoSerializer.serialize(boost::make_shared<StreamInitiationFileInfo>(fileInfo))); - requests->addNode(fileInfoXML); - } - description.addNode(requests); - } - return description.serialize(); +std::string JingleFileTransferDescriptionSerializer::serializePayload(std::shared_ptr<JingleFileTransferDescription> payload) const { + XMLElement description("description", "urn:xmpp:jingle:apps:file-transfer:4"); + + JingleFileTransferFileInfoSerializer fileInfoSerializer; + std::shared_ptr<XMLRawTextNode> fileInfoXML = std::make_shared<XMLRawTextNode>(fileInfoSerializer.serialize(std::make_shared<JingleFileTransferFileInfo>(payload->getFileInfo()))); + description.addNode(fileInfoXML); + return description.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h b/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h index da8fa55..9e77c0a 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h @@ -4,21 +4,24 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/JingleFileTransferDescription.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - class XMLElement; - - class SWIFTEN_API JingleFileTransferDescriptionSerializer : public GenericPayloadSerializer<JingleFileTransferDescription> { - public: - JingleFileTransferDescriptionSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<JingleFileTransferDescription>) const; - }; + class SWIFTEN_API JingleFileTransferDescriptionSerializer : public GenericPayloadSerializer<JingleFileTransferDescription> { + public: + JingleFileTransferDescriptionSerializer(); + + virtual std::string serializePayload(std::shared_ptr<JingleFileTransferDescription>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp new file mode 100644 index 0000000..95996c7 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h> + +#include <memory> + +#include <boost/lexical_cast.hpp> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> +#include <Swiften/StringCodecs/Base64.h> + +namespace Swift { + +JingleFileTransferFileInfoSerializer::JingleFileTransferFileInfoSerializer() { +} + +std::string JingleFileTransferFileInfoSerializer::serializePayload(std::shared_ptr<JingleFileTransferFileInfo> fileInfo) const { + + XMLElement fileElement("file", ""); + + if (fileInfo->getDate() != stringToDateTime("")) { + fileElement.addNode(std::make_shared<XMLElement>("date", "", dateTimeToString(fileInfo->getDate()))); + } + + if (!fileInfo->getDescription().empty()) { + fileElement.addNode(std::make_shared<XMLElement>("desc", "", fileInfo->getDescription())); + } + + if (!fileInfo->getMediaType().empty()) { + fileElement.addNode(std::make_shared<XMLElement>("media-type", "", fileInfo->getMediaType())); + } + + if (!fileInfo->getName().empty()) { + fileElement.addNode(std::make_shared<XMLElement>("name", "", fileInfo->getName())); + } + + if (fileInfo->getSupportsRangeRequests()) { + std::shared_ptr<XMLElement> range = std::make_shared<XMLElement>("range"); + if (fileInfo->getRangeOffset() != 0) { + range->setAttribute("offset", std::to_string(fileInfo->getRangeOffset())); + } + fileElement.addNode(range); + } + + if (fileInfo->getSize() > 0) { + fileElement.addNode(std::make_shared<XMLElement>("size", "", std::to_string(fileInfo->getSize()))); + } + + for (const auto& hashElement : fileInfo->getHashes()) { + std::shared_ptr<XMLElement> hash = std::make_shared<XMLElement>("hash", "urn:xmpp:hashes:1", Base64::encode(hashElement.second)); + hash->setAttribute("algo", hashElement.first); + fileElement.addNode(hash); + } + + return fileElement.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h new file mode 100644 index 0000000..d0f4c17 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { + class SWIFTEN_API JingleFileTransferFileInfoSerializer : public GenericPayloadSerializer<JingleFileTransferFileInfo> { + public: + JingleFileTransferFileInfoSerializer(); + + virtual std::string serializePayload(std::shared_ptr<JingleFileTransferFileInfo>) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp index 2bd3afa..7629721 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp @@ -4,42 +4,42 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h> -#include <string> #include <map> +#include <memory> +#include <string> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> - -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLNode.h> +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> - namespace Swift { JingleFileTransferHashSerializer::JingleFileTransferHashSerializer() { } -std::string JingleFileTransferHashSerializer::serializePayload(boost::shared_ptr<JingleFileTransferHash> payload) const { - // code for version urn:xmpp:jingle:apps:file-transfer:2 - //XMLElement hash("hash", "urn:xmpp:jingle:apps:file-transfer:info:2", payload->getHash()); - - // code for version urn:xmpp:jingle:apps:file-transfer:3 - XMLElement checksum("checksum", "urn:xmpp:jingle:apps:file-transfer:3"); - boost::shared_ptr<XMLElement> file = boost::make_shared<XMLElement>("file"); - checksum.addNode(file); - boost::shared_ptr<XMLElement> hashes = boost::make_shared<XMLElement>("hashes", "urn:xmpp:hashes:0"); - file->addNode(hashes); - foreach(const JingleFileTransferHash::HashesMap::value_type& pair, payload->getHashes()) { - boost::shared_ptr<XMLElement> hash = boost::make_shared<XMLElement>("hash", "", pair.second); - hash->setAttribute("algo", pair.first); - hashes->addNode(hash); - } - - return checksum.serialize(); +std::string JingleFileTransferHashSerializer::serializePayload(std::shared_ptr<JingleFileTransferHash> payload) const { + // code for version urn:xmpp:jingle:apps:file-transfer:2 + //XMLElement hash("hash", "urn:xmpp:jingle:apps:file-transfer:info:2", payload->getHash()); + + // code for version urn:xmpp:jingle:apps:file-transfer:4 + XMLElement checksum("checksum", "urn:xmpp:jingle:apps:file-transfer:4"); + + JingleFileTransferFileInfoSerializer fileSerializer; + + std::shared_ptr<XMLRawTextNode> file = std::make_shared<XMLRawTextNode>(fileSerializer.serialize(std::make_shared<JingleFileTransferFileInfo>(payload->getFileInfo()))); + + checksum.addNode(file); + + return checksum.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h b/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h index 7fa6ac5..bc978ea 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h @@ -4,20 +4,24 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleFileTransferHash.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - class XMLElement; - - class JingleFileTransferHashSerializer : public GenericPayloadSerializer<JingleFileTransferHash> { - public: - JingleFileTransferHashSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<JingleFileTransferHash>) const; - }; + class SWIFTEN_API JingleFileTransferHashSerializer : public GenericPayloadSerializer<JingleFileTransferHash> { + public: + JingleFileTransferHashSerializer(); + + virtual std::string serializePayload(std::shared_ptr<JingleFileTransferHash>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.cpp deleted file mode 100644 index 40be70e..0000000 --- a/Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2011 Tobias Markmann - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. - */ - -#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.h> - -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> - -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLNode.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Serializer/XML/XMLRawTextNode.h> - -#include <Swiften/Serializer/XML/XMLRawTextNode.h> - -namespace Swift { - -JingleFileTransferReceivedSerializer::JingleFileTransferReceivedSerializer() { -} - -std::string JingleFileTransferReceivedSerializer::serializePayload(boost::shared_ptr<JingleFileTransferReceived> payload) const { - XMLElement receivedElement("received", "urn:xmpp:jingle:apps:file-transfer:3"); - XMLElement::ref fileElement = boost::make_shared<XMLElement>("file", "http://jabber.org/protocol/si/profile/file-transfer"); - fileElement->setAttribute("hash", payload->getFileInfo().getHash()); - if (payload->getFileInfo().getAlgo() != "md5") { - fileElement->setAttribute("algo", payload->getFileInfo().getAlgo()); - } - receivedElement.addNode(fileElement); - return receivedElement.serialize(); -} - -} diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.h b/Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.h deleted file mode 100644 index 4151dd0..0000000 --- a/Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2011 Tobias Markmann - * 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/JingleFileTransferReceived.h> - -namespace Swift { - class PayloadSerializerCollection; - class XMLElement; - - class JingleFileTransferReceivedSerializer : public GenericPayloadSerializer<JingleFileTransferReceived> { - public: - JingleFileTransferReceivedSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<JingleFileTransferReceived>) const; - }; -} diff --git a/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp index 61e093f..c5c45e1 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp @@ -4,15 +4,20 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/lexical_cast.hpp> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLNode.h> #include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> namespace Swift { @@ -20,14 +25,14 @@ namespace Swift { JingleIBBTransportPayloadSerializer::JingleIBBTransportPayloadSerializer() { } -std::string JingleIBBTransportPayloadSerializer::serializePayload(boost::shared_ptr<JingleIBBTransportPayload> payload) const { - XMLElement payloadXML("transport", "urn:xmpp:jingle:transports:ibb:1"); - if (payload->getBlockSize()) { - payloadXML.setAttribute("block-size", boost::lexical_cast<std::string>(*payload->getBlockSize())); - } - payloadXML.setAttribute("sid", payload->getSessionID()); +std::string JingleIBBTransportPayloadSerializer::serializePayload(std::shared_ptr<JingleIBBTransportPayload> payload) const { + XMLElement payloadXML("transport", "urn:xmpp:jingle:transports:ibb:1"); + if (payload->getBlockSize()) { + payloadXML.setAttribute("block-size", std::to_string(*payload->getBlockSize())); + } + payloadXML.setAttribute("sid", payload->getSessionID()); - return payloadXML.serialize(); + return payloadXML.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h index ac9cba9..27fb5f1 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h @@ -4,22 +4,24 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> - - +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - class XMLElement; - - class JingleIBBTransportPayloadSerializer : public GenericPayloadSerializer<JingleIBBTransportPayload> { - public: - JingleIBBTransportPayloadSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<JingleIBBTransportPayload>) const; - }; + class SWIFTEN_API JingleIBBTransportPayloadSerializer : public GenericPayloadSerializer<JingleIBBTransportPayload> { + public: + JingleIBBTransportPayloadSerializer(); + + virtual std::string serializePayload(std::shared_ptr<JingleIBBTransportPayload>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.cpp index a04687b..566d556 100644 --- a/Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.cpp @@ -4,144 +4,144 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h> - -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/smart_ptr/intrusive_ptr.hpp> +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLNode.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <memory> -#include <Swiften/Elements/JinglePayload.h> +#include <Swiften/Base/Log.h> #include <Swiften/Elements/JingleContentPayload.h> -#include <Swiften/Elements/JingleIBBTransportPayload.h> #include <Swiften/Elements/JingleFileTransferDescription.h> #include <Swiften/Elements/JingleFileTransferHash.h> -#include <Swiften/Elements/JingleFileTransferReceived.h> +#include <Swiften/Elements/JingleIBBTransportPayload.h> +#include <Swiften/Elements/JinglePayload.h> +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLNode.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> namespace Swift { JinglePayloadSerializer::JinglePayloadSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { } -std::string JinglePayloadSerializer::serializePayload(boost::shared_ptr<JinglePayload> payload) const { - XMLElement jinglePayload("jingle", "urn:xmpp:jingle:1"); - jinglePayload.setAttribute("action", actionToString(payload->getAction())); - jinglePayload.setAttribute("initiator", payload->getInitiator()); - jinglePayload.setAttribute("sid", payload->getSessionID()); +std::string JinglePayloadSerializer::serializePayload(std::shared_ptr<JinglePayload> payload) const { + XMLElement jinglePayload("jingle", "urn:xmpp:jingle:1"); + jinglePayload.setAttribute("action", actionToString(payload->getAction())); + jinglePayload.setAttribute("initiator", payload->getInitiator()); + jinglePayload.setAttribute("sid", payload->getSessionID()); + + std::vector<std::shared_ptr<Payload> > payloads = payload->getPayloads(); + if (!payloads.empty()) { + for (auto&& subPayload : payloads) { + PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload); + if (serializer) { + jinglePayload.addNode(std::make_shared<XMLRawTextNode>(serializer->serialize(subPayload))); + } + } + } + + if (payload->getReason().is_initialized()) { + std::shared_ptr<XMLElement> reason = std::make_shared<XMLElement>("reason"); + reason->addNode(std::make_shared<XMLElement>(reasonTypeToString(payload->getReason()->type))); + if (!payload->getReason()->text.empty()) { + reason->addNode(std::make_shared<XMLElement>("desc", "", payload->getReason()->text)); + } + jinglePayload.addNode(reason); + } - std::vector<boost::shared_ptr<Payload> > payloads = payload->getPayloads(); - if (!payloads.empty()) { - foreach(boost::shared_ptr<Payload> subPayload, payloads) { - PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload); - if (serializer) { - jinglePayload.addNode(boost::make_shared<XMLRawTextNode>(serializer->serialize(subPayload))); - } - } - } - - if (payload->getReason().is_initialized()) { - boost::shared_ptr<XMLElement> reason = boost::make_shared<XMLElement>("reason"); - reason->addNode(boost::make_shared<XMLElement>(reasonTypeToString(payload->getReason()->type))); - if (!payload->getReason()->text.empty()) { - reason->addNode(boost::make_shared<XMLElement>("desc", "", payload->getReason()->text)); - } - jinglePayload.addNode(reason); - } - - return jinglePayload.serialize(); + return jinglePayload.serialize(); } std::string JinglePayloadSerializer::actionToString(JinglePayload::Action action) const { - switch(action) { - case JinglePayload::ContentAccept: - return "content-accept"; - case JinglePayload::ContentAdd: - return "content-add"; - case JinglePayload::ContentModify: - return "content-modify"; - case JinglePayload::ContentReject: - return "content-reject"; - case JinglePayload::ContentRemove: - return "content-remove"; - case JinglePayload::DescriptionInfo: - return "description-info"; - case JinglePayload::SecurityInfo: - return "security-info"; - case JinglePayload::SessionAccept: - return "session-accept"; - case JinglePayload::SessionInfo: - return "session-info"; - case JinglePayload::SessionInitiate: - return "session-initiate"; - case JinglePayload::SessionTerminate: - return "session-terminate"; - case JinglePayload::TransportAccept: - return "transport-accept"; - case JinglePayload::TransportInfo: - return "transport-info"; - case JinglePayload::TransportReject: - return "transport-reject"; - case JinglePayload::TransportReplace: - return "transport-replace"; - case JinglePayload::UnknownAction: - std::cerr << "Serializing unknown action value." << std::endl; - return ""; - } - assert(false); - return ""; + switch(action) { + case JinglePayload::ContentAccept: + return "content-accept"; + case JinglePayload::ContentAdd: + return "content-add"; + case JinglePayload::ContentModify: + return "content-modify"; + case JinglePayload::ContentReject: + return "content-reject"; + case JinglePayload::ContentRemove: + return "content-remove"; + case JinglePayload::DescriptionInfo: + return "description-info"; + case JinglePayload::SecurityInfo: + return "security-info"; + case JinglePayload::SessionAccept: + return "session-accept"; + case JinglePayload::SessionInfo: + return "session-info"; + case JinglePayload::SessionInitiate: + return "session-initiate"; + case JinglePayload::SessionTerminate: + return "session-terminate"; + case JinglePayload::TransportAccept: + return "transport-accept"; + case JinglePayload::TransportInfo: + return "transport-info"; + case JinglePayload::TransportReject: + return "transport-reject"; + case JinglePayload::TransportReplace: + return "transport-replace"; + case JinglePayload::UnknownAction: + SWIFT_LOG(warning) << "Serializing unknown action value."; + return ""; + } + assert(false); + return ""; } std::string JinglePayloadSerializer::reasonTypeToString(JinglePayload::Reason::Type type) const { - switch(type) { - case JinglePayload::Reason::UnknownType: - std::cerr << "Unknown jingle reason type!" << std::endl; - return ""; - case JinglePayload::Reason::AlternativeSession: - return "alternative-session"; - case JinglePayload::Reason::Busy: - return "busy"; - case JinglePayload::Reason::Cancel: - return "cancel"; - case JinglePayload::Reason::ConnectivityError: - return "connectivity-error"; - case JinglePayload::Reason::Decline: - return "decline"; - case JinglePayload::Reason::Expired: - return "expired"; - case JinglePayload::Reason::FailedApplication: - return "failed-application"; - case JinglePayload::Reason::FailedTransport: - return "failed-transport"; - case JinglePayload::Reason::GeneralError: - return "general-error"; - case JinglePayload::Reason::Gone: - return "gone"; - case JinglePayload::Reason::IncompatibleParameters: - return "incompatible-parameters"; - case JinglePayload::Reason::MediaError: - return "media-error"; - case JinglePayload::Reason::SecurityError: - return "security-error"; - case JinglePayload::Reason::Success: - return "success"; - case JinglePayload::Reason::Timeout: - return "timeout"; - case JinglePayload::Reason::UnsupportedApplications: - return "unsupported-applications"; - case JinglePayload::Reason::UnsupportedTransports: - return "unsupported-transports"; - } - assert(false); - return ""; + switch(type) { + case JinglePayload::Reason::UnknownType: + SWIFT_LOG(warning) << "Unknown jingle reason type!"; + return ""; + case JinglePayload::Reason::AlternativeSession: + return "alternative-session"; + case JinglePayload::Reason::Busy: + return "busy"; + case JinglePayload::Reason::Cancel: + return "cancel"; + case JinglePayload::Reason::ConnectivityError: + return "connectivity-error"; + case JinglePayload::Reason::Decline: + return "decline"; + case JinglePayload::Reason::Expired: + return "expired"; + case JinglePayload::Reason::FailedApplication: + return "failed-application"; + case JinglePayload::Reason::FailedTransport: + return "failed-transport"; + case JinglePayload::Reason::GeneralError: + return "general-error"; + case JinglePayload::Reason::Gone: + return "gone"; + case JinglePayload::Reason::IncompatibleParameters: + return "incompatible-parameters"; + case JinglePayload::Reason::MediaError: + return "media-error"; + case JinglePayload::Reason::SecurityError: + return "security-error"; + case JinglePayload::Reason::Success: + return "success"; + case JinglePayload::Reason::Timeout: + return "timeout"; + case JinglePayload::Reason::UnsupportedApplications: + return "unsupported-applications"; + case JinglePayload::Reason::UnsupportedTransports: + return "unsupported-transports"; + } + assert(false); + return ""; } } diff --git a/Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h index 5ac266f..7794855 100644 --- a/Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h @@ -4,28 +4,33 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/JinglePayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - class XMLElement; - - class SWIFTEN_API JinglePayloadSerializer : public GenericPayloadSerializer<JinglePayload> { - public: - JinglePayloadSerializer(PayloadSerializerCollection*); - - virtual std::string serializePayload(boost::shared_ptr<JinglePayload>) const; - - private: - std::string actionToString(JinglePayload::Action action) const; - std::string reasonTypeToString(JinglePayload::Reason::Type type) const; - - private: - PayloadSerializerCollection* serializers; - }; + class PayloadSerializerCollection; + + class SWIFTEN_API JinglePayloadSerializer : public GenericPayloadSerializer<JinglePayload> { + public: + JinglePayloadSerializer(PayloadSerializerCollection*); + + virtual std::string serializePayload(std::shared_ptr<JinglePayload>) const; + + private: + std::string actionToString(JinglePayload::Action action) const; + std::string reasonTypeToString(JinglePayload::Reason::Type type) const; + + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.cpp index c753839..f9a1832 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.cpp @@ -4,84 +4,92 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/lexical_cast.hpp> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLNode.h> +#include <Swiften/Base/Log.h> #include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Base/Log.h> namespace Swift { JingleS5BTransportPayloadSerializer::JingleS5BTransportPayloadSerializer() { } -std::string JingleS5BTransportPayloadSerializer::serializePayload(boost::shared_ptr<JingleS5BTransportPayload> payload) const { - XMLElement payloadXML("transport", "urn:xmpp:jingle:transports:s5b:1"); - payloadXML.setAttribute("sid", payload->getSessionID()); - payloadXML.setAttribute("mode", modeToString(payload->getMode())); - - foreach(JingleS5BTransportPayload::Candidate candidate, payload->getCandidates()) { - boost::shared_ptr<XMLElement> candidateXML = boost::make_shared<XMLElement>("candidate"); - candidateXML->setAttribute("cid", candidate.cid); - candidateXML->setAttribute("host", candidate.hostPort.getAddress().toString()); - candidateXML->setAttribute("jid", candidate.jid.toString()); - candidateXML->setAttribute("port", boost::lexical_cast<std::string>(candidate.hostPort.getPort())); - candidateXML->setAttribute("priority", boost::lexical_cast<std::string>(candidate.priority)); - candidateXML->setAttribute("type", typeToString(candidate.type)); - payloadXML.addNode(candidateXML); - } - - if (payload->hasCandidateError()) { - payloadXML.addNode(boost::make_shared<XMLElement>("candidate-error")); - } - if (payload->hasProxyError()) { - payloadXML.addNode(boost::make_shared<XMLElement>("proxy-error")); - } - - if (!payload->getActivated().empty()) { - boost::shared_ptr<XMLElement> activatedXML = boost::make_shared<XMLElement>("activated"); - activatedXML->setAttribute("cid", payload->getActivated()); - payloadXML.addNode(activatedXML); - } - if (!payload->getCandidateUsed().empty()) { - boost::shared_ptr<XMLElement> candusedXML = boost::make_shared<XMLElement>("candidate-used"); - candusedXML->setAttribute("cid", payload->getCandidateUsed()); - payloadXML.addNode(candusedXML); - } - - return payloadXML.serialize(); +std::string JingleS5BTransportPayloadSerializer::serializePayload(std::shared_ptr<JingleS5BTransportPayload> payload) const { + XMLElement payloadXML("transport", "urn:xmpp:jingle:transports:s5b:1"); + payloadXML.setAttribute("sid", payload->getSessionID()); + payloadXML.setAttribute("mode", modeToString(payload->getMode())); + if (!payload->getDstAddr().empty()) { + payloadXML.setAttribute("dstaddr", payload->getDstAddr()); + } + + for (const auto& candidate : payload->getCandidates()) { + std::shared_ptr<XMLElement> candidateXML = std::make_shared<XMLElement>("candidate"); + candidateXML->setAttribute("cid", candidate.cid); + candidateXML->setAttribute("host", candidate.hostPort.getAddress().toString()); + candidateXML->setAttribute("jid", candidate.jid.toString()); + candidateXML->setAttribute("port", std::to_string(candidate.hostPort.getPort())); + candidateXML->setAttribute("priority", std::to_string(candidate.priority)); + candidateXML->setAttribute("type", typeToString(candidate.type)); + payloadXML.addNode(candidateXML); + } + + if (payload->hasCandidateError()) { + payloadXML.addNode(std::make_shared<XMLElement>("candidate-error")); + } + if (payload->hasProxyError()) { + payloadXML.addNode(std::make_shared<XMLElement>("proxy-error")); + } + + if (!payload->getActivated().empty()) { + std::shared_ptr<XMLElement> activatedXML = std::make_shared<XMLElement>("activated"); + activatedXML->setAttribute("cid", payload->getActivated()); + payloadXML.addNode(activatedXML); + } + if (!payload->getCandidateUsed().empty()) { + std::shared_ptr<XMLElement> candusedXML = std::make_shared<XMLElement>("candidate-used"); + candusedXML->setAttribute("cid", payload->getCandidateUsed()); + payloadXML.addNode(candusedXML); + } + + return payloadXML.serialize(); } std::string JingleS5BTransportPayloadSerializer::modeToString(JingleS5BTransportPayload::Mode mode) const { - switch(mode) { - case JingleS5BTransportPayload::TCPMode: - return "tcp"; - case JingleS5BTransportPayload::UDPMode: - return "udp"; - } - assert(false); - return ""; + switch(mode) { + case JingleS5BTransportPayload::TCPMode: + return "tcp"; + case JingleS5BTransportPayload::UDPMode: + return "udp"; + } + assert(false); + return ""; } std::string JingleS5BTransportPayloadSerializer::typeToString(JingleS5BTransportPayload::Candidate::Type type) const { - switch(type) { - case JingleS5BTransportPayload::Candidate::AssistedType: - return "assisted"; - case JingleS5BTransportPayload::Candidate::DirectType: - return "direct"; - case JingleS5BTransportPayload::Candidate::ProxyType: - return "proxy"; - case JingleS5BTransportPayload::Candidate::TunnelType: - return "tunnel"; - } - assert(false); - return ""; + switch(type) { + case JingleS5BTransportPayload::Candidate::AssistedType: + return "assisted"; + case JingleS5BTransportPayload::Candidate::DirectType: + return "direct"; + case JingleS5BTransportPayload::Candidate::ProxyType: + return "proxy"; + case JingleS5BTransportPayload::Candidate::TunnelType: + return "tunnel"; + } + assert(false); + return ""; } } diff --git a/Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h index 210688d..c081c87 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h @@ -4,24 +4,28 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - class XMLElement; - - class JingleS5BTransportPayloadSerializer : public GenericPayloadSerializer<JingleS5BTransportPayload> { - public: - JingleS5BTransportPayloadSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<JingleS5BTransportPayload>) const; - - private: - std::string modeToString(JingleS5BTransportPayload::Mode) const; - std::string typeToString(JingleS5BTransportPayload::Candidate::Type) const; - }; + class SWIFTEN_API JingleS5BTransportPayloadSerializer : public GenericPayloadSerializer<JingleS5BTransportPayload> { + public: + JingleS5BTransportPayloadSerializer(); + + virtual std::string serializePayload(std::shared_ptr<JingleS5BTransportPayload>) const; + + private: + std::string modeToString(JingleS5BTransportPayload::Mode) const; + std::string typeToString(JingleS5BTransportPayload::Candidate::Type) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/LastSerializer.h b/Swiften/Serializer/PayloadSerializers/LastSerializer.h index e91d702..719eff5 100644 --- a/Swiften/Serializer/PayloadSerializers/LastSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/LastSerializer.h @@ -1,23 +1,24 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/lexical_cast.hpp> -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Last.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class LastSerializer : public GenericPayloadSerializer<Last> { - public: - LastSerializer() : GenericPayloadSerializer<Last>() {} + class SWIFTEN_API LastSerializer : public GenericPayloadSerializer<Last> { + public: + LastSerializer() : GenericPayloadSerializer<Last>() {} - virtual std::string serializePayload(boost::shared_ptr<Last> last) const { - return "<query xmlns='jabber:iq:last' seconds='" + boost::lexical_cast<std::string>(last->getSeconds()) + "'/>"; - } - }; + virtual std::string serializePayload(std::shared_ptr<Last> last) const { + return "<query xmlns='jabber:iq:last' seconds='" + std::to_string(last->getSeconds()) + "'/>"; + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/MAMFinSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MAMFinSerializer.cpp new file mode 100644 index 0000000..6f40277 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMFinSerializer.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MAMFinSerializer.h> + +#include <memory> + +#include <boost/lexical_cast.hpp> + +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +MAMFinSerializer::MAMFinSerializer() { +} + +MAMFinSerializer::~MAMFinSerializer() { +} + +std::string MAMFinSerializer::serializePayload(std::shared_ptr<MAMFin> payload) const { + if (!payload) { + return ""; + } + + XMLElement element("fin", "urn:xmpp:mam:0"); + + if (payload->isComplete()) { + element.setAttribute("complete", "true"); + } + + if (!payload->isStable()) { + element.setAttribute("stable", "false"); + } + + if (payload->getQueryID()) { + element.setAttribute("queryid", *payload->getQueryID()); + } + + if (payload->getResultSet()) { + element.addNode(std::make_shared<XMLRawTextNode>(ResultSetSerializer().serialize(payload->getResultSet()))); + } + + return element.serialize(); +} diff --git a/Swiften/Serializer/PayloadSerializers/MAMFinSerializer.h b/Swiften/Serializer/PayloadSerializers/MAMFinSerializer.h new file mode 100644 index 0000000..d8cff6a --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMFinSerializer.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MAMFin.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class SWIFTEN_API MAMFinSerializer : public GenericPayloadSerializer<MAMFin> { + public: + MAMFinSerializer(); + virtual ~MAMFinSerializer() override; + + virtual std::string serializePayload(std::shared_ptr<MAMFin>) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.cpp b/Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.cpp new file mode 100644 index 0000000..0b61c04 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.h> + +#include <memory> + +#include <boost/lexical_cast.hpp> + +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +MAMQuerySerializer::MAMQuerySerializer() { +} + +MAMQuerySerializer::~MAMQuerySerializer() { +} + +std::string MAMQuerySerializer::serializePayload(std::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->getNode()) { + element.setAttribute("node", *payload->getNode()); + } + + if (payload->getForm()) { + element.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getForm()))); + } + + if (payload->getResultSet()) { + element.addNode(std::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..e2ed063 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MAMQuery.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class SWIFTEN_API MAMQuerySerializer : public GenericPayloadSerializer<MAMQuery> { + public: + MAMQuerySerializer(); + virtual ~MAMQuerySerializer() override; + + virtual std::string serializePayload(std::shared_ptr<MAMQuery>) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MAMResultSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MAMResultSerializer.cpp new file mode 100644 index 0000000..7ef2102 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMResultSerializer.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MAMResultSerializer.h> + +#include <memory> + +#include <boost/lexical_cast.hpp> + +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +MAMResultSerializer::MAMResultSerializer(PayloadSerializerCollection* serializers) : serializers_(serializers) { +} + +MAMResultSerializer::~MAMResultSerializer() { +} + +std::string MAMResultSerializer::serializePayload(std::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(std::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..5cac8c4 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MAMResultSerializer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#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() override; + + virtual std::string serializePayload(std::shared_ptr<MAMResult>) const override; + + private: + PayloadSerializerCollection* serializers_; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXCreateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MIXCreateSerializer.cpp new file mode 100644 index 0000000..2034d86 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXCreateSerializer.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MIXCreateSerializer.h> + +#include <memory> + +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +MIXCreateSerializer::MIXCreateSerializer() { +} + +MIXCreateSerializer::~MIXCreateSerializer() { +} + +std::string MIXCreateSerializer::serializePayload(std::shared_ptr<MIXCreate> payload) const { + if (!payload) { + return ""; + } + XMLElement element("create", "urn:xmpp:mix:0"); + + if(payload->getChannel()) { + element.setAttribute("channel", *payload->getChannel()); + } + + if(payload->getData()) { + element.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); + } + + return element.serialize(); +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXCreateSerializer.h b/Swiften/Serializer/PayloadSerializers/MIXCreateSerializer.h new file mode 100644 index 0000000..54f3adc --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXCreateSerializer.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXCreate.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + + class SWIFTEN_API MIXCreateSerializer : public GenericPayloadSerializer<MIXCreate> { + public: + MIXCreateSerializer(); + virtual ~MIXCreateSerializer() override; + + virtual std::string serializePayload(std::shared_ptr<MIXCreate>) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXDestroySerializer.cpp b/Swiften/Serializer/PayloadSerializers/MIXDestroySerializer.cpp new file mode 100644 index 0000000..ed0d252 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXDestroySerializer.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MIXDestroySerializer.h> + +#include <memory> + +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +MIXDestroySerializer::MIXDestroySerializer() { +} + +MIXDestroySerializer::~MIXDestroySerializer() { +} + +std::string MIXDestroySerializer::serializePayload(std::shared_ptr<MIXDestroy> payload) const { + if (!payload) { + return ""; + } + XMLElement element("destroy", "urn:xmpp:mix:0"); + element.setAttribute("channel", payload->getChannel()); + return element.serialize(); +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXDestroySerializer.h b/Swiften/Serializer/PayloadSerializers/MIXDestroySerializer.h new file mode 100644 index 0000000..a0640a1 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXDestroySerializer.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXDestroy.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + + class SWIFTEN_API MIXDestroySerializer : public GenericPayloadSerializer<MIXDestroy> { + public: + MIXDestroySerializer(); + virtual ~MIXDestroySerializer() override; + + virtual std::string serializePayload(std::shared_ptr<MIXDestroy>) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXJoinSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MIXJoinSerializer.cpp new file mode 100644 index 0000000..509e41e --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXJoinSerializer.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MIXJoinSerializer.h> + +#include <memory> +#include <string> + +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +MIXJoinSerializer::MIXJoinSerializer() { +} + +MIXJoinSerializer::~MIXJoinSerializer() { +} + +std::string MIXJoinSerializer::serializePayload(std::shared_ptr<MIXJoin> payload) const { + if (!payload) { + return ""; + } + XMLElement element("join", "urn:xmpp:mix:0"); + if (payload->getChannel()) { + element.setAttribute("channel", *payload->getChannel()); + } + if (payload->getJID()) { + element.setAttribute("jid", *payload->getJID()); + } + auto subscriptionData = payload->getSubscriptions(); + std::vector<std::string> subscriptions(subscriptionData.begin(), subscriptionData.end()); + std::sort(subscriptions.begin(), subscriptions.end()); + + for (const auto& item : subscriptions) { + auto subscribeElement = std::make_shared<XMLElement>("subscribe"); + subscribeElement->setAttribute("node", item); + element.addNode(subscribeElement); + } + + if (payload->getForm()) { + element.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getForm()))); + } + return element.serialize(); +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXJoinSerializer.h b/Swiften/Serializer/PayloadSerializers/MIXJoinSerializer.h new file mode 100644 index 0000000..9be6915 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXJoinSerializer.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXJoin.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + + class SWIFTEN_API MIXJoinSerializer : public GenericPayloadSerializer<MIXJoin> { + public: + MIXJoinSerializer(); + virtual ~MIXJoinSerializer() override; + + virtual std::string serializePayload(std::shared_ptr<MIXJoin>) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXLeaveSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MIXLeaveSerializer.cpp new file mode 100644 index 0000000..111186a --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXLeaveSerializer.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MIXLeaveSerializer.h> + +#include <memory> + +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { + +MIXLeaveSerializer::MIXLeaveSerializer() { +} + +MIXLeaveSerializer::~MIXLeaveSerializer() { +} + +std::string MIXLeaveSerializer::serializePayload(std::shared_ptr<MIXLeave> payload) const { + if (!payload) { + return ""; + } + XMLElement element("leave", "urn:xmpp:mix:0"); + if (payload->getChannel()) { + element.setAttribute("channel", *payload->getChannel()); + } + return element.serialize(); +} +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXLeaveSerializer.h b/Swiften/Serializer/PayloadSerializers/MIXLeaveSerializer.h new file mode 100644 index 0000000..dd593b6 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXLeaveSerializer.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXLeave.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class SWIFTEN_API MIXLeaveSerializer : public GenericPayloadSerializer<MIXLeave> { + public: + MIXLeaveSerializer(); + virtual ~MIXLeaveSerializer() override; + + virtual std::string serializePayload(std::shared_ptr<MIXLeave>) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXParticipantSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MIXParticipantSerializer.cpp new file mode 100644 index 0000000..3f79dfa --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXParticipantSerializer.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MIXParticipantSerializer.h> + +#include <memory> + +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> + +namespace Swift { + +MIXParticipantSerializer::MIXParticipantSerializer() : GenericPayloadSerializer<MIXParticipant>() { +} + +std::string MIXParticipantSerializer::serializePayload(std::shared_ptr<MIXParticipant> payload) const { + XMLElement participantElement("participant", "urn:xmpp:mix:0"); + + if (payload->getNick()) { + std::shared_ptr<XMLElement> nickElement = std::make_shared<XMLElement>("nick"); + nickElement->addNode(std::make_shared<XMLTextNode>(*payload->getNick())); + participantElement.addNode(nickElement); + } + + if (payload->getJID()) { + std::shared_ptr<XMLElement> jidElement = std::make_shared<XMLElement>("jid"); + jidElement->addNode(std::make_shared<XMLTextNode>(*payload->getJID())); + participantElement.addNode(jidElement); + } + return participantElement.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXParticipantSerializer.h b/Swiften/Serializer/PayloadSerializers/MIXParticipantSerializer.h new file mode 100644 index 0000000..ff6ca3a --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXParticipantSerializer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXParticipant.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class SWIFTEN_API MIXParticipantSerializer : public GenericPayloadSerializer<MIXParticipant> { + public: + MIXParticipantSerializer(); + + virtual std::string serializePayload(std::shared_ptr<MIXParticipant> participant) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MIXPayloadSerializer.cpp new file mode 100644 index 0000000..843270a --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXPayloadSerializer.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MIXPayloadSerializer.h> + +#include <memory> + +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> + +namespace Swift { + +MIXPayloadSerializer::MIXPayloadSerializer() : GenericPayloadSerializer<MIXPayload>() { +} + +std::string MIXPayloadSerializer::serializePayload(std::shared_ptr<MIXPayload> payload) const { + XMLElement mixElement("mix", "urn:xmpp:mix:0"); + + if (payload->getNick()) { + std::shared_ptr<XMLElement> nickElement = std::make_shared<XMLElement>("nick"); + nickElement->addNode(std::make_shared<XMLTextNode>(*payload->getNick())); + mixElement.addNode(nickElement); + } + + if (payload->getJID()) { + std::shared_ptr<XMLElement> jidElement = std::make_shared<XMLElement>("jid"); + jidElement->addNode(std::make_shared<XMLTextNode>(*payload->getJID())); + mixElement.addNode(jidElement); + } + + if (payload->getSubmissionID()) { + std::shared_ptr<XMLElement> subIDElement = std::make_shared<XMLElement>("submission-id"); + subIDElement->addNode(std::make_shared<XMLTextNode>(*payload->getSubmissionID())); + mixElement.addNode(subIDElement); + } + + return mixElement.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MIXPayloadSerializer.h new file mode 100644 index 0000000..bc7ec7f --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXPayloadSerializer.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class SWIFTEN_API MIXPayloadSerializer : public GenericPayloadSerializer<MIXPayload> { + public: + MIXPayloadSerializer(); + + virtual std::string serializePayload(std::shared_ptr<MIXPayload> payload) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXRegisterNickSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MIXRegisterNickSerializer.cpp new file mode 100644 index 0000000..9045ffe --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXRegisterNickSerializer.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MIXRegisterNickSerializer.h> + +#include <memory> + +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> + +namespace Swift { + +MIXRegisterNickSerializer::MIXRegisterNickSerializer() : GenericPayloadSerializer<MIXRegisterNick>() { +} + +std::string MIXRegisterNickSerializer::serializePayload(std::shared_ptr<MIXRegisterNick> payload) const { + XMLElement registernickElement("register", "urn:xmpp:mix:0"); + + auto nickElement = std::make_shared<XMLElement>("nick"); + nickElement->addNode(std::make_shared<XMLTextNode>(payload->getNick())); + registernickElement.addNode(nickElement); + + return registernickElement.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXRegisterNickSerializer.h b/Swiften/Serializer/PayloadSerializers/MIXRegisterNickSerializer.h new file mode 100644 index 0000000..011fb18 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXRegisterNickSerializer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXRegisterNick.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class SWIFTEN_API MIXRegisterNickSerializer : public GenericPayloadSerializer<MIXRegisterNick> { + public: + MIXRegisterNickSerializer(); + + virtual std::string serializePayload(std::shared_ptr<MIXRegisterNick> payload) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXSetNickSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MIXSetNickSerializer.cpp new file mode 100644 index 0000000..d111d8c --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXSetNickSerializer.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MIXSetNickSerializer.h> + +#include <memory> + +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> + +namespace Swift { + +MIXSetNickSerializer::MIXSetNickSerializer() : GenericPayloadSerializer<MIXSetNick>() { +} + +std::string MIXSetNickSerializer::serializePayload(std::shared_ptr<MIXSetNick> payload) const { + XMLElement setnickElement("setnick", "urn:xmpp:mix:0"); + + auto nickElement = std::make_shared<XMLElement>("nick"); + nickElement->addNode(std::make_shared<XMLTextNode>(payload->getNick())); + setnickElement.addNode(nickElement); + + return setnickElement.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXSetNickSerializer.h b/Swiften/Serializer/PayloadSerializers/MIXSetNickSerializer.h new file mode 100644 index 0000000..7c28d8e --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXSetNickSerializer.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXSetNick.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class SWIFTEN_API MIXSetNickSerializer : public GenericPayloadSerializer<MIXSetNick> { + public: + MIXSetNickSerializer(); + + virtual std::string serializePayload(std::shared_ptr<MIXSetNick> payload) const override ; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXUpdateSubscriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MIXUpdateSubscriptionSerializer.cpp new file mode 100644 index 0000000..8e95474 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXUpdateSubscriptionSerializer.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MIXUpdateSubscriptionSerializer.h> + +#include <memory> + +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +namespace Swift { + +MIXUpdateSubscriptionSerializer::MIXUpdateSubscriptionSerializer() { +} + +MIXUpdateSubscriptionSerializer::~MIXUpdateSubscriptionSerializer() { +} + +std::string MIXUpdateSubscriptionSerializer::serializePayload(std::shared_ptr<MIXUpdateSubscription> payload) const { + if (!payload) { + return ""; + } + XMLElement element("update-subscription", "urn:xmpp:mix:0"); + if (payload->getJID()) { + element.setAttribute("jid", *payload->getJID()); + } + auto subscriptionData = payload->getSubscriptions(); + std::vector<std::string> subscriptions(subscriptionData.begin(), subscriptionData.end()); + std::sort(subscriptions.begin(), subscriptions.end()); + + for (const auto& item : subscriptions) { + auto subscribeElement = std::make_shared<XMLElement>("subscribe"); + subscribeElement->setAttribute("node", item); + element.addNode(subscribeElement); + } + return element.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXUpdateSubscriptionSerializer.h b/Swiften/Serializer/PayloadSerializers/MIXUpdateSubscriptionSerializer.h new file mode 100644 index 0000000..4ba9584 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXUpdateSubscriptionSerializer.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXUpdateSubscription.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + + class SWIFTEN_API MIXUpdateSubscriptionSerializer : public GenericPayloadSerializer<MIXUpdateSubscription> { + public: + MIXUpdateSubscriptionSerializer(); + virtual ~MIXUpdateSubscriptionSerializer() override; + + virtual std::string serializePayload(std::shared_ptr<MIXUpdateSubscription>) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXUserPreferenceSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MIXUserPreferenceSerializer.cpp new file mode 100644 index 0000000..618e0b3 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXUserPreferenceSerializer.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/MIXUserPreferenceSerializer.h> + +#include <memory> + +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +namespace Swift { + +MIXUserPreferenceSerializer::MIXUserPreferenceSerializer() { +} + +MIXUserPreferenceSerializer::~MIXUserPreferenceSerializer() { +} + +std::string MIXUserPreferenceSerializer::serializePayload(std::shared_ptr<MIXUserPreference> payload) const { + if (!payload) { + return ""; + } + XMLElement element("user-preference", "urn:xmpp:mix:0"); + if(payload->getData()) { + element.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); + } + return element.serialize(); +} +} diff --git a/Swiften/Serializer/PayloadSerializers/MIXUserPreferenceSerializer.h b/Swiften/Serializer/PayloadSerializers/MIXUserPreferenceSerializer.h new file mode 100644 index 0000000..f262b83 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MIXUserPreferenceSerializer.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/MIXUserPreference.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + + class SWIFTEN_API MIXUserPreferenceSerializer : public GenericPayloadSerializer<MIXUserPreference> { + public: + MIXUserPreferenceSerializer(); + virtual ~MIXUserPreferenceSerializer() override; + + virtual std::string serializePayload(std::shared_ptr<MIXUserPreference>) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp index 8758722..157c99e 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp @@ -1,33 +1,29 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h> +#include <memory> #include <sstream> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> - -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h> - namespace Swift { MUCAdminPayloadSerializer::MUCAdminPayloadSerializer() : GenericPayloadSerializer<MUCAdminPayload>() { } -std::string MUCAdminPayloadSerializer::serializePayload(boost::shared_ptr<MUCAdminPayload> payload) const { - XMLElement mucElement("query", "http://jabber.org/protocol/muc#admin"); - foreach (const MUCItem& item, payload->getItems()) { - mucElement.addNode(MUCItemSerializer::itemToElement(item)); - } - return mucElement.serialize(); +std::string MUCAdminPayloadSerializer::serializePayload(std::shared_ptr<MUCAdminPayload> payload) const { + XMLElement mucElement("query", "http://jabber.org/protocol/muc#admin"); + for (const auto& item : payload->getItems()) { + mucElement.addNode(MUCItemSerializer::itemToElement(item)); + } + return mucElement.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h index a033a9c..c077d2e 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h @@ -1,23 +1,23 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/MUCAdminPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API MUCAdminPayloadSerializer : public GenericPayloadSerializer<MUCAdminPayload> { - public: - MUCAdminPayloadSerializer(); - std::string affiliationToString(MUCOccupant::Affiliation affiliation) const; - std::string roleToString(MUCOccupant::Role role) const; + class SWIFTEN_API MUCAdminPayloadSerializer : public GenericPayloadSerializer<MUCAdminPayload> { + public: + MUCAdminPayloadSerializer(); + std::string affiliationToString(MUCOccupant::Affiliation affiliation) const; + std::string roleToString(MUCOccupant::Role role) const; - virtual std::string serializePayload(boost::shared_ptr<MUCAdminPayload> version) const; - }; + virtual std::string serializePayload(std::shared_ptr<MUCAdminPayload> version) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.cpp index e78a381..96116c7 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.cpp @@ -1,15 +1,13 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> @@ -18,17 +16,17 @@ namespace Swift { MUCDestroyPayloadSerializer::MUCDestroyPayloadSerializer() : GenericPayloadSerializer<MUCDestroyPayload>() { } -std::string MUCDestroyPayloadSerializer::serializePayload(boost::shared_ptr<MUCDestroyPayload> payload) const { - XMLElement mucElement("destroy", ""); - if (!payload->getReason().empty()) { - XMLElement::ref reason = boost::make_shared<XMLElement>("reason", ""); - reason->addNode(boost::make_shared<XMLTextNode>(payload->getReason())); - mucElement.addNode(reason); - } - if (payload->getNewVenue().isValid()) { - mucElement.setAttribute("jid", payload->getNewVenue().toString()); - } - return mucElement.serialize(); +std::string MUCDestroyPayloadSerializer::serializePayload(std::shared_ptr<MUCDestroyPayload> payload) const { + XMLElement mucElement("destroy", ""); + if (!payload->getReason().empty()) { + XMLElement::ref reason = std::make_shared<XMLElement>("reason", ""); + reason->addNode(std::make_shared<XMLTextNode>(payload->getReason())); + mucElement.addNode(reason); + } + if (payload->getNewVenue().isValid()) { + mucElement.setAttribute("jid", payload->getNewVenue().toString()); + } + return mucElement.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.h index 419a683..def362c 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCDestroyPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - class MUCDestroyPayloadSerializer : public GenericPayloadSerializer<MUCDestroyPayload> { - public: - MUCDestroyPayloadSerializer(); - virtual std::string serializePayload(boost::shared_ptr<MUCDestroyPayload> version) const; - }; + class SWIFTEN_API MUCDestroyPayloadSerializer : public GenericPayloadSerializer<MUCDestroyPayload> { + public: + MUCDestroyPayloadSerializer(); + virtual std::string serializePayload(std::shared_ptr<MUCDestroyPayload> version) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp index 26df08c..2004f4c 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp @@ -1,46 +1,43 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h> - namespace Swift { MUCInvitationPayloadSerializer::MUCInvitationPayloadSerializer() : GenericPayloadSerializer<MUCInvitationPayload>() { } -std::string MUCInvitationPayloadSerializer::serializePayload(boost::shared_ptr<MUCInvitationPayload> payload) const { - XMLElement mucElement("x", "jabber:x:conference"); - if (payload->getIsContinuation()) { - mucElement.setAttribute("continue", "true"); - } - if (payload->getJID().isValid()) { - mucElement.setAttribute("jid", payload->getJID().toString()); - } - if (!payload->getPassword().empty()) { - mucElement.setAttribute("password", payload->getPassword()); - } - if (!payload->getReason().empty()) { - mucElement.setAttribute("reason", payload->getReason()); - } - if (!payload->getThread().empty()) { - mucElement.setAttribute("thread", payload->getThread()); - } - if (payload->getIsImpromptu()) { - mucElement.addNode(boost::make_shared<XMLElement>("impromptu", "http://swift.im/impromptu")); - } - return mucElement.serialize(); +std::string MUCInvitationPayloadSerializer::serializePayload(std::shared_ptr<MUCInvitationPayload> payload) const { + XMLElement mucElement("x", "jabber:x:conference"); + if (payload->getIsContinuation()) { + mucElement.setAttribute("continue", "true"); + } + if (payload->getJID().isValid()) { + mucElement.setAttribute("jid", payload->getJID().toString()); + } + if (!payload->getPassword().empty()) { + mucElement.setAttribute("password", payload->getPassword()); + } + if (!payload->getReason().empty()) { + mucElement.setAttribute("reason", payload->getReason()); + } + if (!payload->getThread().empty()) { + mucElement.setAttribute("thread", payload->getThread()); + } + if (payload->getIsImpromptu()) { + mucElement.addNode(std::make_shared<XMLElement>("impromptu", "http://swift.im/impromptu")); + } + return mucElement.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.h index e60d5ca..be21177 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.h @@ -1,20 +1,21 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCInvitationPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class MUCInvitationPayloadSerializer : public GenericPayloadSerializer<MUCInvitationPayload> { - public: - MUCInvitationPayloadSerializer(); + class SWIFTEN_API MUCInvitationPayloadSerializer : public GenericPayloadSerializer<MUCInvitationPayload> { + public: + MUCInvitationPayloadSerializer(); - virtual std::string serializePayload(boost::shared_ptr<MUCInvitationPayload> version) const; - }; + virtual std::string serializePayload(std::shared_ptr<MUCInvitationPayload> version) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h index 2f2623f..22f7859 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h @@ -1,69 +1,70 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <memory> + #include <Swiften/Elements/MUCItem.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> namespace Swift { - class MUCItemSerializer { - public: - static std::string affiliationToString(MUCOccupant::Affiliation affiliation) { - std::string result; - switch (affiliation) { - case MUCOccupant::Owner: result = "owner"; break; - case MUCOccupant::Admin: result = "admin"; break; - case MUCOccupant::Member: result = "member"; break; - case MUCOccupant::Outcast: result = "outcast"; break; - case MUCOccupant::NoAffiliation: result = "none"; break; - } - return result; - } + class MUCItemSerializer { + public: + static std::string affiliationToString(MUCOccupant::Affiliation affiliation) { + std::string result; + switch (affiliation) { + case MUCOccupant::Owner: result = "owner"; break; + case MUCOccupant::Admin: result = "admin"; break; + case MUCOccupant::Member: result = "member"; break; + case MUCOccupant::Outcast: result = "outcast"; break; + case MUCOccupant::NoAffiliation: result = "none"; break; + } + return result; + } - static std::string roleToString(MUCOccupant::Role role) { - std::string result; - switch (role) { - case MUCOccupant::Moderator: result = "moderator"; break; - case MUCOccupant::NoRole: result = "none"; break; - case MUCOccupant::Participant: result = "participant"; break; - case MUCOccupant::Visitor: result = "visitor"; break; - } - return result; + static std::string roleToString(MUCOccupant::Role role) { + std::string result; + switch (role) { + case MUCOccupant::Moderator: result = "moderator"; break; + case MUCOccupant::NoRole: result = "none"; break; + case MUCOccupant::Participant: result = "participant"; break; + case MUCOccupant::Visitor: result = "visitor"; break; + } + return result; - } + } - static boost::shared_ptr<XMLElement> itemToElement(const MUCItem& item) { - boost::shared_ptr<XMLElement> itemElement(new XMLElement("item")); - if (item.affiliation) { - itemElement->setAttribute("affiliation", affiliationToString(item.affiliation.get())); - } - if (item.role) { - itemElement->setAttribute("role", roleToString(item.role.get())); - } - if (item.realJID) { - itemElement->setAttribute("jid", item.realJID.get()); - } - if (item.nick) { - itemElement->setAttribute("nick", item.nick.get()); - } - if (item.actor) { - boost::shared_ptr<XMLElement> actorElement(new XMLElement("actor")); - actorElement->setAttribute("jid", item.actor->toString()); - itemElement->addNode(actorElement); - } - if (item.reason) { - boost::shared_ptr<XMLElement> reasonElement(new XMLElement("reason")); - reasonElement->addNode(boost::make_shared<XMLTextNode>(*item.reason)); - itemElement->addNode(reasonElement); - } - return itemElement; - } - }; + static std::shared_ptr<XMLElement> itemToElement(const MUCItem& item) { + std::shared_ptr<XMLElement> itemElement(new XMLElement("item")); + if (item.affiliation) { + itemElement->setAttribute("affiliation", affiliationToString(item.affiliation.get())); + } + if (item.role) { + itemElement->setAttribute("role", roleToString(item.role.get())); + } + if (item.realJID) { + itemElement->setAttribute("jid", item.realJID.get()); + } + if (item.nick) { + itemElement->setAttribute("nick", item.nick.get()); + } + if (item.actor) { + std::shared_ptr<XMLElement> actorElement(new XMLElement("actor")); + actorElement->setAttribute("jid", item.actor->toString()); + itemElement->addNode(actorElement); + } + if (item.reason) { + std::shared_ptr<XMLElement> reasonElement(new XMLElement("reason")); + reasonElement->addNode(std::make_shared<XMLTextNode>(*item.reason)); + itemElement->addNode(reasonElement); + } + return itemElement; + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.cpp index 3cb8cf6..f385e91 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> #include <Swiften/Serializer/XML/XMLElement.h> @@ -17,16 +17,16 @@ namespace Swift { MUCOwnerPayloadSerializer::MUCOwnerPayloadSerializer(PayloadSerializerCollection* serializers) : GenericPayloadSerializer<MUCOwnerPayload>(), serializers(serializers) { } -std::string MUCOwnerPayloadSerializer::serializePayload(boost::shared_ptr<MUCOwnerPayload> mucOwner) const { - XMLElement mucElement("query", "http://jabber.org/protocol/muc#owner"); - boost::shared_ptr<Payload> payload = mucOwner->getPayload(); - if (payload) { - PayloadSerializer* serializer = serializers->getPayloadSerializer(payload); - if (serializer) { - mucElement.addNode(boost::make_shared<XMLRawTextNode>(serializer->serialize(payload))); - } - } - return mucElement.serialize(); +std::string MUCOwnerPayloadSerializer::serializePayload(std::shared_ptr<MUCOwnerPayload> mucOwner) const { + XMLElement mucElement("query", "http://jabber.org/protocol/muc#owner"); + std::shared_ptr<Payload> payload = mucOwner->getPayload(); + if (payload) { + PayloadSerializer* serializer = serializers->getPayloadSerializer(payload); + if (serializer) { + mucElement.addNode(std::make_shared<XMLRawTextNode>(serializer->serialize(payload))); + } + } + return mucElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.h index 5e6913a..8e2e856 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.h @@ -1,22 +1,23 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCOwnerPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - class MUCOwnerPayloadSerializer : public GenericPayloadSerializer<MUCOwnerPayload> { - public: - MUCOwnerPayloadSerializer(PayloadSerializerCollection* serializers); - virtual std::string serializePayload(boost::shared_ptr<MUCOwnerPayload> version) const; - private: - PayloadSerializerCollection* serializers; - }; + class PayloadSerializerCollection; + class SWIFTEN_API MUCOwnerPayloadSerializer : public GenericPayloadSerializer<MUCOwnerPayload> { + public: + MUCOwnerPayloadSerializer(PayloadSerializerCollection* serializers); + virtual std::string serializePayload(std::shared_ptr<MUCOwnerPayload> version) const; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp index 58f78b8..cde129e 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp @@ -1,57 +1,58 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.h> -#include <boost/lexical_cast.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/lexical_cast.hpp> +#include <Swiften/Base/String.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Base/String.h> namespace Swift { MUCPayloadSerializer::MUCPayloadSerializer() : GenericPayloadSerializer<MUCPayload>() { } -std::string MUCPayloadSerializer::serializePayload(boost::shared_ptr<MUCPayload> muc) const { - XMLElement mucElement("x", "http://jabber.org/protocol/muc"); - boost::shared_ptr<XMLElement> historyElement(new XMLElement("history")); - bool history = false; - if (muc->getMaxChars() >= 0) { - historyElement->setAttribute("maxchars", boost::lexical_cast<std::string>(muc->getMaxChars())); - history = true; - } - if (muc->getMaxStanzas() >= 0) { - historyElement->setAttribute("maxstanzas", boost::lexical_cast<std::string>(muc->getMaxStanzas())); - history = true; - } - if (muc->getSeconds() >= 0) { - historyElement->setAttribute("seconds", boost::lexical_cast<std::string>(muc->getSeconds())); - history = true; - } - if (muc->getSince() != boost::posix_time::not_a_date_time) { - std::string sinceString = std::string(boost::posix_time::to_iso_extended_string(muc->getSince())); - String::replaceAll(sinceString, ',', "."); - sinceString += "Z"; - historyElement->setAttribute("since", sinceString); - history = true; - } - if (muc->getPassword()) { - std::string password = *muc->getPassword(); - boost::shared_ptr<XMLElement> passwordElement(new XMLElement("password")); - passwordElement->addNode(boost::make_shared<XMLTextNode>(password)); - mucElement.addNode(passwordElement); - } - if (history) { - mucElement.addNode(historyElement); - } - return mucElement.serialize(); +std::string MUCPayloadSerializer::serializePayload(std::shared_ptr<MUCPayload> muc) const { + XMLElement mucElement("x", "http://jabber.org/protocol/muc"); + std::shared_ptr<XMLElement> historyElement(new XMLElement("history")); + bool history = false; + if (muc->getMaxChars() >= 0) { + historyElement->setAttribute("maxchars", std::to_string(muc->getMaxChars())); + history = true; + } + if (muc->getMaxStanzas() >= 0) { + historyElement->setAttribute("maxstanzas", std::to_string(muc->getMaxStanzas())); + history = true; + } + if (muc->getSeconds() >= 0) { + historyElement->setAttribute("seconds", std::to_string(muc->getSeconds())); + history = true; + } + if (muc->getSince() != boost::posix_time::not_a_date_time) { + std::string sinceString = std::string(boost::posix_time::to_iso_extended_string(muc->getSince())); + String::replaceAll(sinceString, ',', "."); + sinceString += "Z"; + historyElement->setAttribute("since", sinceString); + history = true; + } + if (muc->getPassword()) { + std::string password = *muc->getPassword(); + std::shared_ptr<XMLElement> passwordElement(new XMLElement("password")); + passwordElement->addNode(std::make_shared<XMLTextNode>(password)); + mucElement.addNode(passwordElement); + } + if (history) { + mucElement.addNode(historyElement); + } + return mucElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.h index 4bf8d22..6b0247d 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.h @@ -1,19 +1,20 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class MUCPayloadSerializer : public GenericPayloadSerializer<MUCPayload> { - public: - MUCPayloadSerializer(); - virtual std::string serializePayload(boost::shared_ptr<MUCPayload> version) const; - }; + class SWIFTEN_API MUCPayloadSerializer : public GenericPayloadSerializer<MUCPayload> { + public: + MUCPayloadSerializer(); + virtual std::string serializePayload(std::shared_ptr<MUCPayload> version) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp index 2e60654..f0f3cfa 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp @@ -1,70 +1,67 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h> +#include <memory> #include <sstream> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> - -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Serializer/XML/XMLTextNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h> -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> namespace Swift { MUCUserPayloadSerializer::MUCUserPayloadSerializer(PayloadSerializerCollection* serializers) : GenericPayloadSerializer<MUCUserPayload>(), serializers(serializers) { } -std::string MUCUserPayloadSerializer::serializePayload(boost::shared_ptr<MUCUserPayload> payload) const { - XMLElement mucElement("x", "http://jabber.org/protocol/muc#user"); - foreach (const MUCUserPayload::StatusCode statusCode, payload->getStatusCodes()) { - boost::shared_ptr<XMLElement> statusElement(new XMLElement("status")); - std::ostringstream code; - code << statusCode.code; - statusElement->setAttribute("code", code.str()); - mucElement.addNode(statusElement); - } - foreach (const MUCItem& item, payload->getItems()) { - mucElement.addNode(MUCItemSerializer::itemToElement(item)); - } +std::string MUCUserPayloadSerializer::serializePayload(std::shared_ptr<MUCUserPayload> payload) const { + XMLElement mucElement("x", "http://jabber.org/protocol/muc#user"); + for (const auto& statusCode : payload->getStatusCodes()) { + std::shared_ptr<XMLElement> statusElement(new XMLElement("status")); + std::ostringstream code; + code << statusCode.code; + statusElement->setAttribute("code", code.str()); + mucElement.addNode(statusElement); + } + for (const auto& item : payload->getItems()) { + mucElement.addNode(MUCItemSerializer::itemToElement(item)); + } - if (payload->getPassword()) { - boost::shared_ptr<XMLElement> passwordElement = boost::make_shared<XMLElement>("password"); - passwordElement->addNode(boost::make_shared<XMLTextNode>(*payload->getPassword())); - } + if (payload->getPassword()) { + std::shared_ptr<XMLElement> passwordElement = std::make_shared<XMLElement>("password"); + passwordElement->addNode(std::make_shared<XMLTextNode>(*payload->getPassword())); + } - if (payload->getInvite()) { - MUCUserPayload::Invite invite = *payload->getInvite(); - boost::shared_ptr<XMLElement> inviteElement = boost::make_shared<XMLElement>("invite"); - if (invite.to.isValid()) { - inviteElement->setAttribute("to", invite.to.toString()); - } - if (invite.from.isValid()) { - inviteElement->setAttribute("from", invite.from.toString()); - } - if (!invite.reason.empty()) { - boost::shared_ptr<XMLElement> reasonElement = boost::make_shared<XMLElement>("reason"); - reasonElement->addNode(boost::make_shared<XMLTextNode>(invite.reason)); - } - mucElement.addNode(inviteElement); - } + if (payload->getInvite()) { + MUCUserPayload::Invite invite = *payload->getInvite(); + std::shared_ptr<XMLElement> inviteElement = std::make_shared<XMLElement>("invite"); + if (invite.to.isValid()) { + inviteElement->setAttribute("to", invite.to.toString()); + } + if (invite.from.isValid()) { + inviteElement->setAttribute("from", invite.from.toString()); + } + if (!invite.reason.empty()) { + std::shared_ptr<XMLElement> reasonElement = std::make_shared<XMLElement>("reason"); + reasonElement->addNode(std::make_shared<XMLTextNode>(invite.reason)); + } + mucElement.addNode(inviteElement); + } - boost::shared_ptr<Payload> childPayload = payload->getPayload(); - if (childPayload) { - PayloadSerializer* serializer = serializers->getPayloadSerializer(childPayload); - if (serializer) { - mucElement.addNode(boost::make_shared<XMLRawTextNode>(serializer->serialize(childPayload))); - } - } - return mucElement.serialize(); + std::shared_ptr<Payload> childPayload = payload->getPayload(); + if (childPayload) { + PayloadSerializer* serializer = serializers->getPayloadSerializer(childPayload); + if (serializer) { + mucElement.addNode(std::make_shared<XMLRawTextNode>(serializer->serialize(childPayload))); + } + } + return mucElement.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h index 8c237e0..ea4b74b 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h @@ -1,23 +1,24 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/MUCUserPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - class MUCUserPayloadSerializer : public GenericPayloadSerializer<MUCUserPayload> { - public: - MUCUserPayloadSerializer(PayloadSerializerCollection* serializers); + class PayloadSerializerCollection; + class SWIFTEN_API MUCUserPayloadSerializer : public GenericPayloadSerializer<MUCUserPayload> { + public: + MUCUserPayloadSerializer(PayloadSerializerCollection* serializers); - virtual std::string serializePayload(boost::shared_ptr<MUCUserPayload> version) const; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<MUCUserPayload> version) const; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/NicknameSerializer.cpp b/Swiften/Serializer/PayloadSerializers/NicknameSerializer.cpp index 33385b0..7bd8931 100644 --- a/Swiften/Serializer/PayloadSerializers/NicknameSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/NicknameSerializer.cpp @@ -1,13 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/NicknameSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> @@ -17,10 +16,10 @@ namespace Swift { NicknameSerializer::NicknameSerializer() : GenericPayloadSerializer<Nickname>() { } -std::string NicknameSerializer::serializePayload(boost::shared_ptr<Nickname> nick) const { - XMLElement nickElement("nick", "http://jabber.org/protocol/nick"); - nickElement.addNode(boost::make_shared<XMLTextNode>(nick->getNickname())); - return nickElement.serialize(); +std::string NicknameSerializer::serializePayload(std::shared_ptr<Nickname> nick) const { + XMLElement nickElement("nick", "http://jabber.org/protocol/nick"); + nickElement.addNode(std::make_shared<XMLTextNode>(nick->getNickname())); + return nickElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/NicknameSerializer.h b/Swiften/Serializer/PayloadSerializers/NicknameSerializer.h index 382ec11..efea9c2 100644 --- a/Swiften/Serializer/PayloadSerializers/NicknameSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/NicknameSerializer.h @@ -1,21 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Nickname.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class NicknameSerializer : public GenericPayloadSerializer<Nickname> { - public: - NicknameSerializer(); + class SWIFTEN_API NicknameSerializer : public GenericPayloadSerializer<Nickname> { + public: + NicknameSerializer(); - virtual std::string serializePayload(boost::shared_ptr<Nickname>) const; - }; + virtual std::string serializePayload(std::shared_ptr<Nickname>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PrioritySerializer.h b/Swiften/Serializer/PayloadSerializers/PrioritySerializer.h index 5a2ef27..fa2cef0 100644 --- a/Swiften/Serializer/PayloadSerializers/PrioritySerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PrioritySerializer.h @@ -1,23 +1,24 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/lexical_cast.hpp> -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Priority.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PrioritySerializer : public GenericPayloadSerializer<Priority> { - public: - PrioritySerializer() : GenericPayloadSerializer<Priority>() {} + class SWIFTEN_API PrioritySerializer : public GenericPayloadSerializer<Priority> { + public: + PrioritySerializer() : GenericPayloadSerializer<Priority>() {} - virtual std::string serializePayload(boost::shared_ptr<Priority> priority) const { - return "<priority>" + boost::lexical_cast<std::string>(priority->getPriority()) + "</priority>"; - } - }; + virtual std::string serializePayload(std::shared_ptr<Priority> priority) const { + return "<priority>" + std::to_string(priority->getPriority()) + "</priority>"; + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.cpp index cfba552..fc410fb 100644 --- a/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.cpp @@ -1,35 +1,33 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializerCollection.h> #include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Serializer/XML/XMLTextNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> namespace Swift { PrivateStorageSerializer::PrivateStorageSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { } -std::string PrivateStorageSerializer::serializePayload(boost::shared_ptr<PrivateStorage> storage) const { - XMLElement storageElement("query", "jabber:iq:private"); - boost::shared_ptr<Payload> payload = storage->getPayload(); - if (payload) { - PayloadSerializer* serializer = serializers->getPayloadSerializer(payload); - if (serializer) { - storageElement.addNode(boost::make_shared<XMLRawTextNode>(serializer->serialize(payload))); - } - } - return storageElement.serialize(); +std::string PrivateStorageSerializer::serializePayload(std::shared_ptr<PrivateStorage> storage) const { + XMLElement storageElement("query", "jabber:iq:private"); + std::shared_ptr<Payload> payload = storage->getPayload(); + if (payload) { + PayloadSerializer* serializer = serializers->getPayloadSerializer(payload); + if (serializer) { + storageElement.addNode(std::make_shared<XMLRawTextNode>(serializer->serialize(payload))); + } + } + return storageElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h b/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h index 3548cac..f2f9d90 100644 --- a/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PrivateStorageSerializer.h @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/PrivateStorage.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; + class PayloadSerializerCollection; - class PrivateStorageSerializer : public GenericPayloadSerializer<PrivateStorage> { - public: - PrivateStorageSerializer(PayloadSerializerCollection* serializers); + class SWIFTEN_API PrivateStorageSerializer : public GenericPayloadSerializer<PrivateStorage> { + public: + PrivateStorageSerializer(PayloadSerializerCollection* serializers); - virtual std::string serializePayload(boost::shared_ptr<PrivateStorage>) const; + virtual std::string serializePayload(std::shared_ptr<PrivateStorage>) const; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.cpp index d5d5ead..e72c304 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.cpp @@ -1,45 +1,42 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> +#include <cassert> -#include <Swiften/Serializer/PayloadSerializerCollection.h> - +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubAffiliationSerializer::PubSubAffiliationSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubAffiliationSerializer::PubSubAffiliationSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubAffiliationSerializer::~PubSubAffiliationSerializer() { } -std::string PubSubAffiliationSerializer::serializePayload(boost::shared_ptr<PubSubAffiliation> payload) const { - if (!payload) { - return ""; - } - XMLElement element("affiliation", "http://jabber.org/protocol/pubsub"); - element.setAttribute("node", payload->getNode()); - element.setAttribute("affiliation", serializeType(payload->getType())); - return element.serialize(); +std::string PubSubAffiliationSerializer::serializePayload(std::shared_ptr<PubSubAffiliation> payload) const { + if (!payload) { + return ""; + } + XMLElement element("affiliation", "http://jabber.org/protocol/pubsub"); + element.setAttribute("node", payload->getNode()); + element.setAttribute("affiliation", serializeType(payload->getType())); + return element.serialize(); } std::string PubSubAffiliationSerializer::serializeType(PubSubAffiliation::Type value) { - switch (value) { - case PubSubAffiliation::None: return "none"; - case PubSubAffiliation::Member: return "member"; - case PubSubAffiliation::Outcast: return "outcast"; - case PubSubAffiliation::Owner: return "owner"; - case PubSubAffiliation::Publisher: return "publisher"; - case PubSubAffiliation::PublishOnly: return "publish-only"; - } - assert(false); - return ""; + switch (value) { + case PubSubAffiliation::None: return "none"; + case PubSubAffiliation::Member: return "member"; + case PubSubAffiliation::Outcast: return "outcast"; + case PubSubAffiliation::Owner: return "owner"; + case PubSubAffiliation::Publisher: return "publisher"; + case PubSubAffiliation::PublishOnly: return "publish-only"; + } + assert(false); + return ""; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.h index f6722c8..9b6dadb 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubAffiliation.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubAffiliationSerializer : public GenericPayloadSerializer<PubSubAffiliation> { - public: - PubSubAffiliationSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubAffiliationSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubAffiliation>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubAffiliationSerializer : public GenericPayloadSerializer<PubSubAffiliation> { + public: + PubSubAffiliationSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubAffiliationSerializer() override; - private: - static std::string serializeType(PubSubAffiliation::Type); + virtual std::string serializePayload(std::shared_ptr<PubSubAffiliation>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + static std::string serializeType(PubSubAffiliation::Type); + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.cpp index 25a0786..9c810da 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.cpp @@ -1,18 +1,16 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -23,18 +21,18 @@ PubSubAffiliationsSerializer::PubSubAffiliationsSerializer(PayloadSerializerColl PubSubAffiliationsSerializer::~PubSubAffiliationsSerializer() { } -std::string PubSubAffiliationsSerializer::serializePayload(boost::shared_ptr<PubSubAffiliations> payload) const { - if (!payload) { - return ""; - } - XMLElement element("affiliations", "http://jabber.org/protocol/pubsub"); - if (payload->getNode()) { - element.setAttribute("node", *payload->getNode()); - } - foreach(boost::shared_ptr<PubSubAffiliation> item, payload->getAffiliations()) { - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubAffiliationSerializer(serializers).serialize(item))); - } - return element.serialize(); +std::string PubSubAffiliationsSerializer::serializePayload(std::shared_ptr<PubSubAffiliations> payload) const { + if (!payload) { + return ""; + } + XMLElement element("affiliations", "http://jabber.org/protocol/pubsub"); + if (payload->getNode()) { + element.setAttribute("node", *payload->getNode()); + } + for (const auto& item : payload->getAffiliations()) { + element.addNode(std::make_shared<XMLRawTextNode>(PubSubAffiliationSerializer(serializers).serialize(item))); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.h index ba3c591..b8096d3 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubAffiliations.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubAffiliationsSerializer : public GenericPayloadSerializer<PubSubAffiliations> { - public: - PubSubAffiliationsSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubAffiliationsSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubAffiliations>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubAffiliationsSerializer : public GenericPayloadSerializer<PubSubAffiliations> { + public: + PubSubAffiliationsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubAffiliationsSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubAffiliations>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.cpp index 86a1ae8..c0b651d 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.cpp @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <memory> + #include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; -PubSubConfigureSerializer::PubSubConfigureSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubConfigureSerializer::PubSubConfigureSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubConfigureSerializer::~PubSubConfigureSerializer() { } -std::string PubSubConfigureSerializer::serializePayload(boost::shared_ptr<PubSubConfigure> payload) const { - if (!payload) { - return ""; - } - XMLElement element("configure", "http://jabber.org/protocol/pubsub"); - element.addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); - return element.serialize(); +std::string PubSubConfigureSerializer::serializePayload(std::shared_ptr<PubSubConfigure> payload) const { + if (!payload) { + return ""; + } + XMLElement element("configure", "http://jabber.org/protocol/pubsub"); + element.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h index 093fd35..ead5c4f 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubConfigure.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubConfigureSerializer : public GenericPayloadSerializer<PubSubConfigure> { - public: - PubSubConfigureSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubConfigureSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubConfigure>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubConfigureSerializer : public GenericPayloadSerializer<PubSubConfigure> { + public: + PubSubConfigureSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubConfigureSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubConfigure>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.cpp index 73b2703..a1efca3 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.cpp @@ -1,33 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubCreateSerializer::PubSubCreateSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubCreateSerializer::PubSubCreateSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubCreateSerializer::~PubSubCreateSerializer() { } -std::string PubSubCreateSerializer::serializePayload(boost::shared_ptr<PubSubCreate> payload) const { - if (!payload) { - return ""; - } - XMLElement element("create", "http://jabber.org/protocol/pubsub"); - element.setAttribute("node", payload->getNode()); - return element.serialize(); +std::string PubSubCreateSerializer::serializePayload(std::shared_ptr<PubSubCreate> payload) const { + if (!payload) { + return ""; + } + XMLElement element("create", "http://jabber.org/protocol/pubsub"); + element.setAttribute("node", payload->getNode()); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.h index 29c2393..0aa32af 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubCreate.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubCreateSerializer : public GenericPayloadSerializer<PubSubCreate> { - public: - PubSubCreateSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubCreateSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubCreate>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubCreateSerializer : public GenericPayloadSerializer<PubSubCreate> { + public: + PubSubCreateSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubCreateSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubCreate>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.cpp index d395c80..e41e09e 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.cpp @@ -1,44 +1,39 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubDefaultSerializer::PubSubDefaultSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubDefaultSerializer::PubSubDefaultSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubDefaultSerializer::~PubSubDefaultSerializer() { } -std::string PubSubDefaultSerializer::serializePayload(boost::shared_ptr<PubSubDefault> payload) const { - if (!payload) { - return ""; - } - XMLElement element("default", "http://jabber.org/protocol/pubsub"); - if (payload->getNode()) { - element.setAttribute("node", *payload->getNode()); - } - element.setAttribute("type", serializeType(payload->getType())); - return element.serialize(); +std::string PubSubDefaultSerializer::serializePayload(std::shared_ptr<PubSubDefault> payload) const { + if (!payload) { + return ""; + } + XMLElement element("default", "http://jabber.org/protocol/pubsub"); + if (payload->getNode()) { + element.setAttribute("node", *payload->getNode()); + } + element.setAttribute("type", serializeType(payload->getType())); + return element.serialize(); } std::string PubSubDefaultSerializer::serializeType(PubSubDefault::Type value) { - switch (value) { - case PubSubDefault::None: return "none"; - case PubSubDefault::Collection: return "collection"; - case PubSubDefault::Leaf: return "leaf"; - } - assert(false); - return ""; + switch (value) { + case PubSubDefault::None: return "none"; + case PubSubDefault::Collection: return "collection"; + case PubSubDefault::Leaf: return "leaf"; + } + assert(false); + return ""; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.h index e7b8a6f..42419e3 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubDefault.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubDefaultSerializer : public GenericPayloadSerializer<PubSubDefault> { - public: - PubSubDefaultSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubDefaultSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubDefault>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubDefaultSerializer : public GenericPayloadSerializer<PubSubDefault> { + public: + PubSubDefaultSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubDefaultSerializer() override; - private: - static std::string serializeType(PubSubDefault::Type); + virtual std::string serializePayload(std::shared_ptr<PubSubDefault>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + static std::string serializeType(PubSubDefault::Type); + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.cpp index a25b71e..1f98e7b 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.cpp @@ -1,13 +1,15 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> + +#include <cassert> #include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; @@ -17,95 +19,95 @@ PubSubErrorSerializer::PubSubErrorSerializer() { PubSubErrorSerializer::~PubSubErrorSerializer() { } -std::string PubSubErrorSerializer::serializePayload(boost::shared_ptr<PubSubError> payload) const { - if (payload->getType() == PubSubError::UnknownType) { - return ""; - } - XMLElement element(serializeType(payload->getType()), "http://jabber.org/protocol/pubsub#errors"); - if (payload->getType() == PubSubError::Unsupported) { - if (payload->getUnsupportedFeatureType() != PubSubError::UnknownUnsupportedFeatureType) { - element.setAttribute("feature", serializeUnsupportedFeatureType(payload->getUnsupportedFeatureType())); - } - } - return element.serialize(); +std::string PubSubErrorSerializer::serializePayload(std::shared_ptr<PubSubError> payload) const { + if (payload->getType() == PubSubError::UnknownType) { + return ""; + } + XMLElement element(serializeType(payload->getType()), "http://jabber.org/protocol/pubsub#errors"); + if (payload->getType() == PubSubError::Unsupported) { + if (payload->getUnsupportedFeatureType() != PubSubError::UnknownUnsupportedFeatureType) { + element.setAttribute("feature", serializeUnsupportedFeatureType(payload->getUnsupportedFeatureType())); + } + } + return element.serialize(); } std::string PubSubErrorSerializer::serializeType(PubSubError::Type value) { - switch (value) { - case PubSubError::UnknownType: assert(false); return ""; - case PubSubError::ClosedNode: return "closed-node"; - case PubSubError::ConfigurationRequired: return "configuration-required"; - case PubSubError::InvalidJID: return "invalid-jid"; - case PubSubError::InvalidOptions: return "invalid-options"; - case PubSubError::InvalidPayload: return "invalid-payload"; - case PubSubError::InvalidSubscriptionID: return "invalid-subid"; - case PubSubError::ItemForbidden: return "item-forbidden"; - case PubSubError::ItemRequired: return "item-required"; - case PubSubError::JIDRequired: return "jid-required"; - case PubSubError::MaximumItemsExceeded: return "max-items-exceeded"; - case PubSubError::MaximumNodesExceeded: return "max-nodes-exceeded"; - case PubSubError::NodeIDRequired: return "nodeid-required"; - case PubSubError::NotInRosterGroup: return "not-in-roster-group"; - case PubSubError::NotSubscribed: return "not-subscribed"; - case PubSubError::PayloadTooBig: return "payload-too-big"; - case PubSubError::PayloadRequired: return "payload-required"; - case PubSubError::PendingSubscription: return "pending-subscription"; - case PubSubError::PresenceSubscriptionRequired: return "presence-subscription-required"; - case PubSubError::SubscriptionIDRequired: return "subid-required"; - case PubSubError::TooManySubscriptions: return "too-many-subscriptions"; - case PubSubError::Unsupported: return "unsupported"; - case PubSubError::UnsupportedAccessModel: return "unsupported-access-model"; - } - assert(false); - return ""; + switch (value) { + case PubSubError::UnknownType: assert(false); return ""; + case PubSubError::ClosedNode: return "closed-node"; + case PubSubError::ConfigurationRequired: return "configuration-required"; + case PubSubError::InvalidJID: return "invalid-jid"; + case PubSubError::InvalidOptions: return "invalid-options"; + case PubSubError::InvalidPayload: return "invalid-payload"; + case PubSubError::InvalidSubscriptionID: return "invalid-subid"; + case PubSubError::ItemForbidden: return "item-forbidden"; + case PubSubError::ItemRequired: return "item-required"; + case PubSubError::JIDRequired: return "jid-required"; + case PubSubError::MaximumItemsExceeded: return "max-items-exceeded"; + case PubSubError::MaximumNodesExceeded: return "max-nodes-exceeded"; + case PubSubError::NodeIDRequired: return "nodeid-required"; + case PubSubError::NotInRosterGroup: return "not-in-roster-group"; + case PubSubError::NotSubscribed: return "not-subscribed"; + case PubSubError::PayloadTooBig: return "payload-too-big"; + case PubSubError::PayloadRequired: return "payload-required"; + case PubSubError::PendingSubscription: return "pending-subscription"; + case PubSubError::PresenceSubscriptionRequired: return "presence-subscription-required"; + case PubSubError::SubscriptionIDRequired: return "subid-required"; + case PubSubError::TooManySubscriptions: return "too-many-subscriptions"; + case PubSubError::Unsupported: return "unsupported"; + case PubSubError::UnsupportedAccessModel: return "unsupported-access-model"; + } + assert(false); + return ""; } std::string PubSubErrorSerializer::serializeUnsupportedFeatureType(PubSubError::UnsupportedFeatureType value) { - switch (value) { - case PubSubError::UnknownUnsupportedFeatureType: assert(false); return ""; - case PubSubError::AccessAuthorize: return "access-authorize"; - case PubSubError::AccessOpen: return "access-open"; - case PubSubError::AccessPresence: return "access-presence"; - case PubSubError::AccessRoster: return "access-roster"; - case PubSubError::AccessWhitelist: return "access-whitelist"; - case PubSubError::AutoCreate: return "auto-create"; - case PubSubError::AutoSubscribe: return "auto-subscribe"; - case PubSubError::Collections: return "collections"; - case PubSubError::ConfigNode: return "config-node"; - case PubSubError::CreateAndConfigure: return "create-and-configure"; - case PubSubError::CreateNodes: return "create-nodes"; - case PubSubError::DeleteItems: return "delete-items"; - case PubSubError::DeleteNodes: return "delete-nodes"; - case PubSubError::FilteredNotifications: return "filtered-notifications"; - case PubSubError::GetPending: return "get-pending"; - case PubSubError::InstantNodes: return "instant-nodes"; - case PubSubError::ItemIDs: return "item-ids"; - case PubSubError::LastPublished: return "last-published"; - case PubSubError::LeasedSubscription: return "leased-subscription"; - case PubSubError::ManageSubscriptions: return "manage-subscriptions"; - case PubSubError::MemberAffiliation: return "member-affiliation"; - case PubSubError::MetaData: return "meta-data"; - case PubSubError::ModifyAffiliations: return "modify-affiliations"; - case PubSubError::MultiCollection: return "multi-collection"; - case PubSubError::MultiSubscribe: return "multi-subscribe"; - case PubSubError::OutcastAffiliation: return "outcast-affiliation"; - case PubSubError::PersistentItems: return "persistent-items"; - case PubSubError::PresenceNotifications: return "presence-notifications"; - case PubSubError::PresenceSubscribe: return "presence-subscribe"; - case PubSubError::Publish: return "publish"; - case PubSubError::PublishOptions: return "publish-options"; - case PubSubError::PublishOnlyAffiliation: return "publish-only-affiliation"; - case PubSubError::PublisherAffiliation: return "publisher-affiliation"; - case PubSubError::PurgeNodes: return "purge-nodes"; - case PubSubError::RetractItems: return "retract-items"; - case PubSubError::RetrieveAffiliations: return "retrieve-affiliations"; - case PubSubError::RetrieveDefault: return "retrieve-default"; - case PubSubError::RetrieveItems: return "retrieve-items"; - case PubSubError::RetrieveSubscriptions: return "retrieve-subscriptions"; - case PubSubError::Subscribe: return "subscribe"; - case PubSubError::SubscriptionOptions: return "subscription-options"; - case PubSubError::SubscriptionNotifications: return "subscription-notifications"; - } - assert(false); - return ""; + switch (value) { + case PubSubError::UnknownUnsupportedFeatureType: assert(false); return ""; + case PubSubError::AccessAuthorize: return "access-authorize"; + case PubSubError::AccessOpen: return "access-open"; + case PubSubError::AccessPresence: return "access-presence"; + case PubSubError::AccessRoster: return "access-roster"; + case PubSubError::AccessWhitelist: return "access-whitelist"; + case PubSubError::AutoCreate: return "auto-create"; + case PubSubError::AutoSubscribe: return "auto-subscribe"; + case PubSubError::Collections: return "collections"; + case PubSubError::ConfigNode: return "config-node"; + case PubSubError::CreateAndConfigure: return "create-and-configure"; + case PubSubError::CreateNodes: return "create-nodes"; + case PubSubError::DeleteItems: return "delete-items"; + case PubSubError::DeleteNodes: return "delete-nodes"; + case PubSubError::FilteredNotifications: return "filtered-notifications"; + case PubSubError::GetPending: return "get-pending"; + case PubSubError::InstantNodes: return "instant-nodes"; + case PubSubError::ItemIDs: return "item-ids"; + case PubSubError::LastPublished: return "last-published"; + case PubSubError::LeasedSubscription: return "leased-subscription"; + case PubSubError::ManageSubscriptions: return "manage-subscriptions"; + case PubSubError::MemberAffiliation: return "member-affiliation"; + case PubSubError::MetaData: return "meta-data"; + case PubSubError::ModifyAffiliations: return "modify-affiliations"; + case PubSubError::MultiCollection: return "multi-collection"; + case PubSubError::MultiSubscribe: return "multi-subscribe"; + case PubSubError::OutcastAffiliation: return "outcast-affiliation"; + case PubSubError::PersistentItems: return "persistent-items"; + case PubSubError::PresenceNotifications: return "presence-notifications"; + case PubSubError::PresenceSubscribe: return "presence-subscribe"; + case PubSubError::Publish: return "publish"; + case PubSubError::PublishOptions: return "publish-options"; + case PubSubError::PublishOnlyAffiliation: return "publish-only-affiliation"; + case PubSubError::PublisherAffiliation: return "publisher-affiliation"; + case PubSubError::PurgeNodes: return "purge-nodes"; + case PubSubError::RetractItems: return "retract-items"; + case PubSubError::RetrieveAffiliations: return "retrieve-affiliations"; + case PubSubError::RetrieveDefault: return "retrieve-default"; + case PubSubError::RetrieveItems: return "retrieve-items"; + case PubSubError::RetrieveSubscriptions: return "retrieve-subscriptions"; + case PubSubError::Subscribe: return "subscribe"; + case PubSubError::SubscriptionOptions: return "subscription-options"; + case PubSubError::SubscriptionNotifications: return "subscription-notifications"; + } + assert(false); + return ""; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h index 3ee09ce..0f075fe 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubError.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubErrorSerializer : public GenericPayloadSerializer<PubSubError> { - public: - PubSubErrorSerializer(); - virtual ~PubSubErrorSerializer(); + class SWIFTEN_API PubSubErrorSerializer : public GenericPayloadSerializer<PubSubError> { + public: + PubSubErrorSerializer(); + virtual ~PubSubErrorSerializer() override; - virtual std::string serializePayload(boost::shared_ptr<PubSubError>) const SWIFTEN_OVERRIDE; + virtual std::string serializePayload(std::shared_ptr<PubSubError>) const override; - private: - static std::string serializeType(PubSubError::Type); - static std::string serializeUnsupportedFeatureType(PubSubError::UnsupportedFeatureType); - }; + private: + static std::string serializeType(PubSubError::Type); + static std::string serializeUnsupportedFeatureType(PubSubError::UnsupportedFeatureType); + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.cpp index 1baf7e4..1070c0b 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.cpp @@ -1,33 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubEventAssociateSerializer::PubSubEventAssociateSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubEventAssociateSerializer::PubSubEventAssociateSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubEventAssociateSerializer::~PubSubEventAssociateSerializer() { } -std::string PubSubEventAssociateSerializer::serializePayload(boost::shared_ptr<PubSubEventAssociate> payload) const { - if (!payload) { - return ""; - } - XMLElement element("associate", "http://jabber.org/protocol/pubsub#event"); - element.setAttribute("node", payload->getNode()); - return element.serialize(); +std::string PubSubEventAssociateSerializer::serializePayload(std::shared_ptr<PubSubEventAssociate> payload) const { + if (!payload) { + return ""; + } + XMLElement element("associate", "http://jabber.org/protocol/pubsub#event"); + element.setAttribute("node", payload->getNode()); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.h index 60cf9c7..766ad93 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventAssociate.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventAssociateSerializer : public GenericPayloadSerializer<PubSubEventAssociate> { - public: - PubSubEventAssociateSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventAssociateSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubEventAssociate>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubEventAssociateSerializer : public GenericPayloadSerializer<PubSubEventAssociate> { + public: + PubSubEventAssociateSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventAssociateSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubEventAssociate>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.cpp index b44acaa..f492194 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.cpp @@ -1,18 +1,19 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> #include <Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -23,17 +24,17 @@ PubSubEventCollectionSerializer::PubSubEventCollectionSerializer(PayloadSerializ PubSubEventCollectionSerializer::~PubSubEventCollectionSerializer() { } -std::string PubSubEventCollectionSerializer::serializePayload(boost::shared_ptr<PubSubEventCollection> payload) const { - if (!payload) { - return ""; - } - XMLElement element("collection", "http://jabber.org/protocol/pubsub#event"); - if (payload->getNode()) { - element.setAttribute("node", *payload->getNode()); - } - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubEventDisassociateSerializer(serializers).serialize(payload->getDisassociate()))); - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubEventAssociateSerializer(serializers).serialize(payload->getAssociate()))); - return element.serialize(); +std::string PubSubEventCollectionSerializer::serializePayload(std::shared_ptr<PubSubEventCollection> payload) const { + if (!payload) { + return ""; + } + XMLElement element("collection", "http://jabber.org/protocol/pubsub#event"); + if (payload->getNode()) { + element.setAttribute("node", *payload->getNode()); + } + element.addNode(std::make_shared<XMLRawTextNode>(PubSubEventDisassociateSerializer(serializers).serialize(payload->getDisassociate()))); + element.addNode(std::make_shared<XMLRawTextNode>(PubSubEventAssociateSerializer(serializers).serialize(payload->getAssociate()))); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.h index ac5e7c4..749abdd 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventCollection.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventCollectionSerializer : public GenericPayloadSerializer<PubSubEventCollection> { - public: - PubSubEventCollectionSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventCollectionSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubEventCollection>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubEventCollectionSerializer : public GenericPayloadSerializer<PubSubEventCollection> { + public: + PubSubEventCollectionSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventCollectionSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubEventCollection>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.cpp index f478e4f..a86cead 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.cpp @@ -1,35 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <memory> + #include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; -PubSubEventConfigurationSerializer::PubSubEventConfigurationSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubEventConfigurationSerializer::PubSubEventConfigurationSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubEventConfigurationSerializer::~PubSubEventConfigurationSerializer() { } -std::string PubSubEventConfigurationSerializer::serializePayload(boost::shared_ptr<PubSubEventConfiguration> payload) const { - if (!payload) { - return ""; - } - XMLElement element("configuration", "http://jabber.org/protocol/pubsub#event"); - element.setAttribute("node", payload->getNode()); - element.addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); - return element.serialize(); +std::string PubSubEventConfigurationSerializer::serializePayload(std::shared_ptr<PubSubEventConfiguration> payload) const { + if (!payload) { + return ""; + } + XMLElement element("configuration", "http://jabber.org/protocol/pubsub#event"); + element.setAttribute("node", payload->getNode()); + element.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.h index 6a73496..3902840 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventConfiguration.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventConfigurationSerializer : public GenericPayloadSerializer<PubSubEventConfiguration> { - public: - PubSubEventConfigurationSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventConfigurationSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubEventConfiguration>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubEventConfigurationSerializer : public GenericPayloadSerializer<PubSubEventConfiguration> { + public: + PubSubEventConfigurationSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventConfigurationSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubEventConfiguration>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.cpp index b45adb8..daa9338 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.cpp @@ -1,17 +1,18 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> #include <Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -22,14 +23,14 @@ PubSubEventDeleteSerializer::PubSubEventDeleteSerializer(PayloadSerializerCollec PubSubEventDeleteSerializer::~PubSubEventDeleteSerializer() { } -std::string PubSubEventDeleteSerializer::serializePayload(boost::shared_ptr<PubSubEventDelete> payload) const { - if (!payload) { - return ""; - } - XMLElement element("delete", "http://jabber.org/protocol/pubsub#event"); - element.setAttribute("node", payload->getNode()); - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubEventRedirectSerializer(serializers).serialize(payload->getRedirects()))); - return element.serialize(); +std::string PubSubEventDeleteSerializer::serializePayload(std::shared_ptr<PubSubEventDelete> payload) const { + if (!payload) { + return ""; + } + XMLElement element("delete", "http://jabber.org/protocol/pubsub#event"); + element.setAttribute("node", payload->getNode()); + element.addNode(std::make_shared<XMLRawTextNode>(PubSubEventRedirectSerializer(serializers).serialize(payload->getRedirects()))); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.h index 10de3c3..94f7441 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventDelete.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventDeleteSerializer : public GenericPayloadSerializer<PubSubEventDelete> { - public: - PubSubEventDeleteSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventDeleteSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubEventDelete>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubEventDeleteSerializer : public GenericPayloadSerializer<PubSubEventDelete> { + public: + PubSubEventDeleteSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventDeleteSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubEventDelete>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.cpp index 60cc562..b90e76e 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.cpp @@ -1,33 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubEventDisassociateSerializer::PubSubEventDisassociateSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubEventDisassociateSerializer::PubSubEventDisassociateSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubEventDisassociateSerializer::~PubSubEventDisassociateSerializer() { } -std::string PubSubEventDisassociateSerializer::serializePayload(boost::shared_ptr<PubSubEventDisassociate> payload) const { - if (!payload) { - return ""; - } - XMLElement element("disassociate", "http://jabber.org/protocol/pubsub#event"); - element.setAttribute("node", payload->getNode()); - return element.serialize(); +std::string PubSubEventDisassociateSerializer::serializePayload(std::shared_ptr<PubSubEventDisassociate> payload) const { + if (!payload) { + return ""; + } + XMLElement element("disassociate", "http://jabber.org/protocol/pubsub#event"); + element.setAttribute("node", payload->getNode()); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.h index c7187c7..8f9fd00 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventDisassociate.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventDisassociateSerializer : public GenericPayloadSerializer<PubSubEventDisassociate> { - public: - PubSubEventDisassociateSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventDisassociateSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubEventDisassociate>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubEventDisassociateSerializer : public GenericPayloadSerializer<PubSubEventDisassociate> { + public: + PubSubEventDisassociateSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventDisassociateSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubEventDisassociate>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.cpp index 2b8b08e..2743ff6 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.cpp @@ -1,17 +1,15 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -22,24 +20,24 @@ PubSubEventItemSerializer::PubSubEventItemSerializer(PayloadSerializerCollection PubSubEventItemSerializer::~PubSubEventItemSerializer() { } -std::string PubSubEventItemSerializer::serializePayload(boost::shared_ptr<PubSubEventItem> payload) const { - if (!payload) { - return ""; - } - XMLElement element("item", "http://jabber.org/protocol/pubsub#event"); - if (payload->getNode()) { - element.setAttribute("node", *payload->getNode()); - } - if (payload->getPublisher()) { - element.setAttribute("publisher", *payload->getPublisher()); - } - foreach(boost::shared_ptr<Payload> item, payload->getData()) { - element.addNode(boost::make_shared<XMLRawTextNode>(serializers->getPayloadSerializer(item)->serialize(item))); - } - if (payload->getID()) { - element.setAttribute("id", *payload->getID()); - } - return element.serialize(); +std::string PubSubEventItemSerializer::serializePayload(std::shared_ptr<PubSubEventItem> payload) const { + if (!payload) { + return ""; + } + XMLElement element("item", "http://jabber.org/protocol/pubsub#event"); + if (payload->getNode()) { + element.setAttribute("node", *payload->getNode()); + } + if (payload->getPublisher()) { + element.setAttribute("publisher", *payload->getPublisher()); + } + for (const auto& item : payload->getData()) { + element.addNode(std::make_shared<XMLRawTextNode>(serializers->getPayloadSerializer(item)->serialize(item))); + } + if (payload->getID()) { + element.setAttribute("id", *payload->getID()); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.h index 93fa5b0..5bb2b83 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventItem.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventItemSerializer : public GenericPayloadSerializer<PubSubEventItem> { - public: - PubSubEventItemSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventItemSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubEventItem>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubEventItemSerializer : public GenericPayloadSerializer<PubSubEventItem> { + public: + PubSubEventItemSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventItemSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubEventItem>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.cpp index 099aa4b..67d611b 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.cpp @@ -1,19 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -24,19 +22,19 @@ PubSubEventItemsSerializer::PubSubEventItemsSerializer(PayloadSerializerCollecti PubSubEventItemsSerializer::~PubSubEventItemsSerializer() { } -std::string PubSubEventItemsSerializer::serializePayload(boost::shared_ptr<PubSubEventItems> payload) const { - if (!payload) { - return ""; - } - XMLElement element("items", "http://jabber.org/protocol/pubsub#event"); - element.setAttribute("node", payload->getNode()); - foreach(boost::shared_ptr<PubSubEventItem> item, payload->getItems()) { - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubEventItemSerializer(serializers).serialize(item))); - } - foreach(boost::shared_ptr<PubSubEventRetract> item, payload->getRetracts()) { - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubEventRetractSerializer(serializers).serialize(item))); - } - return element.serialize(); +std::string PubSubEventItemsSerializer::serializePayload(std::shared_ptr<PubSubEventItems> payload) const { + if (!payload) { + return ""; + } + XMLElement element("items", "http://jabber.org/protocol/pubsub#event"); + element.setAttribute("node", payload->getNode()); + for (const auto& item : payload->getItems()) { + element.addNode(std::make_shared<XMLRawTextNode>(PubSubEventItemSerializer(serializers).serialize(item))); + } + for (const auto& item : payload->getRetracts()) { + element.addNode(std::make_shared<XMLRawTextNode>(PubSubEventRetractSerializer(serializers).serialize(item))); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.h index 6e60ee4..83d3d95 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventItems.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventItemsSerializer : public GenericPayloadSerializer<PubSubEventItems> { - public: - PubSubEventItemsSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventItemsSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubEventItems>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubEventItemsSerializer : public GenericPayloadSerializer<PubSubEventItems> { + public: + PubSubEventItemsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventItemsSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubEventItems>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.cpp index 1387848..2125f59 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.cpp @@ -1,33 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubEventPurgeSerializer::PubSubEventPurgeSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubEventPurgeSerializer::PubSubEventPurgeSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubEventPurgeSerializer::~PubSubEventPurgeSerializer() { } -std::string PubSubEventPurgeSerializer::serializePayload(boost::shared_ptr<PubSubEventPurge> payload) const { - if (!payload) { - return ""; - } - XMLElement element("purge", "http://jabber.org/protocol/pubsub#event"); - element.setAttribute("node", payload->getNode()); - return element.serialize(); +std::string PubSubEventPurgeSerializer::serializePayload(std::shared_ptr<PubSubEventPurge> payload) const { + if (!payload) { + return ""; + } + XMLElement element("purge", "http://jabber.org/protocol/pubsub#event"); + element.setAttribute("node", payload->getNode()); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.h index ab2d1d8..533841f 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventPurge.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventPurgeSerializer : public GenericPayloadSerializer<PubSubEventPurge> { - public: - PubSubEventPurgeSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventPurgeSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubEventPurge>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubEventPurgeSerializer : public GenericPayloadSerializer<PubSubEventPurge> { + public: + PubSubEventPurgeSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventPurgeSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubEventPurge>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.cpp index 7134e58..771c923 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.cpp @@ -1,33 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubEventRedirectSerializer::PubSubEventRedirectSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubEventRedirectSerializer::PubSubEventRedirectSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubEventRedirectSerializer::~PubSubEventRedirectSerializer() { } -std::string PubSubEventRedirectSerializer::serializePayload(boost::shared_ptr<PubSubEventRedirect> payload) const { - if (!payload) { - return ""; - } - XMLElement element("redirect", "http://jabber.org/protocol/pubsub#event"); - element.setAttribute("uri", payload->getURI()); - return element.serialize(); +std::string PubSubEventRedirectSerializer::serializePayload(std::shared_ptr<PubSubEventRedirect> payload) const { + if (!payload) { + return ""; + } + XMLElement element("redirect", "http://jabber.org/protocol/pubsub#event"); + element.setAttribute("uri", payload->getURI()); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.h index 751ff19..391d93e 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventRedirect.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventRedirectSerializer : public GenericPayloadSerializer<PubSubEventRedirect> { - public: - PubSubEventRedirectSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventRedirectSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubEventRedirect>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubEventRedirectSerializer : public GenericPayloadSerializer<PubSubEventRedirect> { + public: + PubSubEventRedirectSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventRedirectSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubEventRedirect>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.cpp index 17d1a0f..f938cd7 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.cpp @@ -1,33 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubEventRetractSerializer::PubSubEventRetractSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubEventRetractSerializer::PubSubEventRetractSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubEventRetractSerializer::~PubSubEventRetractSerializer() { } -std::string PubSubEventRetractSerializer::serializePayload(boost::shared_ptr<PubSubEventRetract> payload) const { - if (!payload) { - return ""; - } - XMLElement element("retract", "http://jabber.org/protocol/pubsub#event"); - element.setAttribute("id", payload->getID()); - return element.serialize(); +std::string PubSubEventRetractSerializer::serializePayload(std::shared_ptr<PubSubEventRetract> payload) const { + if (!payload) { + return ""; + } + XMLElement element("retract", "http://jabber.org/protocol/pubsub#event"); + element.setAttribute("id", payload->getID()); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h index 0d73ec8..5a70fdd 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventRetract.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventRetractSerializer : public GenericPayloadSerializer<PubSubEventRetract> { - public: - PubSubEventRetractSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventRetractSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubEventRetract>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubEventRetractSerializer : public GenericPayloadSerializer<PubSubEventRetract> { + public: + PubSubEventRetractSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventRetractSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubEventRetract>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.cpp index da813cd..51b8b46 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.cpp @@ -1,51 +1,48 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.h> -#include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.h> +#include <memory> + #include <Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.h> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; -PubSubEventSerializer::PubSubEventSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { - pubsubSerializers.push_back(boost::make_shared<PubSubEventSubscriptionSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubEventPurgeSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubEventCollectionSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubEventDeleteSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubEventItemsSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubEventConfigurationSerializer>(serializers)); +PubSubEventSerializer::PubSubEventSerializer(PayloadSerializerCollection* serializers) { + pubsubSerializers.push_back(std::make_shared<PubSubEventSubscriptionSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubEventPurgeSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubEventCollectionSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubEventDeleteSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubEventItemsSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubEventConfigurationSerializer>(serializers)); } PubSubEventSerializer::~PubSubEventSerializer() { } -std::string PubSubEventSerializer::serializePayload(boost::shared_ptr<PubSubEvent> payload) const { - if (!payload) { - return ""; - } - XMLElement element("event", "http://jabber.org/protocol/pubsub#event"); - boost::shared_ptr<PubSubEventPayload> p = payload->getPayload(); - foreach(boost::shared_ptr<PayloadSerializer> serializer, pubsubSerializers) { - if (serializer->canSerialize(p)) { - element.addNode(boost::make_shared<XMLRawTextNode>(serializer->serialize(p))); - } - } - return element.serialize(); +std::string PubSubEventSerializer::serializePayload(std::shared_ptr<PubSubEvent> payload) const { + if (!payload) { + return ""; + } + XMLElement element("event", "http://jabber.org/protocol/pubsub#event"); + std::shared_ptr<PubSubEventPayload> p = payload->getPayload(); + for (const auto& serializer : pubsubSerializers) { + if (serializer->canSerialize(p)) { + element.addNode(std::make_shared<XMLRawTextNode>(serializer->serialize(p))); + } + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.h index 85b5b90..f16a749 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.h @@ -1,33 +1,29 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> +#include <vector> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEvent.h> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventSerializer : public GenericPayloadSerializer<PubSubEvent> { - public: - PubSubEventSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubEvent>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubEventSerializer : public GenericPayloadSerializer<PubSubEvent> { + public: + PubSubEventSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubEvent>) const override; - private: - PayloadSerializerCollection* serializers; - std::vector< boost::shared_ptr<PayloadSerializer> > pubsubSerializers; - }; + private: + std::vector< std::shared_ptr<PayloadSerializer> > pubsubSerializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.cpp index 9b0a334..e39e6ad 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.cpp @@ -1,48 +1,44 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - -#include <Swiften/Serializer/PayloadSerializerCollection.h> #include <Swiften/Base/DateTime.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubEventSubscriptionSerializer::PubSubEventSubscriptionSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubEventSubscriptionSerializer::PubSubEventSubscriptionSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubEventSubscriptionSerializer::~PubSubEventSubscriptionSerializer() { } -std::string PubSubEventSubscriptionSerializer::serializePayload(boost::shared_ptr<PubSubEventSubscription> payload) const { - if (!payload) { - return ""; - } - XMLElement element("subscription", "http://jabber.org/protocol/pubsub#event"); - element.setAttribute("node", payload->getNode()); - element.setAttribute("jid", payload->getJID()); - element.setAttribute("subscription", serializeSubscriptionType(payload->getSubscription())); - if (payload->getSubscriptionID()) { - element.setAttribute("subid", *payload->getSubscriptionID()); - } - element.setAttribute("expiry", dateTimeToString(payload->getExpiry())); - return element.serialize(); +std::string PubSubEventSubscriptionSerializer::serializePayload(std::shared_ptr<PubSubEventSubscription> payload) const { + if (!payload) { + return ""; + } + XMLElement element("subscription", "http://jabber.org/protocol/pubsub#event"); + element.setAttribute("node", payload->getNode()); + element.setAttribute("jid", payload->getJID()); + element.setAttribute("subscription", serializeSubscriptionType(payload->getSubscription())); + if (payload->getSubscriptionID()) { + element.setAttribute("subid", *payload->getSubscriptionID()); + } + element.setAttribute("expiry", dateTimeToString(payload->getExpiry())); + return element.serialize(); } std::string PubSubEventSubscriptionSerializer::serializeSubscriptionType(PubSubEventSubscription::SubscriptionType value) { - switch (value) { - case PubSubEventSubscription::None: return "none"; - case PubSubEventSubscription::Pending: return "pending"; - case PubSubEventSubscription::Subscribed: return "subscribed"; - case PubSubEventSubscription::Unconfigured: return "unconfigured"; - } - assert(false); - return ""; + switch (value) { + case PubSubEventSubscription::None: return "none"; + case PubSubEventSubscription::Pending: return "pending"; + case PubSubEventSubscription::Subscribed: return "subscribed"; + case PubSubEventSubscription::Unconfigured: return "unconfigured"; + } + assert(false); + return ""; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.h index 3b613bd..80830ac 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubEventSubscription.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubEventSubscriptionSerializer : public GenericPayloadSerializer<PubSubEventSubscription> { - public: - PubSubEventSubscriptionSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubEventSubscriptionSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubEventSubscription>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubEventSubscriptionSerializer : public GenericPayloadSerializer<PubSubEventSubscription> { + public: + PubSubEventSubscriptionSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventSubscriptionSerializer() override; - private: - static std::string serializeSubscriptionType(PubSubEventSubscription::SubscriptionType); + virtual std::string serializePayload(std::shared_ptr<PubSubEventSubscription>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + static std::string serializeSubscriptionType(PubSubEventSubscription::SubscriptionType); + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.cpp index 5a82b42..a202c88 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.cpp @@ -1,17 +1,15 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -22,16 +20,18 @@ PubSubItemSerializer::PubSubItemSerializer(PayloadSerializerCollection* serializ PubSubItemSerializer::~PubSubItemSerializer() { } -std::string PubSubItemSerializer::serializePayload(boost::shared_ptr<PubSubItem> payload) const { - if (!payload) { - return ""; - } - XMLElement element("item", "http://jabber.org/protocol/pubsub"); - foreach(boost::shared_ptr<Payload> item, payload->getData()) { - element.addNode(boost::make_shared<XMLRawTextNode>(serializers->getPayloadSerializer(item)->serialize(item))); - } - element.setAttribute("id", payload->getID()); - return element.serialize(); +std::string PubSubItemSerializer::serializePayload(std::shared_ptr<PubSubItem> payload) const { + if (!payload) { + return ""; + } + XMLElement element("item", "http://jabber.org/protocol/pubsub"); + for (const auto& item : payload->getData()) { + element.addNode(std::make_shared<XMLRawTextNode>(serializers->getPayloadSerializer(item)->serialize(item))); + } + if (!payload->getID().empty()) { + element.setAttribute("id", payload->getID()); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h index 56f186d..54a8ead 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubItem.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubItemSerializer : public GenericPayloadSerializer<PubSubItem> { - public: - PubSubItemSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubItemSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubItem>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubItemSerializer : public GenericPayloadSerializer<PubSubItem> { + public: + PubSubItemSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubItemSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubItem>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.cpp index 6bffa6a..b2c7326 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.cpp @@ -1,19 +1,19 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> + +#include <memory> + #include <boost/lexical_cast.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Base/Log.h> #include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -24,22 +24,25 @@ PubSubItemsSerializer::PubSubItemsSerializer(PayloadSerializerCollection* serial PubSubItemsSerializer::~PubSubItemsSerializer() { } -std::string PubSubItemsSerializer::serializePayload(boost::shared_ptr<PubSubItems> payload) const { - if (!payload) { - return ""; - } - XMLElement element("items", "http://jabber.org/protocol/pubsub"); - element.setAttribute("node", payload->getNode()); - foreach(boost::shared_ptr<PubSubItem> item, payload->getItems()) { - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubItemSerializer(serializers).serialize(item))); - } - if (payload->getMaximumItems()) { - element.setAttribute("max_items", boost::lexical_cast<std::string>(*payload->getMaximumItems())); - } - if (payload->getSubscriptionID()) { - element.setAttribute("subid", *payload->getSubscriptionID()); - } - return element.serialize(); +std::string PubSubItemsSerializer::serializePayload(std::shared_ptr<PubSubItems> payload) const { + if (!payload) { + return ""; + } + XMLElement element("items", "http://jabber.org/protocol/pubsub"); + if (payload->getNode().empty()) { + SWIFT_LOG(warning) << "Serializing PubSubItems with empty node attribute"; + } + element.setAttribute("node", payload->getNode()); + for (const auto& item : payload->getItems()) { + element.addNode(std::make_shared<XMLRawTextNode>(PubSubItemSerializer(serializers).serialize(item))); + } + if (payload->getMaximumItems()) { + element.setAttribute("max_items", std::to_string(*payload->getMaximumItems())); + } + if (payload->getSubscriptionID()) { + element.setAttribute("subid", *payload->getSubscriptionID()); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.h index 050e156..416c47e 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubItems.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubItemsSerializer : public GenericPayloadSerializer<PubSubItems> { - public: - PubSubItemsSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubItemsSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubItems>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubItemsSerializer : public GenericPayloadSerializer<PubSubItems> { + public: + PubSubItemsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubItemsSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubItems>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.cpp index db983b9..5059a7c 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.cpp @@ -1,39 +1,37 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <memory> + #include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; -PubSubOptionsSerializer::PubSubOptionsSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubOptionsSerializer::PubSubOptionsSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubOptionsSerializer::~PubSubOptionsSerializer() { } -std::string PubSubOptionsSerializer::serializePayload(boost::shared_ptr<PubSubOptions> payload) const { - if (!payload) { - return ""; - } - XMLElement element("options", "http://jabber.org/protocol/pubsub"); - element.setAttribute("node", payload->getNode()); - element.setAttribute("jid", payload->getJID()); - element.addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); - if (payload->getSubscriptionID()) { - element.setAttribute("subid", *payload->getSubscriptionID()); - } - return element.serialize(); +std::string PubSubOptionsSerializer::serializePayload(std::shared_ptr<PubSubOptions> payload) const { + if (!payload) { + return ""; + } + XMLElement element("options", "http://jabber.org/protocol/pubsub"); + element.setAttribute("node", payload->getNode()); + element.setAttribute("jid", payload->getJID()); + element.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); + if (payload->getSubscriptionID()) { + element.setAttribute("subid", *payload->getSubscriptionID()); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h index 258f1f2..6f30756 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOptions.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOptionsSerializer : public GenericPayloadSerializer<PubSubOptions> { - public: - PubSubOptionsSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOptionsSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubOptions>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubOptionsSerializer : public GenericPayloadSerializer<PubSubOptions> { + public: + PubSubOptionsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOptionsSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubOptions>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.cpp index 3699b8e..1387b07 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.cpp @@ -1,45 +1,43 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> +#include <cassert> #include <Swiften/Serializer/PayloadSerializerCollection.h> - +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubOwnerAffiliationSerializer::PubSubOwnerAffiliationSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubOwnerAffiliationSerializer::PubSubOwnerAffiliationSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubOwnerAffiliationSerializer::~PubSubOwnerAffiliationSerializer() { } -std::string PubSubOwnerAffiliationSerializer::serializePayload(boost::shared_ptr<PubSubOwnerAffiliation> payload) const { - if (!payload) { - return ""; - } - XMLElement element("affiliation", "http://jabber.org/protocol/pubsub#owner"); - element.setAttribute("jid", payload->getJID()); - element.setAttribute("affiliation", serializeType(payload->getType())); - return element.serialize(); +std::string PubSubOwnerAffiliationSerializer::serializePayload(std::shared_ptr<PubSubOwnerAffiliation> payload) const { + if (!payload) { + return ""; + } + XMLElement element("affiliation", "http://jabber.org/protocol/pubsub#owner"); + element.setAttribute("jid", payload->getJID()); + element.setAttribute("affiliation", serializeType(payload->getType())); + return element.serialize(); } std::string PubSubOwnerAffiliationSerializer::serializeType(PubSubOwnerAffiliation::Type value) { - switch (value) { - case PubSubOwnerAffiliation::None: return "none"; - case PubSubOwnerAffiliation::Member: return "member"; - case PubSubOwnerAffiliation::Outcast: return "outcast"; - case PubSubOwnerAffiliation::Owner: return "owner"; - case PubSubOwnerAffiliation::Publisher: return "publisher"; - case PubSubOwnerAffiliation::PublishOnly: return "publish-only"; - } - assert(false); - return ""; + switch (value) { + case PubSubOwnerAffiliation::None: return "none"; + case PubSubOwnerAffiliation::Member: return "member"; + case PubSubOwnerAffiliation::Outcast: return "outcast"; + case PubSubOwnerAffiliation::Owner: return "owner"; + case PubSubOwnerAffiliation::Publisher: return "publisher"; + case PubSubOwnerAffiliation::PublishOnly: return "publish-only"; + } + assert(false); + return ""; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.h index acea723..ae97086 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOwnerAffiliation.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOwnerAffiliationSerializer : public GenericPayloadSerializer<PubSubOwnerAffiliation> { - public: - PubSubOwnerAffiliationSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOwnerAffiliationSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerAffiliation>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubOwnerAffiliationSerializer : public GenericPayloadSerializer<PubSubOwnerAffiliation> { + public: + PubSubOwnerAffiliationSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerAffiliationSerializer() override; - private: - static std::string serializeType(PubSubOwnerAffiliation::Type); + virtual std::string serializePayload(std::shared_ptr<PubSubOwnerAffiliation>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + static std::string serializeType(PubSubOwnerAffiliation::Type); + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.cpp index c393bfb..b9f6bcc 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.cpp @@ -1,18 +1,16 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -23,16 +21,16 @@ PubSubOwnerAffiliationsSerializer::PubSubOwnerAffiliationsSerializer(PayloadSeri PubSubOwnerAffiliationsSerializer::~PubSubOwnerAffiliationsSerializer() { } -std::string PubSubOwnerAffiliationsSerializer::serializePayload(boost::shared_ptr<PubSubOwnerAffiliations> payload) const { - if (!payload) { - return ""; - } - XMLElement element("affiliations", "http://jabber.org/protocol/pubsub#owner"); - element.setAttribute("node", payload->getNode()); - foreach(boost::shared_ptr<PubSubOwnerAffiliation> item, payload->getAffiliations()) { - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubOwnerAffiliationSerializer(serializers).serialize(item))); - } - return element.serialize(); +std::string PubSubOwnerAffiliationsSerializer::serializePayload(std::shared_ptr<PubSubOwnerAffiliations> payload) const { + if (!payload) { + return ""; + } + XMLElement element("affiliations", "http://jabber.org/protocol/pubsub#owner"); + element.setAttribute("node", payload->getNode()); + for (const auto& item : payload->getAffiliations()) { + element.addNode(std::make_shared<XMLRawTextNode>(PubSubOwnerAffiliationSerializer(serializers).serialize(item))); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.h index 3d20042..ed244ff 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOwnerAffiliations.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOwnerAffiliationsSerializer : public GenericPayloadSerializer<PubSubOwnerAffiliations> { - public: - PubSubOwnerAffiliationsSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOwnerAffiliationsSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerAffiliations>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubOwnerAffiliationsSerializer : public GenericPayloadSerializer<PubSubOwnerAffiliations> { + public: + PubSubOwnerAffiliationsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerAffiliationsSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubOwnerAffiliations>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.cpp index 154a370..a14b7ea 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.cpp @@ -1,37 +1,33 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <memory> + #include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; -PubSubOwnerConfigureSerializer::PubSubOwnerConfigureSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubOwnerConfigureSerializer::PubSubOwnerConfigureSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubOwnerConfigureSerializer::~PubSubOwnerConfigureSerializer() { } -std::string PubSubOwnerConfigureSerializer::serializePayload(boost::shared_ptr<PubSubOwnerConfigure> payload) const { - if (!payload) { - return ""; - } - XMLElement element("configure", "http://jabber.org/protocol/pubsub#owner"); - if (payload->getNode()) { - element.setAttribute("node", *payload->getNode()); - } - element.addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); - return element.serialize(); +std::string PubSubOwnerConfigureSerializer::serializePayload(std::shared_ptr<PubSubOwnerConfigure> payload) const { + if (!payload) { + return ""; + } + XMLElement element("configure", "http://jabber.org/protocol/pubsub#owner"); + if (payload->getNode()) { + element.setAttribute("node", *payload->getNode()); + } + element.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); + return element.serialize(); } - - diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.h index 41f2a9d..4512eda 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOwnerConfigure.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOwnerConfigureSerializer : public GenericPayloadSerializer<PubSubOwnerConfigure> { - public: - PubSubOwnerConfigureSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOwnerConfigureSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerConfigure>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubOwnerConfigureSerializer : public GenericPayloadSerializer<PubSubOwnerConfigure> { + public: + PubSubOwnerConfigureSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerConfigureSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubOwnerConfigure>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.cpp index 7ce2e71..68d334d 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.cpp @@ -1,34 +1,30 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <memory> + #include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; -PubSubOwnerDefaultSerializer::PubSubOwnerDefaultSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubOwnerDefaultSerializer::PubSubOwnerDefaultSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubOwnerDefaultSerializer::~PubSubOwnerDefaultSerializer() { } -std::string PubSubOwnerDefaultSerializer::serializePayload(boost::shared_ptr<PubSubOwnerDefault> payload) const { - if (!payload) { - return ""; - } - XMLElement element("default", "http://jabber.org/protocol/pubsub#owner"); - element.addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); - return element.serialize(); +std::string PubSubOwnerDefaultSerializer::serializePayload(std::shared_ptr<PubSubOwnerDefault> payload) const { + if (!payload) { + return ""; + } + XMLElement element("default", "http://jabber.org/protocol/pubsub#owner"); + element.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(payload->getData()))); + return element.serialize(); } - - diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.h index 02aefe8..c19b250 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOwnerDefault.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOwnerDefaultSerializer : public GenericPayloadSerializer<PubSubOwnerDefault> { - public: - PubSubOwnerDefaultSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOwnerDefaultSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerDefault>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubOwnerDefaultSerializer : public GenericPayloadSerializer<PubSubOwnerDefault> { + public: + PubSubOwnerDefaultSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerDefaultSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubOwnerDefault>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.cpp index 010645c..5d1c5a6 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.cpp @@ -1,17 +1,18 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" + #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -22,14 +23,14 @@ PubSubOwnerDeleteSerializer::PubSubOwnerDeleteSerializer(PayloadSerializerCollec PubSubOwnerDeleteSerializer::~PubSubOwnerDeleteSerializer() { } -std::string PubSubOwnerDeleteSerializer::serializePayload(boost::shared_ptr<PubSubOwnerDelete> payload) const { - if (!payload) { - return ""; - } - XMLElement element("delete", "http://jabber.org/protocol/pubsub#owner"); - element.setAttribute("node", payload->getNode()); - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubOwnerRedirectSerializer(serializers).serialize(payload->getRedirect()))); - return element.serialize(); +std::string PubSubOwnerDeleteSerializer::serializePayload(std::shared_ptr<PubSubOwnerDelete> payload) const { + if (!payload) { + return ""; + } + XMLElement element("delete", "http://jabber.org/protocol/pubsub#owner"); + element.setAttribute("node", payload->getNode()); + element.addNode(std::make_shared<XMLRawTextNode>(PubSubOwnerRedirectSerializer(serializers).serialize(payload->getRedirect()))); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.h index d537a4f..7a0cecc 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOwnerDelete.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOwnerDeleteSerializer : public GenericPayloadSerializer<PubSubOwnerDelete> { - public: - PubSubOwnerDeleteSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOwnerDeleteSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerDelete>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubOwnerDeleteSerializer : public GenericPayloadSerializer<PubSubOwnerDelete> { + public: + PubSubOwnerDeleteSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerDeleteSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubOwnerDelete>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.cpp index de7d5a5..b2dfd21 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.cpp @@ -1,51 +1,48 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <memory> + +#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.h> -#include <Swiften/Base/foreach.h> using namespace Swift; -PubSubOwnerPubSubSerializer::PubSubOwnerPubSubSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { - pubsubSerializers.push_back(boost::make_shared<PubSubOwnerConfigureSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubOwnerSubscriptionsSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubOwnerDefaultSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubOwnerPurgeSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubOwnerAffiliationsSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubOwnerDeleteSerializer>(serializers)); +PubSubOwnerPubSubSerializer::PubSubOwnerPubSubSerializer(PayloadSerializerCollection* serializers) { + pubsubSerializers.push_back(std::make_shared<PubSubOwnerConfigureSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubOwnerSubscriptionsSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubOwnerDefaultSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubOwnerPurgeSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubOwnerAffiliationsSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubOwnerDeleteSerializer>(serializers)); } PubSubOwnerPubSubSerializer::~PubSubOwnerPubSubSerializer() { } -std::string PubSubOwnerPubSubSerializer::serializePayload(boost::shared_ptr<PubSubOwnerPubSub> payload) const { - if (!payload) { - return ""; - } - XMLElement element("pubsub", "http://jabber.org/protocol/pubsub#owner"); - boost::shared_ptr<PubSubOwnerPayload> p = payload->getPayload(); - foreach(boost::shared_ptr<PayloadSerializer> serializer, pubsubSerializers) { - if (serializer->canSerialize(p)) { - element.addNode(boost::make_shared<XMLRawTextNode>(serializer->serialize(p))); - } - } - return element.serialize(); +std::string PubSubOwnerPubSubSerializer::serializePayload(std::shared_ptr<PubSubOwnerPubSub> payload) const { + if (!payload) { + return ""; + } + XMLElement element("pubsub", "http://jabber.org/protocol/pubsub#owner"); + std::shared_ptr<PubSubOwnerPayload> p = payload->getPayload(); + for (const auto& serializer : pubsubSerializers) { + if (serializer->canSerialize(p)) { + element.addNode(std::make_shared<XMLRawTextNode>(serializer->serialize(p))); + } + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h index 9f5732b..13889b6 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h @@ -1,33 +1,29 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> +#include <vector> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOwnerPubSub.h> -#include <boost/shared_ptr.hpp> -#include <vector> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOwnerPubSubSerializer : public GenericPayloadSerializer<PubSubOwnerPubSub> { - public: - PubSubOwnerPubSubSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOwnerPubSubSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerPubSub>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubOwnerPubSubSerializer : public GenericPayloadSerializer<PubSubOwnerPubSub> { + public: + PubSubOwnerPubSubSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerPubSubSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubOwnerPubSub>) const override; - private: - PayloadSerializerCollection* serializers; - std::vector< boost::shared_ptr<PayloadSerializer> > pubsubSerializers; - }; + private: + std::vector< std::shared_ptr<PayloadSerializer> > pubsubSerializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.cpp index 591cdf9..cbcccb9 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.cpp @@ -1,33 +1,26 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubOwnerPurgeSerializer::PubSubOwnerPurgeSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubOwnerPurgeSerializer::PubSubOwnerPurgeSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubOwnerPurgeSerializer::~PubSubOwnerPurgeSerializer() { } -std::string PubSubOwnerPurgeSerializer::serializePayload(boost::shared_ptr<PubSubOwnerPurge> payload) const { - if (!payload) { - return ""; - } - XMLElement element("purge", "http://jabber.org/protocol/pubsub#owner"); - element.setAttribute("node", payload->getNode()); - return element.serialize(); +std::string PubSubOwnerPurgeSerializer::serializePayload(std::shared_ptr<PubSubOwnerPurge> payload) const { + if (!payload) { + return ""; + } + XMLElement element("purge", "http://jabber.org/protocol/pubsub#owner"); + element.setAttribute("node", payload->getNode()); + return element.serialize(); } - - diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.h index 51a086f..d361928 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOwnerPurge.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOwnerPurgeSerializer : public GenericPayloadSerializer<PubSubOwnerPurge> { - public: - PubSubOwnerPurgeSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOwnerPurgeSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerPurge>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubOwnerPurgeSerializer : public GenericPayloadSerializer<PubSubOwnerPurge> { + public: + PubSubOwnerPurgeSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerPurgeSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubOwnerPurge>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.cpp index ea7d721..2d06a70 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.cpp @@ -1,33 +1,26 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubOwnerRedirectSerializer::PubSubOwnerRedirectSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubOwnerRedirectSerializer::PubSubOwnerRedirectSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubOwnerRedirectSerializer::~PubSubOwnerRedirectSerializer() { } -std::string PubSubOwnerRedirectSerializer::serializePayload(boost::shared_ptr<PubSubOwnerRedirect> payload) const { - if (!payload) { - return ""; - } - XMLElement element("redirect", "http://jabber.org/protocol/pubsub#owner"); - element.setAttribute("uri", payload->getURI()); - return element.serialize(); +std::string PubSubOwnerRedirectSerializer::serializePayload(std::shared_ptr<PubSubOwnerRedirect> payload) const { + if (!payload) { + return ""; + } + XMLElement element("redirect", "http://jabber.org/protocol/pubsub#owner"); + element.setAttribute("uri", payload->getURI()); + return element.serialize(); } - - diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.h index e5d5af5..c35b3ea 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOwnerRedirect.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOwnerRedirectSerializer : public GenericPayloadSerializer<PubSubOwnerRedirect> { - public: - PubSubOwnerRedirectSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOwnerRedirectSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerRedirect>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubOwnerRedirectSerializer : public GenericPayloadSerializer<PubSubOwnerRedirect> { + public: + PubSubOwnerRedirectSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerRedirectSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubOwnerRedirect>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.cpp index 91bc00b..842df98 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.cpp @@ -1,43 +1,40 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> +#include <cassert> -#include <Swiften/Serializer/PayloadSerializerCollection.h> - +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubOwnerSubscriptionSerializer::PubSubOwnerSubscriptionSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubOwnerSubscriptionSerializer::PubSubOwnerSubscriptionSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubOwnerSubscriptionSerializer::~PubSubOwnerSubscriptionSerializer() { } -std::string PubSubOwnerSubscriptionSerializer::serializePayload(boost::shared_ptr<PubSubOwnerSubscription> payload) const { - if (!payload) { - return ""; - } - XMLElement element("subscription", "http://jabber.org/protocol/pubsub#owner"); - element.setAttribute("jid", payload->getJID()); - element.setAttribute("subscription", serializeSubscriptionType(payload->getSubscription())); - return element.serialize(); +std::string PubSubOwnerSubscriptionSerializer::serializePayload(std::shared_ptr<PubSubOwnerSubscription> payload) const { + if (!payload) { + return ""; + } + XMLElement element("subscription", "http://jabber.org/protocol/pubsub#owner"); + element.setAttribute("jid", payload->getJID()); + element.setAttribute("subscription", serializeSubscriptionType(payload->getSubscription())); + return element.serialize(); } std::string PubSubOwnerSubscriptionSerializer::serializeSubscriptionType(PubSubOwnerSubscription::SubscriptionType value) { - switch (value) { - case PubSubOwnerSubscription::None: return "none"; - case PubSubOwnerSubscription::Pending: return "pending"; - case PubSubOwnerSubscription::Subscribed: return "subscribed"; - case PubSubOwnerSubscription::Unconfigured: return "unconfigured"; - } - assert(false); - return ""; + switch (value) { + case PubSubOwnerSubscription::None: return "none"; + case PubSubOwnerSubscription::Pending: return "pending"; + case PubSubOwnerSubscription::Subscribed: return "subscribed"; + case PubSubOwnerSubscription::Unconfigured: return "unconfigured"; + } + assert(false); + return ""; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.h index 4cecca7..52089b7 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOwnerSubscription.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOwnerSubscriptionSerializer : public GenericPayloadSerializer<PubSubOwnerSubscription> { - public: - PubSubOwnerSubscriptionSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOwnerSubscriptionSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerSubscription>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubOwnerSubscriptionSerializer : public GenericPayloadSerializer<PubSubOwnerSubscription> { + public: + PubSubOwnerSubscriptionSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerSubscriptionSerializer() override; - private: - static std::string serializeSubscriptionType(PubSubOwnerSubscription::SubscriptionType); + virtual std::string serializePayload(std::shared_ptr<PubSubOwnerSubscription>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + static std::string serializeSubscriptionType(PubSubOwnerSubscription::SubscriptionType); + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.cpp index c265662..a5940f6 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.cpp @@ -1,18 +1,16 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.h> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -23,16 +21,16 @@ PubSubOwnerSubscriptionsSerializer::PubSubOwnerSubscriptionsSerializer(PayloadSe PubSubOwnerSubscriptionsSerializer::~PubSubOwnerSubscriptionsSerializer() { } -std::string PubSubOwnerSubscriptionsSerializer::serializePayload(boost::shared_ptr<PubSubOwnerSubscriptions> payload) const { - if (!payload) { - return ""; - } - XMLElement element("subscriptions", "http://jabber.org/protocol/pubsub#owner"); - element.setAttribute("node", payload->getNode()); - foreach(boost::shared_ptr<PubSubOwnerSubscription> item, payload->getSubscriptions()) { - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubOwnerSubscriptionSerializer(serializers).serialize(item))); - } - return element.serialize(); +std::string PubSubOwnerSubscriptionsSerializer::serializePayload(std::shared_ptr<PubSubOwnerSubscriptions> payload) const { + if (!payload) { + return ""; + } + XMLElement element("subscriptions", "http://jabber.org/protocol/pubsub#owner"); + element.setAttribute("node", payload->getNode()); + for (const auto& item : payload->getSubscriptions()) { + element.addNode(std::make_shared<XMLRawTextNode>(PubSubOwnerSubscriptionSerializer(serializers).serialize(item))); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.h index d77bc99..42956cf 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubOwnerSubscriptions.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubOwnerSubscriptionsSerializer : public GenericPayloadSerializer<PubSubOwnerSubscriptions> { - public: - PubSubOwnerSubscriptionsSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubOwnerSubscriptionsSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerSubscriptions>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubOwnerSubscriptionsSerializer : public GenericPayloadSerializer<PubSubOwnerSubscriptions> { + public: + PubSubOwnerSubscriptionsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerSubscriptionsSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubOwnerSubscriptions>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.cpp index 5a150e0..ce8706d 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.cpp @@ -1,18 +1,16 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -23,16 +21,16 @@ PubSubPublishSerializer::PubSubPublishSerializer(PayloadSerializerCollection* se PubSubPublishSerializer::~PubSubPublishSerializer() { } -std::string PubSubPublishSerializer::serializePayload(boost::shared_ptr<PubSubPublish> payload) const { - if (!payload) { - return ""; - } - XMLElement element("publish", "http://jabber.org/protocol/pubsub"); - element.setAttribute("node", payload->getNode()); - foreach(boost::shared_ptr<PubSubItem> item, payload->getItems()) { - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubItemSerializer(serializers).serialize(item))); - } - return element.serialize(); +std::string PubSubPublishSerializer::serializePayload(std::shared_ptr<PubSubPublish> payload) const { + if (!payload) { + return ""; + } + XMLElement element("publish", "http://jabber.org/protocol/pubsub"); + element.setAttribute("node", payload->getNode()); + for (const auto& item : payload->getItems()) { + element.addNode(std::make_shared<XMLRawTextNode>(PubSubItemSerializer(serializers).serialize(item))); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.h index 9d53141..5eeb8bf 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubPublish.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubPublishSerializer : public GenericPayloadSerializer<PubSubPublish> { - public: - PubSubPublishSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubPublishSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubPublish>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubPublishSerializer : public GenericPayloadSerializer<PubSubPublish> { + public: + PubSubPublishSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubPublishSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubPublish>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.cpp index 3f1434b..c82089a 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.cpp @@ -1,18 +1,16 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -23,17 +21,19 @@ PubSubRetractSerializer::PubSubRetractSerializer(PayloadSerializerCollection* se PubSubRetractSerializer::~PubSubRetractSerializer() { } -std::string PubSubRetractSerializer::serializePayload(boost::shared_ptr<PubSubRetract> payload) const { - if (!payload) { - return ""; - } - XMLElement element("retract", "http://jabber.org/protocol/pubsub"); - element.setAttribute("node", payload->getNode()); - foreach(boost::shared_ptr<PubSubItem> item, payload->getItems()) { - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubItemSerializer(serializers).serialize(item))); - } - element.setAttribute("notify", payload->isNotify() ? "true" : "false"); - return element.serialize(); +std::string PubSubRetractSerializer::serializePayload(std::shared_ptr<PubSubRetract> payload) const { + if (!payload) { + return ""; + } + XMLElement element("retract", "http://jabber.org/protocol/pubsub"); + element.setAttribute("node", payload->getNode()); + for (const auto& item : payload->getItems()) { + element.addNode(std::make_shared<XMLRawTextNode>(PubSubItemSerializer(serializers).serialize(item))); + } + if (payload->isNotify().is_initialized()) { + element.setAttribute("notify", payload->isNotify().get() ? "true" : "false"); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.h index 47a01af..23b6b59 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubRetract.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubRetractSerializer : public GenericPayloadSerializer<PubSubRetract> { - public: - PubSubRetractSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubRetractSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubRetract>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubRetractSerializer : public GenericPayloadSerializer<PubSubRetract> { + public: + PubSubRetractSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubRetractSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubRetract>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubSerializer.cpp index 0e61331..648c5a3 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubSerializer.cpp @@ -1,69 +1,66 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.h> -#include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h> #include <Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; PubSubSerializer::PubSubSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { - pubsubSerializers.push_back(boost::make_shared<PubSubItemsSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubCreateSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubPublishSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubOptionsSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubAffiliationsSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubRetractSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubDefaultSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubSubscriptionsSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubSubscribeSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubUnsubscribeSerializer>(serializers)); - pubsubSerializers.push_back(boost::make_shared<PubSubSubscriptionSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubItemsSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubCreateSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubPublishSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubOptionsSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubAffiliationsSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubRetractSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubDefaultSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubSubscriptionsSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubSubscribeSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubUnsubscribeSerializer>(serializers)); + pubsubSerializers.push_back(std::make_shared<PubSubSubscriptionSerializer>(serializers)); } PubSubSerializer::~PubSubSerializer() { } -std::string PubSubSerializer::serializePayload(boost::shared_ptr<PubSub> payload) const { - if (!payload) { - return ""; - } - XMLElement element("pubsub", "http://jabber.org/protocol/pubsub"); - boost::shared_ptr<PubSubPayload> p = payload->getPayload(); - foreach(boost::shared_ptr<PayloadSerializer> serializer, pubsubSerializers) { - if (serializer->canSerialize(p)) { - element.addNode(boost::make_shared<XMLRawTextNode>(serializer->serialize(p))); - if (boost::shared_ptr<PubSubCreate> create = boost::dynamic_pointer_cast<PubSubCreate>(p)) { - element.addNode(boost::make_shared<XMLRawTextNode>(boost::make_shared<PubSubConfigureSerializer>(serializers)->serialize(create->getConfigure()))); - } - if (boost::shared_ptr<PubSubSubscribe> subscribe = boost::dynamic_pointer_cast<PubSubSubscribe>(p)) { - element.addNode(boost::make_shared<XMLRawTextNode>(boost::make_shared<PubSubConfigureSerializer>(serializers)->serialize(subscribe->getOptions()))); - } - } - } - return element.serialize(); +std::string PubSubSerializer::serializePayload(std::shared_ptr<PubSub> payload) const { + if (!payload) { + return ""; + } + XMLElement element("pubsub", "http://jabber.org/protocol/pubsub"); + std::shared_ptr<PubSubPayload> p = payload->getPayload(); + for (const auto& serializer : pubsubSerializers) { + if (serializer->canSerialize(p)) { + element.addNode(std::make_shared<XMLRawTextNode>(serializer->serialize(p))); + if (std::shared_ptr<PubSubCreate> create = std::dynamic_pointer_cast<PubSubCreate>(p)) { + element.addNode(std::make_shared<XMLRawTextNode>(std::make_shared<PubSubConfigureSerializer>(serializers)->serialize(create->getConfigure()))); + } + if (std::shared_ptr<PubSubSubscribe> subscribe = std::dynamic_pointer_cast<PubSubSubscribe>(p)) { + element.addNode(std::make_shared<XMLRawTextNode>(std::make_shared<PubSubConfigureSerializer>(serializers)->serialize(subscribe->getOptions()))); + } + } + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubSerializer.h index 7665800..fb14c29 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubSerializer.h @@ -1,29 +1,29 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSub.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; + class PayloadSerializerCollection; - class SWIFTEN_API PubSubSerializer : public GenericPayloadSerializer<PubSub> { - public: - PubSubSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubSerializer(); + class SWIFTEN_API PubSubSerializer : public GenericPayloadSerializer<PubSub> { + public: + PubSubSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubSerializer() override; - virtual std::string serializePayload(boost::shared_ptr<PubSub>) const SWIFTEN_OVERRIDE; + virtual std::string serializePayload(std::shared_ptr<PubSub>) const override; - private: - std::vector< boost::shared_ptr<PayloadSerializer> > pubsubSerializers; - PayloadSerializerCollection* serializers; - }; + private: + std::vector< std::shared_ptr<PayloadSerializer> > pubsubSerializers; + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.cpp index 7a55228..39550c2 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.cpp @@ -1,33 +1,30 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <memory> + +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubSubscribeOptionsSerializer::PubSubSubscribeOptionsSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubSubscribeOptionsSerializer::PubSubSubscribeOptionsSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubSubscribeOptionsSerializer::~PubSubSubscribeOptionsSerializer() { } -std::string PubSubSubscribeOptionsSerializer::serializePayload(boost::shared_ptr<PubSubSubscribeOptions> payload) const { - if (!payload) { - return ""; - } - XMLElement element("subscribe-options", "http://jabber.org/protocol/pubsub"); - element.addNode(payload->isRequired() ? boost::make_shared<XMLElement>("required", "") : boost::shared_ptr<XMLElement>()); - return element.serialize(); +std::string PubSubSubscribeOptionsSerializer::serializePayload(std::shared_ptr<PubSubSubscribeOptions> payload) const { + if (!payload) { + return ""; + } + XMLElement element("subscribe-options", "http://jabber.org/protocol/pubsub"); + element.addNode(payload->isRequired() ? std::make_shared<XMLElement>("required", "") : std::shared_ptr<XMLElement>()); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.h index 6ffaac7..028a437 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubSubscribeOptions.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubSubscribeOptionsSerializer : public GenericPayloadSerializer<PubSubSubscribeOptions> { - public: - PubSubSubscribeOptionsSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubSubscribeOptionsSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubSubscribeOptions>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubSubscribeOptionsSerializer : public GenericPayloadSerializer<PubSubSubscribeOptions> { + public: + PubSubSubscribeOptionsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubSubscribeOptionsSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubSubscribeOptions>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.cpp index 83a73af..d7970ba 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.cpp @@ -1,36 +1,31 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubSubscribeSerializer::PubSubSubscribeSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubSubscribeSerializer::PubSubSubscribeSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubSubscribeSerializer::~PubSubSubscribeSerializer() { } -std::string PubSubSubscribeSerializer::serializePayload(boost::shared_ptr<PubSubSubscribe> payload) const { - if (!payload) { - return ""; - } - XMLElement element("subscribe", "http://jabber.org/protocol/pubsub"); - if (payload->getNode()) { - element.setAttribute("node", *payload->getNode()); - } - element.setAttribute("jid", payload->getJID()); - return element.serialize(); +std::string PubSubSubscribeSerializer::serializePayload(std::shared_ptr<PubSubSubscribe> payload) const { + if (!payload) { + return ""; + } + XMLElement element("subscribe", "http://jabber.org/protocol/pubsub"); + if (payload->getNode()) { + element.setAttribute("node", *payload->getNode()); + } + element.setAttribute("jid", payload->getJID()); + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.h index b730a4d..1c0070b 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubSubscribe.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubSubscribeSerializer : public GenericPayloadSerializer<PubSubSubscribe> { - public: - PubSubSubscribeSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubSubscribeSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubSubscribe>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubSubscribeSerializer : public GenericPayloadSerializer<PubSubSubscribe> { + public: + PubSubSubscribeSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubSubscribeSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubSubscribe>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.cpp index 8a54afa..14e5e3f 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.cpp @@ -1,17 +1,16 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> #include <Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -22,30 +21,30 @@ PubSubSubscriptionSerializer::PubSubSubscriptionSerializer(PayloadSerializerColl PubSubSubscriptionSerializer::~PubSubSubscriptionSerializer() { } -std::string PubSubSubscriptionSerializer::serializePayload(boost::shared_ptr<PubSubSubscription> payload) const { - if (!payload) { - return ""; - } - XMLElement element("subscription", "http://jabber.org/protocol/pubsub"); - if (payload->getNode()) { - element.setAttribute("node", *payload->getNode()); - } - if (payload->getSubscriptionID()) { - element.setAttribute("subid", *payload->getSubscriptionID()); - } - element.setAttribute("jid", payload->getJID()); - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubSubscribeOptionsSerializer(serializers).serialize(payload->getOptions()))); - element.setAttribute("subscription", serializeSubscriptionType(payload->getSubscription())); - return element.serialize(); +std::string PubSubSubscriptionSerializer::serializePayload(std::shared_ptr<PubSubSubscription> payload) const { + if (!payload) { + return ""; + } + XMLElement element("subscription", "http://jabber.org/protocol/pubsub"); + if (payload->getNode()) { + element.setAttribute("node", *payload->getNode()); + } + if (payload->getSubscriptionID()) { + element.setAttribute("subid", *payload->getSubscriptionID()); + } + element.setAttribute("jid", payload->getJID()); + element.addNode(std::make_shared<XMLRawTextNode>(PubSubSubscribeOptionsSerializer(serializers).serialize(payload->getOptions()))); + element.setAttribute("subscription", serializeSubscriptionType(payload->getSubscription())); + return element.serialize(); } std::string PubSubSubscriptionSerializer::serializeSubscriptionType(PubSubSubscription::SubscriptionType value) { - switch (value) { - case PubSubSubscription::None: return "none"; - case PubSubSubscription::Pending: return "pending"; - case PubSubSubscription::Subscribed: return "subscribed"; - case PubSubSubscription::Unconfigured: return "unconfigured"; - } - assert(false); - return ""; + switch (value) { + case PubSubSubscription::None: return "none"; + case PubSubSubscription::Pending: return "pending"; + case PubSubSubscription::Subscribed: return "subscribed"; + case PubSubSubscription::Unconfigured: return "unconfigured"; + } + assert(false); + return ""; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h index d03bb69..b849269 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h @@ -1,31 +1,31 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubSubscription.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; + class PayloadSerializerCollection; - class SWIFTEN_API PubSubSubscriptionSerializer : public GenericPayloadSerializer<PubSubSubscription> { - public: - PubSubSubscriptionSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubSubscriptionSerializer(); + class SWIFTEN_API PubSubSubscriptionSerializer : public GenericPayloadSerializer<PubSubSubscription> { + public: + PubSubSubscriptionSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubSubscriptionSerializer() override; - virtual std::string serializePayload(boost::shared_ptr<PubSubSubscription>) const SWIFTEN_OVERRIDE; + virtual std::string serializePayload(std::shared_ptr<PubSubSubscription>) const override; - private: - static std::string serializeSubscriptionType(PubSubSubscription::SubscriptionType); + private: + static std::string serializeSubscriptionType(PubSubSubscription::SubscriptionType); - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.cpp index 74f1123..6e01881 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.cpp @@ -1,18 +1,16 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> #include <Swiften/Serializer/PayloadSerializerCollection.h> #include <Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> using namespace Swift; @@ -23,18 +21,18 @@ PubSubSubscriptionsSerializer::PubSubSubscriptionsSerializer(PayloadSerializerCo PubSubSubscriptionsSerializer::~PubSubSubscriptionsSerializer() { } -std::string PubSubSubscriptionsSerializer::serializePayload(boost::shared_ptr<PubSubSubscriptions> payload) const { - if (!payload) { - return ""; - } - XMLElement element("subscriptions", "http://jabber.org/protocol/pubsub"); - if (payload->getNode()) { - element.setAttribute("node", *payload->getNode()); - } - foreach(boost::shared_ptr<PubSubSubscription> item, payload->getSubscriptions()) { - element.addNode(boost::make_shared<XMLRawTextNode>(PubSubSubscriptionSerializer(serializers).serialize(item))); - } - return element.serialize(); +std::string PubSubSubscriptionsSerializer::serializePayload(std::shared_ptr<PubSubSubscriptions> payload) const { + if (!payload) { + return ""; + } + XMLElement element("subscriptions", "http://jabber.org/protocol/pubsub"); + if (payload->getNode()) { + element.setAttribute("node", *payload->getNode()); + } + for (const auto& item : payload->getSubscriptions()) { + element.addNode(std::make_shared<XMLRawTextNode>(PubSubSubscriptionSerializer(serializers).serialize(item))); + } + return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.h index 2b5d8fa..1430cdf 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.h @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubSubscriptions.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubSubscriptionsSerializer : public GenericPayloadSerializer<PubSubSubscriptions> { - public: - PubSubSubscriptionsSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubSubscriptionsSerializer(); + class PayloadSerializerCollection; - virtual std::string serializePayload(boost::shared_ptr<PubSubSubscriptions>) const SWIFTEN_OVERRIDE; + class SWIFTEN_API PubSubSubscriptionsSerializer : public GenericPayloadSerializer<PubSubSubscriptions> { + public: + PubSubSubscriptionsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubSubscriptionsSerializer() override; - private: - + virtual std::string serializePayload(std::shared_ptr<PubSubSubscriptions>) const override; - private: - PayloadSerializerCollection* serializers; - }; + private: + PayloadSerializerCollection* serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.cpp index e0d6cd3..8a6d292 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.cpp @@ -1,39 +1,32 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#pragma clang diagnostic ignored "-Wunused-private-field" - #include <Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> - - -#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XML/XMLElement.h> using namespace Swift; -PubSubUnsubscribeSerializer::PubSubUnsubscribeSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +PubSubUnsubscribeSerializer::PubSubUnsubscribeSerializer(PayloadSerializerCollection* /*serializers*/) { } PubSubUnsubscribeSerializer::~PubSubUnsubscribeSerializer() { } -std::string PubSubUnsubscribeSerializer::serializePayload(boost::shared_ptr<PubSubUnsubscribe> payload) const { - if (!payload) { - return ""; - } - XMLElement element("unsubscribe", "http://jabber.org/protocol/pubsub"); - if (payload->getNode()) { - element.setAttribute("node", *payload->getNode()); - } - element.setAttribute("jid", payload->getJID()); - if (payload->getSubscriptionID()) { - element.setAttribute("subid", *payload->getSubscriptionID()); - } - return element.serialize(); +std::string PubSubUnsubscribeSerializer::serializePayload(std::shared_ptr<PubSubUnsubscribe> payload) const { + if (!payload) { + return ""; + } + XMLElement element("unsubscribe", "http://jabber.org/protocol/pubsub"); + if (payload->getNode()) { + element.setAttribute("node", *payload->getNode()); + } + element.setAttribute("jid", payload->getJID()); + if (payload->getSubscriptionID()) { + element.setAttribute("subid", *payload->getSubscriptionID()); + } + return element.serialize(); } - - diff --git a/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.h index b4f6f62..002d337 100644 --- a/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.h @@ -1,31 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/PubSubUnsubscribe.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API PubSubUnsubscribeSerializer : public GenericPayloadSerializer<PubSubUnsubscribe> { - public: - PubSubUnsubscribeSerializer(PayloadSerializerCollection* serializers); - virtual ~PubSubUnsubscribeSerializer(); - - virtual std::string serializePayload(boost::shared_ptr<PubSubUnsubscribe>) const SWIFTEN_OVERRIDE; + class PayloadSerializerCollection; - private: - + class SWIFTEN_API PubSubUnsubscribeSerializer : public GenericPayloadSerializer<PubSubUnsubscribe> { + public: + PubSubUnsubscribeSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubUnsubscribeSerializer() override; - private: - PayloadSerializerCollection* serializers; - }; + virtual std::string serializePayload(std::shared_ptr<PubSubUnsubscribe>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/RawXMLPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/RawXMLPayloadSerializer.h index 02a5564..1f07e37 100644 --- a/Swiften/Serializer/PayloadSerializers/RawXMLPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/RawXMLPayloadSerializer.h @@ -1,21 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/RawXMLPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class RawXMLPayloadSerializer : public GenericPayloadSerializer<RawXMLPayload> { - public: - RawXMLPayloadSerializer() : GenericPayloadSerializer<RawXMLPayload>() {} + class SWIFTEN_API RawXMLPayloadSerializer : public GenericPayloadSerializer<RawXMLPayload> { + public: + RawXMLPayloadSerializer() : GenericPayloadSerializer<RawXMLPayload>() {} - virtual std::string serializePayload(boost::shared_ptr<RawXMLPayload> p) const { - return p->getRawXML(); - } - }; + virtual std::string serializePayload(std::shared_ptr<RawXMLPayload> p) const { + return p->getRawXML(); + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/ReferencePayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ReferencePayloadSerializer.cpp new file mode 100644 index 0000000..128aac7 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ReferencePayloadSerializer.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/ReferencePayloadSerializer.h> + +#include <memory> + +#include <Swiften/Base/Log.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/PayloadSerializerCollection.h> + +namespace Swift { + +ReferencePayloadSerializer::ReferencePayloadSerializer(PayloadSerializerCollection* payloadSerializers) : GenericPayloadSerializer<ReferencePayload>(), payloadSerializers_(payloadSerializers) { +} + +std::string ReferencePayloadSerializer::serializePayload(ReferencePayload::ref reference) const { + XMLElement element("reference", "urn:xmpp:reference:0"); + + auto type = reference->getType(); + if (type != ReferencePayload::Type::Unknown) { + element.setAttribute("type", getTypeString(type)); + + if (auto uri = reference->getUri()) { + element.setAttribute("uri", *uri); + } + if (auto begin = reference->getBegin()) { + element.setAttribute("begin", *begin); + } + if (auto end = reference->getEnd()) { + element.setAttribute("end", *end); + } + if (auto anchor = reference->getAnchor()) { + element.setAttribute("anchor", *anchor); + } + + std::string serializedPayloads; + for (const auto& payload : reference->getPayloads()) { + if (auto serializer = payloadSerializers_->getPayloadSerializer(payload)) { + element.addNode(std::make_shared<XMLRawTextNode>(serializer->serialize(payload))); + } + else { + SWIFT_LOG(warning) << "Could not find serializer for " << typeid(*(payload.get())).name(); + } + } + } + return element.serialize(); +} + +const std::string ReferencePayloadSerializer::getTypeString(const ReferencePayload::Type type) const { + switch(type) { + case ReferencePayload::Type::Data: return "data"; + case ReferencePayload::Type::Mention: return "mention"; + case ReferencePayload::Type::PubSub: return "pubsub"; + case ReferencePayload::Type::Unknown: return "unknown"; + } + return ""; +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/ReferencePayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/ReferencePayloadSerializer.h new file mode 100644 index 0000000..2af6045 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ReferencePayloadSerializer.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ReferencePayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API ReferencePayloadSerializer : public GenericPayloadSerializer<ReferencePayload> { + public: + ReferencePayloadSerializer(PayloadSerializerCollection* payloadSerializers); + virtual std::string serializePayload(ReferencePayload::ref reference) const; + + private: + const std::string getTypeString(const ReferencePayload::Type type) const; + + PayloadSerializerCollection* payloadSerializers_; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/ReplaceSerializer.h b/Swiften/Serializer/PayloadSerializers/ReplaceSerializer.h index 85c114c..3487b16 100644 --- a/Swiften/Serializer/PayloadSerializers/ReplaceSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/ReplaceSerializer.h @@ -5,24 +5,25 @@ */ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Replace.h> #include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Elements/Replace.h> namespace Swift { - class ReplaceSerializer : public GenericPayloadSerializer<Replace> { - public: - ReplaceSerializer() : GenericPayloadSerializer<Replace>() {} + class SWIFTEN_API ReplaceSerializer : public GenericPayloadSerializer<Replace> { + public: + ReplaceSerializer() : GenericPayloadSerializer<Replace>() {} - virtual std::string serializePayload(boost::shared_ptr<Replace> replace) const { - return "<replace id = '" + replace->getID() + "' xmlns='urn:xmpp:message-correct:0'/>"; - } - }; + virtual std::string serializePayload(std::shared_ptr<Replace> replace) const { + return "<replace id = '" + replace->getID() + "' xmlns='urn:xmpp:message-correct:0'/>"; + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.cpp index c72734b..95a0084 100644 --- a/Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.cpp @@ -1,13 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> @@ -17,19 +16,19 @@ namespace Swift { ResourceBindSerializer::ResourceBindSerializer() : GenericPayloadSerializer<ResourceBind>() { } -std::string ResourceBindSerializer::serializePayload(boost::shared_ptr<ResourceBind> resourceBind) const { - XMLElement bindElement("bind", "urn:ietf:params:xml:ns:xmpp-bind"); - if (resourceBind->getJID().isValid()) { - boost::shared_ptr<XMLElement> jidNode(new XMLElement("jid")); - jidNode->addNode(boost::make_shared<XMLTextNode>(resourceBind->getJID().toString())); - bindElement.addNode(jidNode); - } - else if (!resourceBind->getResource().empty()) { - boost::shared_ptr<XMLElement> resourceNode(new XMLElement("resource")); - resourceNode->addNode(boost::make_shared<XMLTextNode>(resourceBind->getResource())); - bindElement.addNode(resourceNode); - } - return bindElement.serialize(); +std::string ResourceBindSerializer::serializePayload(std::shared_ptr<ResourceBind> resourceBind) const { + XMLElement bindElement("bind", "urn:ietf:params:xml:ns:xmpp-bind"); + if (resourceBind->getJID().isValid()) { + std::shared_ptr<XMLElement> jidNode(new XMLElement("jid")); + jidNode->addNode(std::make_shared<XMLTextNode>(resourceBind->getJID().toString())); + bindElement.addNode(jidNode); + } + else if (!resourceBind->getResource().empty()) { + std::shared_ptr<XMLElement> resourceNode(new XMLElement("resource")); + resourceNode->addNode(std::make_shared<XMLTextNode>(resourceBind->getResource())); + bindElement.addNode(resourceNode); + } + return bindElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.h b/Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.h index fcc8563..bea3ff1 100644 --- a/Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/ResourceBind.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API ResourceBindSerializer : public GenericPayloadSerializer<ResourceBind> { - public: - ResourceBindSerializer(); + class SWIFTEN_API ResourceBindSerializer : public GenericPayloadSerializer<ResourceBind> { + public: + ResourceBindSerializer(); - virtual std::string serializePayload(boost::shared_ptr<ResourceBind>) const; - }; + virtual std::string serializePayload(std::shared_ptr<ResourceBind>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/ResultSetSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ResultSetSerializer.cpp new file mode 100644 index 0000000..3d13ce3 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ResultSetSerializer.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h> + +#include <memory> + +#include <boost/lexical_cast.hpp> + +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +ResultSetSerializer::ResultSetSerializer() { +} + +ResultSetSerializer::~ResultSetSerializer() { +} + +std::string ResultSetSerializer::serializePayload(std::shared_ptr<ResultSet> payload) const { + if (!payload) { + return ""; + } + + XMLElement element("set", "http://jabber.org/protocol/rsm"); + + if (payload->getMaxItems()) { + element.addNode(std::make_shared<XMLElement>("max", "", std::to_string(*payload->getMaxItems()))); + } + + if (payload->getCount()) { + element.addNode(std::make_shared<XMLElement>("count", "", std::to_string(*payload->getCount()))); + } + + if (payload->getIndex()) { + element.addNode(std::make_shared<XMLElement>("index", "", std::to_string(*payload->getIndex()))); + } + + if (payload->getFirstID()) { + std::shared_ptr<XMLElement> firstElement = std::make_shared<XMLElement>("first", "", *payload->getFirstID()); + if (payload->getFirstIDIndex()) { + firstElement->setAttribute("index", std::to_string(*payload->getFirstIDIndex())); + } + element.addNode(firstElement); + } + + if (payload->getLastID()) { + element.addNode(std::make_shared<XMLElement>("last", "", *payload->getLastID())); + } + + if (payload->getBefore()) { + element.addNode(std::make_shared<XMLElement>("before", "", *payload->getBefore())); + } + + if (payload->getAfter()) { + element.addNode(std::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..6f850eb --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/ResultSet.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class SWIFTEN_API ResultSetSerializer : public GenericPayloadSerializer<ResultSet> { + public: + ResultSetSerializer(); + virtual ~ResultSetSerializer() override; + + virtual std::string serializePayload(std::shared_ptr<ResultSet>) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp index 39eaf7d..c7fdc5b 100644 --- a/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp @@ -4,44 +4,48 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Serializer/XML/XMLRawTextNode.h> #include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/XML/XMLTextNode.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.getJID()); - itemElement->setAttribute("name", item.getName()); - - switch (item.getAction()) { - case RosterItemExchangePayload::Item::Add: itemElement->setAttribute("action", "add"); break; - case RosterItemExchangePayload::Item::Modify: itemElement->setAttribute("action", "modify"); break; - case RosterItemExchangePayload::Item::Delete: itemElement->setAttribute("action", "delete"); break; - } - - foreach(const std::string& group, item.getGroups()) { - boost::shared_ptr<XMLElement> groupElement(new XMLElement("group")); - groupElement->addNode(boost::make_shared<XMLTextNode>(group)); - itemElement->addNode(groupElement); - } - - queryElement.addNode(itemElement); - } - - return queryElement.serialize(); +std::string RosterItemExchangeSerializer::serializePayload(std::shared_ptr<RosterItemExchangePayload> roster) const { + XMLElement queryElement("x", "http://jabber.org/protocol/rosterx"); + for (const auto& item : roster->getItems()) { + std::shared_ptr<XMLElement> itemElement(new XMLElement("item")); + itemElement->setAttribute("jid", item.getJID()); + itemElement->setAttribute("name", item.getName()); + + switch (item.getAction()) { + case RosterItemExchangePayload::Item::Add: itemElement->setAttribute("action", "add"); break; + case RosterItemExchangePayload::Item::Modify: itemElement->setAttribute("action", "modify"); break; + case RosterItemExchangePayload::Item::Delete: itemElement->setAttribute("action", "delete"); break; + } + + for (const auto& group : item.getGroups()) { + std::shared_ptr<XMLElement> groupElement(new XMLElement("group")); + groupElement->addNode(std::make_shared<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 index 71a5b5d..6212998 100644 --- a/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h @@ -4,17 +4,23 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/RosterItemExchangePayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API RosterItemExchangeSerializer : public GenericPayloadSerializer<RosterItemExchangePayload> { - public: - RosterItemExchangeSerializer(); + class SWIFTEN_API RosterItemExchangeSerializer : public GenericPayloadSerializer<RosterItemExchangePayload> { + public: + RosterItemExchangeSerializer(); - virtual std::string serializePayload(boost::shared_ptr<RosterItemExchangePayload>) const; - }; + virtual std::string serializePayload(std::shared_ptr<RosterItemExchangePayload>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp b/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp index d2d143d..e706542 100644 --- a/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/RosterSerializer.cpp @@ -1,61 +1,59 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/RosterSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Serializer/XML/XMLRawTextNode.h> #include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> namespace Swift { RosterSerializer::RosterSerializer() : GenericPayloadSerializer<RosterPayload>() { } -std::string RosterSerializer::serializePayload(boost::shared_ptr<RosterPayload> roster) const { - XMLElement queryElement("query", "jabber:iq:roster"); - if (roster->getVersion()) { - queryElement.setAttribute("ver", *roster->getVersion()); - } - foreach(const RosterItemPayload& item, roster->getItems()) { - boost::shared_ptr<XMLElement> itemElement(new XMLElement("item")); - itemElement->setAttribute("jid", item.getJID()); - itemElement->setAttribute("name", item.getName()); - - switch (item.getSubscription()) { - case RosterItemPayload::To: itemElement->setAttribute("subscription", "to"); break; - case RosterItemPayload::From: itemElement->setAttribute("subscription", "from"); break; - case RosterItemPayload::Both: itemElement->setAttribute("subscription", "both"); break; - case RosterItemPayload::Remove: itemElement->setAttribute("subscription", "remove"); break; - case RosterItemPayload::None: itemElement->setAttribute("subscription", "none"); break; - } - - if (item.getSubscriptionRequested()) { - itemElement->setAttribute("ask", "subscribe"); - } - - foreach(const std::string& group, item.getGroups()) { - boost::shared_ptr<XMLElement> groupElement(new XMLElement("group")); - groupElement->addNode(boost::make_shared<XMLTextNode>(group)); - itemElement->addNode(groupElement); - } - - if (!item.getUnknownContent().empty()) { - itemElement->addNode(boost::make_shared<XMLRawTextNode>(item.getUnknownContent())); - } - - - queryElement.addNode(itemElement); - } - - return queryElement.serialize(); +std::string RosterSerializer::serializePayload(std::shared_ptr<RosterPayload> roster) const { + XMLElement queryElement("query", "jabber:iq:roster"); + if (roster->getVersion()) { + queryElement.setAttribute("ver", *roster->getVersion()); + } + for (const auto& item : roster->getItems()) { + std::shared_ptr<XMLElement> itemElement(new XMLElement("item")); + itemElement->setAttribute("jid", item.getJID()); + itemElement->setAttribute("name", item.getName()); + + switch (item.getSubscription()) { + case RosterItemPayload::To: itemElement->setAttribute("subscription", "to"); break; + case RosterItemPayload::From: itemElement->setAttribute("subscription", "from"); break; + case RosterItemPayload::Both: itemElement->setAttribute("subscription", "both"); break; + case RosterItemPayload::Remove: itemElement->setAttribute("subscription", "remove"); break; + case RosterItemPayload::None: itemElement->setAttribute("subscription", "none"); break; + } + + if (item.getSubscriptionRequested()) { + itemElement->setAttribute("ask", "subscribe"); + } + + for (const auto& group : item.getGroups()) { + std::shared_ptr<XMLElement> groupElement(new XMLElement("group")); + groupElement->addNode(std::make_shared<XMLTextNode>(group)); + itemElement->addNode(groupElement); + } + + if (!item.getUnknownContent().empty()) { + itemElement->addNode(std::make_shared<XMLRawTextNode>(item.getUnknownContent())); + } + + + queryElement.addNode(itemElement); + } + + return queryElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/RosterSerializer.h b/Swiften/Serializer/PayloadSerializers/RosterSerializer.h index 9e7ea1b..834f723 100644 --- a/Swiften/Serializer/PayloadSerializers/RosterSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/RosterSerializer.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/RosterPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API RosterSerializer : public GenericPayloadSerializer<RosterPayload> { - public: - RosterSerializer(); + class SWIFTEN_API RosterSerializer : public GenericPayloadSerializer<RosterPayload> { + public: + RosterSerializer(); - virtual std::string serializePayload(boost::shared_ptr<RosterPayload>) const; - }; + virtual std::string serializePayload(std::shared_ptr<RosterPayload>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/S5BProxyRequestSerializer.h b/Swiften/Serializer/PayloadSerializers/S5BProxyRequestSerializer.h index b523588..e992f72 100644 --- a/Swiften/Serializer/PayloadSerializers/S5BProxyRequestSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/S5BProxyRequestSerializer.h @@ -4,35 +4,40 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ #pragma once +#include <memory> + #include <boost/lexical_cast.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/S5BProxyRequest.h> #include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class PayloadSerializerCollection; - - class S5BProxyRequestSerializer : public GenericPayloadSerializer<S5BProxyRequest> { - public: - virtual std::string serializePayload(boost::shared_ptr<S5BProxyRequest> s5bProxyRequest) const { - XMLElement queryElement("query", "http://jabber.org/protocol/bytestreams"); - if (s5bProxyRequest && s5bProxyRequest->getStreamHost()) { - boost::shared_ptr<XMLElement> streamHost = boost::make_shared<XMLElement>("streamhost"); - streamHost->setAttribute("host", s5bProxyRequest->getStreamHost().get().addressPort.getAddress().toString()); - streamHost->setAttribute("port", boost::lexical_cast<std::string>(s5bProxyRequest->getStreamHost().get().addressPort.getPort())); - streamHost->setAttribute("jid", s5bProxyRequest->getStreamHost().get().jid.toString()); - queryElement.addNode(streamHost); - } else if (s5bProxyRequest && s5bProxyRequest->getActivate()) { - queryElement.setAttribute("sid", s5bProxyRequest->getSID()); - boost::shared_ptr<XMLElement> activate = boost::make_shared<XMLElement>("activate", "", s5bProxyRequest->getActivate().get().toString()); - queryElement.addNode(activate); - } - return queryElement.serialize(); - } - }; + class SWIFTEN_API S5BProxyRequestSerializer : public GenericPayloadSerializer<S5BProxyRequest> { + public: + virtual std::string serializePayload(std::shared_ptr<S5BProxyRequest> s5bProxyRequest) const { + XMLElement queryElement("query", "http://jabber.org/protocol/bytestreams"); + if (s5bProxyRequest && s5bProxyRequest->getStreamHost()) { + std::shared_ptr<XMLElement> streamHost = std::make_shared<XMLElement>("streamhost"); + streamHost->setAttribute("host", s5bProxyRequest->getStreamHost().get().host); + streamHost->setAttribute("port", std::to_string(s5bProxyRequest->getStreamHost().get().port)); + streamHost->setAttribute("jid", s5bProxyRequest->getStreamHost().get().jid.toString()); + queryElement.addNode(streamHost); + } else if (s5bProxyRequest && s5bProxyRequest->getActivate()) { + queryElement.setAttribute("sid", s5bProxyRequest->getSID()); + std::shared_ptr<XMLElement> activate = std::make_shared<XMLElement>("activate", "", s5bProxyRequest->getActivate().get().toString()); + queryElement.addNode(activate); + } + return queryElement.serialize(); + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.cpp index 07dd8de..befd76d 100644 --- a/Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.cpp @@ -1,63 +1,61 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> namespace Swift { SearchPayloadSerializer::SearchPayloadSerializer() { } -std::string SearchPayloadSerializer::serializePayload(boost::shared_ptr<SearchPayload> searchPayload) const { - XMLElement searchElement("query", "jabber:iq:search"); +std::string SearchPayloadSerializer::serializePayload(std::shared_ptr<SearchPayload> searchPayload) const { + XMLElement searchElement("query", "jabber:iq:search"); - if (searchPayload->getInstructions()) { - searchElement.addNode(XMLElement::ref(new XMLElement("instructions", "", *searchPayload->getInstructions()))); - } + if (searchPayload->getInstructions()) { + searchElement.addNode(XMLElement::ref(new XMLElement("instructions", "", *searchPayload->getInstructions()))); + } - if (searchPayload->getNick()) { - searchElement.addNode(XMLElement::ref(new XMLElement("nick", "", *searchPayload->getNick()))); - } + if (searchPayload->getNick()) { + searchElement.addNode(XMLElement::ref(new XMLElement("nick", "", *searchPayload->getNick()))); + } - if (searchPayload->getFirst()) { - searchElement.addNode(XMLElement::ref(new XMLElement("first", "", *searchPayload->getFirst()))); - } + if (searchPayload->getFirst()) { + searchElement.addNode(XMLElement::ref(new XMLElement("first", "", *searchPayload->getFirst()))); + } - if (searchPayload->getLast()) { - searchElement.addNode(XMLElement::ref(new XMLElement("last", "", *searchPayload->getLast()))); - } + if (searchPayload->getLast()) { + searchElement.addNode(XMLElement::ref(new XMLElement("last", "", *searchPayload->getLast()))); + } - if (searchPayload->getEMail()) { - searchElement.addNode(XMLElement::ref(new XMLElement("email", "", *searchPayload->getEMail()))); - } + if (searchPayload->getEMail()) { + searchElement.addNode(XMLElement::ref(new XMLElement("email", "", *searchPayload->getEMail()))); + } - foreach(const SearchPayload::Item& item, searchPayload->getItems()) { - XMLElement::ref itemElement(new XMLElement("item")); - itemElement->setAttribute("jid", item.jid); - itemElement->addNode(XMLElement::ref(new XMLElement("first", "", item.first))); - itemElement->addNode(XMLElement::ref(new XMLElement("last", "", item.last))); - itemElement->addNode(XMLElement::ref(new XMLElement("nick", "", item.nick))); - itemElement->addNode(XMLElement::ref(new XMLElement("email", "", item.email))); + for (const auto& item : searchPayload->getItems()) { + XMLElement::ref itemElement(new XMLElement("item")); + itemElement->setAttribute("jid", item.jid); + itemElement->addNode(XMLElement::ref(new XMLElement("first", "", item.first))); + itemElement->addNode(XMLElement::ref(new XMLElement("last", "", item.last))); + itemElement->addNode(XMLElement::ref(new XMLElement("nick", "", item.nick))); + itemElement->addNode(XMLElement::ref(new XMLElement("email", "", item.email))); - searchElement.addNode(itemElement); - } + searchElement.addNode(itemElement); + } - if (Form::ref form = searchPayload->getForm()) { - searchElement.addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); - } + if (Form::ref form = searchPayload->getForm()) { + searchElement.addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); + } - return searchElement.serialize(); + return searchElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.h index 2d8e44b..21c6921 100644 --- a/Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.h @@ -1,23 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/SearchPayload.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API SearchPayloadSerializer : public GenericPayloadSerializer<SearchPayload> { - public: - SearchPayloadSerializer(); + class SWIFTEN_API SearchPayloadSerializer : public GenericPayloadSerializer<SearchPayload> { + public: + SearchPayloadSerializer(); - virtual std::string serializePayload(boost::shared_ptr<SearchPayload>) const; - }; + virtual std::string serializePayload(std::shared_ptr<SearchPayload>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.cpp b/Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.cpp index 7a0b513..b8faf73 100644 --- a/Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.cpp @@ -1,46 +1,46 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.h> -#include <Swiften/Base/foreach.h> + +#include <memory> + +#include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> #include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { SecurityLabelSerializer::SecurityLabelSerializer() : GenericPayloadSerializer<SecurityLabel>() { } -std::string SecurityLabelSerializer::serializePayload(boost::shared_ptr<SecurityLabel> label) const { - XMLElement element("securitylabel", "urn:xmpp:sec-label:0"); - if (!label->getDisplayMarking().empty()) { - boost::shared_ptr<XMLElement> displayMarking(new XMLElement("displaymarking")); - if (!label->getForegroundColor().empty()) { - displayMarking->setAttribute("fgcolor", label->getForegroundColor()); - } - if (!label->getBackgroundColor().empty()) { - displayMarking->setAttribute("bgcolor", label->getBackgroundColor()); - } - displayMarking->addNode(boost::make_shared<XMLTextNode>(label->getDisplayMarking())); - element.addNode(displayMarking); - } - - boost::shared_ptr<XMLElement> labelElement(new XMLElement("label")); - labelElement->addNode(boost::make_shared<XMLRawTextNode>(label->getLabel())); - element.addNode(labelElement); - - foreach(const std::string& equivalentLabel, label->getEquivalentLabels()) { - boost::shared_ptr<XMLElement> equivalentLabelElement(new XMLElement("equivalentlabel")); - equivalentLabelElement->addNode(boost::make_shared<XMLRawTextNode>(equivalentLabel)); - element.addNode(equivalentLabelElement); - } - return element.serialize(); +std::string SecurityLabelSerializer::serializePayload(std::shared_ptr<SecurityLabel> label) const { + XMLElement element("securitylabel", "urn:xmpp:sec-label:0"); + if (!label->getDisplayMarking().empty()) { + std::shared_ptr<XMLElement> displayMarking(new XMLElement("displaymarking")); + if (!label->getForegroundColor().empty()) { + displayMarking->setAttribute("fgcolor", label->getForegroundColor()); + } + if (!label->getBackgroundColor().empty()) { + displayMarking->setAttribute("bgcolor", label->getBackgroundColor()); + } + displayMarking->addNode(std::make_shared<XMLTextNode>(label->getDisplayMarking())); + element.addNode(displayMarking); + } + + std::shared_ptr<XMLElement> labelElement(new XMLElement("label")); + labelElement->addNode(std::make_shared<XMLRawTextNode>(label->getLabel())); + element.addNode(labelElement); + + for (const auto& equivalentLabel : label->getEquivalentLabels()) { + std::shared_ptr<XMLElement> equivalentLabelElement(new XMLElement("equivalentlabel")); + equivalentLabelElement->addNode(std::make_shared<XMLRawTextNode>(equivalentLabel)); + element.addNode(equivalentLabelElement); + } + return element.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.h b/Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.h index 4606546..b1eaaed 100644 --- a/Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/SecurityLabel.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API SecurityLabelSerializer : public GenericPayloadSerializer<SecurityLabel> { - public: - SecurityLabelSerializer(); + class SWIFTEN_API SecurityLabelSerializer : public GenericPayloadSerializer<SecurityLabel> { + public: + SecurityLabelSerializer(); - virtual std::string serializePayload(boost::shared_ptr<SecurityLabel> version) const; - }; + virtual std::string serializePayload(std::shared_ptr<SecurityLabel> version) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.cpp b/Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.cpp index 8871eff..36401a6 100644 --- a/Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.cpp @@ -1,46 +1,46 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.h> -#include <Swiften/Base/foreach.h> + +#include <memory> + +#include <Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.h> namespace Swift { SecurityLabelsCatalogSerializer::SecurityLabelsCatalogSerializer() : GenericPayloadSerializer<SecurityLabelsCatalog>() { } -std::string SecurityLabelsCatalogSerializer::serializePayload(boost::shared_ptr<SecurityLabelsCatalog> catalog) const { - XMLElement element("catalog", "urn:xmpp:sec-label:catalog:2"); - if (!catalog->getName().empty()) { - element.setAttribute("name", catalog->getName()); - } - if (catalog->getTo().isValid()) { - element.setAttribute("to", catalog->getTo()); - } - if (!catalog->getDescription().empty()) { - element.setAttribute("desc", catalog->getDescription()); - } - foreach (const SecurityLabelsCatalog::Item& item, catalog->getItems()) { - boost::shared_ptr<XMLElement> itemElement(new XMLElement("item")); - itemElement->setAttribute("selector", item.getSelector()); - if (item.getIsDefault()) { - itemElement->setAttribute("default", "true"); - } - if (item.getLabel()) { - std::string serializedLabel = SecurityLabelSerializer().serialize(item.getLabel()); - itemElement->addNode(boost::make_shared<XMLRawTextNode>(serializedLabel)); - } - element.addNode(itemElement); - } - return element.serialize(); +std::string SecurityLabelsCatalogSerializer::serializePayload(std::shared_ptr<SecurityLabelsCatalog> catalog) const { + XMLElement element("catalog", "urn:xmpp:sec-label:catalog:2"); + if (!catalog->getName().empty()) { + element.setAttribute("name", catalog->getName()); + } + if (catalog->getTo().isValid()) { + element.setAttribute("to", catalog->getTo()); + } + if (!catalog->getDescription().empty()) { + element.setAttribute("desc", catalog->getDescription()); + } + for (const auto& item : catalog->getItems()) { + std::shared_ptr<XMLElement> itemElement(new XMLElement("item")); + itemElement->setAttribute("selector", item.getSelector()); + if (item.getIsDefault()) { + itemElement->setAttribute("default", "true"); + } + if (item.getLabel()) { + std::string serializedLabel = SecurityLabelSerializer().serialize(item.getLabel()); + itemElement->addNode(std::make_shared<XMLRawTextNode>(serializedLabel)); + } + element.addNode(itemElement); + } + return element.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.h b/Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.h index 02d7c71..c3efc1e 100644 --- a/Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/SecurityLabelsCatalog.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API SecurityLabelsCatalogSerializer : public GenericPayloadSerializer<SecurityLabelsCatalog> { - public: - SecurityLabelsCatalogSerializer(); + class SWIFTEN_API SecurityLabelsCatalogSerializer : public GenericPayloadSerializer<SecurityLabelsCatalog> { + public: + SecurityLabelsCatalogSerializer(); - virtual std::string serializePayload(boost::shared_ptr<SecurityLabelsCatalog> version) const; - }; + virtual std::string serializePayload(std::shared_ptr<SecurityLabelsCatalog> version) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.cpp index e117167..2245030 100644 --- a/Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.h> @@ -11,19 +11,19 @@ namespace Swift { SoftwareVersionSerializer::SoftwareVersionSerializer() : GenericPayloadSerializer<SoftwareVersion>() { } -std::string SoftwareVersionSerializer::serializePayload(boost::shared_ptr<SoftwareVersion> version) const { - std::string result("<query xmlns=\"jabber:iq:version\">"); - if (!version->getName().empty()) { - result += "<name>" + version->getName() + "</name>"; - } - if (!version->getVersion().empty()) { - result += "<version>" + version->getVersion() + "</version>"; - } - if (!version->getOS().empty()) { - result += "<os>" + version->getOS() + "</os>"; - } - result += "</query>"; - return result; +std::string SoftwareVersionSerializer::serializePayload(std::shared_ptr<SoftwareVersion> version) const { + std::string result("<query xmlns=\"jabber:iq:version\">"); + if (!version->getName().empty()) { + result += "<name>" + version->getName() + "</name>"; + } + if (!version->getVersion().empty()) { + result += "<version>" + version->getVersion() + "</version>"; + } + if (!version->getOS().empty()) { + result += "<os>" + version->getOS() + "</os>"; + } + result += "</query>"; + return result; } } diff --git a/Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.h b/Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.h index 333059d..7f0875b 100644 --- a/Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/SoftwareVersion.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API SoftwareVersionSerializer : public GenericPayloadSerializer<SoftwareVersion> { - public: - SoftwareVersionSerializer(); + class SWIFTEN_API SoftwareVersionSerializer : public GenericPayloadSerializer<SoftwareVersion> { + public: + SoftwareVersionSerializer(); - virtual std::string serializePayload(boost::shared_ptr<SoftwareVersion> version) const; - }; + virtual std::string serializePayload(std::shared_ptr<SoftwareVersion> version) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/StartSessionSerializer.h b/Swiften/Serializer/PayloadSerializers/StartSessionSerializer.h index 2082f4b..12e6994 100644 --- a/Swiften/Serializer/PayloadSerializers/StartSessionSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/StartSessionSerializer.h @@ -1,23 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/lexical_cast.hpp> -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StartSession.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class StartSessionSerializer : public GenericPayloadSerializer<StartSession> { - public: - StartSessionSerializer() : GenericPayloadSerializer<StartSession>() {} + class SWIFTEN_API StartSessionSerializer : public GenericPayloadSerializer<StartSession> { + public: + StartSessionSerializer() : GenericPayloadSerializer<StartSession>() {} - virtual std::string serializePayload(boost::shared_ptr<StartSession>) const { - return XMLElement("session", "urn:ietf:params:xml:ns:xmpp-session").serialize(); - } - }; + virtual std::string serializePayload(std::shared_ptr<StartSession>) const { + return XMLElement("session", "urn:ietf:params:xml:ns:xmpp-session").serialize(); + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/StatusSerializer.h b/Swiften/Serializer/PayloadSerializers/StatusSerializer.h index bd076ae..0e81a26 100644 --- a/Swiften/Serializer/PayloadSerializers/StatusSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/StatusSerializer.h @@ -1,27 +1,28 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Status.h> #include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Elements/Status.h> namespace Swift { - class StatusSerializer : public GenericPayloadSerializer<Status> { - public: - StatusSerializer() : GenericPayloadSerializer<Status>() {} + class SWIFTEN_API StatusSerializer : public GenericPayloadSerializer<Status> { + public: + StatusSerializer() : GenericPayloadSerializer<Status>() {} - virtual std::string serializePayload(boost::shared_ptr<Status> status) const { - XMLElement element("status"); - element.addNode(boost::make_shared<XMLTextNode>(status->getText())); - return element.serialize(); - } - }; + virtual std::string serializePayload(std::shared_ptr<Status> status) const { + XMLElement element("status"); + element.addNode(std::make_shared<XMLTextNode>(status->getText())); + return element.serialize(); + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/StatusShowSerializer.h b/Swiften/Serializer/PayloadSerializers/StatusShowSerializer.h index e65c1b6..155b645 100644 --- a/Swiften/Serializer/PayloadSerializers/StatusShowSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/StatusShowSerializer.h @@ -1,36 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StatusShow.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class StatusShowSerializer : public GenericPayloadSerializer<StatusShow> { - public: - StatusShowSerializer() : GenericPayloadSerializer<StatusShow>() {} + class SWIFTEN_API StatusShowSerializer : public GenericPayloadSerializer<StatusShow> { + public: + StatusShowSerializer() : GenericPayloadSerializer<StatusShow>() {} - virtual std::string serializePayload(boost::shared_ptr<StatusShow> statusShow) const { - if (statusShow->getType () == StatusShow::Online || statusShow->getType() == StatusShow::None) { - return ""; - } - else { - std::string result("<show>"); - switch (statusShow->getType()) { - case StatusShow::Away: result += "away"; break; - case StatusShow::XA: result += "xa"; break; - case StatusShow::FFC: result += "chat"; break; - case StatusShow::DND: result += "dnd"; break; - case StatusShow::Online: assert(false); break; - case StatusShow::None: assert(false); break; - } - result += "</show>"; - return result; - } - } - }; + virtual std::string serializePayload(std::shared_ptr<StatusShow> statusShow) const { + if (statusShow->getType () == StatusShow::Online || statusShow->getType() == StatusShow::None) { + return ""; + } + else { + std::string result("<show>"); + switch (statusShow->getType()) { + case StatusShow::Away: result += "away"; break; + case StatusShow::XA: result += "xa"; break; + case StatusShow::FFC: result += "chat"; break; + case StatusShow::DND: result += "dnd"; break; + case StatusShow::Online: assert(false); break; + case StatusShow::None: assert(false); break; + } + result += "</show>"; + return result; + } + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/StorageSerializer.cpp b/Swiften/Serializer/PayloadSerializers/StorageSerializer.cpp index 296d5dd..ffebcf4 100644 --- a/Swiften/Serializer/PayloadSerializers/StorageSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/StorageSerializer.cpp @@ -1,15 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/StorageSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> @@ -18,35 +16,35 @@ namespace Swift { StorageSerializer::StorageSerializer() : GenericPayloadSerializer<Storage>() { } -std::string StorageSerializer::serializePayload(boost::shared_ptr<Storage> storage) const { - XMLElement storageElement("storage", "storage:bookmarks"); - - foreach(const Storage::Room& room, storage->getRooms()) { - boost::shared_ptr<XMLElement> conferenceElement(new XMLElement("conference")); - conferenceElement->setAttribute("name", room.name); - conferenceElement->setAttribute("jid", room.jid); - conferenceElement->setAttribute("autojoin", room.autoJoin ? "1" : "0"); - if (!room.nick.empty()) { - boost::shared_ptr<XMLElement> nickElement(new XMLElement("nick")); - nickElement->addNode(boost::make_shared<XMLTextNode>(room.nick)); - conferenceElement->addNode(nickElement); - } - if (room.password) { - boost::shared_ptr<XMLElement> passwordElement(new XMLElement("password")); - passwordElement->addNode(boost::make_shared<XMLTextNode>(*room.password)); - conferenceElement->addNode(passwordElement); - } - storageElement.addNode(conferenceElement); - } - - foreach(const Storage::URL& url, storage->getURLs()) { - boost::shared_ptr<XMLElement> urlElement(new XMLElement("url")); - urlElement->setAttribute("name", url.name); - urlElement->setAttribute("url", url.url); - storageElement.addNode(urlElement); - } - - return storageElement.serialize(); +std::string StorageSerializer::serializePayload(std::shared_ptr<Storage> storage) const { + XMLElement storageElement("storage", "storage:bookmarks"); + + for (const auto& room : storage->getRooms()) { + std::shared_ptr<XMLElement> conferenceElement(new XMLElement("conference")); + conferenceElement->setAttribute("name", room.name); + conferenceElement->setAttribute("jid", room.jid); + conferenceElement->setAttribute("autojoin", room.autoJoin ? "1" : "0"); + if (!room.nick.empty()) { + std::shared_ptr<XMLElement> nickElement(new XMLElement("nick")); + nickElement->addNode(std::make_shared<XMLTextNode>(room.nick)); + conferenceElement->addNode(nickElement); + } + if (room.password) { + std::shared_ptr<XMLElement> passwordElement(new XMLElement("password")); + passwordElement->addNode(std::make_shared<XMLTextNode>(*room.password)); + conferenceElement->addNode(passwordElement); + } + storageElement.addNode(conferenceElement); + } + + for (const auto& url : storage->getURLs()) { + std::shared_ptr<XMLElement> urlElement(new XMLElement("url")); + urlElement->setAttribute("name", url.name); + urlElement->setAttribute("url", url.url); + storageElement.addNode(urlElement); + } + + return storageElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/StorageSerializer.h b/Swiften/Serializer/PayloadSerializers/StorageSerializer.h index 6f4f03b..9f88fa1 100644 --- a/Swiften/Serializer/PayloadSerializers/StorageSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/StorageSerializer.h @@ -1,19 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/Storage.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class StorageSerializer : public GenericPayloadSerializer<Storage> { - public: - StorageSerializer(); + class SWIFTEN_API StorageSerializer : public GenericPayloadSerializer<Storage> { + public: + StorageSerializer(); - virtual std::string serializePayload(boost::shared_ptr<Storage>) const; - }; + virtual std::string serializePayload(std::shared_ptr<Storage>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.cpp b/Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.cpp index 7b0cad8..718e550 100644 --- a/Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.cpp @@ -4,53 +4,56 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/lexical_cast.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/Base/DateTime.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> #include <Swiften/Serializer/XML/XMLTextNode.h> - - namespace Swift { StreamInitiationFileInfoSerializer::StreamInitiationFileInfoSerializer() { } - -std::string StreamInitiationFileInfoSerializer::serializePayload(boost::shared_ptr<StreamInitiationFileInfo> fileInfo) const { - XMLElement fileElement("file", "http://jabber.org/protocol/si/profile/file-transfer"); - - if (fileInfo->getDate() != stringToDateTime("")) { - fileElement.setAttribute("date", dateTimeToString(fileInfo->getDate())); - } - fileElement.setAttribute("hash", fileInfo->getHash()); - if (fileInfo->getAlgo() != "md5") { - fileElement.setAttribute("algo", fileInfo->getAlgo()); - } - if (!fileInfo->getName().empty()) { - fileElement.setAttribute("name", fileInfo->getName()); - } - if (fileInfo->getSize() != 0) { - fileElement.setAttribute("size", boost::lexical_cast<std::string>(fileInfo->getSize())); - } - if (!fileInfo->getDescription().empty()) { - boost::shared_ptr<XMLElement> desc = boost::make_shared<XMLElement>("desc", "", fileInfo->getDescription()); - fileElement.addNode(desc); - } - if (fileInfo->getSupportsRangeRequests()) { - boost::shared_ptr<XMLElement> range = boost::make_shared<XMLElement>("range"); - if (fileInfo->getRangeOffset() != 0) { - range->setAttribute("offset", boost::lexical_cast<std::string>(fileInfo->getRangeOffset())); - } - fileElement.addNode(range); - } - return fileElement.serialize(); + +std::string StreamInitiationFileInfoSerializer::serializePayload(std::shared_ptr<StreamInitiationFileInfo> fileInfo) const { + XMLElement fileElement("file", "http://jabber.org/protocol/si/profile/file-transfer"); + + if (fileInfo->getDate() != stringToDateTime("")) { + fileElement.setAttribute("date", dateTimeToString(fileInfo->getDate())); + } + fileElement.setAttribute("hash", fileInfo->getHash()); + if (fileInfo->getAlgo() != "md5") { + fileElement.setAttribute("algo", fileInfo->getAlgo()); + } + if (!fileInfo->getName().empty()) { + fileElement.setAttribute("name", fileInfo->getName()); + } + if (fileInfo->getSize() != 0) { + fileElement.setAttribute("size", std::to_string(fileInfo->getSize())); + } + if (!fileInfo->getDescription().empty()) { + std::shared_ptr<XMLElement> desc = std::make_shared<XMLElement>("desc", "", fileInfo->getDescription()); + fileElement.addNode(desc); + } + if (fileInfo->getSupportsRangeRequests()) { + std::shared_ptr<XMLElement> range = std::make_shared<XMLElement>("range"); + if (fileInfo->getRangeOffset() != 0) { + range->setAttribute("offset", std::to_string(fileInfo->getRangeOffset())); + } + fileElement.addNode(range); + } + return fileElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h b/Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h index 1f1e9d7..b352f7f 100644 --- a/Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h @@ -4,22 +4,25 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/StreamInitiationFileInfo.h> - +#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class PayloadSerializerCollection; - - class SWIFTEN_API StreamInitiationFileInfoSerializer : public GenericPayloadSerializer<StreamInitiationFileInfo> { - public: - StreamInitiationFileInfoSerializer(); + class SWIFTEN_API StreamInitiationFileInfoSerializer : public GenericPayloadSerializer<StreamInitiationFileInfo> { + public: + StreamInitiationFileInfoSerializer(); - virtual std::string serializePayload(boost::shared_ptr<StreamInitiationFileInfo>) const; - }; + virtual std::string serializePayload(std::shared_ptr<StreamInitiationFileInfo>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp index 973ced9..813edb4 100644 --- a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp @@ -1,16 +1,15 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <memory> #include <boost/lexical_cast.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> @@ -25,51 +24,51 @@ namespace Swift { StreamInitiationSerializer::StreamInitiationSerializer() { } -std::string StreamInitiationSerializer::serializePayload(boost::shared_ptr<StreamInitiation> streamInitiation) const { - assert(streamInitiation->getIsFileTransfer()); +std::string StreamInitiationSerializer::serializePayload(std::shared_ptr<StreamInitiation> streamInitiation) const { + assert(streamInitiation->getIsFileTransfer()); - XMLElement siElement("si", "http://jabber.org/protocol/si"); - if (!streamInitiation->getID().empty()) { - siElement.setAttribute("id", streamInitiation->getID()); - } - siElement.setAttribute("profile", FILE_TRANSFER_NS); + XMLElement siElement("si", "http://jabber.org/protocol/si"); + if (!streamInitiation->getID().empty()) { + siElement.setAttribute("id", streamInitiation->getID()); + } + siElement.setAttribute("profile", FILE_TRANSFER_NS); - if (streamInitiation->getFileInfo()) { - StreamInitiationFileInfo file = *streamInitiation->getFileInfo(); - boost::shared_ptr<XMLElement> fileElement(new XMLElement("file", "http://jabber.org/protocol/si/profile/file-transfer")); - fileElement->setAttribute("name", file.getName()); - if (file.getSize() != 0) { - fileElement->setAttribute("size", boost::lexical_cast<std::string>(file.getSize())); - } - if (!file.getDescription().empty()) { - boost::shared_ptr<XMLElement> descElement(new XMLElement("desc")); - descElement->addNode(boost::make_shared<XMLTextNode>(file.getDescription())); - fileElement->addNode(descElement); - } - siElement.addNode(fileElement); - } + if (streamInitiation->getFileInfo()) { + StreamInitiationFileInfo file = *streamInitiation->getFileInfo(); + std::shared_ptr<XMLElement> fileElement(new XMLElement("file", "http://jabber.org/protocol/si/profile/file-transfer")); + fileElement->setAttribute("name", file.getName()); + if (file.getSize() != 0) { + fileElement->setAttribute("size", std::to_string(file.getSize())); + } + if (!file.getDescription().empty()) { + std::shared_ptr<XMLElement> descElement(new XMLElement("desc")); + descElement->addNode(std::make_shared<XMLTextNode>(file.getDescription())); + fileElement->addNode(descElement); + } + siElement.addNode(fileElement); + } - boost::shared_ptr<XMLElement> featureElement(new XMLElement("feature", FEATURE_NEG_NS)); - if (streamInitiation->getProvidedMethods().size() > 0) { - Form::ref form(new Form(Form::FormType)); - FormField::ref field = boost::make_shared<FormField>(FormField::ListSingleType); - field->setName("stream-method"); - foreach(const std::string& method, streamInitiation->getProvidedMethods()) { - field->addOption(FormField::Option("", method)); - } - form->addField(field); - featureElement->addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); - } - else if (!streamInitiation->getRequestedMethod().empty()) { - Form::ref form(new Form(Form::SubmitType)); - FormField::ref field = boost::make_shared<FormField>(FormField::ListSingleType); - field->addValue(streamInitiation->getRequestedMethod()); - field->setName("stream-method"); - form->addField(field); - featureElement->addNode(boost::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); - } - siElement.addNode(featureElement); - return siElement.serialize(); + std::shared_ptr<XMLElement> featureElement(new XMLElement("feature", FEATURE_NEG_NS)); + if (streamInitiation->getProvidedMethods().size() > 0) { + Form::ref form(new Form(Form::FormType)); + FormField::ref field = std::make_shared<FormField>(FormField::ListSingleType); + field->setName("stream-method"); + for (const auto& method : streamInitiation->getProvidedMethods()) { + field->addOption(FormField::Option("", method)); + } + form->addField(field); + featureElement->addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); + } + else if (!streamInitiation->getRequestedMethod().empty()) { + Form::ref form(new Form(Form::SubmitType)); + FormField::ref field = std::make_shared<FormField>(FormField::ListSingleType); + field->addValue(streamInitiation->getRequestedMethod()); + field->setName("stream-method"); + form->addField(field); + featureElement->addNode(std::make_shared<XMLRawTextNode>(FormSerializer().serialize(form))); + } + siElement.addNode(featureElement); + return siElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h index 63f845f..73dbc39 100644 --- a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/StreamInitiation.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API StreamInitiationSerializer : public GenericPayloadSerializer<StreamInitiation> { - public: - StreamInitiationSerializer(); + class SWIFTEN_API StreamInitiationSerializer : public GenericPayloadSerializer<StreamInitiation> { + public: + StreamInitiationSerializer(); - virtual std::string serializePayload(boost::shared_ptr<StreamInitiation>) const; - }; + virtual std::string serializePayload(std::shared_ptr<StreamInitiation>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/SubjectSerializer.h b/Swiften/Serializer/PayloadSerializers/SubjectSerializer.h index fe82499..20f95fd 100644 --- a/Swiften/Serializer/PayloadSerializers/SubjectSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/SubjectSerializer.h @@ -1,23 +1,24 @@ /* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Subject.h> #include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Elements/Subject.h> namespace Swift { - class SubjectSerializer : public GenericPayloadSerializer<Subject> { - public: - SubjectSerializer() : GenericPayloadSerializer<Subject>() {} + class SWIFTEN_API SubjectSerializer : public GenericPayloadSerializer<Subject> { + public: + SubjectSerializer() : GenericPayloadSerializer<Subject>() {} - virtual std::string serializePayload(boost::shared_ptr<Subject> subject) const { - XMLTextNode textNode(subject->getText()); - return "<subject>" + textNode.serialize() + "</subject>"; - } - }; + virtual std::string serializePayload(std::shared_ptr<Subject> subject) const { + XMLTextNode textNode(subject->getText()); + return "<subject>" + textNode.serialize() + "</subject>"; + } + }; } diff --git a/Swiften/Serializer/PayloadSerializers/ThreadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ThreadSerializer.cpp new file mode 100644 index 0000000..5914cf2 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ThreadSerializer.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/ThreadSerializer.h> + +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { + ThreadSerializer::ThreadSerializer() : GenericPayloadSerializer<Thread>() { + } + + ThreadSerializer::~ThreadSerializer() { + } + + std::string ThreadSerializer::serializePayload(std::shared_ptr<Thread> thread) const { + XMLElement threadNode("thread", "", thread->getText()); + if (!thread->getParent().empty()) { + threadNode.setAttribute("parent", thread->getParent()); + } + return threadNode.serialize(); + } +} diff --git a/Swiften/Serializer/PayloadSerializers/ThreadSerializer.h b/Swiften/Serializer/PayloadSerializers/ThreadSerializer.h new file mode 100644 index 0000000..07ecb82 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/ThreadSerializer.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Thread.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> + +namespace Swift { + class SWIFTEN_API ThreadSerializer : public GenericPayloadSerializer<Thread> { + public: + ThreadSerializer(); + virtual ~ThreadSerializer(); + + virtual std::string serializePayload(std::shared_ptr<Thread> thread) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/BlockSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/BlockSerializerTest.cpp index 7772381..9b9e00d 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/BlockSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/BlockSerializerTest.cpp @@ -4,52 +4,58 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/PayloadSerializers/BlockSerializer.h> #include <Swiften/Elements/BlockListPayload.h> #include <Swiften/Elements/BlockPayload.h> #include <Swiften/Elements/UnblockPayload.h> #include <Swiften/JID/JID.h> +#include <Swiften/Serializer/PayloadSerializers/BlockSerializer.h> using namespace Swift; class BlockSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(BlockSerializerTest); - CPPUNIT_TEST(testExample4); - CPPUNIT_TEST(testExample6); - CPPUNIT_TEST(testExample10); - CPPUNIT_TEST_SUITE_END(); - - public: - BlockSerializerTest() {} - - void testExample4() { - BlockSerializer<BlockListPayload> testling("blocklist"); - boost::shared_ptr<BlockListPayload> blocklist = boost::make_shared<BlockListPayload>(); - blocklist->addItem(JID("romeo@montague.net")); - blocklist->addItem(JID("iago@shakespeare.lit")); - - CPPUNIT_ASSERT_EQUAL(std::string("<blocklist xmlns=\"urn:xmpp:blocking\"><item jid=\"romeo@montague.net\"/><item jid=\"iago@shakespeare.lit\"/></blocklist>"), testling.serialize(blocklist)); - } - - void testExample6() { - BlockSerializer<BlockPayload> testling("block"); - boost::shared_ptr<BlockPayload> block = boost::make_shared<BlockPayload>(); - block->addItem(JID("romeo@montague.net")); - - CPPUNIT_ASSERT_EQUAL(std::string("<block xmlns=\"urn:xmpp:blocking\"><item jid=\"romeo@montague.net\"/></block>"), testling.serialize(block)); - } - - void testExample10() { - BlockSerializer<UnblockPayload> testling("unblock"); - boost::shared_ptr<UnblockPayload> unblock = boost::make_shared<UnblockPayload>(); - unblock->addItem(JID("romeo@montague.net")); - - CPPUNIT_ASSERT_EQUAL(std::string("<unblock xmlns=\"urn:xmpp:blocking\"><item jid=\"romeo@montague.net\"/></unblock>"), testling.serialize(unblock)); - } + CPPUNIT_TEST_SUITE(BlockSerializerTest); + CPPUNIT_TEST(testExample4); + CPPUNIT_TEST(testExample6); + CPPUNIT_TEST(testExample10); + CPPUNIT_TEST_SUITE_END(); + + public: + BlockSerializerTest() {} + + void testExample4() { + BlockSerializer<BlockListPayload> testling("blocklist"); + std::shared_ptr<BlockListPayload> blocklist = std::make_shared<BlockListPayload>(); + blocklist->addItem(JID("romeo@montague.net")); + blocklist->addItem(JID("iago@shakespeare.lit")); + + CPPUNIT_ASSERT_EQUAL(std::string("<blocklist xmlns=\"urn:xmpp:blocking\"><item jid=\"romeo@montague.net\"/><item jid=\"iago@shakespeare.lit\"/></blocklist>"), testling.serialize(blocklist)); + } + + void testExample6() { + BlockSerializer<BlockPayload> testling("block"); + std::shared_ptr<BlockPayload> block = std::make_shared<BlockPayload>(); + block->addItem(JID("romeo@montague.net")); + + CPPUNIT_ASSERT_EQUAL(std::string("<block xmlns=\"urn:xmpp:blocking\"><item jid=\"romeo@montague.net\"/></block>"), testling.serialize(block)); + } + + void testExample10() { + BlockSerializer<UnblockPayload> testling("unblock"); + std::shared_ptr<UnblockPayload> unblock = std::make_shared<UnblockPayload>(); + unblock->addItem(JID("romeo@montague.net")); + + CPPUNIT_ASSERT_EQUAL(std::string("<unblock xmlns=\"urn:xmpp:blocking\"><item jid=\"romeo@montague.net\"/></unblock>"), testling.serialize(unblock)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(BlockSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/CapsInfoSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/CapsInfoSerializerTest.cpp index 270d165..c4e3ad8 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/CapsInfoSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/CapsInfoSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,19 +13,19 @@ using namespace Swift; class CapsInfoSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(CapsInfoSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(CapsInfoSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); - public: - CapsInfoSerializerTest() {} + public: + CapsInfoSerializerTest() {} - void testSerialize() { - CapsInfoSerializer testling; - boost::shared_ptr<CapsInfo> priority(new CapsInfo("http://swift.im", "myversion", "sha-1")); + void testSerialize() { + CapsInfoSerializer testling; + std::shared_ptr<CapsInfo> priority(new CapsInfo("http://swift.im", "myversion", "sha-1")); - CPPUNIT_ASSERT_EQUAL(std::string("<c hash=\"sha-1\" node=\"http://swift.im\" ver=\"myversion\" xmlns=\"http://jabber.org/protocol/caps\"/>"), testling.serialize(priority)); - } + CPPUNIT_ASSERT_EQUAL(std::string("<c hash=\"sha-1\" node=\"http://swift.im\" ver=\"myversion\" xmlns=\"http://jabber.org/protocol/caps\"/>"), testling.serialize(priority)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(CapsInfoSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/CarbonsSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/CarbonsSerializerTest.cpp new file mode 100644 index 0000000..9ac8416 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/CarbonsSerializerTest.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Elements/CarbonsDisable.h> +#include <Swiften/Elements/CarbonsEnable.h> +#include <Swiften/Elements/CarbonsPrivate.h> +#include <Swiften/Elements/CarbonsReceived.h> +#include <Swiften/Elements/CarbonsSent.h> +#include <Swiften/Elements/Forwarded.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Thread.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Serializer/PayloadSerializers/CarbonsDisableSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CarbonsEnableSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CarbonsPrivateSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CarbonsReceivedSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/CarbonsSentSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +class CarbonsSerializerTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(CarbonsSerializerTest); + CPPUNIT_TEST(testSerializeExample3); + CPPUNIT_TEST(testSerializeExample6); + CPPUNIT_TEST(testSerializeExample12); + CPPUNIT_TEST(testSerializeExample14); + CPPUNIT_TEST(testSerializeExample15); + CPPUNIT_TEST_SUITE_END(); + + public: + CarbonsSerializerTest() {} + + /* + * Test serializing of example 3 in XEP-0280. + */ + void testSerializeExample3() { + CarbonsEnableSerializer testling; + + CPPUNIT_ASSERT_EQUAL(std::string("<enable xmlns=\"urn:xmpp:carbons:2\"/>"), testling.serialize(std::make_shared<CarbonsEnable>())); + } + + /* + * Test serializing of example 6 in XEP-0280. + */ + void testSerializeExample6() { + CarbonsDisableSerializer testling; + + CPPUNIT_ASSERT_EQUAL(std::string("<disable xmlns=\"urn:xmpp:carbons:2\"/>"), testling.serialize(std::make_shared<CarbonsDisable>())); + } + + /* + * Test serializing of example 12 in XEP-0280. + */ + void testSerializeExample12() { + CarbonsReceivedSerializer testling(&serializers); + + CarbonsReceived::ref received = std::make_shared<CarbonsReceived>(); + + std::shared_ptr<Forwarded> forwarded = std::make_shared<Forwarded>(); + + Message::ref message = std::make_shared<Message>(); + message->setFrom(JID("juliet@capulet.example/balcony")); + message->setTo(JID("romeo@montague.example/garden")); + message->setBody("What man art thou that, thus bescreen'd in night, so stumblest on my counsel?"); + message->addPayload(std::make_shared<Thread>("0e3141cd80894871a68e6fe6b1ec56fa")); + + forwarded->setStanza(message); + received->setForwarded(forwarded); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<received xmlns=\"urn:xmpp:carbons:2\">" + "<forwarded xmlns=\"urn:xmpp:forward:0\">" + "<message from=\"juliet@capulet.example/balcony\"" + " to=\"romeo@montague.example/garden\"" + " type=\"chat\"" + " xmlns=\"jabber:client\">" + "<body>What man art thou that, thus bescreen'd in night, so stumblest on my counsel?</body>" + "<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>" + "</message>" + "</forwarded>" + "</received>"), testling.serialize(received)); + } + + /* + * Test serializing of example 14 in XEP-0280. + */ + void testSerializeExample14() { + CarbonsSentSerializer testling(&serializers); + + CarbonsSent::ref sent = std::make_shared<CarbonsSent>(); + + std::shared_ptr<Forwarded> forwarded = std::make_shared<Forwarded>(); + + Message::ref message = std::make_shared<Message>(); + message->setTo(JID("juliet@capulet.example/balcony")); + message->setFrom(JID("romeo@montague.example/home")); + message->setBody("Neither, fair saint, if either thee dislike."); + message->addPayload(std::make_shared<Thread>("0e3141cd80894871a68e6fe6b1ec56fa")); + + forwarded->setStanza(message); + sent->setForwarded(forwarded); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<sent xmlns=\"urn:xmpp:carbons:2\">" + "<forwarded xmlns=\"urn:xmpp:forward:0\">" + "<message from=\"romeo@montague.example/home\"" + " to=\"juliet@capulet.example/balcony\"" + " type=\"chat\"" + " xmlns=\"jabber:client\">" + "<body>Neither, fair saint, if either thee dislike.</body>" + "<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>" + "</message>" + "</forwarded>" + "</sent>"), testling.serialize(sent)); + } + + /* + * Test serializing of example 15 in XEP-0280. + */ + void testSerializeExample15() { + CarbonsPrivateSerializer testling; + + CPPUNIT_ASSERT_EQUAL(std::string("<private xmlns=\"urn:xmpp:carbons:2\"/>"), testling.serialize(std::make_shared<CarbonsPrivate>())); + } + private: + FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(CarbonsSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/ChatStateSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/ChatStateSerializerTest.cpp new file mode 100644 index 0000000..018d2cc --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/ChatStateSerializerTest.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h> + +using namespace Swift; + +class ChatStateSerializerTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ChatStateSerializerTest); + CPPUNIT_TEST(testSerialize_ActiveState); + CPPUNIT_TEST(testSerialize_GoneState); + CPPUNIT_TEST(testSerialize_ComposingState); + CPPUNIT_TEST(testSerialize_PausedState); + CPPUNIT_TEST(testSerialize_InacativeState); + CPPUNIT_TEST_SUITE_END(); + + public: + ChatStateSerializerTest() {} + ChatStateSerializer testling; + + void testSerialize_ActiveState() { + std::shared_ptr<ChatState> priority(new ChatState(ChatState::Active)); + CPPUNIT_ASSERT_EQUAL(std::string("<active xmlns=\"http://jabber.org/protocol/chatstates\"/>"), testling.serialize(priority)); + } + + void testSerialize_GoneState() { + std::shared_ptr<ChatState> priority(new ChatState(ChatState::Gone)); + CPPUNIT_ASSERT_EQUAL(std::string("<gone xmlns=\"http://jabber.org/protocol/chatstates\"/>"), testling.serialize(priority)); + } + + void testSerialize_ComposingState() { + std::shared_ptr<ChatState> priority(new ChatState(ChatState::Composing)); + CPPUNIT_ASSERT_EQUAL(std::string("<composing xmlns=\"http://jabber.org/protocol/chatstates\"/>"), testling.serialize(priority)); + } + + void testSerialize_PausedState() { + std::shared_ptr<ChatState> priority(new ChatState(ChatState::Paused)); + CPPUNIT_ASSERT_EQUAL(std::string("<paused xmlns=\"http://jabber.org/protocol/chatstates\"/>"), testling.serialize(priority)); + } + + void testSerialize_InacativeState() { + std::shared_ptr<ChatState> priority(new ChatState(ChatState::Inactive)); + CPPUNIT_ASSERT_EQUAL(std::string("<inactive xmlns=\"http://jabber.org/protocol/chatstates\"/>"), testling.serialize(priority)); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ChatStateSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/ClientStateSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/ClientStateSerializerTest.cpp new file mode 100644 index 0000000..1622354 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/ClientStateSerializerTest.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/ClientStateSerializer.h> + +using namespace Swift; + +TEST(ClientStateSerializerTest, testSerialize_ActiveState) { + ClientStateSerializer testling; + std::shared_ptr<ClientState> priority(new ClientState(ClientState::ClientStateType::Active)); + + ASSERT_EQ(std::string("<active xmlns=\"urn:xmpp:csi:0\"/>"), testling.serialize(priority)); +} + +TEST(ClientStateSerializerTest, testSerialize_InacativeState) { + ClientStateSerializer testling; + std::shared_ptr<ClientState> priority(new ClientState(ClientState::ClientStateType::Inactive)); + + ASSERT_EQ(std::string("<inactive xmlns=\"urn:xmpp:csi:0\"/>"), testling.serialize(priority)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/DeliveryReceiptSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/DeliveryReceiptSerializerTest.cpp index 9282db4..7ed9421 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/DeliveryReceiptSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/DeliveryReceiptSerializerTest.cpp @@ -4,41 +4,46 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.h> #include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/DeliveryReceiptSerializer.h> using namespace Swift; class DeliveryReceiptSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DeliveryReceiptSerializerTest); - CPPUNIT_TEST(testSerialize_XEP0184Example3); - CPPUNIT_TEST(testSerialize_XEP0184Example4); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(DeliveryReceiptSerializerTest); + CPPUNIT_TEST(testSerialize_XEP0184Example3); + CPPUNIT_TEST(testSerialize_XEP0184Example4); + CPPUNIT_TEST_SUITE_END(); - public: - void testSerialize_XEP0184Example3() { - std::string expected = "<request xmlns=\"urn:xmpp:receipts\"/>"; + public: + void testSerialize_XEP0184Example3() { + std::string expected = "<request xmlns=\"urn:xmpp:receipts\"/>"; - DeliveryReceiptRequest::ref receipt = boost::make_shared<DeliveryReceiptRequest>(); + DeliveryReceiptRequest::ref receipt = std::make_shared<DeliveryReceiptRequest>(); - boost::shared_ptr<DeliveryReceiptRequestSerializer> serializer = boost::make_shared<DeliveryReceiptRequestSerializer>(); - CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(receipt)); - } + std::shared_ptr<DeliveryReceiptRequestSerializer> serializer = std::make_shared<DeliveryReceiptRequestSerializer>(); + CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(receipt)); + } - void testSerialize_XEP0184Example4() { - std::string expected = "<received id=\"richard2-4.1.247\" xmlns=\"urn:xmpp:receipts\"/>"; + void testSerialize_XEP0184Example4() { + std::string expected = "<received id=\"richard2-4.1.247\" xmlns=\"urn:xmpp:receipts\"/>"; - DeliveryReceipt::ref receipt = boost::make_shared<DeliveryReceipt>("richard2-4.1.247"); + DeliveryReceipt::ref receipt = std::make_shared<DeliveryReceipt>("richard2-4.1.247"); - boost::shared_ptr<DeliveryReceiptSerializer> serializer = boost::make_shared<DeliveryReceiptSerializer>(); - CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(receipt)); - } + std::shared_ptr<DeliveryReceiptSerializer> serializer = std::make_shared<DeliveryReceiptSerializer>(); + CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(receipt)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(DeliveryReceiptSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/DiscoInfoSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/DiscoInfoSerializerTest.cpp index 32f5f49..318c3d7 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/DiscoInfoSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/DiscoInfoSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,54 +13,54 @@ using namespace Swift; class DiscoInfoSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DiscoInfoSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_Form); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(DiscoInfoSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_Form); + CPPUNIT_TEST_SUITE_END(); - public: - DiscoInfoSerializerTest() {} + public: + DiscoInfoSerializerTest() {} - void testSerialize() { - DiscoInfoSerializer testling; - boost::shared_ptr<DiscoInfo> discoInfo(new DiscoInfo()); - discoInfo->addIdentity(DiscoInfo::Identity("Swift", "client", "pc")); - discoInfo->addIdentity(DiscoInfo::Identity("Vlug", "client", "pc", "nl")); - discoInfo->addFeature("http://jabber.org/protocol/caps"); - discoInfo->addFeature("http://jabber.org/protocol/disco#info"); - discoInfo->setNode("http://swift.im#bla"); + void testSerialize() { + DiscoInfoSerializer testling; + std::shared_ptr<DiscoInfo> discoInfo(new DiscoInfo()); + discoInfo->addIdentity(DiscoInfo::Identity("Swift", "client", "pc")); + discoInfo->addIdentity(DiscoInfo::Identity("Vlug", "client", "pc", "nl")); + discoInfo->addFeature("http://jabber.org/protocol/caps"); + discoInfo->addFeature("http://jabber.org/protocol/disco#info"); + discoInfo->setNode("http://swift.im#bla"); - std::string expectedResult = - "<query node=\"http://swift.im#bla\" xmlns=\"http://jabber.org/protocol/disco#info\">" - "<identity category=\"client\" name=\"Swift\" type=\"pc\"/>" - "<identity category=\"client\" name=\"Vlug\" type=\"pc\" xml:lang=\"nl\"/>" - "<feature var=\"http://jabber.org/protocol/caps\"/>" - "<feature var=\"http://jabber.org/protocol/disco#info\"/>" - "</query>"; + std::string expectedResult = + "<query node=\"http://swift.im#bla\" xmlns=\"http://jabber.org/protocol/disco#info\">" + "<identity category=\"client\" name=\"Swift\" type=\"pc\"/>" + "<identity category=\"client\" name=\"Vlug\" type=\"pc\" xml:lang=\"nl\"/>" + "<feature var=\"http://jabber.org/protocol/caps\"/>" + "<feature var=\"http://jabber.org/protocol/disco#info\"/>" + "</query>"; - CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(discoInfo)); - } + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(discoInfo)); + } - void testSerialize_Form() { - DiscoInfoSerializer testling; - boost::shared_ptr<DiscoInfo> discoInfo(new DiscoInfo()); - discoInfo->addFeature("http://jabber.org/protocol/caps"); - discoInfo->addFeature("http://jabber.org/protocol/disco#info"); - boost::shared_ptr<Form> form(new Form(Form::FormType)); - form->setTitle("Bot Configuration"); - discoInfo->addExtension(form); + void testSerialize_Form() { + DiscoInfoSerializer testling; + std::shared_ptr<DiscoInfo> discoInfo(new DiscoInfo()); + discoInfo->addFeature("http://jabber.org/protocol/caps"); + discoInfo->addFeature("http://jabber.org/protocol/disco#info"); + std::shared_ptr<Form> form(new Form(Form::FormType)); + form->setTitle("Bot Configuration"); + discoInfo->addExtension(form); - std::string expectedResult = - "<query xmlns=\"http://jabber.org/protocol/disco#info\">" - "<feature var=\"http://jabber.org/protocol/caps\"/>" - "<feature var=\"http://jabber.org/protocol/disco#info\"/>" - "<x type=\"form\" xmlns=\"jabber:x:data\">" - "<title>Bot Configuration</title>" - "</x>" - "</query>"; + std::string expectedResult = + "<query xmlns=\"http://jabber.org/protocol/disco#info\">" + "<feature var=\"http://jabber.org/protocol/caps\"/>" + "<feature var=\"http://jabber.org/protocol/disco#info\"/>" + "<x type=\"form\" xmlns=\"jabber:x:data\">" + "<title>Bot Configuration</title>" + "</x>" + "</query>"; - CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(discoInfo)); - } + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(discoInfo)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(DiscoInfoSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/ErrorSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/ErrorSerializerTest.cpp index d1408f7..68a72b8 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/ErrorSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/ErrorSerializerTest.cpp @@ -1,45 +1,46 @@ /* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Elements/Delay.h> #include <Swiften/Serializer/PayloadSerializers/ErrorSerializer.h> #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> -#include <Swiften/Elements/Delay.h> using namespace Swift; class ErrorSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ErrorSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_Payload); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerialize() { - ErrorSerializer testling(&serializers); - boost::shared_ptr<ErrorPayload> error(new ErrorPayload(ErrorPayload::BadRequest, ErrorPayload::Cancel, "My Error")); - - CPPUNIT_ASSERT_EQUAL(std::string("<error type=\"cancel\"><bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/><text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">My Error</text></error>"), testling.serialize(error)); - } - - void testSerialize_Payload() { - ErrorSerializer testling(&serializers); - boost::shared_ptr<ErrorPayload> error = boost::make_shared<ErrorPayload>(); - error->setPayload(boost::make_shared<Delay>()); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<error type=\"cancel\"><undefined-condition xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/><delay stamp=\"not-a-date-timeZ\" xmlns=\"urn:xmpp:delay\"/></error>" - ), testling.serialize(error)); - } - - private: - FullPayloadSerializerCollection serializers; + CPPUNIT_TEST_SUITE(ErrorSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_Payload); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + ErrorSerializer testling(&serializers); + std::shared_ptr<ErrorPayload> error(new ErrorPayload(ErrorPayload::BadRequest, ErrorPayload::Cancel, "My Error")); + + CPPUNIT_ASSERT_EQUAL(std::string("<error type=\"cancel\"><bad-request xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/><text xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">My Error</text></error>"), testling.serialize(error)); + } + + void testSerialize_Payload() { + ErrorSerializer testling(&serializers); + std::shared_ptr<ErrorPayload> error = std::make_shared<ErrorPayload>(); + error->setPayload(std::make_shared<Delay>()); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<error type=\"cancel\"><undefined-condition xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/><delay stamp=\"not-a-date-timeZ\" xmlns=\"urn:xmpp:delay\"/></error>" + ), testling.serialize(error)); + } + + private: + FullPayloadSerializerCollection serializers; }; CPPUNIT_TEST_SUITE_REGISTRATION(ErrorSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp index e4ce2c8..6534dce 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp @@ -1,233 +1,298 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> using namespace Swift; class FormSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(FormSerializerTest); - CPPUNIT_TEST(testSerializeFormInformation); - CPPUNIT_TEST(testSerializeFields); - CPPUNIT_TEST(testSerializeFormItems); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerializeFormInformation() { - FormSerializer testling; - boost::shared_ptr<Form> form(new Form(Form::FormType)); - form->setTitle("Bot Configuration"); - form->setInstructions("Hello!\nFill out this form to configure your new bot!"); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<x type=\"form\" xmlns=\"jabber:x:data\">" - "<title>Bot Configuration</title>" - "<instructions>Hello!</instructions>" - "<instructions>Fill out this form to configure your new bot!</instructions>" - "</x>"), testling.serialize(form)); - } - - void testSerializeFields() { - FormSerializer testling; - boost::shared_ptr<Form> form(new Form(Form::FormType)); - - FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:bot"); - field->setName("FORM_TYPE"); - form->addField(field); - - form->addField(boost::make_shared<FormField>(FormField::FixedType, "Section 1: Bot Info")); - - field = boost::make_shared<FormField>(FormField::TextSingleType); - field->setName("botname"); - field->setLabel("The name of your bot"); - form->addField(field); - - field = boost::make_shared<FormField>(FormField::TextMultiType); - field->setTextMultiValue("This is a bot.\nA quite good one actually"); - field->setName("description"); - field->setLabel("Helpful description of your bot"); - form->addField(field); - - field = boost::make_shared<FormField>(FormField::BooleanType, "1"); - field->setName("public"); - field->setLabel("Public bot?"); - field->setRequired(true); - form->addField(field); - - field = boost::make_shared<FormField>(FormField::TextPrivateType); - field->setName("password"); - field->setLabel("Password for special access"); - form->addField(field); - - field = boost::make_shared<FormField>(FormField::ListMultiType); - field->addValue("news"); - field->addValue("search"); - field->setName("features"); - field->setLabel("What features will the bot support?"); - field->addOption(FormField::Option("Contests", "contests")); - field->addOption(FormField::Option("News", "news")); - field->addOption(FormField::Option("Polls", "polls")); - field->addOption(FormField::Option("Reminders", "reminders")); - field->addOption(FormField::Option("Search", "search")); - form->addField(field); - - field = boost::make_shared<FormField>(FormField::ListSingleType, "20"); - field->setName("maxsubs"); - field->setLabel("Maximum number of subscribers"); - field->addOption(FormField::Option("10", "10")); - field->addOption(FormField::Option("20", "20")); - field->addOption(FormField::Option("30", "30")); - field->addOption(FormField::Option("50", "50")); - field->addOption(FormField::Option("100", "100")); - field->addOption(FormField::Option("", "none")); - form->addField(field); - - std::vector<JID> jids; - field = boost::make_shared<FormField>(FormField::JIDMultiType); - field->addValue("foo@bar.com"); - field->addValue("baz@fum.org"); - field->setName("invitelist"); - field->setLabel("People to invite"); - field->setDescription("Tell all your friends about your new bot!"); - form->addField(field); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<x type=\"form\" xmlns=\"jabber:x:data\">" - "<field type=\"hidden\" var=\"FORM_TYPE\">" - "<value>jabber:bot</value>" - "</field>" - "<field type=\"fixed\"><value>Section 1: Bot Info</value></field>" - "<field label=\"The name of your bot\" type=\"text-single\" var=\"botname\"/>" - "<field label=\"Helpful description of your bot\" type=\"text-multi\" var=\"description\"><value>This is a bot.</value><value>A quite good one actually</value></field>" - "<field label=\"Public bot?\" type=\"boolean\" var=\"public\">" - "<required/>" - "<value>1</value>" - "</field>" - "<field label=\"Password for special access\" type=\"text-private\" var=\"password\"/>" - "<field label=\"What features will the bot support?\" type=\"list-multi\" var=\"features\">" - "<value>news</value>" - "<value>search</value>" - "<option label=\"Contests\"><value>contests</value></option>" - "<option label=\"News\"><value>news</value></option>" - "<option label=\"Polls\"><value>polls</value></option>" - "<option label=\"Reminders\"><value>reminders</value></option>" - "<option label=\"Search\"><value>search</value></option>" - "</field>" - "<field label=\"Maximum number of subscribers\" type=\"list-single\" var=\"maxsubs\">" - "<value>20</value>" - "<option label=\"10\"><value>10</value></option>" - "<option label=\"20\"><value>20</value></option>" - "<option label=\"30\"><value>30</value></option>" - "<option label=\"50\"><value>50</value></option>" - "<option label=\"100\"><value>100</value></option>" - "<option><value>none</value></option>" - "</field>" - "<field label=\"People to invite\" type=\"jid-multi\" var=\"invitelist\">" - "<desc>Tell all your friends about your new bot!</desc>" - "<value>foo@bar.com</value>" - "<value>baz@fum.org</value>" - "</field>" - "</x>"), testling.serialize(form)); - } - - void testSerializeFormItems() { - FormSerializer testling; - boost::shared_ptr<Form> form(new Form(Form::ResultType)); - - - FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:iq:search"); - field->setName("FORM_TYPE"); - form->addField(field); - - // reported fields - field = boost::make_shared<FormField>(FormField::TextSingleType); - field->setName("first"); - field->setLabel("Given Name"); - form->addReportedField(field); - - field = boost::make_shared<FormField>(FormField::TextSingleType); - field->setName("last"); - field->setLabel("Family Name"); - form->addReportedField(field); - - field = boost::make_shared<FormField>(FormField::JIDSingleType); - field->setName("jid"); - field->setLabel("Jabber ID"); - form->addReportedField(field); - - field = boost::make_shared<FormField>(FormField::ListSingleType); - field->setName("x-gender"); - field->setLabel("Gender"); - form->addReportedField(field); - - Form::FormItem firstItem; - field = boost::make_shared<FormField>(FormField::TextSingleType, "Benvolio"); - field->setName("first"); - firstItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); - field->setName("last"); - firstItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::JIDSingleType, JID("benvolio@montague.net")); - field->setName("jid"); - firstItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); - field->setName("x-gender"); - firstItem.push_back(field); - - Form::FormItem secondItem; - field = boost::make_shared<FormField>(FormField::TextSingleType, "Romeo"); - field->setName("first"); - secondItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); - field->setName("last"); - secondItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::JIDSingleType, JID("romeo@montague.net")); - field->setName("jid"); - secondItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); - field->setName("x-gender"); - secondItem.push_back(field); - - form->addItem(firstItem); - form->addItem(secondItem); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<x type=\"result\" xmlns=\"jabber:x:data\">" - "<field type=\"hidden\" var=\"FORM_TYPE\">" - "<value>jabber:iq:search</value>" - "</field>" - "<reported>" - "<field label=\"Given Name\" type=\"text-single\" var=\"first\"/>" - "<field label=\"Family Name\" type=\"text-single\" var=\"last\"/>" - "<field label=\"Jabber ID\" type=\"jid-single\" var=\"jid\"/>" - "<field label=\"Gender\" type=\"list-single\" var=\"x-gender\"/>" - "</reported>" - "<item>" - "<field var=\"first\"><value>Benvolio</value></field>" - "<field var=\"last\"><value>Montague</value></field>" - "<field var=\"jid\"><value>benvolio@montague.net</value></field>" - "<field var=\"x-gender\"><value>male</value></field>" - "</item>" - "<item>" - "<field var=\"first\"><value>Romeo</value></field>" - "<field var=\"last\"><value>Montague</value></field>" - "<field var=\"jid\"><value>romeo@montague.net</value></field>" - "<field var=\"x-gender\"><value>male</value></field>" - "</item>" - "</x>"), testling.serialize(form)); - } + CPPUNIT_TEST_SUITE(FormSerializerTest); + CPPUNIT_TEST(testSerializeFormInformation); + CPPUNIT_TEST(testSerializeLayout); + CPPUNIT_TEST(testSerializeFields); + CPPUNIT_TEST(testSerializeFormItems); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerializeFormInformation() { + FormSerializer testling; + std::shared_ptr<Form> form(new Form(Form::FormType)); + form->setTitle("Bot Configuration"); + form->setInstructions("Hello!\nFill out this form to configure your new bot!"); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<x type=\"form\" xmlns=\"jabber:x:data\">" + "<title>Bot Configuration</title>" + "<instructions>Hello!</instructions>" + "<instructions>Fill out this form to configure your new bot!</instructions>" + "</x>"), testling.serialize(form)); + } + + void testSerializeLayout() { + FormSerializer testling; + std::shared_ptr<Form> form(new Form(Form::FormType)); + + FormPage::page page = std::make_shared<FormPage>(); + page->setLabel("P1"); + FormReportedRef::ref reportedRef = std::make_shared<FormReportedRef>(); + page->addReportedRef(reportedRef); + FormText::text formText = std::make_shared<FormText>(); + formText->setTextString("P1T1"); + page->addTextElement(formText); + FormField::ref field = std::make_shared<FormField>(FormField::TextSingleType); + field->setName("P1F1"); + field->setLabel("field one"); + page->addField(field); + + FormSection::section section = std::make_shared<FormSection>(); + section->setLabel("P1S1"); + formText = std::make_shared<FormText>(); + formText->setTextString("P1S1T1"); + section->addTextElement(formText); + field = std::make_shared<FormField>(FormField::TextSingleType); + field->setName("P1S1F1"); + field->setLabel("field two"); + section->addField(field); + page->addChildSection(section); + form->addPage(page); + + page = std::make_shared<FormPage>(); + page->setLabel("P2"); + section = std::make_shared<FormSection>(); + section->setLabel("P2S1"); + FormSection::section subSection = std::make_shared<FormSection>(); + subSection->setLabel("P2S2"); + FormSection::section subSection2 = std::make_shared<FormSection>(); + subSection2->setLabel("P2S3"); + subSection->addChildSection(subSection2); + section->addChildSection(subSection); + page->addChildSection(section); + form->addPage(page); + + // P1 = page one, S1 = section one, F1 = field one, T1 = text one + CPPUNIT_ASSERT_EQUAL(std::string( + "<x type=\"form\" xmlns=\"jabber:x:data\">" + "<page label=\"P1\" xmlns=\"http://jabber.org/protocol/xdata-layout\">" + "<text>P1T1</text>" + "<fieldref var=\"P1F1\"/>" + "<reportedref/>" + "<section label=\"P1S1\">" + "<text>P1S1T1</text>" + "<fieldref var=\"P1S1F1\"/>" + "</section>" + "</page>" + "<page label=\"P2\" xmlns=\"http://jabber.org/protocol/xdata-layout\">" + "<section label=\"P2S1\">" + "<section label=\"P2S2\">" + "<section label=\"P2S3\"/>" + "</section>" + "</section>" + "</page>" + "<field label=\"field one\" type=\"text-single\" var=\"P1F1\"/>" + "<field label=\"field two\" type=\"text-single\" var=\"P1S1F1\"/>" + "</x>"), testling.serialize(form)); + } + + void testSerializeFields() { + FormSerializer testling; + std::shared_ptr<Form> form(new Form(Form::FormType)); + + FormField::ref field = std::make_shared<FormField>(FormField::HiddenType, "jabber:bot"); + field->setName("FORM_TYPE"); + form->addField(field); + + form->addField(std::make_shared<FormField>(FormField::FixedType, "Section 1: Bot Info")); + + field = std::make_shared<FormField>(FormField::TextSingleType); + field->setName("botname"); + field->setLabel("The name of your bot"); + form->addField(field); + + field = std::make_shared<FormField>(FormField::TextMultiType); + field->setTextMultiValue("This is a bot.\nA quite good one actually"); + field->setName("description"); + field->setLabel("Helpful description of your bot"); + form->addField(field); + + field = std::make_shared<FormField>(FormField::BooleanType, "1"); + field->setName("public"); + field->setLabel("Public bot?"); + field->setRequired(true); + form->addField(field); + + field = std::make_shared<FormField>(FormField::TextPrivateType); + field->setName("password"); + field->setLabel("Password for special access"); + form->addField(field); + + field = std::make_shared<FormField>(FormField::ListMultiType); + field->addValue("news"); + field->addValue("search"); + field->setName("features"); + field->setLabel("What features will the bot support?"); + field->addOption(FormField::Option("Contests", "contests")); + field->addOption(FormField::Option("News", "news")); + field->addOption(FormField::Option("Polls", "polls")); + field->addOption(FormField::Option("Reminders", "reminders")); + field->addOption(FormField::Option("Search", "search")); + form->addField(field); + + field = std::make_shared<FormField>(FormField::ListSingleType, "20"); + field->setName("maxsubs"); + field->setLabel("Maximum number of subscribers"); + field->addOption(FormField::Option("10", "10")); + field->addOption(FormField::Option("20", "20")); + field->addOption(FormField::Option("30", "30")); + field->addOption(FormField::Option("50", "50")); + field->addOption(FormField::Option("100", "100")); + field->addOption(FormField::Option("", "none")); + form->addField(field); + + std::vector<JID> jids; + field = std::make_shared<FormField>(FormField::JIDMultiType); + field->addValue("foo@bar.com"); + field->addValue("baz@fum.org"); + field->setName("invitelist"); + field->setLabel("People to invite"); + field->setDescription("Tell all your friends about your new bot!"); + form->addField(field); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<x type=\"form\" xmlns=\"jabber:x:data\">" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>jabber:bot</value>" + "</field>" + "<field type=\"fixed\"><value>Section 1: Bot Info</value></field>" + "<field label=\"The name of your bot\" type=\"text-single\" var=\"botname\"/>" + "<field label=\"Helpful description of your bot\" type=\"text-multi\" var=\"description\"><value>This is a bot.</value><value>A quite good one actually</value></field>" + "<field label=\"Public bot?\" type=\"boolean\" var=\"public\">" + "<required/>" + "<value>1</value>" + "</field>" + "<field label=\"Password for special access\" type=\"text-private\" var=\"password\"/>" + "<field label=\"What features will the bot support?\" type=\"list-multi\" var=\"features\">" + "<value>news</value>" + "<value>search</value>" + "<option label=\"Contests\"><value>contests</value></option>" + "<option label=\"News\"><value>news</value></option>" + "<option label=\"Polls\"><value>polls</value></option>" + "<option label=\"Reminders\"><value>reminders</value></option>" + "<option label=\"Search\"><value>search</value></option>" + "</field>" + "<field label=\"Maximum number of subscribers\" type=\"list-single\" var=\"maxsubs\">" + "<value>20</value>" + "<option label=\"10\"><value>10</value></option>" + "<option label=\"20\"><value>20</value></option>" + "<option label=\"30\"><value>30</value></option>" + "<option label=\"50\"><value>50</value></option>" + "<option label=\"100\"><value>100</value></option>" + "<option><value>none</value></option>" + "</field>" + "<field label=\"People to invite\" type=\"jid-multi\" var=\"invitelist\">" + "<desc>Tell all your friends about your new bot!</desc>" + "<value>foo@bar.com</value>" + "<value>baz@fum.org</value>" + "</field>" + "</x>"), testling.serialize(form)); + } + + void testSerializeFormItems() { + FormSerializer testling; + std::shared_ptr<Form> form(new Form(Form::ResultType)); + + FormField::ref field = std::make_shared<FormField>(FormField::HiddenType, "jabber:iq:search"); + field->setName("FORM_TYPE"); + form->addField(field); + + // reported fields + field = std::make_shared<FormField>(FormField::TextSingleType); + field->setName("first"); + field->setLabel("Given Name"); + form->addReportedField(field); + + field = std::make_shared<FormField>(FormField::TextSingleType); + field->setName("last"); + field->setLabel("Family Name"); + form->addReportedField(field); + + field = std::make_shared<FormField>(FormField::JIDSingleType); + field->setName("jid"); + field->setLabel("Jabber ID"); + form->addReportedField(field); + + field = std::make_shared<FormField>(FormField::ListSingleType); + field->setName("x-gender"); + field->setLabel("Gender"); + form->addReportedField(field); + + Form::FormItem firstItem; + field = std::make_shared<FormField>(FormField::TextSingleType, "Benvolio"); + field->setName("first"); + firstItem.push_back(field); + + field = std::make_shared<FormField>(FormField::TextSingleType, "Montague"); + field->setName("last"); + firstItem.push_back(field); + + field = std::make_shared<FormField>(FormField::JIDSingleType, JID("benvolio@montague.net")); + field->setName("jid"); + firstItem.push_back(field); + + field = std::make_shared<FormField>(FormField::ListSingleType, "male"); + field->setName("x-gender"); + firstItem.push_back(field); + + Form::FormItem secondItem; + field = std::make_shared<FormField>(FormField::TextSingleType, "Romeo"); + field->setName("first"); + secondItem.push_back(field); + + field = std::make_shared<FormField>(FormField::TextSingleType, "Montague"); + field->setName("last"); + secondItem.push_back(field); + + field = std::make_shared<FormField>(FormField::JIDSingleType, JID("romeo@montague.net")); + field->setName("jid"); + secondItem.push_back(field); + + field = std::make_shared<FormField>(FormField::ListSingleType, "male"); + field->setName("x-gender"); + secondItem.push_back(field); + + form->addItem(firstItem); + form->addItem(secondItem); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<x type=\"result\" xmlns=\"jabber:x:data\">" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>jabber:iq:search</value>" + "</field>" + "<reported>" + "<field label=\"Given Name\" type=\"text-single\" var=\"first\"/>" + "<field label=\"Family Name\" type=\"text-single\" var=\"last\"/>" + "<field label=\"Jabber ID\" type=\"jid-single\" var=\"jid\"/>" + "<field label=\"Gender\" type=\"list-single\" var=\"x-gender\"/>" + "</reported>" + "<item>" + "<field var=\"first\"><value>Benvolio</value></field>" + "<field var=\"last\"><value>Montague</value></field>" + "<field var=\"jid\"><value>benvolio@montague.net</value></field>" + "<field var=\"x-gender\"><value>male</value></field>" + "</item>" + "<item>" + "<field var=\"first\"><value>Romeo</value></field>" + "<field var=\"last\"><value>Montague</value></field>" + "<field var=\"jid\"><value>romeo@montague.net</value></field>" + "<field var=\"x-gender\"><value>male</value></field>" + "</item>" + "</x>"), testling.serialize(form)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(FormSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/ForwardedSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/ForwardedSerializerTest.cpp new file mode 100644 index 0000000..b0f41d4 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/ForwardedSerializerTest.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> + +#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); + + std::shared_ptr<IQ> iq = IQ::createResult(JID("juliet@capulet.lit/balcony"), JID("romeo@montague.lit/orchard"), "id0"); + + std::shared_ptr<Forwarded> forwarded(std::make_shared<Forwarded>()); + forwarded->setStanza(iq); + forwarded->setDelay(std::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); + + std::shared_ptr<Message> message(std::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."); + + std::shared_ptr<Forwarded> forwarded(std::make_shared<Forwarded>()); + forwarded->setStanza(message); + forwarded->setDelay(std::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); + + std::shared_ptr<Message> message(std::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."); + + std::shared_ptr<Forwarded> forwarded(std::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); + + std::shared_ptr<Presence> presence(std::make_shared<Presence>()); + presence->setType(Presence::Subscribe); + + std::shared_ptr<Forwarded> forwarded(std::make_shared<Forwarded>()); + forwarded->setStanza(presence); + forwarded->setDelay(std::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/IBBSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/IBBSerializerTest.cpp new file mode 100644 index 0000000..84412c9 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/IBBSerializerTest.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Elements/IBB.h> +#include <Swiften/Serializer/PayloadSerializers/IBBSerializer.h> + +using namespace Swift; + +class IBBSerializerTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(IBBSerializerTest); + CPPUNIT_TEST(testSerialize_data); + CPPUNIT_TEST_SUITE_END(); + + public: + IBBSerializerTest() {} + + void testSerialize_data() { + IBBSerializer testling; + std::shared_ptr<IBB> ibb = std::make_shared<IBB>(); + ibb->setAction(IBB::Data); + ibb->setData(createByteArray("abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\x0a")); + ibb->setSequenceNumber(4); + CPPUNIT_ASSERT_EQUAL(std::string("<data seq=\"4\" sid=\"\" xmlns=\"http://jabber.org/protocol/ibb\">" + "YWJjZGVmZ2loamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjEyMzQ1" + "Njc4OTAK" + "</data>"), testling.serialize(ibb)); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(IBBSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/IdleSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/IdleSerializerTest.cpp index 9700869..46598da 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/IdleSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/IdleSerializerTest.cpp @@ -4,29 +4,35 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/make_shared.hpp> - #include <Swiften/Serializer/PayloadSerializers/IdleSerializer.h> using namespace Swift; class IdleSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IdleSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(IdleSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); - public: - IdleSerializerTest() {} + public: + IdleSerializerTest() {} - void testSerialize() { - IdleSerializer testling; - Idle::ref idle = boost::make_shared<Idle>(stringToDateTime("1969-07-21T02:56:15Z")); + void testSerialize() { + IdleSerializer testling; + Idle::ref idle = std::make_shared<Idle>(stringToDateTime("1969-07-21T02:56:15Z")); - CPPUNIT_ASSERT_EQUAL(std::string("<idle xmlns='urn:xmpp:idle:1' since='1969-07-21T02:56:15Z'/>"), testling.serialize(idle)); - } + CPPUNIT_ASSERT_EQUAL(std::string("<idle xmlns='urn:xmpp:idle:1' since='1969-07-21T02:56:15Z'/>"), testling.serialize(idle)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(IdleSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp index 7cbce35..44ac7a1 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp @@ -1,62 +1,63 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h> using namespace Swift; class InBandRegistrationPayloadSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(InBandRegistrationPayloadSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_Form); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerialize() { - InBandRegistrationPayloadSerializer testling; - boost::shared_ptr<InBandRegistrationPayload> registration(new InBandRegistrationPayload()); - registration->setRegistered(true); - - std::string expectedResult = - "<query xmlns=\"jabber:iq:register\">" - "<registered/>" - "</query>"; - - CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(registration)); - } - void testSerialize_Form() { - InBandRegistrationPayloadSerializer testling; - boost::shared_ptr<InBandRegistrationPayload> registration(new InBandRegistrationPayload()); - registration->setInstructions("Use the enclosed form to register."); - - boost::shared_ptr<Form> form(new Form(Form::FormType)); - form->setTitle("Contest Registration"); - - FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:iq:register"); - field->setName("FORM_TYPE"); - form->addField(field); - registration->setForm(form); - - std::string expectedResult = - "<query xmlns=\"jabber:iq:register\">" - "<instructions>Use the enclosed form to register.</instructions>" - "<x type=\"form\" xmlns=\"jabber:x:data\">" - "<title>Contest Registration</title>" - "<field type=\"hidden\" var=\"FORM_TYPE\">" - "<value>jabber:iq:register</value>" - "</field>" - "</x>" - "</query>"; - - CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(registration)); - } + CPPUNIT_TEST_SUITE(InBandRegistrationPayloadSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_Form); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + InBandRegistrationPayloadSerializer testling; + std::shared_ptr<InBandRegistrationPayload> registration(new InBandRegistrationPayload()); + registration->setRegistered(true); + + std::string expectedResult = + "<query xmlns=\"jabber:iq:register\">" + "<registered/>" + "</query>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(registration)); + } + void testSerialize_Form() { + InBandRegistrationPayloadSerializer testling; + std::shared_ptr<InBandRegistrationPayload> registration(new InBandRegistrationPayload()); + registration->setInstructions("Use the enclosed form to register."); + + std::shared_ptr<Form> form(new Form(Form::FormType)); + form->setTitle("Contest Registration"); + + FormField::ref field = std::make_shared<FormField>(FormField::HiddenType, "jabber:iq:register"); + field->setName("FORM_TYPE"); + form->addField(field); + registration->setForm(form); + + std::string expectedResult = + "<query xmlns=\"jabber:iq:register\">" + "<instructions>Use the enclosed form to register.</instructions>" + "<x type=\"form\" xmlns=\"jabber:x:data\">" + "<title>Contest Registration</title>" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>jabber:iq:register</value>" + "</field>" + "</x>" + "</query>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(registration)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(InBandRegistrationPayloadSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/IsodeIQDelegationSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/IsodeIQDelegationSerializerTest.cpp new file mode 100644 index 0000000..4a466ba --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/IsodeIQDelegationSerializerTest.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2015 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#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/IsodeIQDelegation.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/Subject.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/IsodeIQDelegationSerializer.h> + +using namespace Swift; + +class IsodeIQDelegationSerializerTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(IsodeIQDelegationSerializerTest); + CPPUNIT_TEST(testSerialize_Forwarded_IQ); + CPPUNIT_TEST(testSerialize_Forwarded_Message); + CPPUNIT_TEST(testSerialize_Forwarded_MessageNoDelay); + CPPUNIT_TEST(testSerialize_Forwarded_Presence); + CPPUNIT_TEST_SUITE_END(); + + public: + IsodeIQDelegationSerializerTest() {} + + void testSerialize_Forwarded_IQ() { + IsodeIQDelegationSerializer testling(&serializers); + std::shared_ptr<IsodeIQDelegation> isodeIQDelegation = std::make_shared<IsodeIQDelegation>(); + + std::shared_ptr<IQ> iq = IQ::createResult(JID("juliet@capulet.lit/balcony"), JID("romeo@montague.lit/orchard"), "id0", std::make_shared<Subject>("text")); + + std::shared_ptr<Forwarded> forwarded(std::make_shared<Forwarded>()); + forwarded->setStanza(iq); + forwarded->setDelay(std::make_shared<Delay>(stringToDateTime(std::string("2010-07-10T23:08:25Z")))); + isodeIQDelegation->setForward(forwarded); + + CPPUNIT_ASSERT_EQUAL(std::string("<delegate xmlns=\"http://isode.com/iq_delegation\">" + "<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\"><subject>text</subject></iq>" + "</forwarded>" + "</delegate>"), testling.serialize(isodeIQDelegation)); + } + + void testSerialize_Forwarded_Message() { + IsodeIQDelegationSerializer testling(&serializers); + std::shared_ptr<IsodeIQDelegation> isodeIQDelegation = std::make_shared<IsodeIQDelegation>(); + + std::shared_ptr<Message> message(std::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."); + + std::shared_ptr<Forwarded> forwarded(std::make_shared<Forwarded>()); + forwarded->setStanza(message); + forwarded->setDelay(std::make_shared<Delay>(stringToDateTime(std::string("2010-07-10T23:08:25Z")))); + + isodeIQDelegation->setForward(forwarded); + CPPUNIT_ASSERT_EQUAL(std::string("<delegate xmlns=\"http://isode.com/iq_delegation\">" + "<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>" + "</delegate>"), testling.serialize(isodeIQDelegation)); + } + + void testSerialize_Forwarded_MessageNoDelay() { + IsodeIQDelegationSerializer testling(&serializers); + std::shared_ptr<IsodeIQDelegation> isodeIQDelegation = std::make_shared<IsodeIQDelegation>(); + + std::shared_ptr<Message> message(std::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."); + + std::shared_ptr<Forwarded> forwarded(std::make_shared<Forwarded>()); + forwarded->setStanza(message); + isodeIQDelegation->setForward(forwarded); + + CPPUNIT_ASSERT_EQUAL(std::string("<delegate xmlns=\"http://isode.com/iq_delegation\">" + "<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>" + "</delegate>"), testling.serialize(isodeIQDelegation)); + } + + void testSerialize_Forwarded_Presence() { + IsodeIQDelegationSerializer testling(&serializers); + std::shared_ptr<IsodeIQDelegation> isodeIQDelegation = std::make_shared<IsodeIQDelegation>(); + + std::shared_ptr<Presence> presence(std::make_shared<Presence>()); + presence->setType(Presence::Subscribe); + + std::shared_ptr<Forwarded> forwarded(std::make_shared<Forwarded>()); + forwarded->setStanza(presence); + forwarded->setDelay(std::make_shared<Delay>(stringToDateTime(std::string("2010-07-10T23:08:25Z")))); + isodeIQDelegation->setForward(forwarded); + + CPPUNIT_ASSERT_EQUAL(std::string("<delegate xmlns=\"http://isode.com/iq_delegation\">" + "<forwarded xmlns=\"urn:xmpp:forward:0\">" + "<delay stamp=\"2010-07-10T23:08:25Z\" xmlns=\"urn:xmpp:delay\"/>" + "<presence type=\"subscribe\" xmlns=\"jabber:client\"/>" + "</forwarded>" + "</delegate>"), testling.serialize(isodeIQDelegation)); + } + private: + FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(IsodeIQDelegationSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp index e3ec8fc..c259cce 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp @@ -4,508 +4,404 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h> -#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Base/DateTime.h> #include <Swiften/Elements/JingleFileTransferDescription.h> -#include <Swiften/Elements/StreamInitiationFileInfo.h> -#include <Swiften/Elements/JingleIBBTransportPayload.h> -#include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h> #include <Swiften/Elements/JingleFileTransferHash.h> +#include <Swiften/Elements/JingleIBBTransportPayload.h> #include <Swiften/Elements/JinglePayload.h> -#include <Swiften/Elements/JingleFileTransferReceived.h> -#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h> +#include <Swiften/StringCodecs/Base64.h> using namespace Swift; class JingleSerializersTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(JingleSerializersTest); - CPPUNIT_TEST(testSerialize_StreamInitiationFileInfo); - CPPUNIT_TEST(testSerialize_StreamInitiationFileInfoRange); - - CPPUNIT_TEST(testSerialize_Xep0261_Example1); - CPPUNIT_TEST(testSerialize_Xep0261_Example9); - CPPUNIT_TEST(testSerialize_Xep0261_Example13); - - CPPUNIT_TEST(testSerialize_Xep0234_Example1); - CPPUNIT_TEST(testSerialize_Xep0234_Example3); - CPPUNIT_TEST(testSerialize_Xep0234_Example5); - CPPUNIT_TEST(testSerialize_Xep0234_Example8); - CPPUNIT_TEST(testSerialize_Xep0234_Example10); - CPPUNIT_TEST(testSerialize_Xep0234_Example13); - - CPPUNIT_TEST(testSerialize_Xep0260_Example1); - - CPPUNIT_TEST_SUITE_END(); - - boost::shared_ptr<JinglePayloadSerializer> createTestling() { - return boost::make_shared<JinglePayloadSerializer>(&collection); - } - - - public: - void testSerialize_StreamInitiationFileInfo() { - std::string expected = "<file" - " date=\"1969-07-21T02:56:15Z\"" - " hash=\"552da749930852c69ae5d2141d3766b1\"" - " name=\"test.txt\"" - " size=\"1022\"" - " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" - "<desc>This is a test. If this were a real file...</desc>" - "<range/>" - "</file>"; - - StreamInitiationFileInfo::ref fileInfo = boost::make_shared<StreamInitiationFileInfo>(); - fileInfo->setDate(stringToDateTime("1969-07-21T02:56:15Z")); - fileInfo->setHash("552da749930852c69ae5d2141d3766b1"); - fileInfo->setSize(1022); - fileInfo->setName("test.txt"); - fileInfo->setDescription("This is a test. If this were a real file..."); - fileInfo->setSupportsRangeRequests(true); - - boost::shared_ptr<StreamInitiationFileInfoSerializer> serializer = boost::make_shared<StreamInitiationFileInfoSerializer>(); - CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(fileInfo)); - } - - void testSerialize_StreamInitiationFileInfoRange() { - std::string expected = "<file hash=\"552da749930852c69ae5d2141d3766b1\"" - " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" - "<range offset=\"270336\"/>" - "</file>"; - - StreamInitiationFileInfo::ref fileInfo = boost::make_shared<StreamInitiationFileInfo>(); - fileInfo->setHash("552da749930852c69ae5d2141d3766b1"); - fileInfo->setSupportsRangeRequests(true); - fileInfo->setRangeOffset(270336); - - boost::shared_ptr<StreamInitiationFileInfoSerializer> serializer = boost::make_shared<StreamInitiationFileInfoSerializer>(); - CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(fileInfo)); - } - - - // IBB Transport Method Examples - - // http://xmpp.org/extensions/xep-0261.html#example-1 - void testSerialize_Xep0261_Example1() { - std::string expected = - "<jingle action=\"session-initiate\"" - " initiator=\"romeo@montague.lit/orchard\"" - " sid=\"a73sjjvkla37jfea\"" - " xmlns=\"urn:xmpp:jingle:1\">" - "<content creator=\"initiator\" name=\"ex\">" - "<transport block-size=\"4096\"" - " sid=\"ch3d9s71\"" - " xmlns=\"urn:xmpp:jingle:transports:ibb:1\"/>" - "</content>" - "</jingle>"; - - JinglePayload::ref payload = boost::make_shared<JinglePayload>(); - payload->setAction(JinglePayload::SessionInitiate); - payload->setSessionID("a73sjjvkla37jfea"); - payload->setInitiator(JID("romeo@montague.lit/orchard")); - - JingleIBBTransportPayload::ref transport = boost::make_shared<JingleIBBTransportPayload>(); - transport->setBlockSize(4096); - transport->setSessionID("ch3d9s71"); - - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(JingleContentPayload::InitiatorCreator); - content->setName("ex"); - content->addTransport(transport); - - payload->addPayload(content); - - CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); - } - - // http://xmpp.org/extensions/xep-0261.html#example-9 - void testSerialize_Xep0261_Example9() { - std::string expected = - "<jingle action=\"transport-info\"" - " initiator=\"romeo@montague.lit/orchard\"" - " sid=\"a73sjjvkla37jfea\"" - " xmlns=\"urn:xmpp:jingle:1\">" - "<content creator=\"initiator\" name=\"ex\">" - "<transport block-size=\"2048\"" - " sid=\"bt8a71h6\"" - " xmlns=\"urn:xmpp:jingle:transports:ibb:1\"/>" - "</content>" - "</jingle>"; - - JinglePayload::ref payload = boost::make_shared<JinglePayload>(); - payload->setAction(JinglePayload::TransportInfo); - payload->setInitiator(JID("romeo@montague.lit/orchard")); - payload->setSessionID("a73sjjvkla37jfea"); - - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(JingleContentPayload::InitiatorCreator); - content->setName("ex"); - - JingleIBBTransportPayload::ref transport = boost::make_shared<JingleIBBTransportPayload>(); - transport->setBlockSize(2048); - transport->setSessionID("bt8a71h6"); - - content->addTransport(transport); - payload->addPayload(content); - - CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); - } - - // http://xmpp.org/extensions/xep-0261.html#example-13 - void testSerialize_Xep0261_Example13() { - std::string expected = - "<jingle action=\"session-terminate\"" - " initiator=\"romeo@montague.lit/orchard\"" - " sid=\"a73sjjvkla37jfea\"" - " xmlns=\"urn:xmpp:jingle:1\">" - "<reason><success/></reason>" - "</jingle>"; - - JinglePayload::ref payload = boost::make_shared<JinglePayload>(); - payload->setAction(JinglePayload::SessionTerminate); - payload->setInitiator(JID("romeo@montague.lit/orchard")); - payload->setSessionID("a73sjjvkla37jfea"); - payload->setReason(JinglePayload::Reason(JinglePayload::Reason::Success)); - - CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); - } - - // http://xmpp.org/extensions/xep-0234.html#example-1 - void testSerialize_Xep0234_Example1() { - std::string expected = "<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">" - "<offer>" - "<file" - " date=\"1969-07-21T02:56:15Z\"" - " hash=\"552da749930852c69ae5d2141d3766b1\"" - " name=\"test.txt\"" - " size=\"1022\"" - " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" - "<desc>This is a test. If this were a real file...</desc>" - "<range/>" - "</file>" - "</offer>" - "</description>"; - JingleFileTransferDescription::ref desc = boost::make_shared<JingleFileTransferDescription>(); - StreamInitiationFileInfo fileInfo; - - fileInfo.setDate(stringToDateTime("1969-07-21T02:56:15Z")); - fileInfo.setHash("552da749930852c69ae5d2141d3766b1"); - fileInfo.setSize(1022); - fileInfo.setName("test.txt"); - fileInfo.setDescription("This is a test. If this were a real file..."); - fileInfo.setSupportsRangeRequests(true); - - desc->addOffer(fileInfo); - - CPPUNIT_ASSERT_EQUAL(expected, boost::make_shared<JingleFileTransferDescriptionSerializer>()->serialize(desc)); - } - - // http://xmpp.org/extensions/xep-0234.html#example-3 - void testSerialize_Xep0234_Example3() { - std::string expected = - "<jingle action=\"session-accept\"" - " initiator=\"romeo@montague.lit/orchard\"" - " sid=\"851ba2\"" - " xmlns=\"urn:xmpp:jingle:1\">" - "<content creator=\"initiator\" name=\"a-file-offer\">" - "<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">" - "<offer>" - "<file" - " date=\"1969-07-21T02:56:15Z\"" - " hash=\"552da749930852c69ae5d2141d3766b1\"" - " name=\"test.txt\"" - " size=\"1022\"" - " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" - "<desc>This is a test. If this were a real file...</desc>" - "<range/>" - "</file>" - "</offer>" - "</description>" - /*"<transport xmlns=\"urn:xmpp:jingle:transports:s5b:1\"" - " mode=\"tcp\"" - " sid=\"vj3hs98y\">" - "<candidate cid=\"ht567dq\"" - " host=\"192.169.1.10\"" - " jid=\"juliet@capulet.lit/balcony\"" - " port=\"6539\"" - " priority=\"8257636\"" - " type=\"direct\"/>" - "<candidate cid=\"hr65dqyd\"" - " host=\"134.102.201.180\"" - " jid=\"juliet@capulet.lit/balcony\"" - " port=\"16453\"" - " priority=\"7929856\"" - " type=\"assisted\"/>" - "<candidate cid=\"grt654q2\"" - " host=\"2001:638:708:30c9:219:d1ff:fea4:a17d\"" - " jid=\"juliet@capulet.lit/balcony\"" - " port=\"6539\"" - " priority=\"8257606\"" - " type=\"direct\"/>" - "</transport>"*/ - "</content>" - "</jingle>"; - - JinglePayload::ref payload = boost::make_shared<JinglePayload>(); - payload->setAction(JinglePayload::SessionAccept); - payload->setInitiator(JID("romeo@montague.lit/orchard")); - payload->setSessionID("851ba2"); - - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(JingleContentPayload::InitiatorCreator); - content->setName("a-file-offer"); - - JingleFileTransferDescription::ref description = boost::make_shared<JingleFileTransferDescription>(); - StreamInitiationFileInfo fileInfo; - fileInfo.setName("test.txt"); - fileInfo.setSize(1022); - fileInfo.setHash("552da749930852c69ae5d2141d3766b1"); - fileInfo.setDate(stringToDateTime("1969-07-21T02:56:15Z")); - fileInfo.setDescription("This is a test. If this were a real file..."); - fileInfo.setSupportsRangeRequests(true); - - description->addOffer(fileInfo); - content->addDescription(description); - payload->addPayload(content); - - CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); - } - - // http://xmpp.org/extensions/xep-0234.html#example-5 - void testSerialize_Xep0234_Example5() { - std::string expected = - "<jingle" - " action=\"transport-info\"" - " initiator=\"romeo@montague.lit/orchard\"" - " sid=\"a73sjjvkla37jfea\"" - " xmlns=\"urn:xmpp:jingle:1\">" - "<content creator=\"initiator\" name=\"ex\"/>" - /*"<transport" - " sid=\"vj3hs98y\"" - " xmlns=\"urn:xmpp:jingle:transports:s5b:1\">" - "<candidate-used cid=\"hr65dqyd\"/>" - "</transport>"*/ - //"</content>" - "</jingle>"; - - JinglePayload::ref payload = boost::make_shared<JinglePayload>(); - payload->setAction(JinglePayload::TransportInfo); - payload->setInitiator(JID("romeo@montague.lit/orchard")); - payload->setSessionID("a73sjjvkla37jfea"); - - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(JingleContentPayload::InitiatorCreator); - content->setName("ex"); - payload->addPayload(content); - - CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); - } - - // http://xmpp.org/extensions/xep-0234.html#example-8 - void testSerialize_Xep0234_Example8() { - std::string expected = - "<jingle" - " action=\"session-info\"" - " initiator=\"romeo@montague.lit/orchard\"" - " sid=\"a73sjjvkla37jfea\"" - " xmlns=\"urn:xmpp:jingle:1\">" - "<checksum xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">" - "<file>" - "<hashes xmlns=\"urn:xmpp:hashes:0\">" - "<hash algo=\"sha-1\">552da749930852c69ae5d2141d3766b1</hash>" - "</hashes>" - "</file>" - "</checksum>" - "</jingle>"; - - JinglePayload::ref payload = boost::make_shared<JinglePayload>(); - payload->setAction(JinglePayload::SessionInfo); - payload->setInitiator(JID("romeo@montague.lit/orchard")); - payload->setSessionID("a73sjjvkla37jfea"); - - JingleFileTransferHash::ref hash = boost::make_shared<JingleFileTransferHash>(); - hash->setHash("sha-1", "552da749930852c69ae5d2141d3766b1"); - - payload->addPayload(hash); - - CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); - } - - // http://xmpp.org/extensions/xep-0234.html#example-10 - void testSerialize_Xep0234_Example10() { - std::string expected = - "<jingle" - " action=\"session-initiate\"" - " initiator=\"romeo@montague.lit/orchard\"" - " sid=\"uj3b2\"" - " xmlns=\"urn:xmpp:jingle:1\">" - "<content creator=\"initiator\" name=\"a-file-request\">" - "<description" - " xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">" - "<request>" - "<file" - " hash=\"552da749930852c69ae5d2141d3766b1\"" - " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" - "<range offset=\"270336\"/>" - "</file>" - "</request>" - "</description>" - /*"<transport" - " mode=\"tcp\"" - " sid=\"xig361fj\"" - " xmlns=\"urn:xmpp:jingle:transports:s5b:1\">" - "<candidate" - " cid=\"ht567dq\"" - " host=\"192.169.1.10\"" - " jid=\"juliet@capulet.lit/balcony\"" - " port=\"6539\"" - " priority=\"8257636\"" - " type=\"direct\"/>" - "<candidate" - " cid=\"hr65dqyd\"" - " host=\"134.102.201.180\"" - " jid=\"juliet@capulet.lit/balcony\"" - " port=\"16453\"" - " priority=\"7929856\"" - " type=\"assisted\"/>" - "<candidate" - " cid=\"grt654q2\"" - " host=\"2001:638:708:30c9:219:d1ff:fea4:a17d\"" - " jid=\"juliet@capulet.lit/balcony\"" - " port=\"6539\"" - " priority=\"8257606\"" - " type=\"direct\"/>" - "</transport>"*/ - "</content>" - "</jingle>"; - - JinglePayload::ref payload = boost::make_shared<JinglePayload>(); - payload->setAction(JinglePayload::SessionInitiate); - payload->setInitiator(JID("romeo@montague.lit/orchard")); - payload->setSessionID("uj3b2"); - - StreamInitiationFileInfo fileInfo; - fileInfo.setHash("552da749930852c69ae5d2141d3766b1"); - fileInfo.setRangeOffset(270336); - - JingleFileTransferDescription::ref desc = boost::make_shared<JingleFileTransferDescription>(); - desc->addRequest(fileInfo); - - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(JingleContentPayload::InitiatorCreator); - content->setName("a-file-request"); - content->addDescription(desc); - - payload->addPayload(content); - - CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); - } - - // http://xmpp.org/extensions/xep-0234.html#example-10 - void testSerialize_Xep0234_Example13() { - std::string expected = - "<jingle" - " action=\"session-info\"" - " initiator=\"romeo@montague.lit/orchard\"" - " sid=\"a73sjjvkla37jfea\"" - " xmlns=\"urn:xmpp:jingle:1\">" - "<received xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">" - "<file" - " hash=\"a749930852c69ae5d2141d3766b1552d\"" - " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\"/>" - "</received>" - "</jingle>"; - - JinglePayload::ref payload = boost::make_shared<JinglePayload>(); - payload->setAction(JinglePayload::SessionInfo); - payload->setInitiator(JID("romeo@montague.lit/orchard")); - payload->setSessionID("a73sjjvkla37jfea"); - - JingleFileTransferReceived::ref received = boost::make_shared<JingleFileTransferReceived>(); - - StreamInitiationFileInfo fileInfo; - fileInfo.setHash("a749930852c69ae5d2141d3766b1552d"); - - received->setFileInfo(fileInfo); - payload->addPayload(received); - - CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); - } - - // http://xmpp.org/extensions/xep-0260.html#example-1 - void testSerialize_Xep0260_Example1() { - std::string expected = - "<jingle" - " action=\"session-initiate\"" - " initiator=\"romeo@montague.lit/orchard\"" - " sid=\"a73sjjvkla37jfea\"" - " xmlns=\"urn:xmpp:jingle:1\">" - "<content creator=\"initiator\" name=\"ex\">" - "<transport" - " mode=\"tcp\"" - " sid=\"vj3hs98y\"" - " xmlns=\"urn:xmpp:jingle:transports:s5b:1\">" - "<candidate cid=\"hft54dqy\"" - " host=\"192.168.4.1\"" - " jid=\"romeo@montague.lit/orchard\"" - " port=\"5086\"" - " priority=\"8257636\"" - " type=\"direct\"/>" - "<candidate cid=\"hutr46fe\"" - " host=\"24.24.24.1\"" - " jid=\"romeo@montague.lit/orchard\"" - " port=\"5087\"" - " priority=\"8258636\"" - " type=\"direct\"/>" - "</transport>" - "</content>" - "</jingle>"; - - JinglePayload::ref payload = boost::make_shared<JinglePayload>(); - payload->setAction(JinglePayload::SessionInitiate); - payload->setInitiator(JID("romeo@montague.lit/orchard")); - payload->setSessionID("a73sjjvkla37jfea"); - - JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); - content->setCreator(JingleContentPayload::InitiatorCreator); - content->setName("ex"); - - JingleS5BTransportPayload::ref transport = boost::make_shared<JingleS5BTransportPayload>(); - transport->setMode(JingleS5BTransportPayload::TCPMode); - transport->setSessionID("vj3hs98y"); - - JingleS5BTransportPayload::Candidate candidate1; - candidate1.cid = "hft54dqy"; - candidate1.hostPort = HostAddressPort(HostAddress("192.168.4.1"), 5086); - candidate1.jid = JID("romeo@montague.lit/orchard"); - candidate1.priority = 8257636; - candidate1.type = JingleS5BTransportPayload::Candidate::DirectType; - transport->addCandidate(candidate1); - - JingleS5BTransportPayload::Candidate candidate2; - candidate2.cid = "hutr46fe"; - candidate2.hostPort = HostAddressPort(HostAddress("24.24.24.1"), 5087); - candidate2.jid = JID("romeo@montague.lit/orchard"); - candidate2.priority = 8258636; - candidate2.type = JingleS5BTransportPayload::Candidate::DirectType; - transport->addCandidate(candidate2); - - content->addTransport(transport); - - payload->addPayload(content); - - CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); - } - - private: - FullPayloadSerializerCollection collection; + CPPUNIT_TEST_SUITE(JingleSerializersTest); + CPPUNIT_TEST(testSerialize_StreamInitiationFileInfo); + CPPUNIT_TEST(testSerialize_StreamInitiationFileInfoRange); + + CPPUNIT_TEST(testSerialize_Xep0261_Example1); + CPPUNIT_TEST(testSerialize_Xep0261_Example9); + CPPUNIT_TEST(testSerialize_Xep0261_Example13); + + CPPUNIT_TEST(testSerialize_Xep0234_Example1); + CPPUNIT_TEST(testSerialize_Xep0234_Example3); + CPPUNIT_TEST(testSerialize_Xep0234_Example5); + CPPUNIT_TEST(testSerialize_Xep0234_Example8); + + CPPUNIT_TEST(testSerialize_Xep0260_Example1); + + CPPUNIT_TEST_SUITE_END(); + + std::shared_ptr<JinglePayloadSerializer> createTestling() { + return std::make_shared<JinglePayloadSerializer>(&collection); + } + + + public: + void testSerialize_StreamInitiationFileInfo() { + std::string expected = "<file" + " date=\"1969-07-21T02:56:15Z\"" + " hash=\"552da749930852c69ae5d2141d3766b1\"" + " name=\"test.txt\"" + " size=\"1022\"" + " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" + "<desc>This is a test. If this were a real file...</desc>" + "<range/>" + "</file>"; + + StreamInitiationFileInfo::ref fileInfo = std::make_shared<StreamInitiationFileInfo>(); + fileInfo->setDate(stringToDateTime("1969-07-21T02:56:15Z")); + fileInfo->setHash("552da749930852c69ae5d2141d3766b1"); + fileInfo->setSize(1022); + fileInfo->setName("test.txt"); + fileInfo->setDescription("This is a test. If this were a real file..."); + fileInfo->setSupportsRangeRequests(true); + + std::shared_ptr<StreamInitiationFileInfoSerializer> serializer = std::make_shared<StreamInitiationFileInfoSerializer>(); + CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(fileInfo)); + } + + void testSerialize_StreamInitiationFileInfoRange() { + std::string expected = "<file hash=\"552da749930852c69ae5d2141d3766b1\"" + " xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" + "<range offset=\"270336\"/>" + "</file>"; + + StreamInitiationFileInfo::ref fileInfo = std::make_shared<StreamInitiationFileInfo>(); + fileInfo->setHash("552da749930852c69ae5d2141d3766b1"); + fileInfo->setSupportsRangeRequests(true); + fileInfo->setRangeOffset(270336); + + std::shared_ptr<StreamInitiationFileInfoSerializer> serializer = std::make_shared<StreamInitiationFileInfoSerializer>(); + CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(fileInfo)); + } + + + // IBB Transport Method Examples + + // http://xmpp.org/extensions/xep-0261.html#example-1 + void testSerialize_Xep0261_Example1() { + std::string expected = + "<jingle action=\"session-initiate\"" + " initiator=\"romeo@montague.lit/orchard\"" + " sid=\"a73sjjvkla37jfea\"" + " xmlns=\"urn:xmpp:jingle:1\">" + "<content creator=\"initiator\" name=\"ex\">" + "<transport block-size=\"4096\"" + " sid=\"ch3d9s71\"" + " xmlns=\"urn:xmpp:jingle:transports:ibb:1\"/>" + "</content>" + "</jingle>"; + + JinglePayload::ref payload = std::make_shared<JinglePayload>(); + payload->setAction(JinglePayload::SessionInitiate); + payload->setSessionID("a73sjjvkla37jfea"); + payload->setInitiator(JID("romeo@montague.lit/orchard")); + + JingleIBBTransportPayload::ref transport = std::make_shared<JingleIBBTransportPayload>(); + transport->setBlockSize(4096); + transport->setSessionID("ch3d9s71"); + + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(JingleContentPayload::InitiatorCreator); + content->setName("ex"); + content->addTransport(transport); + + payload->addPayload(content); + + CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); + } + + // http://xmpp.org/extensions/xep-0261.html#example-9 + void testSerialize_Xep0261_Example9() { + std::string expected = + "<jingle action=\"transport-info\"" + " initiator=\"romeo@montague.lit/orchard\"" + " sid=\"a73sjjvkla37jfea\"" + " xmlns=\"urn:xmpp:jingle:1\">" + "<content creator=\"initiator\" name=\"ex\">" + "<transport block-size=\"2048\"" + " sid=\"bt8a71h6\"" + " xmlns=\"urn:xmpp:jingle:transports:ibb:1\"/>" + "</content>" + "</jingle>"; + + JinglePayload::ref payload = std::make_shared<JinglePayload>(); + payload->setAction(JinglePayload::TransportInfo); + payload->setInitiator(JID("romeo@montague.lit/orchard")); + payload->setSessionID("a73sjjvkla37jfea"); + + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(JingleContentPayload::InitiatorCreator); + content->setName("ex"); + + JingleIBBTransportPayload::ref transport = std::make_shared<JingleIBBTransportPayload>(); + transport->setBlockSize(2048); + transport->setSessionID("bt8a71h6"); + + content->addTransport(transport); + payload->addPayload(content); + + CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); + } + + // http://xmpp.org/extensions/xep-0261.html#example-13 + void testSerialize_Xep0261_Example13() { + std::string expected = + "<jingle action=\"session-terminate\"" + " initiator=\"romeo@montague.lit/orchard\"" + " sid=\"a73sjjvkla37jfea\"" + " xmlns=\"urn:xmpp:jingle:1\">" + "<reason><success/></reason>" + "</jingle>"; + + JinglePayload::ref payload = std::make_shared<JinglePayload>(); + payload->setAction(JinglePayload::SessionTerminate); + payload->setInitiator(JID("romeo@montague.lit/orchard")); + payload->setSessionID("a73sjjvkla37jfea"); + payload->setReason(JinglePayload::Reason(JinglePayload::Reason::Success)); + + CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); + } + + // http://xmpp.org/extensions/xep-0234.html#example-1 + void testSerialize_Xep0234_Example1() { + std::string expected = "<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:4\">" + "<file>" + "<date>1969-07-21T02:56:15Z</date>" + "<desc>This is a test. If this were a real file...</desc>" + "<name>test.txt</name>" + "<range/>" + "<size>1022</size>" + "<hash algo=\"sha-1\" xmlns=\"urn:xmpp:hashes:1\">VS2nSZMIUsaa5dIUHTdmsQ==</hash>" + "</file>" + "</description>"; + JingleFileTransferDescription::ref desc = std::make_shared<JingleFileTransferDescription>(); + JingleFileTransferFileInfo fileInfo; + + fileInfo.setDate(stringToDateTime("1969-07-21T02:56:15Z")); + fileInfo.addHash(HashElement("sha-1", Base64::decode("VS2nSZMIUsaa5dIUHTdmsQ=="))); + fileInfo.setSize(1022); + fileInfo.setName("test.txt"); + fileInfo.setDescription("This is a test. If this were a real file..."); + fileInfo.setSupportsRangeRequests(true); + + desc->setFileInfo(fileInfo); + + CPPUNIT_ASSERT_EQUAL(expected, std::make_shared<JingleFileTransferDescriptionSerializer>()->serialize(desc)); + } + + // http://xmpp.org/extensions/xep-0234.html#example-3 + void testSerialize_Xep0234_Example3() { + std::string expected = + "<jingle action=\"session-accept\"" + " initiator=\"romeo@montague.lit/orchard\"" + " sid=\"851ba2\"" + " xmlns=\"urn:xmpp:jingle:1\">" + "<content creator=\"initiator\" name=\"a-file-offer\">" + "<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:4\">" + "<file>" + "<date>1969-07-21T02:56:15Z</date>" + "<desc>This is a test. If this were a real file...</desc>" + "<name>test.txt</name>" + "<range/>" + "<size>1022</size>" + "<hash algo=\"sha-1\" xmlns=\"urn:xmpp:hashes:1\">VS2nSZMIUsaa5dIUHTdmsQ==</hash>" + "</file>" + "</description>" + /*"<transport xmlns=\"urn:xmpp:jingle:transports:s5b:1\"" + " mode=\"tcp\"" + " sid=\"vj3hs98y\">" + "<candidate cid=\"ht567dq\"" + " host=\"192.169.1.10\"" + " jid=\"juliet@capulet.lit/balcony\"" + " port=\"6539\"" + " priority=\"8257636\"" + " type=\"direct\"/>" + "<candidate cid=\"hr65dqyd\"" + " host=\"134.102.201.180\"" + " jid=\"juliet@capulet.lit/balcony\"" + " port=\"16453\"" + " priority=\"7929856\"" + " type=\"assisted\"/>" + "<candidate cid=\"grt654q2\"" + " host=\"2001:638:708:30c9:219:d1ff:fea4:a17d\"" + " jid=\"juliet@capulet.lit/balcony\"" + " port=\"6539\"" + " priority=\"8257606\"" + " type=\"direct\"/>" + "</transport>"*/ + "</content>" + "</jingle>"; + + JinglePayload::ref payload = std::make_shared<JinglePayload>(); + payload->setAction(JinglePayload::SessionAccept); + payload->setInitiator(JID("romeo@montague.lit/orchard")); + payload->setSessionID("851ba2"); + + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(JingleContentPayload::InitiatorCreator); + content->setName("a-file-offer"); + + JingleFileTransferDescription::ref description = std::make_shared<JingleFileTransferDescription>(); + JingleFileTransferFileInfo fileInfo; + fileInfo.setName("test.txt"); + fileInfo.setSize(1022); + fileInfo.addHash(HashElement("sha-1", Base64::decode("VS2nSZMIUsaa5dIUHTdmsQ=="))); + fileInfo.setDate(stringToDateTime("1969-07-21T02:56:15Z")); + fileInfo.setDescription("This is a test. If this were a real file..."); + fileInfo.setSupportsRangeRequests(true); + + description->setFileInfo(fileInfo); + content->addDescription(description); + payload->addPayload(content); + + CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); + } + + // http://xmpp.org/extensions/xep-0234.html#example-5 + void testSerialize_Xep0234_Example5() { + std::string expected = + "<jingle" + " action=\"transport-info\"" + " initiator=\"romeo@montague.lit/orchard\"" + " sid=\"a73sjjvkla37jfea\"" + " xmlns=\"urn:xmpp:jingle:1\">" + "<content creator=\"initiator\" name=\"ex\"/>" + /*"<transport" + " sid=\"vj3hs98y\"" + " xmlns=\"urn:xmpp:jingle:transports:s5b:1\">" + "<candidate-used cid=\"hr65dqyd\"/>" + "</transport>"*/ + //"</content>" + "</jingle>"; + + JinglePayload::ref payload = std::make_shared<JinglePayload>(); + payload->setAction(JinglePayload::TransportInfo); + payload->setInitiator(JID("romeo@montague.lit/orchard")); + payload->setSessionID("a73sjjvkla37jfea"); + + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(JingleContentPayload::InitiatorCreator); + content->setName("ex"); + payload->addPayload(content); + + CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); + } + + // http://xmpp.org/extensions/xep-0234.html#example-8 + void testSerialize_Xep0234_Example8() { + std::string expected = + "<jingle" + " action=\"session-info\"" + " initiator=\"romeo@montague.lit/orchard\"" + " sid=\"a73sjjvkla37jfea\"" + " xmlns=\"urn:xmpp:jingle:1\">" + "<checksum xmlns=\"urn:xmpp:jingle:apps:file-transfer:4\">" + "<file>" + "<hash algo=\"sha-1\" xmlns=\"urn:xmpp:hashes:1\">VS2nSZMIUsaa5dIUHTdmsQ==</hash>" + "</file>" + "</checksum>" + "</jingle>"; + + JinglePayload::ref payload = std::make_shared<JinglePayload>(); + payload->setAction(JinglePayload::SessionInfo); + payload->setInitiator(JID("romeo@montague.lit/orchard")); + payload->setSessionID("a73sjjvkla37jfea"); + + JingleFileTransferHash::ref hash = std::make_shared<JingleFileTransferHash>(); + hash->getFileInfo().addHash(HashElement("sha-1", Base64::decode("VS2nSZMIUsaa5dIUHTdmsQ=="))); + + payload->addPayload(hash); + + CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); + } + + // http://xmpp.org/extensions/xep-0260.html#example-1 + void testSerialize_Xep0260_Example1() { + std::string expected = + "<jingle" + " action=\"session-initiate\"" + " initiator=\"romeo@montague.lit/orchard\"" + " sid=\"a73sjjvkla37jfea\"" + " xmlns=\"urn:xmpp:jingle:1\">" + "<content creator=\"initiator\" name=\"ex\">" + "<transport" + " dstaddr=\"1a12fb7bc625e55f3ed5b29a53dbe0e4aa7d80ba\"" + " mode=\"tcp\"" + " sid=\"vj3hs98y\"" + " xmlns=\"urn:xmpp:jingle:transports:s5b:1\">" + "<candidate cid=\"hft54dqy\"" + " host=\"192.168.4.1\"" + " jid=\"romeo@montague.lit/orchard\"" + " port=\"5086\"" + " priority=\"8257636\"" + " type=\"direct\"/>" + "<candidate cid=\"hutr46fe\"" + " host=\"24.24.24.1\"" + " jid=\"romeo@montague.lit/orchard\"" + " port=\"5087\"" + " priority=\"8258636\"" + " type=\"direct\"/>" + "</transport>" + "</content>" + "</jingle>"; + + JinglePayload::ref payload = std::make_shared<JinglePayload>(); + payload->setAction(JinglePayload::SessionInitiate); + payload->setInitiator(JID("romeo@montague.lit/orchard")); + payload->setSessionID("a73sjjvkla37jfea"); + + JingleContentPayload::ref content = std::make_shared<JingleContentPayload>(); + content->setCreator(JingleContentPayload::InitiatorCreator); + content->setName("ex"); + + JingleS5BTransportPayload::ref transport = std::make_shared<JingleS5BTransportPayload>(); + transport->setMode(JingleS5BTransportPayload::TCPMode); + transport->setDstAddr("1a12fb7bc625e55f3ed5b29a53dbe0e4aa7d80ba"); + transport->setSessionID("vj3hs98y"); + + JingleS5BTransportPayload::Candidate candidate1; + candidate1.cid = "hft54dqy"; + candidate1.hostPort = HostAddressPort(HostAddress::fromString("192.168.4.1").get(), 5086); + candidate1.jid = JID("romeo@montague.lit/orchard"); + candidate1.priority = 8257636; + candidate1.type = JingleS5BTransportPayload::Candidate::DirectType; + transport->addCandidate(candidate1); + + JingleS5BTransportPayload::Candidate candidate2; + candidate2.cid = "hutr46fe"; + candidate2.hostPort = HostAddressPort(HostAddress::fromString("24.24.24.1").get(), 5087); + candidate2.jid = JID("romeo@montague.lit/orchard"); + candidate2.priority = 8258636; + candidate2.type = JingleS5BTransportPayload::Candidate::DirectType; + transport->addCandidate(candidate2); + + content->addTransport(transport); + + payload->addPayload(content); + + CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); + } + + private: + FullPayloadSerializerCollection collection; }; CPPUNIT_TEST_SUITE_REGISTRATION(JingleSerializersTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MAMFinSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMFinSerializerTest.cpp new file mode 100644 index 0000000..198f73c --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMFinSerializerTest.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/MAMFinSerializer.h> + +using namespace Swift; + +class MAMFinSerializerTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(MAMFinSerializerTest); + CPPUNIT_TEST(testSerialize_XEP0313_Exmaple1); + CPPUNIT_TEST(testSerialize_XEP0313_Exmaple9); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize_XEP0313_Exmaple1() { + MAMFinSerializer serializer; + + std::shared_ptr<MAMFin> fin = std::make_shared<MAMFin>(); + fin->setQueryID("f27"); + + std::string expectedResult = + "<fin queryid=\"f27\" xmlns=\"urn:xmpp:mam:0\"/>"; + CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(fin)); + } + + void testSerialize_XEP0313_Exmaple9() { + MAMFinSerializer serializer; + + std::shared_ptr<MAMFin> fin = std::make_shared<MAMFin>(); + fin->setComplete(true); + + std::shared_ptr<ResultSet> set = std::make_shared<ResultSet>(); + set->setFirstID(std::string("23452-4534-1")); + set->setFirstIDIndex(0); + set->setLastID(std::string("390-2342-22")); + set->setCount(16); + + fin->setResultSet(set); + + std::string expectedResult = + "<fin complete=\"true\" xmlns=\"urn:xmpp:mam:0\">" + "<set xmlns=\"http://jabber.org/protocol/rsm\">" + "<count>16</count>" + "<first index=\"0\">23452-4534-1</first>" + "<last>390-2342-22</last>" + "</set>" + "</fin>"; + CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(fin)); + } + + private: + FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MAMFinSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MAMQuerySerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMQuerySerializerTest.cpp new file mode 100644 index 0000000..cc46ef9 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMQuerySerializerTest.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> + +#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/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/MAMQuerySerializer.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; + + std::shared_ptr<Form> parameters(std::make_shared<Form>()); + + std::shared_ptr<FormField> fieldType = std::make_shared<FormField>(FormField::TextSingleType); + fieldType->setName("FORM_TYPE"); + fieldType->addValue("urn:xmpp:mam:0"); + parameters->addField(fieldType); + + std::shared_ptr<FormField> fieldStart = std::make_shared<FormField>(FormField::TextSingleType); + fieldStart->setName("start"); + fieldStart->addValue("2010-08-07T00:00:00Z"); + parameters->addField(fieldStart); + + std::shared_ptr<ResultSet> set = std::make_shared<ResultSet>(); + set->setMaxItems(10); + + std::shared_ptr<MAMQuery> query(std::make_shared<MAMQuery>()); + query->setQueryID(std::string("id0")); + query->setNode(std::string("node1")); + query->setForm(parameters); + query->setResultSet(set); + + std::string expectedResult = + "<query node=\"node1\" 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..09bec39 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MAMResultSerializerTest.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> + +#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/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/MAMResultSerializer.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); + + std::shared_ptr<Message> message(std::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."); + + std::shared_ptr<Forwarded> forwarded(std::make_shared<Forwarded>()); + forwarded->setStanza(message); + forwarded->setDelay(std::make_shared<Delay>(stringToDateTime(std::string("2010-07-10T23:08:25Z")))); + + std::shared_ptr<MAMResult> result(std::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/MIXCreateSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXCreateSerializerTest.cpp new file mode 100644 index 0000000..80210a5 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXCreateSerializerTest.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/MIXCreateSerializer.h> + +using namespace Swift; + +TEST(MIXCreateSerializerTest, XEP0369_Example31) { + MIXCreateSerializer testling; + + auto create = std::make_shared<MIXCreate>(); + std::string expectedResult = "<create xmlns=\"urn:xmpp:mix:0\"/>"; + ASSERT_EQ(expectedResult, testling.serialize(create)); +} + +TEST(MIXCreateSerializerTest, XEP0369_Example66) { + MIXCreateSerializer testling; + + auto create = std::make_shared<MIXCreate>(); + create->setChannel(std::string("coven")); + + std::string expectedResult = "<create channel=\"coven\" xmlns=\"urn:xmpp:mix:0\"/>"; + ASSERT_EQ(expectedResult, testling.serialize(create)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MIXDestroySerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXDestroySerializerTest.cpp new file mode 100644 index 0000000..5b21873 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXDestroySerializerTest.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/MIXDestroySerializer.h> + +using namespace Swift; + +TEST(MIXDestroySerializerTest, XEP0369_Example31) { + MIXDestroySerializer testling; + + auto destroy = std::make_shared<MIXDestroy>(); + destroy->setChannel(std::string("coven")); + + std::string expectedResult = "<destroy channel=\"coven\" xmlns=\"urn:xmpp:mix:0\"/>"; + ASSERT_EQ(expectedResult, testling.serialize(destroy)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MIXJoinSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXJoinSerializerTest.cpp new file mode 100644 index 0000000..2987a20 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXJoinSerializerTest.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/MIXJoinSerializer.h> + +using namespace Swift; + +TEST(MIXJoinSerializerTest, XEP0369_Example22) { + MIXJoinSerializer testling; + + auto join = std::make_shared<MIXJoin>(); + join->setChannel(JID("coven@mix.shakespeare.example")); + + join->addSubscription(std::string("urn:xmpp:mix:nodes:messages")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:presence")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:participants")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:config")); + + std::string expectedResult = "<join channel=\"coven@mix.shakespeare.example\" xmlns=\"urn:xmpp:mix:0\">" + "<subscribe node=\"urn:xmpp:mix:nodes:config\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:participants\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:presence\"/>" + "</join>"; + ASSERT_EQ(expectedResult, testling.serialize(join)); +} + +TEST(MIXJoinSerializerTest, XEP0369_Example23) { + MIXJoinSerializer testling; + + std::shared_ptr<MIXJoin> join(new MIXJoin()); + + join->addSubscription(std::string("urn:xmpp:mix:nodes:messages")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:presence")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:participants")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:config")); + + std::string expectedResult = "<join xmlns=\"urn:xmpp:mix:0\">" + "<subscribe node=\"urn:xmpp:mix:nodes:config\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:participants\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:presence\"/>" + "</join>"; + ASSERT_EQ(expectedResult, testling.serialize(join)); +} + +TEST(MIXJoinSerializerTest, XEP0369_Example24) { + MIXJoinSerializer testling; + + std::shared_ptr<MIXJoin> join(new MIXJoin()); + join->setJID(JID("123456#coven@mix.shakespeare.example")); + + join->addSubscription(std::string("urn:xmpp:mix:nodes:messages")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:presence")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:participants")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:config")); + + std::string expectedResult = "<join jid=\"123456#coven@mix.shakespeare.example\" xmlns=\"urn:xmpp:mix:0\">" + "<subscribe node=\"urn:xmpp:mix:nodes:config\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:participants\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:presence\"/>" + "</join>"; + ASSERT_EQ(expectedResult, testling.serialize(join)); +} + +TEST(MIXJoinSerializerTest, XEP0369_Example29) { + MIXJoinSerializer testling; + + std::shared_ptr<MIXJoin> join(new MIXJoin()); + + join->addSubscription(std::string("urn:xmpp:mix:nodes:messages")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:presence")); + + std::shared_ptr<Form> parameters(std::make_shared<Form>()); + parameters->setType(Form::Type::SubmitType); + + std::shared_ptr<FormField> fieldType = std::make_shared<FormField>(FormField::HiddenType); + fieldType->setName("FORM_TYPE"); + fieldType->addValue("urn:xmpp:mix:0"); + parameters->addField(fieldType); + + std::shared_ptr<FormField> fieldJIDVisibility = std::make_shared<FormField>(); + fieldJIDVisibility->setName("JID Visibility"); + fieldJIDVisibility->addValue("never"); + parameters->addField(fieldJIDVisibility); + + join->setForm(parameters); + + std::string expectedResult = "<join xmlns=\"urn:xmpp:mix:0\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:presence\"/>" + "<x type=\"submit\" xmlns=\"jabber:x:data\">" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>urn:xmpp:mix:0</value>" + "</field>" + "<field var=\"JID Visibility\">" + "<value>never</value>" + "</field>" + "</x>" + "</join>"; + ASSERT_EQ(expectedResult, testling.serialize(join)); +} + +TEST(MIXJoinSerializerTest, XEP0369_Example30) { + MIXJoinSerializer testling; + + std::shared_ptr<MIXJoin> join(new MIXJoin()); + join->setJID(JID("hag66@shakespeare.example")); + + join->addSubscription(std::string("urn:xmpp:mix:nodes:messages")); + join->addSubscription(std::string("urn:xmpp:mix:nodes:presence")); + + std::shared_ptr<Form> parameters(std::make_shared<Form>()); + parameters->setType(Form::Type::ResultType); + + std::shared_ptr<FormField> fieldType = std::make_shared<FormField>(FormField::HiddenType); + fieldType->setName("FORM_TYPE"); + fieldType->addValue("urn:xmpp:mix:0"); + parameters->addField(fieldType); + + std::shared_ptr<FormField> fieldJIDVisibility = std::make_shared<FormField>(); + fieldJIDVisibility->setName("JID Visibility"); + fieldJIDVisibility->addValue("never"); + parameters->addField(fieldJIDVisibility); + + std::shared_ptr<FormField> fieldprivateMessages = std::make_shared<FormField>(); + fieldprivateMessages->setName("Private Messages"); + fieldprivateMessages->addValue("allow"); + parameters->addField(fieldprivateMessages); + + std::shared_ptr<FormField> vCard = std::make_shared<FormField>(); + vCard->setName("vCard"); + vCard->addValue("block"); + parameters->addField(vCard); + + join->setForm(parameters); + + std::string expectedResult = "<join jid=\"hag66@shakespeare.example\" xmlns=\"urn:xmpp:mix:0\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "<subscribe node=\"urn:xmpp:mix:nodes:presence\"/>" + "<x type=\"result\" xmlns=\"jabber:x:data\">" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>urn:xmpp:mix:0</value>" + "</field>" + "<field var=\"JID Visibility\">" + "<value>never</value>" + "</field>" + "<field var=\"Private Messages\">" + "<value>allow</value>" + "</field>" + "<field var=\"vCard\">" + "<value>block</value>" + "</field>" + "</x>" + "</join>"; + ASSERT_EQ(expectedResult, testling.serialize(join)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MIXLeaveSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXLeaveSerializerTest.cpp new file mode 100644 index 0000000..d9537a8 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXLeaveSerializerTest.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/MIXLeaveSerializer.h> + +using namespace Swift; + +TEST(MIXLeaveSerializerTest, XEP0369_Example33) { + MIXLeaveSerializer testling; + + auto leave = std::shared_ptr<MIXLeave>(new MIXLeave()); + leave->setChannel(JID("coven@mix.shakespeare.example")); + + std::string expectedResult = "<leave channel=\"coven@mix.shakespeare.example\" xmlns=\"urn:xmpp:mix:0\"/>"; + ASSERT_EQ(expectedResult, testling.serialize(leave)); +} + +TEST(MIXLeaveSerializerTest, XEP0369_Example34) { + MIXLeaveSerializer testling; + + auto leave = std::shared_ptr<MIXLeave>(new MIXLeave()); + + std::string expectedResult = "<leave xmlns=\"urn:xmpp:mix:0\"/>"; + ASSERT_EQ(expectedResult, testling.serialize(leave)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MIXParticipantSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXParticipantSerializerTest.cpp new file mode 100644 index 0000000..a298d78 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXParticipantSerializerTest.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/MIXParticipantSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +TEST(MIXParticipantSerializerTest, testSerializeEmpty) { + MIXParticipantSerializer testling; + + std::shared_ptr<MIXParticipant> participant(new MIXParticipant()); + + std::string expectedResult = "<participant xmlns=\"urn:xmpp:mix:0\"/>"; + ASSERT_EQ(expectedResult, testling.serialize(participant)); +} + +TEST(MIXParticipantSerializerTest, testSerializeNick) { + MIXParticipantSerializer testling; + + std::shared_ptr<MIXParticipant> participant(new MIXParticipant()); + participant->setNick("thirdwitch"); + + std::string expectedResult = "<participant xmlns=\"urn:xmpp:mix:0\">" + "<nick>thirdwitch</nick>" + "</participant>"; + ASSERT_EQ(expectedResult, testling.serialize(participant)); +} + +TEST(MIXParticipantSerializerTest, testSerializeJID) { + MIXParticipantSerializer testling; + + std::shared_ptr<MIXParticipant> participant(new MIXParticipant()); + participant->setJID(JID("hecate@mix.shakespeare.example")); + + std::string expectedResult = "<participant xmlns=\"urn:xmpp:mix:0\">" + "<jid>hecate@mix.shakespeare.example</jid>" + "</participant>"; + ASSERT_EQ(expectedResult, testling.serialize(participant)); +} + +TEST(MIXParticipantSerializerTest, testSerializeJIDAndNick) { + MIXParticipantSerializer testling; + + std::shared_ptr<MIXParticipant> participant(new MIXParticipant()); + participant->setNick("thirdwitch"); + participant->setJID(JID("hecate@mix.shakespeare.example")); + + std::string expectedResult = "<participant xmlns=\"urn:xmpp:mix:0\">" + "<nick>thirdwitch</nick>" + "<jid>hecate@mix.shakespeare.example</jid>" + "</participant>"; + ASSERT_EQ(expectedResult, testling.serialize(participant)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MIXPayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXPayloadSerializerTest.cpp new file mode 100644 index 0000000..266b066 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXPayloadSerializerTest.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/MIXPayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +TEST(MIXPayloadSerializerTest, testSerializeEmpty) { + MIXPayloadSerializer testling; + + auto mix = std::shared_ptr<MIXPayload>(new MIXPayload()); + + std::string expectedResult = "<mix xmlns=\"urn:xmpp:mix:0\"/>"; + ASSERT_EQ(expectedResult, testling.serialize(mix)); +} + +TEST(MIXPayloadSerializerTest, testSerializeNick) { + MIXPayloadSerializer testling; + + auto mix = std::shared_ptr<MIXPayload>(new MIXPayload()); + mix->setNick("thirdwitch"); + + std::string expectedResult = "<mix xmlns=\"urn:xmpp:mix:0\">" + "<nick>thirdwitch</nick>" + "</mix>"; + ASSERT_EQ(expectedResult, testling.serialize(mix)); +} + +TEST(MIXPayloadSerializerTest, testSerializeJID) { + MIXPayloadSerializer testling; + + auto mix = std::shared_ptr<MIXPayload>(new MIXPayload()); + mix->setJID(JID("hecate@mix.shakespeare.example")); + + std::string expectedResult = "<mix xmlns=\"urn:xmpp:mix:0\">" + "<jid>hecate@mix.shakespeare.example</jid>" + "</mix>"; + ASSERT_EQ(expectedResult, testling.serialize(mix)); +} + +TEST(MIXPayloadSerializerTest, testSerializeAll) { + MIXPayloadSerializer testling; + + auto mix = std::shared_ptr<MIXPayload>(new MIXPayload()); + mix->setNick("thirdwitch"); + mix->setJID(JID("hecate@mix.shakespeare.example")); + mix->setSubmissionID("92vax143g"); + + std::string expectedResult = "<mix xmlns=\"urn:xmpp:mix:0\">" + "<nick>thirdwitch</nick>" + "<jid>hecate@mix.shakespeare.example</jid>" + "<submission-id>92vax143g</submission-id>" + "</mix>"; + ASSERT_EQ(expectedResult, testling.serialize(mix)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MIXRegisterNickSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXRegisterNickSerializerTest.cpp new file mode 100644 index 0000000..dc6cf0c --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXRegisterNickSerializerTest.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/MIXRegisterNickSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +TEST(MIXRegisterNickSerializerTest, testSerializeNick) { + MIXRegisterNickSerializer testling; + + auto mix = std::shared_ptr<MIXRegisterNick>(new MIXRegisterNick()); + mix->setNick(std::string("thirdwitch")); + + std::string expectedResult = "<register xmlns=\"urn:xmpp:mix:0\"><nick>thirdwitch</nick></register>"; + ASSERT_EQ(expectedResult, testling.serialize(mix)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MIXSetNickSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXSetNickSerializerTest.cpp new file mode 100644 index 0000000..ab29bc5 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXSetNickSerializerTest.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/MIXSetNickSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +TEST(MIXSetNickSerializerTest, testSerializeNick) { + MIXSetNickSerializer testling; + + auto mix = std::shared_ptr<MIXSetNick>(new MIXSetNick()); + mix->setNick(std::string("thirdwitch")); + + std::string expectedResult = "<setnick xmlns=\"urn:xmpp:mix:0\"><nick>thirdwitch</nick></setnick>"; + ASSERT_EQ(expectedResult, testling.serialize(mix)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MIXUpdateSubscriptionSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXUpdateSubscriptionSerializerTest.cpp new file mode 100644 index 0000000..3e35a82 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXUpdateSubscriptionSerializerTest.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/MIXUpdateSubscriptionSerializer.h> + +using namespace Swift; + +TEST(MIXUpdateSubscriptionSerializerTest, XEP0369_Example28) { + MIXUpdateSubscriptionSerializer testling; + + auto update = std::make_shared<MIXUpdateSubscription>(); + update->addSubscription(std::string("urn:xmpp:mix:nodes:messages")); + + std::string expectedResult = "<update-subscription xmlns=\"urn:xmpp:mix:0\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "</update-subscription>"; + ASSERT_EQ(expectedResult, testling.serialize(update)); +} + +TEST(MIXUpdateSubscriptionSerializerTest, XEP0369_Example28WithJID) { + MIXUpdateSubscriptionSerializer testling; + + auto update = std::make_shared<MIXUpdateSubscription>(); + update->setJID(JID("hag66@shakespeare.example")); + update->addSubscription(std::string("urn:xmpp:mix:nodes:messages")); + + std::string expectedResult = "<update-subscription jid=\"hag66@shakespeare.example\" xmlns=\"urn:xmpp:mix:0\">" + "<subscribe node=\"urn:xmpp:mix:nodes:messages\"/>" + "</update-subscription>"; + ASSERT_EQ(expectedResult, testling.serialize(update)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MIXUserPreferenceSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXUserPreferenceSerializerTest.cpp new file mode 100644 index 0000000..0226b0f --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MIXUserPreferenceSerializerTest.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017 Tarun Gupta + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/MIXUserPreferenceSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +TEST(MIXUserPreferenceSerializerTest, XEP0369_Example31) { + MIXUserPreferenceSerializer testling; + + auto userpreference = std::shared_ptr<MIXUserPreference>(new MIXUserPreference()); + std::string expectedResult = "<user-preference xmlns=\"urn:xmpp:mix:0\"/>"; + ASSERT_EQ(expectedResult, testling.serialize(userpreference)); +} + +TEST(MIXUserPreferenceSerializerTest, XEP0369_Example32) { + MIXUserPreferenceSerializer testling; + + auto userpreference = std::shared_ptr<MIXUserPreference>(new MIXUserPreference()); + std::shared_ptr<Form> parameters(std::make_shared<Form>()); + parameters->setType(Form::Type::ResultType); + + std::shared_ptr<FormField> fieldType = std::make_shared<FormField>(FormField::HiddenType); + fieldType->setName("FORM_TYPE"); + fieldType->addValue("urn:xmpp:mix:0"); + parameters->addField(fieldType); + + std::shared_ptr<FormField> fieldJIDVisibility = std::make_shared<FormField>(); + fieldJIDVisibility->setName("JID Visibility"); + fieldJIDVisibility->addValue("never"); + parameters->addField(fieldJIDVisibility); + + std::shared_ptr<FormField> fieldprivateMessages = std::make_shared<FormField>(); + fieldprivateMessages->setName("Private Messages"); + fieldprivateMessages->addValue("allow"); + parameters->addField(fieldprivateMessages); + + std::shared_ptr<FormField> vCard = std::make_shared<FormField>(); + vCard->setName("vCard"); + vCard->addValue("block"); + parameters->addField(vCard); + + userpreference->setData(parameters); + + std::string expectedResult = "<user-preference xmlns=\"urn:xmpp:mix:0\">" + "<x type=\"result\" xmlns=\"jabber:x:data\">" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>urn:xmpp:mix:0</value>" + "</field>" + "<field var=\"JID Visibility\">" + "<value>never</value>" + "</field>" + "<field var=\"Private Messages\">" + "<value>allow</value>" + "</field>" + "<field var=\"vCard\">" + "<value>block</value>" + "</field>" + "</x>" + "</user-preference>"; + ASSERT_EQ(expectedResult, testling.serialize(userpreference)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp index a8acf80..5aeb9dd 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp @@ -1,39 +1,39 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h> using namespace Swift; class MUCAdminPayloadSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(MUCAdminPayloadSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); - - public: - MUCAdminPayloadSerializerTest() {} - - void testSerialize() { - MUCAdminPayloadSerializer testling; - boost::shared_ptr<MUCAdminPayload> admin = boost::make_shared<MUCAdminPayload>(); - MUCItem item; - item.affiliation = MUCOccupant::Owner; - item.role = MUCOccupant::Visitor; - item.reason = "malice"; - item.actor = JID("kev@tester.lit"); - admin->addItem(item); - - CPPUNIT_ASSERT_EQUAL(std::string("<query xmlns=\"http://jabber.org/protocol/muc#admin\"><item affiliation=\"owner\" role=\"visitor\"><actor jid=\"kev@tester.lit\"/><reason>malice</reason></item></query>"), testling.serialize(admin)); - } + CPPUNIT_TEST_SUITE(MUCAdminPayloadSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); + + public: + MUCAdminPayloadSerializerTest() {} + + void testSerialize() { + MUCAdminPayloadSerializer testling; + std::shared_ptr<MUCAdminPayload> admin = std::make_shared<MUCAdminPayload>(); + MUCItem item; + item.affiliation = MUCOccupant::Owner; + item.role = MUCOccupant::Visitor; + item.reason = "malice"; + item.actor = JID("kev@tester.lit"); + admin->addItem(item); + + CPPUNIT_ASSERT_EQUAL(std::string("<query xmlns=\"http://jabber.org/protocol/muc#admin\"><item affiliation=\"owner\" role=\"visitor\"><actor jid=\"kev@tester.lit\"/><reason>malice</reason></item></query>"), testling.serialize(admin)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(MUCAdminPayloadSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.cpp index 9eed97e..d34ea38 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.h> @@ -12,15 +12,15 @@ namespace Swift { -std::string PayloadsSerializer::serialize(boost::shared_ptr<Payload> payload) { - PayloadSerializer* serializer = serializers.getPayloadSerializer(payload); - if (serializer) { - return serializer->serialize(payload); - } - else { - CPPUNIT_ASSERT(false); - return ""; - } +std::string PayloadsSerializer::serialize(std::shared_ptr<Payload> payload) { + PayloadSerializer* serializer = serializers.getPayloadSerializer(payload); + if (serializer) { + return serializer->serialize(payload); + } + else { + CPPUNIT_ASSERT(false); + return ""; + } } diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.h b/Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.h index 01f07e4..5e0f0c5 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.h @@ -1,23 +1,23 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> #include <Swiften/Elements/Payload.h> -#include <string> #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> namespace Swift { - class PayloadsSerializer { - public: - std::string serialize(boost::shared_ptr<Payload> payload); + class PayloadsSerializer { + public: + std::string serialize(std::shared_ptr<Payload> payload); - private: - FullPayloadSerializerCollection serializers; - }; + private: + FullPayloadSerializerCollection serializers; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/PrioritySerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/PrioritySerializerTest.cpp index f5b8bee..87d7d0f 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/PrioritySerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/PrioritySerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,19 +13,19 @@ using namespace Swift; class PrioritySerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PrioritySerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(PrioritySerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); - public: - PrioritySerializerTest() {} + public: + PrioritySerializerTest() {} - void testSerialize() { - PrioritySerializer testling; - boost::shared_ptr<Priority> priority(new Priority(-113)); + void testSerialize() { + PrioritySerializer testling; + std::shared_ptr<Priority> priority(new Priority(-113)); - CPPUNIT_ASSERT_EQUAL(std::string("<priority>-113</priority>"), testling.serialize(priority)); - } + CPPUNIT_ASSERT_EQUAL(std::string("<priority>-113</priority>"), testling.serialize(priority)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(PrioritySerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp index 23d71aa..4e77e7d 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp @@ -1,50 +1,50 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.h> #include <Swiften/Elements/PrivateStorage.h> #include <Swiften/Elements/Storage.h> +#include <Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.h> using namespace Swift; class PrivateStorageSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PrivateStorageSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); - - public: - PrivateStorageSerializerTest() {} - - void testSerialize() { - PayloadsSerializer serializer; - - boost::shared_ptr<PrivateStorage> privateStorage(new PrivateStorage()); - boost::shared_ptr<Storage> storage(new Storage()); - Storage::Room room; - room.name = "Swift"; - room.jid = JID("swift@rooms.swift.im"); - room.nick = "Alice"; - storage->addRoom(room); - privateStorage->setPayload(storage); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<query xmlns=\"jabber:iq:private\">" - "<storage xmlns=\"storage:bookmarks\">" - "<conference " - "autojoin=\"0\" " - "jid=\"swift@rooms.swift.im\" " - "name=\"Swift\">" - "<nick>Alice</nick>" - "</conference>" - "</storage>" - "</query>"), serializer.serialize(privateStorage)); - } + CPPUNIT_TEST_SUITE(PrivateStorageSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); + + public: + PrivateStorageSerializerTest() {} + + void testSerialize() { + PayloadsSerializer serializer; + + std::shared_ptr<PrivateStorage> privateStorage(new PrivateStorage()); + std::shared_ptr<Storage> storage(new Storage()); + Storage::Room room; + room.name = "Swift"; + room.jid = JID("swift@rooms.swift.im"); + room.nick = "Alice"; + storage->addRoom(room); + privateStorage->setPayload(storage); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<query xmlns=\"jabber:iq:private\">" + "<storage xmlns=\"storage:bookmarks\">" + "<conference " + "autojoin=\"0\" " + "jid=\"swift@rooms.swift.im\" " + "name=\"Swift\">" + "<nick>Alice</nick>" + "</conference>" + "</storage>" + "</query>"), serializer.serialize(privateStorage)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(PrivateStorageSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/PubSubItemSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/PubSubItemSerializerTest.cpp new file mode 100644 index 0000000..e8673b9 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/PubSubItemSerializerTest.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Elements/PubSubItem.h> +#include <Swiften/Elements/RawXMLPayload.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h> + +using namespace Swift; + +class PubSubItemSerializerTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(PubSubItemSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerializeEmptyID); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + PubSubItemSerializer serializer(&serializers); + + std::shared_ptr<RawXMLPayload> payload(std::make_shared<RawXMLPayload>()); + payload->setRawXML("<payload xmlns=\"tmp\"/>"); + + std::shared_ptr<PubSubItem> item(std::make_shared<PubSubItem>()); + item->addData(payload); + item->setID("pubsub-item-1"); + + std::string expectedResult = + "<item id=\"pubsub-item-1\" xmlns=\"http://jabber.org/protocol/pubsub\">" + "<payload xmlns=\"tmp\"/>" + "</item>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(item)); + } + + void testSerializeEmptyID() { + PubSubItemSerializer serializer(&serializers); + + std::shared_ptr<PubSubItem> item(std::make_shared<PubSubItem>()); + + std::string expectedResult = + "<item xmlns=\"http://jabber.org/protocol/pubsub\"/>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(item)); + } + + private: + FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(PubSubItemSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/PubSubItemsSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/PubSubItemsSerializerTest.cpp new file mode 100644 index 0000000..0194553 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/PubSubItemsSerializerTest.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Elements/PubSubItems.h> +#include <Swiften/Elements/RawXMLPayload.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.h> + +using namespace Swift; + +class PubSubItemsSerializerTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(PubSubItemsSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerializeEmptyItems); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + PubSubItemsSerializer serializer(&serializers); + + std::shared_ptr<RawXMLPayload> payload1(std::make_shared<RawXMLPayload>()); + payload1->setRawXML("<payload xmlns=\"tmp\"/>"); + + std::shared_ptr<PubSubItem> item1(std::make_shared<PubSubItem>()); + item1->addData(payload1); + item1->setID("pubsub-item-1"); + + std::shared_ptr<RawXMLPayload> payload2(std::make_shared<RawXMLPayload>()); + payload2->setRawXML("<payload xmlns=\"other-tmp\"/>"); + + std::shared_ptr<PubSubItem> item2(std::make_shared<PubSubItem>()); + item2->addData(payload2); + item2->setID("pubsub-item-2"); + + std::shared_ptr<PubSubItems> items(std::make_shared<PubSubItems>()); + items->setNode("test-node"); + items->setSubscriptionID(std::string("sub-id")); + items->addItem(item1); + items->addItem(item2); + + std::string expectedResult = + "<items node=\"test-node\" subid=\"sub-id\" xmlns=\"http://jabber.org/protocol/pubsub\">" + "<item id=\"pubsub-item-1\" xmlns=\"http://jabber.org/protocol/pubsub\">" + "<payload xmlns=\"tmp\"/>" + "</item>" + "<item id=\"pubsub-item-2\" xmlns=\"http://jabber.org/protocol/pubsub\">" + "<payload xmlns=\"other-tmp\"/>" + "</item>" + "</items>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(items)); + } + + void testSerializeEmptyItems() { + PubSubItemsSerializer serializer(&serializers); + + std::shared_ptr<PubSubItems> items(std::make_shared<PubSubItems>()); + + std::string expectedResult = + "<items node=\"\" xmlns=\"http://jabber.org/protocol/pubsub\"/>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(items)); + } + + private: + FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(PubSubItemsSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/PubSubRetractSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/PubSubRetractSerializerTest.cpp new file mode 100644 index 0000000..f00eddc --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/PubSubRetractSerializerTest.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.h> + +using namespace Swift; + +class PubSubRetractSerializerTest: public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(PubSubRetractSerializerTest); + CPPUNIT_TEST(testSerializeDefault); + CPPUNIT_TEST(testSerializeNotify); + CPPUNIT_TEST_SUITE_END(); + + public: + PubSubRetractSerializerTest() {} + + std::shared_ptr<PubSubItem> somePubSubItem() { + auto item = std::make_shared<PubSubItem>(); + item->setID("ae890ac52d0df67ed7cfdf51b644e901"); + return item; + } + + void testSerializeDefault() { + PubSubRetractSerializer testling(&serializer); + auto retract = std::make_shared<PubSubRetract>(); + retract->setNode("princely_musings"); + retract->setItems({somePubSubItem()}); + CPPUNIT_ASSERT_EQUAL(std::string("<retract node=\"princely_musings\" xmlns=\"http://jabber.org/protocol/pubsub\"><item id=\"ae890ac52d0df67ed7cfdf51b644e901\" xmlns=\"http://jabber.org/protocol/pubsub\"/></retract>"), testling.serialize(retract)); + } + + void testSerializeNotify() { + PubSubRetractSerializer testling(&serializer); + auto retract = std::make_shared<PubSubRetract>(); + retract->setNode("princely_musings"); + retract->setItems({somePubSubItem()}); + retract->setNotify(true); + CPPUNIT_ASSERT_EQUAL(std::string("<retract node=\"princely_musings\" notify=\"true\" xmlns=\"http://jabber.org/protocol/pubsub\"><item id=\"ae890ac52d0df67ed7cfdf51b644e901\" xmlns=\"http://jabber.org/protocol/pubsub\"/></retract>"), testling.serialize(retract)); + + retract = std::make_shared<PubSubRetract>(); + retract->setNode("princely_musings"); + retract->setItems({somePubSubItem()}); + retract->setNotify(false); + CPPUNIT_ASSERT_EQUAL(std::string("<retract node=\"princely_musings\" notify=\"false\" xmlns=\"http://jabber.org/protocol/pubsub\"><item id=\"ae890ac52d0df67ed7cfdf51b644e901\" xmlns=\"http://jabber.org/protocol/pubsub\"/></retract>"), testling.serialize(retract)); + } + + private: + FullPayloadSerializerCollection serializer; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(PubSubRetractSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/ReferencePayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/ReferencePayloadSerializerTest.cpp new file mode 100644 index 0000000..82465d7 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/ReferencePayloadSerializerTest.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <gtest/gtest.h> + +#include <Swiften/Serializer/PayloadSerializers/ReferencePayloadSerializer.h> + +#include <Swiften/Elements/Body.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> + +using namespace Swift; + +static FullPayloadSerializerCollection serializers; + +TEST(ReferencePayloadSerializerTest, testSerialize) { + ReferencePayloadSerializer testling(&serializers); + auto reference = std::make_shared<ReferencePayload>(); + reference->setType(ReferencePayload::Type::Data); + reference->setUri(boost::optional<std::string>("https://www.example.com/mindBlowingImage.jpeg")); + reference->setBegin(boost::optional<std::string>("11")); + reference->setEnd(boost::optional<std::string>("22")); + reference->setAnchor(boost::optional<std::string>("xmpp:data@localhost.example.test")); + + std::string expectedResult = + "<reference " + "anchor=\"xmpp:data@localhost.example.test\" " + "begin=\"11\" " + "end=\"22\" " + "type=\"data\" " + "uri=\"https://www.example.com/mindBlowingImage.jpeg\" " + "xmlns=\"urn:xmpp:reference:0\"/>"; + + ASSERT_EQ(expectedResult, testling.serialize(reference)); +} + +TEST(ReferencePayloadSerializerTest, testSerializeNoType) { + ReferencePayloadSerializer testling(&serializers); + auto reference = std::make_shared<ReferencePayload>(); + reference->setUri(boost::optional<std::string>("https://www.example.com/mindBlowingImage.jpeg")); + reference->setBegin(boost::optional<std::string>("11")); + reference->setEnd(boost::optional<std::string>("22")); + reference->setAnchor(boost::optional<std::string>("xmpp:data@localhost.example.test")); + + std::string expectedResult = + "<reference " + "anchor=\"xmpp:data@localhost.example.test\" " + "begin=\"11\" " + "end=\"22\" " + "type=\"data\" " + "uri=\"https://www.example.com/mindBlowingImage.jpeg\" " + "xmlns=\"urn:xmpp:reference:0\"/>"; + + ASSERT_EQ(expectedResult, testling.serialize(reference)); +} + +TEST(ReferencePayloadSerializerTest, testSerializeWithEmbeddedPayload) { + ReferencePayloadSerializer testling(&serializers); + auto reference = std::make_shared<ReferencePayload>(); + reference->setUri(boost::optional<std::string>("https://www.example.com/mindBlowingImage.jpeg")); + reference->setBegin(boost::optional<std::string>("11")); + reference->setEnd(boost::optional<std::string>("22")); + reference->setAnchor(boost::optional<std::string>("xmpp:data@localhost.example.test")); + auto payload = std::make_shared<Body>(std::string("Look, I'm in a reference")); + reference->addPayload(payload); + + std::string expectedResult = + "<reference " + "anchor=\"xmpp:data@localhost.example.test\" " + "begin=\"11\" " + "end=\"22\" " + "type=\"data\" " + "uri=\"https://www.example.com/mindBlowingImage.jpeg\" " + "xmlns=\"urn:xmpp:reference:0\">" + "<body>Look, I'm in a reference</body>" + "</reference>"; + + ASSERT_EQ(expectedResult, testling.serialize(reference)); +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/ReplaceSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/ReplaceSerializerTest.cpp index 70f351c..4aab334 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/ReplaceSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/ReplaceSerializerTest.cpp @@ -5,9 +5,9 @@ */ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -18,19 +18,19 @@ using namespace Swift; class ReplaceSerializerTest: public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ReplaceSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); - - public: - ReplaceSerializerTest() {} - - void testSerialize() { - ReplaceSerializer testling; - boost::shared_ptr<Replace> replace(new Replace()); - replace->setID("bad1"); - CPPUNIT_ASSERT_EQUAL(std::string("<replace id = 'bad1' xmlns='urn:xmpp:message-correct:0'/>"), testling.serialize(replace)); - } + CPPUNIT_TEST_SUITE(ReplaceSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); + + public: + ReplaceSerializerTest() {} + + void testSerialize() { + ReplaceSerializer testling; + std::shared_ptr<Replace> replace(new Replace()); + replace->setID("bad1"); + CPPUNIT_ASSERT_EQUAL(std::string("<replace id = 'bad1' xmlns='urn:xmpp:message-correct:0'/>"), testling.serialize(replace)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(ReplaceSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/ResourceBindSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/ResourceBindSerializerTest.cpp index f8d3d30..30cd6e7 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/ResourceBindSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/ResourceBindSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,43 +13,43 @@ using namespace Swift; class ResourceBindSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ResourceBindSerializerTest); - CPPUNIT_TEST(testSerialize_JID); - CPPUNIT_TEST(testSerialize_Resource); - CPPUNIT_TEST(testSerialize_Empty); - CPPUNIT_TEST_SUITE_END(); - - public: - ResourceBindSerializerTest() {} - - void testSerialize_JID() { - ResourceBindSerializer testling; - boost::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); - resourceBind->setJID(JID("somenode@example.com/someresource")); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">" - "<jid>somenode@example.com/someresource</jid>" - "</bind>"), testling.serialize(resourceBind)); - } - - void testSerialize_Resource() { - ResourceBindSerializer testling; - boost::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); - resourceBind->setResource("someresource"); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">" - "<resource>someresource</resource>" - "</bind>"), testling.serialize(resourceBind)); - } - - void testSerialize_Empty() { - ResourceBindSerializer testling; - boost::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); - - CPPUNIT_ASSERT_EQUAL(std::string("<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"), testling.serialize(resourceBind)); - } + CPPUNIT_TEST_SUITE(ResourceBindSerializerTest); + CPPUNIT_TEST(testSerialize_JID); + CPPUNIT_TEST(testSerialize_Resource); + CPPUNIT_TEST(testSerialize_Empty); + CPPUNIT_TEST_SUITE_END(); + + public: + ResourceBindSerializerTest() {} + + void testSerialize_JID() { + ResourceBindSerializer testling; + std::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); + resourceBind->setJID(JID("somenode@example.com/someresource")); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">" + "<jid>somenode@example.com/someresource</jid>" + "</bind>"), testling.serialize(resourceBind)); + } + + void testSerialize_Resource() { + ResourceBindSerializer testling; + std::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); + resourceBind->setResource("someresource"); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">" + "<resource>someresource</resource>" + "</bind>"), testling.serialize(resourceBind)); + } + + void testSerialize_Empty() { + ResourceBindSerializer testling; + std::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); + + CPPUNIT_ASSERT_EQUAL(std::string("<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"), testling.serialize(resourceBind)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(ResourceBindSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/ResultSetSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/ResultSetSerializerTest.cpp new file mode 100644 index 0000000..fecd3c5 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/ResultSetSerializerTest.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Elements/ResultSet.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/ResultSetSerializer.h> + +using namespace Swift; + +class ResultSetSerializerTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(ResultSetSerializerTest); + CPPUNIT_TEST(testSerializeFull); + CPPUNIT_TEST(testSerializeMaxItems); + CPPUNIT_TEST(testSerializeEmptyBefore); + CPPUNIT_TEST(testSerializeFirst); + CPPUNIT_TEST(testSerializeFirstWithIndex); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerializeFull() { + ResultSetSerializer serializer; + + std::shared_ptr<ResultSet> resultSet(std::make_shared<ResultSet>()); + + resultSet->setMaxItems(100); + resultSet->setCount(800); + resultSet->setIndex(0); + resultSet->setFirstIDIndex(123); + resultSet->setFirstID(std::string("stpeter@jabber.org")); + resultSet->setLastID(std::string("peterpan@neverland.lit")); + resultSet->setAfter(std::string("09af3-cc343-b409f")); + resultSet->setBefore(std::string("decaf-badba-dbad1")); + + std::string expectedResult = + "<set xmlns=\"http://jabber.org/protocol/rsm\">" + "<max>100</max>" + "<count>800</count>" + "<index>0</index>" + "<first index=\"123\">stpeter@jabber.org</first>" + "<last>peterpan@neverland.lit</last>" + "<before>decaf-badba-dbad1</before>" + "<after>09af3-cc343-b409f</after>" + "</set>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(resultSet)); + } + + void testSerializeMaxItems() { + ResultSetSerializer serializer; + + std::shared_ptr<ResultSet> resultSet(std::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 testSerializeEmptyBefore() { + ResultSetSerializer serializer; + + std::shared_ptr<ResultSet> resultSet(std::make_shared<ResultSet>()); + + resultSet->setBefore(std::string()); + + std::string expectedResult = + "<set xmlns=\"http://jabber.org/protocol/rsm\">" + "<before/>" + "</set>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, serializer.serialize(resultSet)); + } + + void testSerializeFirst() { + ResultSetSerializer serializer; + + std::shared_ptr<ResultSet> resultSet(std::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; + + std::shared_ptr<ResultSet> resultSet(std::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/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp index b6a90d9..652becb 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterItemExchangeSerializerTest.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -13,42 +19,42 @@ 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.setJID("foo@bar.com"); - item1.setName("Foo @ Bar"); - item1.setAction(RosterItemExchangePayload::Item::Add); - item1.addGroup("Group 1"); - item1.addGroup("Group 2"); - roster->addItem(item1); - - RosterItemExchangePayload::Item item2; - item2.setJID("baz@blo.com"); - item2.setName("Baz"); - item2.setAction(RosterItemExchangePayload::Item::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(RosterItemExchangeSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); + + public: + RosterItemExchangeSerializerTest() {} + + void testSerialize() { + RosterItemExchangeSerializer testling; + std::shared_ptr<RosterItemExchangePayload> roster(new RosterItemExchangePayload()); + + RosterItemExchangePayload::Item item1; + item1.setJID("foo@bar.com"); + item1.setName("Foo @ Bar"); + item1.setAction(RosterItemExchangePayload::Item::Add); + item1.addGroup("Group 1"); + item1.addGroup("Group 2"); + roster->addItem(item1); + + RosterItemExchangePayload::Item item2; + item2.setJID("baz@blo.com"); + item2.setName("Baz"); + item2.setAction(RosterItemExchangePayload::Item::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); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp index 9ecddc3..0c576d2 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/RosterSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -12,90 +12,90 @@ using namespace Swift; class RosterSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(RosterSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_ItemWithUnknownContent); - CPPUNIT_TEST(testSerialize_WithVersion); - CPPUNIT_TEST(testSerialize_WithEmptyVersion); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerialize() { - RosterSerializer testling; - boost::shared_ptr<RosterPayload> roster(new RosterPayload()); - - RosterItemPayload item1; - item1.setJID(JID("foo@bar.com")); - item1.setName("Foo @ Bar"); - item1.setSubscription(RosterItemPayload::From); - item1.addGroup("Group 1"); - item1.addGroup("Group 2"); - item1.setSubscriptionRequested(); - roster->addItem(item1); - - RosterItemPayload item2; - item2.setJID(JID("baz@blo.com")); - item2.setName("Baz"); - roster->addItem(item2); - - std::string expectedResult = - "<query xmlns=\"jabber:iq:roster\">" - "<item ask=\"subscribe\" jid=\"foo@bar.com\" name=\"Foo @ Bar\" subscription=\"from\">" - "<group>Group 1</group>" - "<group>Group 2</group>" - "</item>" - "<item jid=\"baz@blo.com\" name=\"Baz\" subscription=\"none\"/>" - "</query>"; - - CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); - } - - void testSerialize_ItemWithUnknownContent() { - RosterSerializer testling; - boost::shared_ptr<RosterPayload> roster(new RosterPayload()); - - RosterItemPayload item; - item.setJID(JID("baz@blo.com")); - item.setName("Baz"); - item.addGroup("Group 1"); - item.addGroup("Group 2"); - item.addUnknownContent(std::string( - "<foo xmlns=\"http://example.com\"><bar xmlns=\"http://example.com\">Baz</bar></foo>" - "<baz xmlns=\"jabber:iq:roster\"><fum xmlns=\"jabber:iq:roster\">foo</fum></baz>")); - roster->addItem(item); - - std::string expectedResult = - "<query xmlns=\"jabber:iq:roster\">" - "<item jid=\"baz@blo.com\" name=\"Baz\" subscription=\"none\">" - "<group>Group 1</group>" - "<group>Group 2</group>" - "<foo xmlns=\"http://example.com\"><bar xmlns=\"http://example.com\">Baz</bar></foo>" - "<baz xmlns=\"jabber:iq:roster\"><fum xmlns=\"jabber:iq:roster\">foo</fum></baz>" - "</item>" - "</query>"; - - CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); - } - - void testSerialize_WithVersion() { - RosterSerializer testling; - boost::shared_ptr<RosterPayload> roster(new RosterPayload()); - roster->setVersion("ver20"); - - std::string expectedResult = "<query ver=\"ver20\" xmlns=\"jabber:iq:roster\"/>"; - - CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); - } - - void testSerialize_WithEmptyVersion() { - RosterSerializer testling; - boost::shared_ptr<RosterPayload> roster(new RosterPayload()); - roster->setVersion(""); - - std::string expectedResult = "<query ver=\"\" xmlns=\"jabber:iq:roster\"/>"; - - CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); - } + CPPUNIT_TEST_SUITE(RosterSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_ItemWithUnknownContent); + CPPUNIT_TEST(testSerialize_WithVersion); + CPPUNIT_TEST(testSerialize_WithEmptyVersion); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + RosterSerializer testling; + std::shared_ptr<RosterPayload> roster(new RosterPayload()); + + RosterItemPayload item1; + item1.setJID(JID("foo@bar.com")); + item1.setName("Foo @ Bar"); + item1.setSubscription(RosterItemPayload::From); + item1.addGroup("Group 1"); + item1.addGroup("Group 2"); + item1.setSubscriptionRequested(); + roster->addItem(item1); + + RosterItemPayload item2; + item2.setJID(JID("baz@blo.com")); + item2.setName("Baz"); + roster->addItem(item2); + + std::string expectedResult = + "<query xmlns=\"jabber:iq:roster\">" + "<item ask=\"subscribe\" jid=\"foo@bar.com\" name=\"Foo @ Bar\" subscription=\"from\">" + "<group>Group 1</group>" + "<group>Group 2</group>" + "</item>" + "<item jid=\"baz@blo.com\" name=\"Baz\" subscription=\"none\"/>" + "</query>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); + } + + void testSerialize_ItemWithUnknownContent() { + RosterSerializer testling; + std::shared_ptr<RosterPayload> roster(new RosterPayload()); + + RosterItemPayload item; + item.setJID(JID("baz@blo.com")); + item.setName("Baz"); + item.addGroup("Group 1"); + item.addGroup("Group 2"); + item.addUnknownContent(std::string( + "<foo xmlns=\"http://example.com\"><bar xmlns=\"http://example.com\">Baz</bar></foo>" + "<baz xmlns=\"jabber:iq:roster\"><fum xmlns=\"jabber:iq:roster\">foo</fum></baz>")); + roster->addItem(item); + + std::string expectedResult = + "<query xmlns=\"jabber:iq:roster\">" + "<item jid=\"baz@blo.com\" name=\"Baz\" subscription=\"none\">" + "<group>Group 1</group>" + "<group>Group 2</group>" + "<foo xmlns=\"http://example.com\"><bar xmlns=\"http://example.com\">Baz</bar></foo>" + "<baz xmlns=\"jabber:iq:roster\"><fum xmlns=\"jabber:iq:roster\">foo</fum></baz>" + "</item>" + "</query>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); + } + + void testSerialize_WithVersion() { + RosterSerializer testling; + std::shared_ptr<RosterPayload> roster(new RosterPayload()); + roster->setVersion("ver20"); + + std::string expectedResult = "<query ver=\"ver20\" xmlns=\"jabber:iq:roster\"/>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); + } + + void testSerialize_WithEmptyVersion() { + RosterSerializer testling; + std::shared_ptr<RosterPayload> roster(new RosterPayload()); + roster->setVersion(""); + + std::string expectedResult = "<query ver=\"\" xmlns=\"jabber:iq:roster\"/>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(roster)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(RosterSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp index 29e20c9..3deca11 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp @@ -1,176 +1,177 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.h> using namespace Swift; class SearchPayloadSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SearchPayloadSerializerTest); - CPPUNIT_TEST(testSerialize_Request); - CPPUNIT_TEST(testSerialize_Items); - CPPUNIT_TEST(testSerialize_DataForm); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerialize_Request() { - SearchPayloadSerializer testling; - - SearchPayload::ref payload(new SearchPayload()); - payload->setFirst("Juliet"); - payload->setLast("Capulet"); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<query xmlns=\"jabber:iq:search\">" - "<first>Juliet</first>" - "<last>Capulet</last>" - "</query>" - ), testling.serialize(payload)); - } - - void testSerialize_Items() { - SearchPayloadSerializer testling; - - SearchPayload::ref payload(new SearchPayload()); - SearchPayload::Item item1; - item1.jid = JID("juliet@capulet.com"); - item1.first = "Juliet"; - item1.last = "Capulet"; - item1.nick = "JuliC"; - item1.email = "juliet@shakespeare.lit"; - payload->addItem(item1); - - SearchPayload::Item item2; - item2.jid = JID("tybalt@shakespeare.lit"); - item2.first = "Tybalt"; - item2.last = "Capulet"; - item2.nick = "ty"; - item2.email = "tybalt@shakespeare.lit"; - payload->addItem(item2); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<query xmlns=\"jabber:iq:search\">" - "<item jid=\"juliet@capulet.com\">" - "<first>Juliet</first>" - "<last>Capulet</last>" - "<nick>JuliC</nick>" - "<email>juliet@shakespeare.lit</email>" - "</item>" - "<item jid=\"tybalt@shakespeare.lit\">" - "<first>Tybalt</first>" - "<last>Capulet</last>" - "<nick>ty</nick>" - "<email>tybalt@shakespeare.lit</email>" - "</item>" - "</query>" - ), testling.serialize(payload)); - } - - void testSerialize_DataForm() { - SearchPayloadSerializer testling; - - SearchPayload::ref payload(new SearchPayload()); - boost::shared_ptr<Form> form(new Form(Form::ResultType)); - - FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:iq:search"); - field->setName("FORM_TYPE"); - form->addField(field); - - // reported fields - field = boost::make_shared<FormField>(FormField::TextSingleType); - field->setName("first"); - field->setLabel("Given Name"); - form->addReportedField(field); - - field = boost::make_shared<FormField>(FormField::TextSingleType); - field->setName("last"); - field->setLabel("Family Name"); - form->addReportedField(field); - - field = boost::make_shared<FormField>(FormField::JIDSingleType); - field->setName("jid"); - field->setLabel("Jabber ID"); - form->addReportedField(field); - - field = boost::make_shared<FormField>(FormField::ListSingleType); - field->setName("x-gender"); - field->setLabel("Gender"); - form->addReportedField(field); - - Form::FormItem firstItem; - field = boost::make_shared<FormField>(FormField::TextSingleType, "Benvolio"); - field->setName("first"); - firstItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); - field->setName("last"); - firstItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::TextSingleType, "benvolio@montague.net"); - field->setName("jid"); - firstItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); - field->setName("x-gender"); - firstItem.push_back(field); - - Form::FormItem secondItem; - field = boost::make_shared<FormField>(FormField::TextSingleType, "Romeo"); - field->setName("first"); - secondItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); - field->setName("last"); - secondItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::TextSingleType, "romeo@montague.net"); - field->setName("jid"); - secondItem.push_back(field); - - field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); - field->setName("x-gender"); - secondItem.push_back(field); - - form->addItem(firstItem); - form->addItem(secondItem); - - payload->setForm(form); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<query xmlns=\"jabber:iq:search\">" - "<x type=\"result\" xmlns=\"jabber:x:data\">" - "<field type=\"hidden\" var=\"FORM_TYPE\">" - "<value>jabber:iq:search</value>" - "</field>" - "<reported>" - "<field label=\"Given Name\" type=\"text-single\" var=\"first\"/>" - "<field label=\"Family Name\" type=\"text-single\" var=\"last\"/>" - "<field label=\"Jabber ID\" type=\"jid-single\" var=\"jid\"/>" - "<field label=\"Gender\" type=\"list-single\" var=\"x-gender\"/>" - "</reported>" - "<item>" - "<field var=\"first\"><value>Benvolio</value></field>" - "<field var=\"last\"><value>Montague</value></field>" - "<field var=\"jid\"><value>benvolio@montague.net</value></field>" - "<field var=\"x-gender\"><value>male</value></field>" - "</item>" - "<item>" - "<field var=\"first\"><value>Romeo</value></field>" - "<field var=\"last\"><value>Montague</value></field>" - "<field var=\"jid\"><value>romeo@montague.net</value></field>" - "<field var=\"x-gender\"><value>male</value></field>" - "</item>" - "</x>" - "</query>"), testling.serialize(payload)); - - } + CPPUNIT_TEST_SUITE(SearchPayloadSerializerTest); + CPPUNIT_TEST(testSerialize_Request); + CPPUNIT_TEST(testSerialize_Items); + CPPUNIT_TEST(testSerialize_DataForm); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize_Request() { + SearchPayloadSerializer testling; + + SearchPayload::ref payload(new SearchPayload()); + payload->setFirst("Juliet"); + payload->setLast("Capulet"); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<query xmlns=\"jabber:iq:search\">" + "<first>Juliet</first>" + "<last>Capulet</last>" + "</query>" + ), testling.serialize(payload)); + } + + void testSerialize_Items() { + SearchPayloadSerializer testling; + + SearchPayload::ref payload(new SearchPayload()); + SearchPayload::Item item1; + item1.jid = JID("juliet@capulet.com"); + item1.first = "Juliet"; + item1.last = "Capulet"; + item1.nick = "JuliC"; + item1.email = "juliet@shakespeare.lit"; + payload->addItem(item1); + + SearchPayload::Item item2; + item2.jid = JID("tybalt@shakespeare.lit"); + item2.first = "Tybalt"; + item2.last = "Capulet"; + item2.nick = "ty"; + item2.email = "tybalt@shakespeare.lit"; + payload->addItem(item2); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<query xmlns=\"jabber:iq:search\">" + "<item jid=\"juliet@capulet.com\">" + "<first>Juliet</first>" + "<last>Capulet</last>" + "<nick>JuliC</nick>" + "<email>juliet@shakespeare.lit</email>" + "</item>" + "<item jid=\"tybalt@shakespeare.lit\">" + "<first>Tybalt</first>" + "<last>Capulet</last>" + "<nick>ty</nick>" + "<email>tybalt@shakespeare.lit</email>" + "</item>" + "</query>" + ), testling.serialize(payload)); + } + + void testSerialize_DataForm() { + SearchPayloadSerializer testling; + + SearchPayload::ref payload(new SearchPayload()); + std::shared_ptr<Form> form(new Form(Form::ResultType)); + + FormField::ref field = std::make_shared<FormField>(FormField::HiddenType, "jabber:iq:search"); + field->setName("FORM_TYPE"); + form->addField(field); + + // reported fields + field = std::make_shared<FormField>(FormField::TextSingleType); + field->setName("first"); + field->setLabel("Given Name"); + form->addReportedField(field); + + field = std::make_shared<FormField>(FormField::TextSingleType); + field->setName("last"); + field->setLabel("Family Name"); + form->addReportedField(field); + + field = std::make_shared<FormField>(FormField::JIDSingleType); + field->setName("jid"); + field->setLabel("Jabber ID"); + form->addReportedField(field); + + field = std::make_shared<FormField>(FormField::ListSingleType); + field->setName("x-gender"); + field->setLabel("Gender"); + form->addReportedField(field); + + Form::FormItem firstItem; + field = std::make_shared<FormField>(FormField::TextSingleType, "Benvolio"); + field->setName("first"); + firstItem.push_back(field); + + field = std::make_shared<FormField>(FormField::TextSingleType, "Montague"); + field->setName("last"); + firstItem.push_back(field); + + field = std::make_shared<FormField>(FormField::TextSingleType, "benvolio@montague.net"); + field->setName("jid"); + firstItem.push_back(field); + + field = std::make_shared<FormField>(FormField::ListSingleType, "male"); + field->setName("x-gender"); + firstItem.push_back(field); + + Form::FormItem secondItem; + field = std::make_shared<FormField>(FormField::TextSingleType, "Romeo"); + field->setName("first"); + secondItem.push_back(field); + + field = std::make_shared<FormField>(FormField::TextSingleType, "Montague"); + field->setName("last"); + secondItem.push_back(field); + + field = std::make_shared<FormField>(FormField::TextSingleType, "romeo@montague.net"); + field->setName("jid"); + secondItem.push_back(field); + + field = std::make_shared<FormField>(FormField::ListSingleType, "male"); + field->setName("x-gender"); + secondItem.push_back(field); + + form->addItem(firstItem); + form->addItem(secondItem); + + payload->setForm(form); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<query xmlns=\"jabber:iq:search\">" + "<x type=\"result\" xmlns=\"jabber:x:data\">" + "<field type=\"hidden\" var=\"FORM_TYPE\">" + "<value>jabber:iq:search</value>" + "</field>" + "<reported>" + "<field label=\"Given Name\" type=\"text-single\" var=\"first\"/>" + "<field label=\"Family Name\" type=\"text-single\" var=\"last\"/>" + "<field label=\"Jabber ID\" type=\"jid-single\" var=\"jid\"/>" + "<field label=\"Gender\" type=\"list-single\" var=\"x-gender\"/>" + "</reported>" + "<item>" + "<field var=\"first\"><value>Benvolio</value></field>" + "<field var=\"last\"><value>Montague</value></field>" + "<field var=\"jid\"><value>benvolio@montague.net</value></field>" + "<field var=\"x-gender\"><value>male</value></field>" + "</item>" + "<item>" + "<field var=\"first\"><value>Romeo</value></field>" + "<field var=\"last\"><value>Montague</value></field>" + "<field var=\"jid\"><value>romeo@montague.net</value></field>" + "<field var=\"x-gender\"><value>male</value></field>" + "</item>" + "</x>" + "</query>"), testling.serialize(payload)); + + } }; CPPUNIT_TEST_SUITE_REGISTRATION(SearchPayloadSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/SecurityLabelSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/SecurityLabelSerializerTest.cpp index 0de509d..6b65fd4 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/SecurityLabelSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/SecurityLabelSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -12,49 +12,49 @@ using namespace Swift; class SecurityLabelSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SecurityLabelSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_EmptyLabel); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerialize() { - SecurityLabelSerializer testling; - boost::shared_ptr<SecurityLabel> securityLabel(new SecurityLabel()); - securityLabel->setDisplayMarking("SECRET"); - securityLabel->setForegroundColor("black"); - securityLabel->setBackgroundColor("red"); - securityLabel->setLabel("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"); - securityLabel->addEquivalentLabel("<icismlabel xmlns=\"http://example.gov/IC-ISM/0\" classification=\"S\" ownerProducer=\"USA\" disseminationControls=\"FOUO\"/>"); - securityLabel->addEquivalentLabel("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MRUCAgD9DA9BcXVhIChvYnNvbGV0ZSk=</esssecuritylabel>"); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" - "<displaymarking bgcolor=\"red\" fgcolor=\"black\">SECRET</displaymarking>" - "<label>" - "<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>" - "</label>" - "<equivalentlabel>" - "<icismlabel xmlns=\"http://example.gov/IC-ISM/0\" classification=\"S\" ownerProducer=\"USA\" disseminationControls=\"FOUO\"/>" - "</equivalentlabel>" - "<equivalentlabel>" - "<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MRUCAgD9DA9BcXVhIChvYnNvbGV0ZSk=</esssecuritylabel>" - "</equivalentlabel>" - "</securitylabel>"), testling.serialize(securityLabel)); - } - - void testSerialize_EmptyLabel() { - SecurityLabelSerializer testling; - boost::shared_ptr<SecurityLabel> securityLabel(new SecurityLabel()); - securityLabel->setDisplayMarking("SECRET"); - securityLabel->setLabel(""); - - CPPUNIT_ASSERT_EQUAL(std::string( - "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" - "<displaymarking>SECRET</displaymarking>" - "<label></label>" - "</securitylabel>"), testling.serialize(securityLabel)); - } + CPPUNIT_TEST_SUITE(SecurityLabelSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_EmptyLabel); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + SecurityLabelSerializer testling; + std::shared_ptr<SecurityLabel> securityLabel(new SecurityLabel()); + securityLabel->setDisplayMarking("SECRET"); + securityLabel->setForegroundColor("black"); + securityLabel->setBackgroundColor("red"); + securityLabel->setLabel("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"); + securityLabel->addEquivalentLabel("<icismlabel xmlns=\"http://example.gov/IC-ISM/0\" classification=\"S\" ownerProducer=\"USA\" disseminationControls=\"FOUO\"/>"); + securityLabel->addEquivalentLabel("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MRUCAgD9DA9BcXVhIChvYnNvbGV0ZSk=</esssecuritylabel>"); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" + "<displaymarking bgcolor=\"red\" fgcolor=\"black\">SECRET</displaymarking>" + "<label>" + "<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>" + "</label>" + "<equivalentlabel>" + "<icismlabel xmlns=\"http://example.gov/IC-ISM/0\" classification=\"S\" ownerProducer=\"USA\" disseminationControls=\"FOUO\"/>" + "</equivalentlabel>" + "<equivalentlabel>" + "<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MRUCAgD9DA9BcXVhIChvYnNvbGV0ZSk=</esssecuritylabel>" + "</equivalentlabel>" + "</securitylabel>"), testling.serialize(securityLabel)); + } + + void testSerialize_EmptyLabel() { + SecurityLabelSerializer testling; + std::shared_ptr<SecurityLabel> securityLabel(new SecurityLabel()); + securityLabel->setDisplayMarking("SECRET"); + securityLabel->setLabel(""); + + CPPUNIT_ASSERT_EQUAL(std::string( + "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" + "<displaymarking>SECRET</displaymarking>" + "<label></label>" + "</securitylabel>"), testling.serialize(securityLabel)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(SecurityLabelSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/SecurityLabelsCatalogSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/SecurityLabelsCatalogSerializerTest.cpp index c060e41..c3a72a5 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/SecurityLabelsCatalogSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/SecurityLabelsCatalogSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,63 +13,63 @@ using namespace Swift; class SecurityLabelsCatalogSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SecurityLabelsCatalogSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(SecurityLabelsCatalogSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); - public: - SecurityLabelsCatalogSerializerTest() {} + public: + SecurityLabelsCatalogSerializerTest() {} - void testSerialize() { - SecurityLabelsCatalogSerializer testling; - boost::shared_ptr<SecurityLabelsCatalog> catalog(new SecurityLabelsCatalog()); - catalog->setTo(JID("example.com")); - catalog->setName("Default"); - catalog->setDescription("an example set of labels"); + void testSerialize() { + SecurityLabelsCatalogSerializer testling; + std::shared_ptr<SecurityLabelsCatalog> catalog(new SecurityLabelsCatalog()); + catalog->setTo(JID("example.com")); + catalog->setName("Default"); + catalog->setDescription("an example set of labels"); - SecurityLabelsCatalog::Item item1; - boost::shared_ptr<SecurityLabel> securityLabel1(new SecurityLabel()); - item1.setLabel(securityLabel1); - securityLabel1->setDisplayMarking("SECRET"); - securityLabel1->setForegroundColor("black"); - securityLabel1->setBackgroundColor("red"); - item1.setIsDefault(false); - item1.setSelector("Classified|SECRET"); - securityLabel1->setLabel("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"); - catalog->addItem(item1); + SecurityLabelsCatalog::Item item1; + std::shared_ptr<SecurityLabel> securityLabel1(new SecurityLabel()); + item1.setLabel(securityLabel1); + securityLabel1->setDisplayMarking("SECRET"); + securityLabel1->setForegroundColor("black"); + securityLabel1->setBackgroundColor("red"); + item1.setIsDefault(false); + item1.setSelector("Classified|SECRET"); + securityLabel1->setLabel("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel>"); + catalog->addItem(item1); - SecurityLabelsCatalog::Item item2; - boost::shared_ptr<SecurityLabel> securityLabel2(new SecurityLabel()); - item2.setLabel(securityLabel2); - securityLabel2->setDisplayMarking("CONFIDENTIAL"); - securityLabel2->setForegroundColor("black"); - securityLabel2->setBackgroundColor("navy"); - item2.setIsDefault(true); - item2.setSelector("Classified|CONFIDENTIAL"); - securityLabel2->setLabel("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel>"); - catalog->addItem(item2); + SecurityLabelsCatalog::Item item2; + std::shared_ptr<SecurityLabel> securityLabel2(new SecurityLabel()); + item2.setLabel(securityLabel2); + securityLabel2->setDisplayMarking("CONFIDENTIAL"); + securityLabel2->setForegroundColor("black"); + securityLabel2->setBackgroundColor("navy"); + item2.setIsDefault(true); + item2.setSelector("Classified|CONFIDENTIAL"); + securityLabel2->setLabel("<esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel>"); + catalog->addItem(item2); - SecurityLabelsCatalog::Item item3; - item3.setSelector("Unclassified|UNCLASSIFIED"); - catalog->addItem(item3); + SecurityLabelsCatalog::Item item3; + item3.setSelector("Unclassified|UNCLASSIFIED"); + catalog->addItem(item3); - CPPUNIT_ASSERT_EQUAL(std::string( - "<catalog desc=\"an example set of labels\" name=\"Default\" to=\"example.com\" xmlns=\"urn:xmpp:sec-label:catalog:2\">" - "<item selector=\"Classified|SECRET\">" - "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" - "<displaymarking bgcolor=\"red\" fgcolor=\"black\">SECRET</displaymarking>" - "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel></label>" - "</securitylabel>" - "</item>" - "<item default=\"true\" selector=\"Classified|CONFIDENTIAL\">" - "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" - "<displaymarking bgcolor=\"navy\" fgcolor=\"black\">CONFIDENTIAL</displaymarking>" - "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel></label>" - "</securitylabel>" - "</item>" - "<item selector=\"Unclassified|UNCLASSIFIED\"/>" - "</catalog>"), testling.serialize(catalog)); - } + CPPUNIT_ASSERT_EQUAL(std::string( + "<catalog desc=\"an example set of labels\" name=\"Default\" to=\"example.com\" xmlns=\"urn:xmpp:sec-label:catalog:2\">" + "<item selector=\"Classified|SECRET\">" + "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" + "<displaymarking bgcolor=\"red\" fgcolor=\"black\">SECRET</displaymarking>" + "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQYCAQQGASk=</esssecuritylabel></label>" + "</securitylabel>" + "</item>" + "<item default=\"true\" selector=\"Classified|CONFIDENTIAL\">" + "<securitylabel xmlns=\"urn:xmpp:sec-label:0\">" + "<displaymarking bgcolor=\"navy\" fgcolor=\"black\">CONFIDENTIAL</displaymarking>" + "<label><esssecuritylabel xmlns=\"urn:xmpp:sec-label:ess:0\">MQMGASk=</esssecuritylabel></label>" + "</securitylabel>" + "</item>" + "<item selector=\"Unclassified|UNCLASSIFIED\"/>" + "</catalog>"), testling.serialize(catalog)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(SecurityLabelsCatalogSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/SoftwareVersionSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/SoftwareVersionSerializerTest.cpp index ad1e9b4..a20efb7 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/SoftwareVersionSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/SoftwareVersionSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,19 +13,19 @@ using namespace Swift; class SoftwareVersionSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SoftwareVersionSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(SoftwareVersionSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); - public: - SoftwareVersionSerializerTest() {} + public: + SoftwareVersionSerializerTest() {} - void testSerialize() { - SoftwareVersionSerializer testling; - boost::shared_ptr<SoftwareVersion> softwareVersion(new SoftwareVersion("Swift", "0.1", "Mac OS X")); + void testSerialize() { + SoftwareVersionSerializer testling; + std::shared_ptr<SoftwareVersion> softwareVersion(new SoftwareVersion("Swift", "0.1", "Mac OS X")); - CPPUNIT_ASSERT_EQUAL(std::string("<query xmlns=\"jabber:iq:version\"><name>Swift</name><version>0.1</version><os>Mac OS X</os></query>"), testling.serialize(softwareVersion)); - } + CPPUNIT_ASSERT_EQUAL(std::string("<query xmlns=\"jabber:iq:version\"><name>Swift</name><version>0.1</version><os>Mac OS X</os></query>"), testling.serialize(softwareVersion)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(SoftwareVersionSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/StatusSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/StatusSerializerTest.cpp index af90a0a..03a3ef5 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/StatusSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/StatusSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,19 +13,19 @@ using namespace Swift; class StatusSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StatusSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(StatusSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); - public: - StatusSerializerTest() {} + public: + StatusSerializerTest() {} - void testSerialize() { - StatusSerializer testling; - boost::shared_ptr<Status> status(new Status("I am away")); + void testSerialize() { + StatusSerializer testling; + std::shared_ptr<Status> status(new Status("I am away")); - CPPUNIT_ASSERT_EQUAL(std::string("<status>I am away</status>"), testling.serialize(status)); - } + CPPUNIT_ASSERT_EQUAL(std::string("<status>I am away</status>"), testling.serialize(status)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StatusSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/StatusShowSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/StatusShowSerializerTest.cpp index 898c835..eb3b221 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/StatusShowSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/StatusShowSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,52 +13,52 @@ using namespace Swift; class StatusShowSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StatusShowSerializerTest); - CPPUNIT_TEST(testSerialize_Online); - CPPUNIT_TEST(testSerialize_Away); - CPPUNIT_TEST(testSerialize_FFC); - CPPUNIT_TEST(testSerialize_XA); - CPPUNIT_TEST(testSerialize_DND); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(StatusShowSerializerTest); + CPPUNIT_TEST(testSerialize_Online); + CPPUNIT_TEST(testSerialize_Away); + CPPUNIT_TEST(testSerialize_FFC); + CPPUNIT_TEST(testSerialize_XA); + CPPUNIT_TEST(testSerialize_DND); + CPPUNIT_TEST_SUITE_END(); - public: - StatusShowSerializerTest() {} + public: + StatusShowSerializerTest() {} - void testSerialize_Online() { - StatusShowSerializer testling; - boost::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::Online)); - CPPUNIT_ASSERT_EQUAL(std::string(""), testling.serialize(statusShow)); - } + void testSerialize_Online() { + StatusShowSerializer testling; + std::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::Online)); + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.serialize(statusShow)); + } - void testSerialize_Away() { - StatusShowSerializer testling; - boost::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::Away)); - CPPUNIT_ASSERT_EQUAL(std::string("<show>away</show>"), testling.serialize(statusShow)); - } + void testSerialize_Away() { + StatusShowSerializer testling; + std::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::Away)); + CPPUNIT_ASSERT_EQUAL(std::string("<show>away</show>"), testling.serialize(statusShow)); + } - void testSerialize_FFC() { - StatusShowSerializer testling; - boost::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::FFC)); - CPPUNIT_ASSERT_EQUAL(std::string("<show>chat</show>"), testling.serialize(statusShow)); - } + void testSerialize_FFC() { + StatusShowSerializer testling; + std::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::FFC)); + CPPUNIT_ASSERT_EQUAL(std::string("<show>chat</show>"), testling.serialize(statusShow)); + } - void testSerialize_XA() { - StatusShowSerializer testling; - boost::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::XA)); - CPPUNIT_ASSERT_EQUAL(std::string("<show>xa</show>"), testling.serialize(statusShow)); - } + void testSerialize_XA() { + StatusShowSerializer testling; + std::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::XA)); + CPPUNIT_ASSERT_EQUAL(std::string("<show>xa</show>"), testling.serialize(statusShow)); + } - void testSerialize_DND() { - StatusShowSerializer testling; - boost::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::DND)); - CPPUNIT_ASSERT_EQUAL(std::string("<show>dnd</show>"), testling.serialize(statusShow)); - } + void testSerialize_DND() { + StatusShowSerializer testling; + std::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::DND)); + CPPUNIT_ASSERT_EQUAL(std::string("<show>dnd</show>"), testling.serialize(statusShow)); + } - void testSerialize_None() { - StatusShowSerializer testling; - boost::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::None)); - CPPUNIT_ASSERT_EQUAL(std::string(""), testling.serialize(statusShow)); - } + void testSerialize_None() { + StatusShowSerializer testling; + std::shared_ptr<StatusShow> statusShow(new StatusShow(StatusShow::None)); + CPPUNIT_ASSERT_EQUAL(std::string(""), testling.serialize(statusShow)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StatusShowSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/StorageSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/StorageSerializerTest.cpp index b963a9c..33c63cb 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/StorageSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/StorageSerializerTest.cpp @@ -1,71 +1,71 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.h> #include <Swiften/Elements/Storage.h> +#include <Swiften/Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.h> using namespace Swift; class StorageSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StorageSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_NoNickOrPassword); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(StorageSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_NoNickOrPassword); + CPPUNIT_TEST_SUITE_END(); - public: - StorageSerializerTest() {} + public: + StorageSerializerTest() {} - void testSerialize() { - PayloadsSerializer serializer; - boost::shared_ptr<Storage> storage(new Storage()); - Storage::Room room; - room.name = "Council of Oberon"; - room.autoJoin = true; - room.jid = JID("council@conference.underhill.org"); - room.nick = "Puck"; - room.password = "MyPass"; - storage->addRoom(room); - Storage::URL url; - url.name = "Complete Works of Shakespeare"; - url.url = "http://the-tech.mit.edu/Shakespeare/"; - storage->addURL(url); + void testSerialize() { + PayloadsSerializer serializer; + std::shared_ptr<Storage> storage(new Storage()); + Storage::Room room; + room.name = "Council of Oberon"; + room.autoJoin = true; + room.jid = JID("council@conference.underhill.org"); + room.nick = "Puck"; + room.password = "MyPass"; + storage->addRoom(room); + Storage::URL url; + url.name = "Complete Works of Shakespeare"; + url.url = "http://the-tech.mit.edu/Shakespeare/"; + storage->addURL(url); - CPPUNIT_ASSERT_EQUAL(std::string( - "<storage xmlns=\"storage:bookmarks\">" - "<conference " - "autojoin=\"1\" " - "jid=\"council@conference.underhill.org\" " - "name=\"Council of Oberon\">" - "<nick>Puck</nick>" - "<password>MyPass</password>" - "</conference>" - "<url name=\"Complete Works of Shakespeare\" url=\"http://the-tech.mit.edu/Shakespeare/\"/>" - "</storage>"), serializer.serialize(storage)); - } + CPPUNIT_ASSERT_EQUAL(std::string( + "<storage xmlns=\"storage:bookmarks\">" + "<conference " + "autojoin=\"1\" " + "jid=\"council@conference.underhill.org\" " + "name=\"Council of Oberon\">" + "<nick>Puck</nick>" + "<password>MyPass</password>" + "</conference>" + "<url name=\"Complete Works of Shakespeare\" url=\"http://the-tech.mit.edu/Shakespeare/\"/>" + "</storage>"), serializer.serialize(storage)); + } - void testSerialize_NoNickOrPassword() { - PayloadsSerializer serializer; - boost::shared_ptr<Storage> storage(new Storage()); - Storage::Room room; - room.name = "Council of Oberon"; - room.autoJoin = true; - room.jid = JID("council@conference.underhill.org"); - storage->addRoom(room); + void testSerialize_NoNickOrPassword() { + PayloadsSerializer serializer; + std::shared_ptr<Storage> storage(new Storage()); + Storage::Room room; + room.name = "Council of Oberon"; + room.autoJoin = true; + room.jid = JID("council@conference.underhill.org"); + storage->addRoom(room); - CPPUNIT_ASSERT_EQUAL(std::string( - "<storage xmlns=\"storage:bookmarks\">" - "<conference " - "autojoin=\"1\" " - "jid=\"council@conference.underhill.org\" " - "name=\"Council of Oberon\"/>" - "</storage>"), serializer.serialize(storage)); - } + CPPUNIT_ASSERT_EQUAL(std::string( + "<storage xmlns=\"storage:bookmarks\">" + "<conference " + "autojoin=\"1\" " + "jid=\"council@conference.underhill.org\" " + "name=\"Council of Oberon\"/>" + "</storage>"), serializer.serialize(storage)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StorageSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp index 7b96298..a38295c 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -12,57 +12,57 @@ using namespace Swift; class StreamInitiationSerializerTest : public CppUnit::TestFixture{ - CPPUNIT_TEST_SUITE(StreamInitiationSerializerTest); - CPPUNIT_TEST(testSerialize_Request); - CPPUNIT_TEST(testSerialize_Response); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(StreamInitiationSerializerTest); + CPPUNIT_TEST(testSerialize_Request); + CPPUNIT_TEST(testSerialize_Response); + CPPUNIT_TEST_SUITE_END(); - public: - void testSerialize_Request() { - StreamInitiationSerializer testling; - boost::shared_ptr<StreamInitiation> streamInitiation(new StreamInitiation()); - StreamInitiationFileInfo fileInfo("test.txt", "This is info about the file.", 1022); - streamInitiation->setID("a0"); - streamInitiation->setFileInfo(fileInfo); - streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams"); - streamInitiation->addProvidedMethod("jabber:iq:oob"); - streamInitiation->addProvidedMethod("http://jabber.org/protocol/ibb"); + public: + void testSerialize_Request() { + StreamInitiationSerializer testling; + std::shared_ptr<StreamInitiation> streamInitiation(new StreamInitiation()); + StreamInitiationFileInfo fileInfo("test.txt", "This is info about the file.", 1022); + streamInitiation->setID("a0"); + streamInitiation->setFileInfo(fileInfo); + streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams"); + streamInitiation->addProvidedMethod("jabber:iq:oob"); + streamInitiation->addProvidedMethod("http://jabber.org/protocol/ibb"); - CPPUNIT_ASSERT_EQUAL(std::string( - "<si id=\"a0\" profile=\"http://jabber.org/protocol/si/profile/file-transfer\" xmlns=\"http://jabber.org/protocol/si\">" - "<file name=\"test.txt\" size=\"1022\" xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" - "<desc>This is info about the file.</desc>" - "</file>" - "<feature xmlns=\"http://jabber.org/protocol/feature-neg\">" - "<x type=\"form\" xmlns=\"jabber:x:data\">" - "<field type=\"list-single\" var=\"stream-method\">" - "<option><value>http://jabber.org/protocol/bytestreams</value></option>" - "<option><value>jabber:iq:oob</value></option>" - "<option><value>http://jabber.org/protocol/ibb</value></option>" - "</field>" - "</x>" - "</feature>" - "</si>" - ), testling.serialize(streamInitiation)); - } + CPPUNIT_ASSERT_EQUAL(std::string( + "<si id=\"a0\" profile=\"http://jabber.org/protocol/si/profile/file-transfer\" xmlns=\"http://jabber.org/protocol/si\">" + "<file name=\"test.txt\" size=\"1022\" xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" + "<desc>This is info about the file.</desc>" + "</file>" + "<feature xmlns=\"http://jabber.org/protocol/feature-neg\">" + "<x type=\"form\" xmlns=\"jabber:x:data\">" + "<field type=\"list-single\" var=\"stream-method\">" + "<option><value>http://jabber.org/protocol/bytestreams</value></option>" + "<option><value>jabber:iq:oob</value></option>" + "<option><value>http://jabber.org/protocol/ibb</value></option>" + "</field>" + "</x>" + "</feature>" + "</si>" + ), testling.serialize(streamInitiation)); + } - void testSerialize_Response() { - StreamInitiationSerializer testling; - boost::shared_ptr<StreamInitiation> streamInitiation(new StreamInitiation()); - streamInitiation->setRequestedMethod("http://jabber.org/protocol/bytestreams"); + void testSerialize_Response() { + StreamInitiationSerializer testling; + std::shared_ptr<StreamInitiation> streamInitiation(new StreamInitiation()); + streamInitiation->setRequestedMethod("http://jabber.org/protocol/bytestreams"); - CPPUNIT_ASSERT_EQUAL(std::string( - "<si profile=\"http://jabber.org/protocol/si/profile/file-transfer\" xmlns=\"http://jabber.org/protocol/si\">" - "<feature xmlns=\"http://jabber.org/protocol/feature-neg\">" - "<x type=\"submit\" xmlns=\"jabber:x:data\">" - "<field type=\"list-single\" var=\"stream-method\">" - "<value>http://jabber.org/protocol/bytestreams</value>" - "</field>" - "</x>" - "</feature>" - "</si>" - ), testling.serialize(streamInitiation)); - } + CPPUNIT_ASSERT_EQUAL(std::string( + "<si profile=\"http://jabber.org/protocol/si/profile/file-transfer\" xmlns=\"http://jabber.org/protocol/si\">" + "<feature xmlns=\"http://jabber.org/protocol/feature-neg\">" + "<x type=\"submit\" xmlns=\"jabber:x:data\">" + "<field type=\"list-single\" var=\"stream-method\">" + "<value>http://jabber.org/protocol/bytestreams</value>" + "</field>" + "</x>" + "</feature>" + "</si>" + ), testling.serialize(streamInitiation)); + } }; diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/UserLocationSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/UserLocationSerializerTest.cpp new file mode 100644 index 0000000..1a3adb9 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/UserLocationSerializerTest.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/UserLocation.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h> + +using namespace Swift; + +class UserLocationSerializerTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(UserLocationSerializerTest); + CPPUNIT_TEST(testSerialize_withAllVariablesSet); + CPPUNIT_TEST(testSerialize_withSomeVariablesSet); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize_withAllVariablesSet() { + UserLocationSerializer testling(&serializers); + std::shared_ptr<UserLocation> userLocation(new UserLocation()); + userLocation->setArea(boost::optional<std::string>("Barbaric")); + userLocation->setAltitude(5.75); + userLocation->setLocality(boost::optional<std::string>("Near")); + userLocation->setLatitude(boost::optional<double>(5.75)); + userLocation->setAccuracy(5.75); + userLocation->setDescription(boost::optional<std::string>("Nice")); + userLocation->setCountryCode(boost::optional<std::string>("+91")); + userLocation->setTimestamp(stringToDateTime("2015-06-11T20:55:50Z")); + userLocation->setFloor(boost::optional<std::string>("3")); + userLocation->setBuilding(boost::optional<std::string>("First")); + userLocation->setRoom(boost::optional<std::string>("E315")); + userLocation->setCountry(boost::optional<std::string>("USA")); + userLocation->setRegion(boost::optional<std::string>("NewSode")); + userLocation->setURI(boost::optional<std::string>("URIs")); + userLocation->setLongitude(5.75); + userLocation->setError(5.75); + userLocation->setPostalCode(boost::optional<std::string>("67")); + userLocation->setBearing(5.75); + userLocation->setText(boost::optional<std::string>("Hello")); + userLocation->setDatum(boost::optional<std::string>("Datee")); + userLocation->setStreet(boost::optional<std::string>("Highway")); + userLocation->setSpeed(5.75); + + std::string expectedResult = + "<geoloc xmlns=\"http://jabber.org/protocol/geoloc\">" + "<area>Barbaric</area><alt>5.75</alt><locality>Near</locality>" + "<lat>5.75</lat><accuracy>5.75</accuracy><description>Nice</description>" + "<countrycode>+91</countrycode><timestamp>2015-06-11T20:55:50Z</timestamp><floor>3</floor>" + "<building>First</building><room>E315</room><country>USA</country>" + "<region>NewSode</region><uri>URIs</uri><lon>5.75</lon><error>5.75</error>" + "<postalcode>67</postalcode><bearing>5.75</bearing><text>Hello</text>" + "<datum>Datee</datum><street>Highway</street><speed>5.75</speed></geoloc>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(userLocation)); + } + + void testSerialize_withSomeVariablesSet() { + UserLocationSerializer testling(&serializers); + std::shared_ptr<UserLocation> userLocation(new UserLocation()); + userLocation->setArea(boost::optional<std::string>("Barbaric")); + userLocation->setAltitude(5.75); + userLocation->setLocality(boost::optional<std::string>("Near")); + userLocation->setAccuracy(5.75); + userLocation->setDescription(boost::optional<std::string>("Nice")); + userLocation->setCountryCode(boost::optional<std::string>("+91")); + userLocation->setTimestamp(stringToDateTime("2015-06-11T20:55:50Z")); + userLocation->setFloor(boost::optional<std::string>("3")); + userLocation->setRegion(boost::optional<std::string>("NewSode")); + userLocation->setURI(boost::optional<std::string>("URIs")); + userLocation->setLongitude(5.75); + userLocation->setError(5.75); + userLocation->setPostalCode(boost::optional<std::string>("67")); + userLocation->setBearing(5.75); + userLocation->setText(boost::optional<std::string>("Hello")); + + std::string expectedResult = + "<geoloc xmlns=\"http://jabber.org/protocol/geoloc\">" + "<area>Barbaric</area><alt>5.75</alt><locality>Near</locality>" + "<accuracy>5.75</accuracy><description>Nice</description>" + "<countrycode>+91</countrycode><timestamp>2015-06-11T20:55:50Z</timestamp><floor>3</floor>" + "<region>NewSode</region><uri>URIs</uri><lon>5.75</lon><error>5.75</error>" + "<postalcode>67</postalcode><bearing>5.75</bearing><text>Hello</text></geoloc>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(userLocation)); + } + private: + FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(UserLocationSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/UserTuneSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/UserTuneSerializerTest.cpp new file mode 100644 index 0000000..df79f0d --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/UserTuneSerializerTest.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/Elements/UserTune.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h> + +using namespace Swift; + +class UserTuneSerializerTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(UserTuneSerializerTest); + CPPUNIT_TEST(testSerialize_withAllVariablesSet); + CPPUNIT_TEST(testSerialize_withSomeVariablesSet); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize_withAllVariablesSet() { + UserTuneSerializer testling(&serializers); + std::shared_ptr<UserTune> userTune(new UserTune()); + userTune->setRating(5); + userTune->setTitle(boost::optional<std::string>("Minion")); + userTune->setTrack(boost::optional<std::string>("Yellow")); + userTune->setArtist(boost::optional<std::string>("Ice")); + userTune->setURI(boost::optional<std::string>("Fire")); + userTune->setSource(boost::optional<std::string>("Origin")); + userTune->setLength(226); + + std::string expectedResult = + "<tune xmlns=\"http://jabber.org/protocol/tune\">" + "<rating>5</rating><title>Minion</title><track>Yellow</track><artist>Ice</artist><uri>Fire</uri><source>Origin</source><length>226</length></tune>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(userTune)); + } + + void testSerialize_withSomeVariablesSet() { + UserTuneSerializer testling(&serializers); + std::shared_ptr<UserTune> userTune(new UserTune()); + userTune->setTitle(boost::optional<std::string>("Minion")); + userTune->setTrack(boost::optional<std::string>("Yellow")); + userTune->setArtist(boost::optional<std::string>("Ice")); + userTune->setSource(boost::optional<std::string>("Origin")); + userTune->setLength(226); + + std::string expectedResult = + "<tune xmlns=\"http://jabber.org/protocol/tune\">" + "<title>Minion</title><track>Yellow</track><artist>Ice</artist><source>Origin</source><length>226</length></tune>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(userTune)); + } + private: + FullPayloadSerializerCollection serializers; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(UserTuneSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp index 01c8e77..49402ec 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,136 +13,136 @@ using namespace Swift; class VCardSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(VCardSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerialize() { - VCardSerializer testling; - boost::shared_ptr<VCard> vcard(new VCard()); - vcard->setVersion("2.0"); - vcard->setFullName("Alice In Wonderland"); - vcard->setPrefix("Mrs"); - vcard->setGivenName("Alice"); - vcard->setMiddleName("In"); - vcard->setFamilyName("Wonderland"); - vcard->setSuffix("PhD"); - vcard->setNickname("DreamGirl"); - vcard->setPhoto(createByteArray("abcdef")); - vcard->setPhotoType("image/png"); - vcard->setBirthday(boost::posix_time::ptime(boost::gregorian::date(1865, 5, 4))); - vcard->addUnknownContent("<MAILER>mutt</MAILER>"); - - VCard::EMailAddress emailAddress1; - emailAddress1.address = "alice@wonderland.lit"; - emailAddress1.isHome = true; - emailAddress1.isPreferred = true; - emailAddress1.isInternet = true; - vcard->addEMailAddress(emailAddress1); - - VCard::EMailAddress address2; - address2.address = "alice@teaparty.lit"; - address2.isWork = true; - address2.isX400 = true; - vcard->addEMailAddress(address2); - - VCard::Telephone telephone1; - telephone1.number = "555-6273"; - telephone1.isHome = true; - telephone1.isVoice = true; - vcard->addTelephone(telephone1); - - VCard::Address address1; - address1.locality = "Any Town"; - address1.street = "Fake Street 123"; - address1.postalCode = "12345"; - address1.country = "USA"; - address1.isHome = true; - vcard->addAddress(address1); - - VCard::AddressLabel label1; - label1.lines.push_back("Fake Street 123"); - label1.lines.push_back("12345 Any Town"); - label1.lines.push_back("USA"); - label1.isHome = true; - vcard->addAddressLabel(label1); - - vcard->addJID(JID("alice@teaparty.lit")); - vcard->addJID(JID("alice@wonderland.lit")); - - vcard->setDescription("I once fell down a rabbit hole."); - - VCard::Organization org1; - org1.name = "Alice In Wonderland Inc."; - vcard->addOrganization(org1); - - vcard->addTitle("Some Title"); - vcard->addRole("Main Character"); - vcard->addURL("http://wonderland.lit/~alice"); - vcard->addURL("http://teaparty.lit/~alice2"); - - std::string expectedResult = - "<vCard xmlns=\"vcard-temp\">" - "<VERSION>2.0</VERSION>" - "<FN>Alice In Wonderland</FN>" - "<N>" - "<FAMILY>Wonderland</FAMILY>" - "<GIVEN>Alice</GIVEN>" - "<MIDDLE>In</MIDDLE>" - "<PREFIX>Mrs</PREFIX>" - "<SUFFIX>PhD</SUFFIX>" - "</N>" - "<EMAIL>" - "<USERID>alice@wonderland.lit</USERID>" - "<HOME/>" - "<INTERNET/>" - "<PREF/>" - "</EMAIL>" - "<EMAIL>" - "<USERID>alice@teaparty.lit</USERID>" - "<WORK/>" - "<X400/>" - "</EMAIL>" - "<NICKNAME>DreamGirl</NICKNAME>" - "<PHOTO>" - "<TYPE>image/png</TYPE>" - "<BINVAL>YWJjZGVm</BINVAL>" - "</PHOTO>" - "<BDAY>1865-05-04T00:00:00Z</BDAY>" - "<TEL>" - "<NUMBER>555-6273</NUMBER>" - "<HOME/>" - "<VOICE/>" - "</TEL>" - "<ADR>" - "<STREET>Fake Street 123</STREET>" - "<LOCALITY>Any Town</LOCALITY>" - "<PCODE>12345</PCODE>" - "<CTRY>USA</CTRY>" - "<HOME/>" - "</ADR>" - "<LABEL>" - "<LINE>Fake Street 123</LINE>" - "<LINE>12345 Any Town</LINE>" - "<LINE>USA</LINE>" - "<HOME/>" - "</LABEL>" - "<JID>alice@teaparty.lit</JID>" - "<JID>alice@wonderland.lit</JID>" - "<DESC>I once fell down a rabbit hole.</DESC>" - "<ORG>" - "<ORGNAME>Alice In Wonderland Inc.</ORGNAME>" - "</ORG>" - "<TITLE>Some Title</TITLE>" - "<ROLE>Main Character</ROLE>" - "<URL>http://wonderland.lit/~alice</URL>" - "<URL>http://teaparty.lit/~alice2</URL>" - "<MAILER>mutt</MAILER>" - "</vCard>"; - - CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(vcard)); - } + CPPUNIT_TEST_SUITE(VCardSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + VCardSerializer testling; + std::shared_ptr<VCard> vcard(new VCard()); + vcard->setVersion("2.0"); + vcard->setFullName("Alice In Wonderland"); + vcard->setPrefix("Mrs"); + vcard->setGivenName("Alice"); + vcard->setMiddleName("In"); + vcard->setFamilyName("Wonderland"); + vcard->setSuffix("PhD"); + vcard->setNickname("DreamGirl"); + vcard->setPhoto(createByteArray("abcdef")); + vcard->setPhotoType("image/png"); + vcard->setBirthday(boost::posix_time::ptime(boost::gregorian::date(1865, 5, 4))); + vcard->addUnknownContent("<MAILER>mutt</MAILER>"); + + VCard::EMailAddress emailAddress1; + emailAddress1.address = "alice@wonderland.lit"; + emailAddress1.isHome = true; + emailAddress1.isPreferred = true; + emailAddress1.isInternet = true; + vcard->addEMailAddress(emailAddress1); + + VCard::EMailAddress address2; + address2.address = "alice@teaparty.lit"; + address2.isWork = true; + address2.isX400 = true; + vcard->addEMailAddress(address2); + + VCard::Telephone telephone1; + telephone1.number = "555-6273"; + telephone1.isHome = true; + telephone1.isVoice = true; + vcard->addTelephone(telephone1); + + VCard::Address address1; + address1.locality = "Any Town"; + address1.street = "Fake Street 123"; + address1.postalCode = "12345"; + address1.country = "USA"; + address1.isHome = true; + vcard->addAddress(address1); + + VCard::AddressLabel label1; + label1.lines.push_back("Fake Street 123"); + label1.lines.push_back("12345 Any Town"); + label1.lines.push_back("USA"); + label1.isHome = true; + vcard->addAddressLabel(label1); + + vcard->addJID(JID("alice@teaparty.lit")); + vcard->addJID(JID("alice@wonderland.lit")); + + vcard->setDescription("I once fell down a rabbit hole."); + + VCard::Organization org1; + org1.name = "Alice In Wonderland Inc."; + vcard->addOrganization(org1); + + vcard->addTitle("Some Title"); + vcard->addRole("Main Character"); + vcard->addURL("http://wonderland.lit/~alice"); + vcard->addURL("http://teaparty.lit/~alice2"); + + std::string expectedResult = + "<vCard xmlns=\"vcard-temp\">" + "<VERSION>2.0</VERSION>" + "<FN>Alice In Wonderland</FN>" + "<N>" + "<FAMILY>Wonderland</FAMILY>" + "<GIVEN>Alice</GIVEN>" + "<MIDDLE>In</MIDDLE>" + "<PREFIX>Mrs</PREFIX>" + "<SUFFIX>PhD</SUFFIX>" + "</N>" + "<EMAIL>" + "<USERID>alice@wonderland.lit</USERID>" + "<HOME/>" + "<INTERNET/>" + "<PREF/>" + "</EMAIL>" + "<EMAIL>" + "<USERID>alice@teaparty.lit</USERID>" + "<WORK/>" + "<X400/>" + "</EMAIL>" + "<NICKNAME>DreamGirl</NICKNAME>" + "<PHOTO>" + "<TYPE>image/png</TYPE>" + "<BINVAL>YWJjZGVm</BINVAL>" + "</PHOTO>" + "<BDAY>1865-05-04T00:00:00Z</BDAY>" + "<TEL>" + "<NUMBER>555-6273</NUMBER>" + "<HOME/>" + "<VOICE/>" + "</TEL>" + "<ADR>" + "<STREET>Fake Street 123</STREET>" + "<LOCALITY>Any Town</LOCALITY>" + "<PCODE>12345</PCODE>" + "<CTRY>USA</CTRY>" + "<HOME/>" + "</ADR>" + "<LABEL>" + "<LINE>Fake Street 123</LINE>" + "<LINE>12345 Any Town</LINE>" + "<LINE>USA</LINE>" + "<HOME/>" + "</LABEL>" + "<JID>alice@teaparty.lit</JID>" + "<JID>alice@wonderland.lit</JID>" + "<DESC>I once fell down a rabbit hole.</DESC>" + "<ORG>" + "<ORGNAME>Alice In Wonderland Inc.</ORGNAME>" + "</ORG>" + "<TITLE>Some Title</TITLE>" + "<ROLE>Main Character</ROLE>" + "<URL>http://wonderland.lit/~alice</URL>" + "<URL>http://teaparty.lit/~alice2</URL>" + "<MAILER>mutt</MAILER>" + "</vCard>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(vcard)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardUpdateSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardUpdateSerializerTest.cpp index 613b465..e3fc5ff 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardUpdateSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardUpdateSerializerTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,25 +13,25 @@ using namespace Swift; class VCardUpdateSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(VCardUpdateSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(VCardUpdateSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); - public: - VCardUpdateSerializerTest() {} + public: + VCardUpdateSerializerTest() {} - void testSerialize() { - VCardUpdateSerializer testling; - boost::shared_ptr<VCardUpdate> update(new VCardUpdate()); - update->setPhotoHash("sha1-hash-of-image"); + void testSerialize() { + VCardUpdateSerializer testling; + std::shared_ptr<VCardUpdate> update(new VCardUpdate()); + update->setPhotoHash("sha1-hash-of-image"); - std::string expectedResult = - "<x xmlns=\"vcard-temp:x:update\">" - "<photo>sha1-hash-of-image</photo>" - "</x>"; + std::string expectedResult = + "<x xmlns=\"vcard-temp:x:update\">" + "<photo>sha1-hash-of-image</photo>" + "</x>"; - CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(update)); - } + CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(update)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardUpdateSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp index e257654..e0e496c 100644 --- a/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp @@ -1,94 +1,98 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/lexical_cast.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/Base/DateTime.h> #include <Swiften/Serializer/XML/XMLElement.h> -namespace Swift { +using namespace Swift; -UserLocationSerializer::UserLocationSerializer() { +UserLocationSerializer::UserLocationSerializer(PayloadSerializerCollection* /*serializers*/) { } -std::string UserLocationSerializer::serializePayload( - boost::shared_ptr<UserLocation> payload) const { - XMLElement result("geoloc", "http://jabber.org/protocol/geoloc"); - if (boost::optional<std::string> value = payload->getArea()) { - result.addNode(boost::make_shared<XMLElement>("area", "", *value)); - } - if (boost::optional<float> value = payload->getAltitude()) { - result.addNode(boost::make_shared<XMLElement>("alt", "", boost::lexical_cast<std::string>(*value))); - } - if (boost::optional<std::string> value = payload->getLocality()) { - result.addNode(boost::make_shared<XMLElement>("locality", "", *value)); - } - if (boost::optional<float> value = payload->getLatitude()) { - result.addNode(boost::make_shared<XMLElement>("lat", "", boost::lexical_cast<std::string>(*value))); - } - if (boost::optional<float> value = payload->getAccuracy()) { - result.addNode(boost::make_shared<XMLElement>("accuracy", "", boost::lexical_cast<std::string>(*value))); - } - if (boost::optional<std::string> value = payload->getDescription()) { - result.addNode(boost::make_shared<XMLElement>("description", "", *value)); - } - if (boost::optional<std::string> value = payload->getCountryCode()) { - result.addNode(boost::make_shared<XMLElement>("countrycode", "", *value)); - } - if (boost::optional<boost::posix_time::ptime> value = payload->getTimestamp()) { - result.addNode(boost::make_shared<XMLElement>("timestamp", "", dateTimeToString(*value))); - } - if (boost::optional<std::string> value = payload->getFloor()) { - result.addNode(boost::make_shared<XMLElement>("floor", "", *value)); - } - if (boost::optional<std::string> value = payload->getBuilding()) { - result.addNode(boost::make_shared<XMLElement>("building", "", *value)); - } - if (boost::optional<std::string> value = payload->getRoom()) { - result.addNode(boost::make_shared<XMLElement>("room", "", *value)); - } - if (boost::optional<std::string> value = payload->getCountry()) { - result.addNode(boost::make_shared<XMLElement>("country", "", *value)); - } - if (boost::optional<std::string> value = payload->getRegion()) { - result.addNode(boost::make_shared<XMLElement>("region", "", *value)); - } - if (boost::optional<std::string> value = payload->getURI()) { - result.addNode(boost::make_shared<XMLElement>("uri", "", *value)); - } - if (boost::optional<float> value = payload->getLongitude()) { - result.addNode(boost::make_shared<XMLElement>("lon", "", boost::lexical_cast<std::string>(*value))); - } - if (boost::optional<float> value = payload->getError()) { - result.addNode(boost::make_shared<XMLElement>("error", "", boost::lexical_cast<std::string>(*value))); - } - if (boost::optional<std::string> value = payload->getPostalCode()) { - result.addNode(boost::make_shared<XMLElement>("postalcode", "", *value)); - } - if (boost::optional<float> value = payload->getBearing()) { - result.addNode(boost::make_shared<XMLElement>("bearing", "", boost::lexical_cast<std::string>(*value))); - } - if (boost::optional<std::string> value = payload->getText()) { - result.addNode(boost::make_shared<XMLElement>("text", "", *value)); - } - if (boost::optional<std::string> value = payload->getDatum()) { - result.addNode(boost::make_shared<XMLElement>("datum", "", *value)); - } - if (boost::optional<std::string> value = payload->getStreet()) { - result.addNode(boost::make_shared<XMLElement>("street", "", *value)); - } - if (boost::optional<float> value = payload->getSpeed()) { - result.addNode(boost::make_shared<XMLElement>("speed", "", boost::lexical_cast<std::string>(*value))); - } - return result.serialize(); +UserLocationSerializer::~UserLocationSerializer() { } +std::string UserLocationSerializer::serializePayload(std::shared_ptr<UserLocation> payload) const { + if (!payload) { + return ""; + } + XMLElement element("geoloc", "http://jabber.org/protocol/geoloc"); + if (payload->getArea()) { + element.addNode(std::make_shared<XMLElement>("area", "", *payload->getArea())); + } + if (payload->getAltitude()) { + element.addNode(std::make_shared<XMLElement>("alt", "", boost::lexical_cast<std::string>(*payload->getAltitude()))); + } + if (payload->getLocality()) { + element.addNode(std::make_shared<XMLElement>("locality", "", *payload->getLocality())); + } + if (payload->getLatitude()) { + element.addNode(std::make_shared<XMLElement>("lat", "", boost::lexical_cast<std::string>(*payload->getLatitude()))); + } + if (payload->getAccuracy()) { + element.addNode(std::make_shared<XMLElement>("accuracy", "", boost::lexical_cast<std::string>(*payload->getAccuracy()))); + } + if (payload->getDescription()) { + element.addNode(std::make_shared<XMLElement>("description", "", *payload->getDescription())); + } + if (payload->getCountryCode()) { + element.addNode(std::make_shared<XMLElement>("countrycode", "", *payload->getCountryCode())); + } + if (payload->getTimestamp()) { + element.addNode(std::make_shared<XMLElement>("timestamp", "", dateTimeToString(*payload->getTimestamp()))); + } + if (payload->getFloor()) { + element.addNode(std::make_shared<XMLElement>("floor", "", *payload->getFloor())); + } + if (payload->getBuilding()) { + element.addNode(std::make_shared<XMLElement>("building", "", *payload->getBuilding())); + } + if (payload->getRoom()) { + element.addNode(std::make_shared<XMLElement>("room", "", *payload->getRoom())); + } + if (payload->getCountry()) { + element.addNode(std::make_shared<XMLElement>("country", "", *payload->getCountry())); + } + if (payload->getRegion()) { + element.addNode(std::make_shared<XMLElement>("region", "", *payload->getRegion())); + } + if (payload->getURI()) { + element.addNode(std::make_shared<XMLElement>("uri", "", *payload->getURI())); + } + if (payload->getLongitude()) { + element.addNode(std::make_shared<XMLElement>("lon", "", boost::lexical_cast<std::string>(*payload->getLongitude()))); + } + if (payload->getError()) { + element.addNode(std::make_shared<XMLElement>("error", "", boost::lexical_cast<std::string>(*payload->getError()))); + } + if (payload->getPostalCode()) { + element.addNode(std::make_shared<XMLElement>("postalcode", "", *payload->getPostalCode())); + } + if (payload->getBearing()) { + element.addNode(std::make_shared<XMLElement>("bearing", "", boost::lexical_cast<std::string>(*payload->getBearing()))); + } + if (payload->getText()) { + element.addNode(std::make_shared<XMLElement>("text", "", *payload->getText())); + } + if (payload->getDatum()) { + element.addNode(std::make_shared<XMLElement>("datum", "", *payload->getDatum())); + } + if (payload->getStreet()) { + element.addNode(std::make_shared<XMLElement>("street", "", *payload->getStreet())); + } + if (payload->getSpeed()) { + element.addNode(std::make_shared<XMLElement>("speed", "", boost::lexical_cast<std::string>(*payload->getSpeed()))); + } + return element.serialize(); } + + diff --git a/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h b/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h index 28a5fe8..9c2f2db 100644 --- a/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h @@ -1,19 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <memory> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/UserLocation.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class UserLocationSerializer : public GenericPayloadSerializer<UserLocation> { - public: - UserLocationSerializer(); + class PayloadSerializerCollection; + + class SWIFTEN_API UserLocationSerializer : public GenericPayloadSerializer<UserLocation> { + public: + UserLocationSerializer(PayloadSerializerCollection* serializers); + virtual ~UserLocationSerializer() override; - virtual std::string serializePayload(boost::shared_ptr<UserLocation>) const; - }; + virtual std::string serializePayload(std::shared_ptr<UserLocation>) const override; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.cpp b/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.cpp new file mode 100644 index 0000000..8bb3a4b --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h> + +#include <memory> + +#include <boost/lexical_cast.hpp> + +#include <Swiften/Serializer/XML/XMLElement.h> + +using namespace Swift; + +UserTuneSerializer::UserTuneSerializer(PayloadSerializerCollection* /*serializers*/) { +} + +UserTuneSerializer::~UserTuneSerializer() { +} + +std::string UserTuneSerializer::serializePayload(std::shared_ptr<UserTune> payload) const { + if (!payload) { + return ""; + } + XMLElement element("tune", "http://jabber.org/protocol/tune"); + if (payload->getRating()) { + element.addNode(std::make_shared<XMLElement>("rating", "", std::to_string(*payload->getRating()))); + } + if (payload->getTitle()) { + element.addNode(std::make_shared<XMLElement>("title", "", *payload->getTitle())); + } + if (payload->getTrack()) { + element.addNode(std::make_shared<XMLElement>("track", "", *payload->getTrack())); + } + if (payload->getArtist()) { + element.addNode(std::make_shared<XMLElement>("artist", "", *payload->getArtist())); + } + if (payload->getURI()) { + element.addNode(std::make_shared<XMLElement>("uri", "", *payload->getURI())); + } + if (payload->getSource()) { + element.addNode(std::make_shared<XMLElement>("source", "", *payload->getSource())); + } + if (payload->getLength()) { + element.addNode(std::make_shared<XMLElement>("length", "", std::to_string(*payload->getLength()))); + } + return element.serialize(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h b/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h new file mode 100644 index 0000000..1d5737a --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/UserTune.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API UserTuneSerializer : public GenericPayloadSerializer<UserTune> { + public: + UserTuneSerializer(PayloadSerializerCollection* serializers); + virtual ~UserTuneSerializer() override; + + virtual std::string serializePayload(std::shared_ptr<UserTune>) const override; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp b/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp index 22d59b4..725d125 100644 --- a/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp @@ -1,251 +1,249 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/VCardSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <Swiften/Base/DateTime.h> #include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Serializer/XML/XMLTextNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> #include <Swiften/StringCodecs/Base64.h> -#include <Swiften/Base/DateTime.h> -#include <Swiften/Base/foreach.h> namespace Swift { VCardSerializer::VCardSerializer() : GenericPayloadSerializer<VCard>() { } -std::string VCardSerializer::serializePayload(boost::shared_ptr<VCard> vcard) const { - XMLElement queryElement("vCard", "vcard-temp"); - if (!vcard->getVersion().empty()) { - queryElement.addNode(boost::make_shared<XMLElement>("VERSION", "", vcard->getVersion())); - } - if (!vcard->getFullName().empty()) { - queryElement.addNode(boost::make_shared<XMLElement>("FN", "", vcard->getFullName())); - } - if (!vcard->getGivenName().empty() || !vcard->getFamilyName().empty() || !vcard->getMiddleName().empty() || !vcard->getPrefix().empty() || !vcard->getSuffix().empty()) { - boost::shared_ptr<XMLElement> nameElement(new XMLElement("N")); - if (!vcard->getFamilyName().empty()) { - nameElement->addNode(boost::make_shared<XMLElement>("FAMILY", "", vcard->getFamilyName())); - } - if (!vcard->getGivenName().empty()) { - nameElement->addNode(boost::make_shared<XMLElement>("GIVEN", "", vcard->getGivenName())); - } - if (!vcard->getMiddleName().empty()) { - nameElement->addNode(boost::make_shared<XMLElement>("MIDDLE", "", vcard->getMiddleName())); - } - if (!vcard->getPrefix().empty()) { - nameElement->addNode(boost::make_shared<XMLElement>("PREFIX", "", vcard->getPrefix())); - } - if (!vcard->getSuffix().empty()) { - nameElement->addNode(boost::make_shared<XMLElement>("SUFFIX", "", vcard->getSuffix())); - } - queryElement.addNode(nameElement); - } - foreach(const VCard::EMailAddress& emailAddress, vcard->getEMailAddresses()) { - boost::shared_ptr<XMLElement> emailElement(new XMLElement("EMAIL")); - emailElement->addNode(boost::make_shared<XMLElement>("USERID", "", emailAddress.address)); - if (emailAddress.isHome) { - emailElement->addNode(boost::make_shared<XMLElement>("HOME")); - } - if (emailAddress.isWork) { - emailElement->addNode(boost::make_shared<XMLElement>("WORK")); - } - if (emailAddress.isInternet) { - emailElement->addNode(boost::make_shared<XMLElement>("INTERNET")); - } - if (emailAddress.isPreferred) { - emailElement->addNode(boost::make_shared<XMLElement>("PREF")); - } - if (emailAddress.isX400) { - emailElement->addNode(boost::make_shared<XMLElement>("X400")); - } - queryElement.addNode(emailElement); - } - if (!vcard->getNickname().empty()) { - queryElement.addNode(boost::make_shared<XMLElement>("NICKNAME", "", vcard->getNickname())); - } - if (!vcard->getPhoto().empty() || !vcard->getPhotoType().empty()) { - XMLElement::ref photoElement(new XMLElement("PHOTO")); - if (!vcard->getPhotoType().empty()) { - photoElement->addNode(boost::make_shared<XMLElement>("TYPE", "", vcard->getPhotoType())); - } - if (!vcard->getPhoto().empty()) { - photoElement->addNode(boost::make_shared<XMLElement>("BINVAL", "", Base64::encode(vcard->getPhoto()))); - } - queryElement.addNode(photoElement); - } - if (!vcard->getBirthday().is_not_a_date_time()) { - queryElement.addNode(boost::make_shared<XMLElement>("BDAY", "", dateTimeToString(vcard->getBirthday()))); - } - - foreach(const VCard::Telephone& telephone, vcard->getTelephones()) { - boost::shared_ptr<XMLElement> telElement(new XMLElement("TEL")); - telElement->addNode(boost::make_shared<XMLElement>("NUMBER", "", telephone.number)); - if (telephone.isHome) { - telElement->addNode(boost::make_shared<XMLElement>("HOME")); - } - if (telephone.isWork) { - telElement->addNode(boost::make_shared<XMLElement>("WORK")); - } - if (telephone.isVoice) { - telElement->addNode(boost::make_shared<XMLElement>("VOICE")); - } - if (telephone.isFax) { - telElement->addNode(boost::make_shared<XMLElement>("FAX")); - } - if (telephone.isPager) { - telElement->addNode(boost::make_shared<XMLElement>("PAGER")); - } - if (telephone.isMSG) { - telElement->addNode(boost::make_shared<XMLElement>("MSG")); - } - if (telephone.isCell) { - telElement->addNode(boost::make_shared<XMLElement>("CELL")); - } - if (telephone.isVideo) { - telElement->addNode(boost::make_shared<XMLElement>("VIDEO")); - } - if (telephone.isBBS) { - telElement->addNode(boost::make_shared<XMLElement>("BBS")); - } - if (telephone.isModem) { - telElement->addNode(boost::make_shared<XMLElement>("MODEM")); - } - if (telephone.isISDN) { - telElement->addNode(boost::make_shared<XMLElement>("ISDN")); - } - if (telephone.isPCS) { - telElement->addNode(boost::make_shared<XMLElement>("PCS")); - } - if (telephone.isPreferred) { - telElement->addNode(boost::make_shared<XMLElement>("PREF")); - } - queryElement.addNode(telElement); - } - - foreach(const VCard::Address& address, vcard->getAddresses()) { - boost::shared_ptr<XMLElement> adrElement = boost::make_shared<XMLElement>("ADR"); - if (!address.poBox.empty()) { - adrElement->addNode(boost::make_shared<XMLElement>("POBOX", "", address.poBox)); - } - if (!address.addressExtension.empty()) { - adrElement->addNode(boost::make_shared<XMLElement>("EXTADD", "", address.addressExtension)); - } - if (!address.street.empty()) { - adrElement->addNode(boost::make_shared<XMLElement>("STREET", "", address.street)); - } - if (!address.locality.empty()) { - adrElement->addNode(boost::make_shared<XMLElement>("LOCALITY", "", address.locality)); - } - if (!address.region.empty()) { - adrElement->addNode(boost::make_shared<XMLElement>("REGION", "", address.region)); - } - if (!address.postalCode.empty()) { - adrElement->addNode(boost::make_shared<XMLElement>("PCODE", "", address.postalCode)); - } - if (!address.country.empty()) { - adrElement->addNode(boost::make_shared<XMLElement>("CTRY", "", address.country)); - } - - if (address.isHome) { - adrElement->addNode(boost::make_shared<XMLElement>("HOME")); - } - if (address.isWork) { - adrElement->addNode(boost::make_shared<XMLElement>("WORK")); - } - if (address.isPostal) { - adrElement->addNode(boost::make_shared<XMLElement>("POSTAL")); - } - if (address.isParcel) { - adrElement->addNode(boost::make_shared<XMLElement>("PARCEL")); - } - if (address.deliveryType == VCard::DomesticDelivery) { - adrElement->addNode(boost::make_shared<XMLElement>("DOM")); - } - if (address.deliveryType == VCard::InternationalDelivery) { - adrElement->addNode(boost::make_shared<XMLElement>("INTL")); - } - if (address.isPreferred) { - adrElement->addNode(boost::make_shared<XMLElement>("PREF")); - } - queryElement.addNode(adrElement); - } - - foreach(const VCard::AddressLabel& addressLabel, vcard->getAddressLabels()) { - boost::shared_ptr<XMLElement> labelElement = boost::make_shared<XMLElement>("LABEL"); - - foreach(const std::string& line, addressLabel.lines) { - labelElement->addNode(boost::make_shared<XMLElement>("LINE", "", line)); - } - - if (addressLabel.isHome) { - labelElement->addNode(boost::make_shared<XMLElement>("HOME")); - } - if (addressLabel.isWork) { - labelElement->addNode(boost::make_shared<XMLElement>("WORK")); - } - if (addressLabel.isPostal) { - labelElement->addNode(boost::make_shared<XMLElement>("POSTAL")); - } - if (addressLabel.isParcel) { - labelElement->addNode(boost::make_shared<XMLElement>("PARCEL")); - } - if (addressLabel.deliveryType == VCard::DomesticDelivery) { - labelElement->addNode(boost::make_shared<XMLElement>("DOM")); - } - if (addressLabel.deliveryType == VCard::InternationalDelivery) { - labelElement->addNode(boost::make_shared<XMLElement>("INTL")); - } - if (addressLabel.isPreferred) { - labelElement->addNode(boost::make_shared<XMLElement>("PREF")); - } - queryElement.addNode(labelElement); - } - - foreach(const JID& jid, vcard->getJIDs()) { - queryElement.addNode(boost::make_shared<XMLElement>("JID", "", jid.toString())); - } - - if (!vcard->getDescription().empty()) { - queryElement.addNode(boost::make_shared<XMLElement>("DESC", "", vcard->getDescription())); - } - - foreach(const VCard::Organization& org, vcard->getOrganizations()) { - boost::shared_ptr<XMLElement> orgElement = boost::make_shared<XMLElement>("ORG"); - if (!org.name.empty()) { - orgElement->addNode(boost::make_shared<XMLElement>("ORGNAME", "", org.name)); - } - if (!org.units.empty()) { - foreach(const std::string& unit, org.units) { - orgElement->addNode(boost::make_shared<XMLElement>("ORGUNIT", "", unit)); - } - } - queryElement.addNode(orgElement); - } - - foreach(const std::string& title, vcard->getTitles()) { - queryElement.addNode(boost::make_shared<XMLElement>("TITLE", "", title)); - } - - foreach(const std::string& role, vcard->getRoles()) { - queryElement.addNode(boost::make_shared<XMLElement>("ROLE", "", role)); - } - - foreach(const std::string& url, vcard->getURLs()) { - queryElement.addNode(boost::make_shared<XMLElement>("URL", "", url)); - } - - if (!vcard->getUnknownContent().empty()) { - queryElement.addNode(boost::make_shared<XMLRawTextNode>(vcard->getUnknownContent())); - } - return queryElement.serialize(); +std::string VCardSerializer::serializePayload(std::shared_ptr<VCard> vcard) const { + XMLElement queryElement("vCard", "vcard-temp"); + if (!vcard->getVersion().empty()) { + queryElement.addNode(std::make_shared<XMLElement>("VERSION", "", vcard->getVersion())); + } + if (!vcard->getFullName().empty()) { + queryElement.addNode(std::make_shared<XMLElement>("FN", "", vcard->getFullName())); + } + if (!vcard->getGivenName().empty() || !vcard->getFamilyName().empty() || !vcard->getMiddleName().empty() || !vcard->getPrefix().empty() || !vcard->getSuffix().empty()) { + std::shared_ptr<XMLElement> nameElement(new XMLElement("N")); + if (!vcard->getFamilyName().empty()) { + nameElement->addNode(std::make_shared<XMLElement>("FAMILY", "", vcard->getFamilyName())); + } + if (!vcard->getGivenName().empty()) { + nameElement->addNode(std::make_shared<XMLElement>("GIVEN", "", vcard->getGivenName())); + } + if (!vcard->getMiddleName().empty()) { + nameElement->addNode(std::make_shared<XMLElement>("MIDDLE", "", vcard->getMiddleName())); + } + if (!vcard->getPrefix().empty()) { + nameElement->addNode(std::make_shared<XMLElement>("PREFIX", "", vcard->getPrefix())); + } + if (!vcard->getSuffix().empty()) { + nameElement->addNode(std::make_shared<XMLElement>("SUFFIX", "", vcard->getSuffix())); + } + queryElement.addNode(nameElement); + } + for (const auto& emailAddress : vcard->getEMailAddresses()) { + std::shared_ptr<XMLElement> emailElement(new XMLElement("EMAIL")); + emailElement->addNode(std::make_shared<XMLElement>("USERID", "", emailAddress.address)); + if (emailAddress.isHome) { + emailElement->addNode(std::make_shared<XMLElement>("HOME")); + } + if (emailAddress.isWork) { + emailElement->addNode(std::make_shared<XMLElement>("WORK")); + } + if (emailAddress.isInternet) { + emailElement->addNode(std::make_shared<XMLElement>("INTERNET")); + } + if (emailAddress.isPreferred) { + emailElement->addNode(std::make_shared<XMLElement>("PREF")); + } + if (emailAddress.isX400) { + emailElement->addNode(std::make_shared<XMLElement>("X400")); + } + queryElement.addNode(emailElement); + } + if (!vcard->getNickname().empty()) { + queryElement.addNode(std::make_shared<XMLElement>("NICKNAME", "", vcard->getNickname())); + } + if (!vcard->getPhoto().empty() || !vcard->getPhotoType().empty()) { + XMLElement::ref photoElement(new XMLElement("PHOTO")); + if (!vcard->getPhotoType().empty()) { + photoElement->addNode(std::make_shared<XMLElement>("TYPE", "", vcard->getPhotoType())); + } + if (!vcard->getPhoto().empty()) { + photoElement->addNode(std::make_shared<XMLElement>("BINVAL", "", Base64::encode(vcard->getPhoto()))); + } + queryElement.addNode(photoElement); + } + if (!vcard->getBirthday().is_not_a_date_time()) { + queryElement.addNode(std::make_shared<XMLElement>("BDAY", "", dateTimeToString(vcard->getBirthday()))); + } + + for (const auto& telephone : vcard->getTelephones()) { + std::shared_ptr<XMLElement> telElement(new XMLElement("TEL")); + telElement->addNode(std::make_shared<XMLElement>("NUMBER", "", telephone.number)); + if (telephone.isHome) { + telElement->addNode(std::make_shared<XMLElement>("HOME")); + } + if (telephone.isWork) { + telElement->addNode(std::make_shared<XMLElement>("WORK")); + } + if (telephone.isVoice) { + telElement->addNode(std::make_shared<XMLElement>("VOICE")); + } + if (telephone.isFax) { + telElement->addNode(std::make_shared<XMLElement>("FAX")); + } + if (telephone.isPager) { + telElement->addNode(std::make_shared<XMLElement>("PAGER")); + } + if (telephone.isMSG) { + telElement->addNode(std::make_shared<XMLElement>("MSG")); + } + if (telephone.isCell) { + telElement->addNode(std::make_shared<XMLElement>("CELL")); + } + if (telephone.isVideo) { + telElement->addNode(std::make_shared<XMLElement>("VIDEO")); + } + if (telephone.isBBS) { + telElement->addNode(std::make_shared<XMLElement>("BBS")); + } + if (telephone.isModem) { + telElement->addNode(std::make_shared<XMLElement>("MODEM")); + } + if (telephone.isISDN) { + telElement->addNode(std::make_shared<XMLElement>("ISDN")); + } + if (telephone.isPCS) { + telElement->addNode(std::make_shared<XMLElement>("PCS")); + } + if (telephone.isPreferred) { + telElement->addNode(std::make_shared<XMLElement>("PREF")); + } + queryElement.addNode(telElement); + } + + for (const auto& address : vcard->getAddresses()) { + std::shared_ptr<XMLElement> adrElement = std::make_shared<XMLElement>("ADR"); + if (!address.poBox.empty()) { + adrElement->addNode(std::make_shared<XMLElement>("POBOX", "", address.poBox)); + } + if (!address.addressExtension.empty()) { + adrElement->addNode(std::make_shared<XMLElement>("EXTADD", "", address.addressExtension)); + } + if (!address.street.empty()) { + adrElement->addNode(std::make_shared<XMLElement>("STREET", "", address.street)); + } + if (!address.locality.empty()) { + adrElement->addNode(std::make_shared<XMLElement>("LOCALITY", "", address.locality)); + } + if (!address.region.empty()) { + adrElement->addNode(std::make_shared<XMLElement>("REGION", "", address.region)); + } + if (!address.postalCode.empty()) { + adrElement->addNode(std::make_shared<XMLElement>("PCODE", "", address.postalCode)); + } + if (!address.country.empty()) { + adrElement->addNode(std::make_shared<XMLElement>("CTRY", "", address.country)); + } + + if (address.isHome) { + adrElement->addNode(std::make_shared<XMLElement>("HOME")); + } + if (address.isWork) { + adrElement->addNode(std::make_shared<XMLElement>("WORK")); + } + if (address.isPostal) { + adrElement->addNode(std::make_shared<XMLElement>("POSTAL")); + } + if (address.isParcel) { + adrElement->addNode(std::make_shared<XMLElement>("PARCEL")); + } + if (address.deliveryType == VCard::DomesticDelivery) { + adrElement->addNode(std::make_shared<XMLElement>("DOM")); + } + if (address.deliveryType == VCard::InternationalDelivery) { + adrElement->addNode(std::make_shared<XMLElement>("INTL")); + } + if (address.isPreferred) { + adrElement->addNode(std::make_shared<XMLElement>("PREF")); + } + queryElement.addNode(adrElement); + } + + for (const auto& addressLabel : vcard->getAddressLabels()) { + std::shared_ptr<XMLElement> labelElement = std::make_shared<XMLElement>("LABEL"); + + for (const auto& line : addressLabel.lines) { + labelElement->addNode(std::make_shared<XMLElement>("LINE", "", line)); + } + + if (addressLabel.isHome) { + labelElement->addNode(std::make_shared<XMLElement>("HOME")); + } + if (addressLabel.isWork) { + labelElement->addNode(std::make_shared<XMLElement>("WORK")); + } + if (addressLabel.isPostal) { + labelElement->addNode(std::make_shared<XMLElement>("POSTAL")); + } + if (addressLabel.isParcel) { + labelElement->addNode(std::make_shared<XMLElement>("PARCEL")); + } + if (addressLabel.deliveryType == VCard::DomesticDelivery) { + labelElement->addNode(std::make_shared<XMLElement>("DOM")); + } + if (addressLabel.deliveryType == VCard::InternationalDelivery) { + labelElement->addNode(std::make_shared<XMLElement>("INTL")); + } + if (addressLabel.isPreferred) { + labelElement->addNode(std::make_shared<XMLElement>("PREF")); + } + queryElement.addNode(labelElement); + } + + for (const auto& jid : vcard->getJIDs()) { + queryElement.addNode(std::make_shared<XMLElement>("JID", "", jid.toString())); + } + + if (!vcard->getDescription().empty()) { + queryElement.addNode(std::make_shared<XMLElement>("DESC", "", vcard->getDescription())); + } + + for (const auto& org : vcard->getOrganizations()) { + std::shared_ptr<XMLElement> orgElement = std::make_shared<XMLElement>("ORG"); + if (!org.name.empty()) { + orgElement->addNode(std::make_shared<XMLElement>("ORGNAME", "", org.name)); + } + if (!org.units.empty()) { + for (const auto& unit : org.units) { + orgElement->addNode(std::make_shared<XMLElement>("ORGUNIT", "", unit)); + } + } + queryElement.addNode(orgElement); + } + + for (const auto& title : vcard->getTitles()) { + queryElement.addNode(std::make_shared<XMLElement>("TITLE", "", title)); + } + + for (const auto& role : vcard->getRoles()) { + queryElement.addNode(std::make_shared<XMLElement>("ROLE", "", role)); + } + + for (const auto& url : vcard->getURLs()) { + queryElement.addNode(std::make_shared<XMLElement>("URL", "", url)); + } + + if (!vcard->getUnknownContent().empty()) { + queryElement.addNode(std::make_shared<XMLRawTextNode>(vcard->getUnknownContent())); + } + return queryElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/VCardSerializer.h b/Swiften/Serializer/PayloadSerializers/VCardSerializer.h index 04c1843..ad83f9a 100644 --- a/Swiften/Serializer/PayloadSerializers/VCardSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/VCardSerializer.h @@ -1,21 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericPayloadSerializer.h> -#include <Swiften/Elements/VCard.h> - #include <Swiften/Base/API.h> +#include <Swiften/Elements/VCard.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API VCardSerializer : public GenericPayloadSerializer<VCard> { - public: - VCardSerializer(); + class SWIFTEN_API VCardSerializer : public GenericPayloadSerializer<VCard> { + public: + VCardSerializer(); - virtual std::string serializePayload(boost::shared_ptr<VCard>) const; - }; + virtual std::string serializePayload(std::shared_ptr<VCard>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.cpp index 78c700b..607cf72 100644 --- a/Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.cpp @@ -1,13 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.h> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> @@ -17,12 +16,12 @@ namespace Swift { VCardUpdateSerializer::VCardUpdateSerializer() : GenericPayloadSerializer<VCardUpdate>() { } -std::string VCardUpdateSerializer::serializePayload(boost::shared_ptr<VCardUpdate> vcardUpdate) const { - XMLElement updateElement("x", "vcard-temp:x:update"); - boost::shared_ptr<XMLElement> photoElement(new XMLElement("photo")); - photoElement->addNode(boost::make_shared<XMLTextNode>(vcardUpdate->getPhotoHash())); - updateElement.addNode(photoElement); - return updateElement.serialize(); +std::string VCardUpdateSerializer::serializePayload(std::shared_ptr<VCardUpdate> vcardUpdate) const { + XMLElement updateElement("x", "vcard-temp:x:update"); + std::shared_ptr<XMLElement> photoElement(new XMLElement("photo")); + photoElement->addNode(std::make_shared<XMLTextNode>(vcardUpdate->getPhotoHash())); + updateElement.addNode(photoElement); + return updateElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.h b/Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.h index 6a63236..cea8ebd 100644 --- a/Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.h @@ -1,20 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/VCardUpdate.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> namespace Swift { - class SWIFTEN_API VCardUpdateSerializer : public GenericPayloadSerializer<VCardUpdate> { - public: - VCardUpdateSerializer(); + class SWIFTEN_API VCardUpdateSerializer : public GenericPayloadSerializer<VCardUpdate> { + public: + VCardUpdateSerializer(); - virtual std::string serializePayload(boost::shared_ptr<VCardUpdate>) const; - }; + virtual std::string serializePayload(std::shared_ptr<VCardUpdate>) const; + }; } diff --git a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp index 97dc94e..f38f5b7 100644 --- a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp @@ -4,197 +4,205 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h> -#include <iostream> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/lexical_cast.hpp> -#include <Swiften/Serializer/XML/XMLTextNode.h> + +#include <Swiften/Base/Log.h> +#include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h> -#include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> namespace Swift { - void WhiteboardElementSerializingVisitor::visit(WhiteboardLineElement& line) { - element = boost::make_shared<XMLElement>("line"); - try { - element->setAttribute("x1", boost::lexical_cast<std::string>(line.x1())); - element->setAttribute("y1", boost::lexical_cast<std::string>(line.y1())); - element->setAttribute("x2", boost::lexical_cast<std::string>(line.x2())); - element->setAttribute("y2", boost::lexical_cast<std::string>(line.y2())); - element->setAttribute("id", line.getID()); - element->setAttribute("stroke", line.getColor().toHex()); - element->setAttribute("stroke-width", boost::lexical_cast<std::string>(line.getPenWidth())); - element->setAttribute("opacity", alphaToOpacity(line.getColor().getAlpha())); - } catch (boost::bad_lexical_cast&) { - } - } - - void WhiteboardElementSerializingVisitor::visit(WhiteboardFreehandPathElement& path) { - element = boost::make_shared<XMLElement>("path"); - element->setAttribute("id", path.getID()); - element->setAttribute("stroke", path.getColor().toHex()); - try { - element->setAttribute("stroke-width", boost::lexical_cast<std::string>(path.getPenWidth())); - element->setAttribute("opacity", alphaToOpacity(path.getColor().getAlpha())); - std::string pathData; - if (path.getPoints().size() != 0) { - std::vector<std::pair<int, int> >::const_iterator it = path.getPoints().begin(); - pathData = "M"+boost::lexical_cast<std::string>(it->first)+" "+boost::lexical_cast<std::string>(it->second)+"L"; - for (; it != path.getPoints().end(); ++it) { - pathData += boost::lexical_cast<std::string>(it->first)+" "+boost::lexical_cast<std::string>(it->second)+" "; - } - } - element->setAttribute("d", pathData); - } catch (boost::bad_lexical_cast&) { - } - } - - void WhiteboardElementSerializingVisitor::visit(WhiteboardRectElement& rect) { - element = boost::make_shared<XMLElement>("rect"); - try { - element->setAttribute("x", boost::lexical_cast<std::string>(rect.getX())); - element->setAttribute("y", boost::lexical_cast<std::string>(rect.getY())); - element->setAttribute("width", boost::lexical_cast<std::string>(rect.getWidth())); - element->setAttribute("height", boost::lexical_cast<std::string>(rect.getHeight())); - element->setAttribute("id", rect.getID()); - element->setAttribute("stroke", rect.getPenColor().toHex()); - element->setAttribute("fill", rect.getBrushColor().toHex());; - element->setAttribute("stroke-width", boost::lexical_cast<std::string>(rect.getPenWidth())); - element->setAttribute("opacity", alphaToOpacity(rect.getPenColor().getAlpha())); - element->setAttribute("fill-opacity", alphaToOpacity(rect.getBrushColor().getAlpha())); - } catch (boost::bad_lexical_cast&) { - } - } - - void WhiteboardElementSerializingVisitor::visit(WhiteboardPolygonElement& polygon) { - element = boost::make_shared<XMLElement>("polygon"); - try { - element->setAttribute("id", polygon.getID()); - element->setAttribute("stroke", polygon.getPenColor().toHex()); - element->setAttribute("fill", polygon.getBrushColor().toHex());; - element->setAttribute("stroke-width", boost::lexical_cast<std::string>(polygon.getPenWidth())); - element->setAttribute("opacity", alphaToOpacity(polygon.getPenColor().getAlpha())); - element->setAttribute("fill-opacity", alphaToOpacity(polygon.getBrushColor().getAlpha())); - std::string points; - std::vector<std::pair<int, int> >::const_iterator it = polygon.getPoints().begin(); - for (; it != polygon.getPoints().end(); ++it) { - points += boost::lexical_cast<std::string>(it->first)+","+boost::lexical_cast<std::string>(it->second)+" "; - } - element->setAttribute("points", points); - } catch (boost::bad_lexical_cast&) { - } - } - - void WhiteboardElementSerializingVisitor::visit(WhiteboardTextElement& text) { - element = boost::make_shared<XMLElement>("text"); - try { - element->setAttribute("x", boost::lexical_cast<std::string>(text.getX())); - element->setAttribute("y", boost::lexical_cast<std::string>(text.getY())); - element->setAttribute("font-size", boost::lexical_cast<std::string>(text.getSize())); - element->setAttribute("id", text.getID()); - element->setAttribute("fill", text.getColor().toHex()); - element->setAttribute("opacity", alphaToOpacity(text.getColor().getAlpha())); - element->addNode(boost::make_shared<XMLTextNode>(text.getText())); - } catch (boost::bad_lexical_cast&) { - } - } - - void WhiteboardElementSerializingVisitor::visit(WhiteboardEllipseElement& ellipse) { - element = boost::make_shared<XMLElement>("ellipse"); - try { - element->setAttribute("cx", boost::lexical_cast<std::string>(ellipse.getCX())); - element->setAttribute("cy", boost::lexical_cast<std::string>(ellipse.getCY())); - element->setAttribute("rx", boost::lexical_cast<std::string>(ellipse.getRX())); - element->setAttribute("ry", boost::lexical_cast<std::string>(ellipse.getRY())); - element->setAttribute("id", ellipse.getID()); - element->setAttribute("stroke", ellipse.getPenColor().toHex()); - element->setAttribute("fill", ellipse.getBrushColor().toHex());; - element->setAttribute("stroke-width", boost::lexical_cast<std::string>(ellipse.getPenWidth())); - element->setAttribute("opacity", alphaToOpacity(ellipse.getPenColor().getAlpha())); - element->setAttribute("fill-opacity", alphaToOpacity(ellipse.getBrushColor().getAlpha())); - } catch (boost::bad_lexical_cast&) { - } - } - - XMLElement::ref WhiteboardElementSerializingVisitor::getResult() const { - return element; - } - - std::string WhiteboardElementSerializingVisitor::alphaToOpacity(int alpha) const { - int opacity = 100*alpha/254; - if (opacity == 100) { - return "1"; - } else { - return "."+boost::lexical_cast<std::string>(opacity); - } - } - - std::string WhiteboardSerializer::serializePayload(boost::shared_ptr<WhiteboardPayload> payload) const { - XMLElement element("wb", "http://swift.im/whiteboard"); - if (payload->getType() == WhiteboardPayload::Data) { - XMLElement::ref operationNode = boost::make_shared<XMLElement>("operation"); - WhiteboardElementSerializingVisitor visitor; -// payload->getElement()->accept(visitor); - WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(payload->getOperation()); - if (insertOp) { - try { - operationNode->setAttribute("type", "insert"); - operationNode->setAttribute("pos", boost::lexical_cast<std::string>(insertOp->getPos())); - operationNode->setAttribute("id", insertOp->getID()); - operationNode->setAttribute("parentid", insertOp->getParentID()); - } catch (boost::bad_lexical_cast&) { - } - insertOp->getElement()->accept(visitor); - operationNode->addNode(visitor.getResult()); - } - WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast<WhiteboardUpdateOperation>(payload->getOperation()); - if (updateOp) { - try { - operationNode->setAttribute("type", "update"); - operationNode->setAttribute("pos", boost::lexical_cast<std::string>(updateOp->getPos())); - operationNode->setAttribute("id", updateOp->getID()); - operationNode->setAttribute("parentid", updateOp->getParentID()); - operationNode->setAttribute("newpos", boost::lexical_cast<std::string>(updateOp->getNewPos())); - } catch (boost::bad_lexical_cast&) { - } - updateOp->getElement()->accept(visitor); - operationNode->addNode(visitor.getResult()); - - } - - WhiteboardDeleteOperation::ref deleteOp = boost::dynamic_pointer_cast<WhiteboardDeleteOperation>(payload->getOperation()); - if (deleteOp) { - try { - operationNode->setAttribute("type", "delete"); - operationNode->setAttribute("pos", boost::lexical_cast<std::string>(deleteOp->getPos())); - operationNode->setAttribute("id", deleteOp->getID()); - operationNode->setAttribute("parentid", deleteOp->getParentID()); - operationNode->setAttribute("elementid", deleteOp->getElementID()); - } catch (boost::bad_lexical_cast&) { - } - } - element.addNode(operationNode); - } - element.setAttribute("type", typeToString(payload->getType())); - return element.serialize(); - } - - std::string WhiteboardSerializer::typeToString(WhiteboardPayload::Type type) const { - switch (type) { - case WhiteboardPayload::Data: - return "data"; - case WhiteboardPayload::SessionRequest: - return "session-request"; - case WhiteboardPayload::SessionAccept: - return "session-accept"; - case WhiteboardPayload::SessionTerminate: - return "session-terminate"; - case WhiteboardPayload::UnknownType: - std::cerr << "Warning: Serializing unknown action value." << std::endl; - return ""; - } - assert(false); - return ""; - } + void WhiteboardElementSerializingVisitor::visit(WhiteboardLineElement& line) { + element = std::make_shared<XMLElement>("line"); + try { + element->setAttribute("x1", std::to_string(line.x1())); + element->setAttribute("y1", std::to_string(line.y1())); + element->setAttribute("x2", std::to_string(line.x2())); + element->setAttribute("y2", std::to_string(line.y2())); + element->setAttribute("id", line.getID()); + element->setAttribute("stroke", line.getColor().toHex()); + element->setAttribute("stroke-width", std::to_string(line.getPenWidth())); + element->setAttribute("opacity", alphaToOpacity(line.getColor().getAlpha())); + } catch (boost::bad_lexical_cast&) { + } + } + + void WhiteboardElementSerializingVisitor::visit(WhiteboardFreehandPathElement& path) { + element = std::make_shared<XMLElement>("path"); + element->setAttribute("id", path.getID()); + element->setAttribute("stroke", path.getColor().toHex()); + try { + element->setAttribute("stroke-width", std::to_string(path.getPenWidth())); + element->setAttribute("opacity", alphaToOpacity(path.getColor().getAlpha())); + std::string pathData; + if (path.getPoints().size() != 0) { + std::vector<std::pair<int, int> >::const_iterator it = path.getPoints().begin(); + pathData = "M"+std::to_string(it->first)+" "+std::to_string(it->second)+"L"; + for (; it != path.getPoints().end(); ++it) { + pathData += std::to_string(it->first)+" "+std::to_string(it->second)+" "; + } + } + element->setAttribute("d", pathData); + } catch (boost::bad_lexical_cast&) { + } + } + + void WhiteboardElementSerializingVisitor::visit(WhiteboardRectElement& rect) { + element = std::make_shared<XMLElement>("rect"); + try { + element->setAttribute("x", std::to_string(rect.getX())); + element->setAttribute("y", std::to_string(rect.getY())); + element->setAttribute("width", std::to_string(rect.getWidth())); + element->setAttribute("height", std::to_string(rect.getHeight())); + element->setAttribute("id", rect.getID()); + element->setAttribute("stroke", rect.getPenColor().toHex()); + element->setAttribute("fill", rect.getBrushColor().toHex()); + element->setAttribute("stroke-width", std::to_string(rect.getPenWidth())); + element->setAttribute("opacity", alphaToOpacity(rect.getPenColor().getAlpha())); + element->setAttribute("fill-opacity", alphaToOpacity(rect.getBrushColor().getAlpha())); + } catch (boost::bad_lexical_cast&) { + } + } + + void WhiteboardElementSerializingVisitor::visit(WhiteboardPolygonElement& polygon) { + element = std::make_shared<XMLElement>("polygon"); + try { + element->setAttribute("id", polygon.getID()); + element->setAttribute("stroke", polygon.getPenColor().toHex()); + element->setAttribute("fill", polygon.getBrushColor().toHex()); + element->setAttribute("stroke-width", std::to_string(polygon.getPenWidth())); + element->setAttribute("opacity", alphaToOpacity(polygon.getPenColor().getAlpha())); + element->setAttribute("fill-opacity", alphaToOpacity(polygon.getBrushColor().getAlpha())); + std::string points; + std::vector<std::pair<int, int> >::const_iterator it = polygon.getPoints().begin(); + for (; it != polygon.getPoints().end(); ++it) { + points += std::to_string(it->first)+","+std::to_string(it->second)+" "; + } + element->setAttribute("points", points); + } catch (boost::bad_lexical_cast&) { + } + } + + void WhiteboardElementSerializingVisitor::visit(WhiteboardTextElement& text) { + element = std::make_shared<XMLElement>("text"); + try { + element->setAttribute("x", std::to_string(text.getX())); + element->setAttribute("y", std::to_string(text.getY())); + element->setAttribute("font-size", std::to_string(text.getSize())); + element->setAttribute("id", text.getID()); + element->setAttribute("fill", text.getColor().toHex()); + element->setAttribute("opacity", alphaToOpacity(text.getColor().getAlpha())); + element->addNode(std::make_shared<XMLTextNode>(text.getText())); + } catch (boost::bad_lexical_cast&) { + } + } + + void WhiteboardElementSerializingVisitor::visit(WhiteboardEllipseElement& ellipse) { + element = std::make_shared<XMLElement>("ellipse"); + try { + element->setAttribute("cx", std::to_string(ellipse.getCX())); + element->setAttribute("cy", std::to_string(ellipse.getCY())); + element->setAttribute("rx", std::to_string(ellipse.getRX())); + element->setAttribute("ry", std::to_string(ellipse.getRY())); + element->setAttribute("id", ellipse.getID()); + element->setAttribute("stroke", ellipse.getPenColor().toHex()); + element->setAttribute("fill", ellipse.getBrushColor().toHex()); + element->setAttribute("stroke-width", std::to_string(ellipse.getPenWidth())); + element->setAttribute("opacity", alphaToOpacity(ellipse.getPenColor().getAlpha())); + element->setAttribute("fill-opacity", alphaToOpacity(ellipse.getBrushColor().getAlpha())); + } catch (boost::bad_lexical_cast&) { + } + } + + XMLElement::ref WhiteboardElementSerializingVisitor::getResult() const { + return element; + } + + std::string WhiteboardElementSerializingVisitor::alphaToOpacity(int alpha) const { + int opacity = 100*alpha/254; + if (opacity == 100) { + return "1"; + } else { + return "."+std::to_string(opacity); + } + } + + std::string WhiteboardSerializer::serializePayload(std::shared_ptr<WhiteboardPayload> payload) const { + XMLElement element("wb", "http://swift.im/whiteboard"); + if (payload->getType() == WhiteboardPayload::Data) { + XMLElement::ref operationNode = std::make_shared<XMLElement>("operation"); + WhiteboardElementSerializingVisitor visitor; +// payload->getElement()->accept(visitor); + WhiteboardInsertOperation::ref insertOp = std::dynamic_pointer_cast<WhiteboardInsertOperation>(payload->getOperation()); + if (insertOp) { + try { + operationNode->setAttribute("type", "insert"); + operationNode->setAttribute("pos", std::to_string(insertOp->getPos())); + operationNode->setAttribute("id", insertOp->getID()); + operationNode->setAttribute("parentid", insertOp->getParentID()); + } catch (boost::bad_lexical_cast&) { + } + insertOp->getElement()->accept(visitor); + operationNode->addNode(visitor.getResult()); + } + WhiteboardUpdateOperation::ref updateOp = std::dynamic_pointer_cast<WhiteboardUpdateOperation>(payload->getOperation()); + if (updateOp) { + try { + operationNode->setAttribute("type", "update"); + operationNode->setAttribute("pos", std::to_string(updateOp->getPos())); + operationNode->setAttribute("id", updateOp->getID()); + operationNode->setAttribute("parentid", updateOp->getParentID()); + operationNode->setAttribute("newpos", std::to_string(updateOp->getNewPos())); + } catch (boost::bad_lexical_cast&) { + } + updateOp->getElement()->accept(visitor); + operationNode->addNode(visitor.getResult()); + + } + + WhiteboardDeleteOperation::ref deleteOp = std::dynamic_pointer_cast<WhiteboardDeleteOperation>(payload->getOperation()); + if (deleteOp) { + try { + operationNode->setAttribute("type", "delete"); + operationNode->setAttribute("pos", std::to_string(deleteOp->getPos())); + operationNode->setAttribute("id", deleteOp->getID()); + operationNode->setAttribute("parentid", deleteOp->getParentID()); + operationNode->setAttribute("elementid", deleteOp->getElementID()); + } catch (boost::bad_lexical_cast&) { + } + } + element.addNode(operationNode); + } + element.setAttribute("type", typeToString(payload->getType())); + return element.serialize(); + } + + std::string WhiteboardSerializer::typeToString(WhiteboardPayload::Type type) const { + switch (type) { + case WhiteboardPayload::Data: + return "data"; + case WhiteboardPayload::SessionRequest: + return "session-request"; + case WhiteboardPayload::SessionAccept: + return "session-accept"; + case WhiteboardPayload::SessionTerminate: + return "session-terminate"; + case WhiteboardPayload::UnknownType: + SWIFT_LOG(warning) << "Serializing unknown action value."; + return ""; + } + assert(false); + return ""; + } } diff --git a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h index 26b76cb..1fde636 100644 --- a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h @@ -4,41 +4,48 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Elements/WhiteboardPayload.h> -#include <Swiften/Elements/Whiteboard/WhiteboardLineElement.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Whiteboard/WhiteboardElementVisitor.h> +#include <Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h> #include <Swiften/Elements/Whiteboard/WhiteboardFreehandPathElement.h> -#include <Swiften/Elements/Whiteboard/WhiteboardRectElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardLineElement.h> #include <Swiften/Elements/Whiteboard/WhiteboardPolygonElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardRectElement.h> #include <Swiften/Elements/Whiteboard/WhiteboardTextElement.h> -#include <Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h> -#include <Swiften/Elements/Whiteboard/WhiteboardElementVisitor.h> +#include <Swiften/Elements/WhiteboardPayload.h> #include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class WhiteboardElementSerializingVisitor : public WhiteboardElementVisitor { - public: - void visit(WhiteboardLineElement& line); - void visit(WhiteboardFreehandPathElement& path); - void visit(WhiteboardRectElement& rect); - void visit(WhiteboardPolygonElement& polygon); - void visit(WhiteboardTextElement& text); - void visit(WhiteboardEllipseElement& ellipse); - XMLElement::ref getResult() const; - - private: - std::string alphaToOpacity(int alpha) const; - - XMLElement::ref element; - }; - - class WhiteboardSerializer : public GenericPayloadSerializer<WhiteboardPayload> { - public: - std::string serializePayload(boost::shared_ptr<WhiteboardPayload> payload) const; - - private: - std::string typeToString(WhiteboardPayload::Type type) const; - }; + class SWIFTEN_API WhiteboardElementSerializingVisitor : public WhiteboardElementVisitor { + public: + void visit(WhiteboardLineElement& line); + void visit(WhiteboardFreehandPathElement& path); + void visit(WhiteboardRectElement& rect); + void visit(WhiteboardPolygonElement& polygon); + void visit(WhiteboardTextElement& text); + void visit(WhiteboardEllipseElement& ellipse); + XMLElement::ref getResult() const; + + private: + std::string alphaToOpacity(int alpha) const; + + XMLElement::ref element; + }; + + class SWIFTEN_API WhiteboardSerializer : public GenericPayloadSerializer<WhiteboardPayload> { + public: + std::string serializePayload(std::shared_ptr<WhiteboardPayload> payload) const; + + private: + std::string typeToString(WhiteboardPayload::Type type) const; + }; } diff --git a/Swiften/Serializer/PresenceSerializer.cpp b/Swiften/Serializer/PresenceSerializer.cpp index 20eda4b..fc398a4 100644 --- a/Swiften/Serializer/PresenceSerializer.cpp +++ b/Swiften/Serializer/PresenceSerializer.cpp @@ -1,33 +1,36 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/PresenceSerializer.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <Swiften/Base/Log.h> +#include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { -PresenceSerializer::PresenceSerializer(PayloadSerializerCollection* payloadSerializers) : - GenericStanzaSerializer<Presence>("presence", payloadSerializers) { +PresenceSerializer::PresenceSerializer(PayloadSerializerCollection* payloadSerializers, const boost::optional<std::string>& explicitNS) : + GenericStanzaSerializer<Presence>("presence", payloadSerializers, explicitNS) { + } void PresenceSerializer::setStanzaSpecificAttributesGeneric( - boost::shared_ptr<Presence> presence, - XMLElement& element) const { - switch (presence->getType()) { - case Presence::Unavailable: element.setAttribute("type","unavailable"); break; - case Presence::Probe: element.setAttribute("type","probe"); break; - case Presence::Subscribe: element.setAttribute("type","subscribe"); break; - case Presence::Subscribed: element.setAttribute("type","subscribed"); break; - case Presence::Unsubscribe: element.setAttribute("type","unsubscribe"); break; - case Presence::Unsubscribed: element.setAttribute("type","unsubscribed"); break; - case Presence::Error: element.setAttribute("type","error"); break; - case Presence::Available: break; - } + std::shared_ptr<Presence> presence, + XMLElement& element) const { + switch (presence->getType()) { + case Presence::Unavailable: element.setAttribute("type","unavailable"); break; + case Presence::Probe: element.setAttribute("type","probe"); break; + case Presence::Subscribe: element.setAttribute("type","subscribe"); break; + case Presence::Subscribed: element.setAttribute("type","subscribed"); break; + case Presence::Unsubscribe: element.setAttribute("type","unsubscribe"); break; + case Presence::Unsubscribed: element.setAttribute("type","unsubscribed"); break; + case Presence::Error: element.setAttribute("type","error"); break; + case Presence::Available: break; + } } } diff --git a/Swiften/Serializer/PresenceSerializer.h b/Swiften/Serializer/PresenceSerializer.h index e5d9f30..b0e1a4f 100644 --- a/Swiften/Serializer/PresenceSerializer.h +++ b/Swiften/Serializer/PresenceSerializer.h @@ -1,22 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericStanzaSerializer.h> +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Presence.h> +#include <Swiften/Serializer/GenericStanzaSerializer.h> namespace Swift { - class PresenceSerializer : public GenericStanzaSerializer<Presence> { - public: - PresenceSerializer(PayloadSerializerCollection* payloadSerializers); + class SWIFTEN_API PresenceSerializer : public GenericStanzaSerializer<Presence> { + public: + PresenceSerializer(PayloadSerializerCollection* payloadSerializers, const boost::optional<std::string>& explicitNS = boost::optional<std::string>()); + ~PresenceSerializer() {} - private: - virtual void setStanzaSpecificAttributesGeneric( - boost::shared_ptr<Presence> presence, - XMLElement& element) const; - }; + private: + virtual void setStanzaSpecificAttributesGeneric( + std::shared_ptr<Presence> presence, + XMLElement& element) const; + }; } diff --git a/Swiften/Serializer/StanzaAckRequestSerializer.h b/Swiften/Serializer/StanzaAckRequestSerializer.h index fff2a83..f738231 100644 --- a/Swiften/Serializer/StanzaAckRequestSerializer.h +++ b/Swiften/Serializer/StanzaAckRequestSerializer.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StanzaAckRequest.h> #include <Swiften/Serializer/GenericElementSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class StanzaAckRequestSerializer : public GenericElementSerializer<StanzaAckRequest> { - public: - StanzaAckRequestSerializer() : GenericElementSerializer<StanzaAckRequest>() { - } + class SWIFTEN_API StanzaAckRequestSerializer : public GenericElementSerializer<StanzaAckRequest> { + public: + StanzaAckRequestSerializer() : GenericElementSerializer<StanzaAckRequest>() { + } - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const { - return createSafeByteArray(XMLElement("r", "urn:xmpp:sm:2").serialize()); - } - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const { + return createSafeByteArray(XMLElement("r", "urn:xmpp:sm:2").serialize()); + } + }; } diff --git a/Swiften/Serializer/StanzaAckSerializer.h b/Swiften/Serializer/StanzaAckSerializer.h index ea1e8ad..228d67b 100644 --- a/Swiften/Serializer/StanzaAckSerializer.h +++ b/Swiften/Serializer/StanzaAckSerializer.h @@ -1,30 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/lexical_cast.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StanzaAck.h> #include <Swiften/Serializer/GenericElementSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class StanzaAckSerializer : public GenericElementSerializer<StanzaAck> { - public: - StanzaAckSerializer() : GenericElementSerializer<StanzaAck>() { - } + class SWIFTEN_API StanzaAckSerializer : public GenericElementSerializer<StanzaAck> { + public: + StanzaAckSerializer() : GenericElementSerializer<StanzaAck>() { + } - virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const { - StanzaAck::ref stanzaAck(boost::dynamic_pointer_cast<StanzaAck>(element)); - assert(stanzaAck->isValid()); - XMLElement result("a", "urn:xmpp:sm:2"); - result.setAttribute("h", std::string(boost::lexical_cast<std::string>(stanzaAck->getHandledStanzasCount()))); - return createSafeByteArray(result.serialize()); - } - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const { + StanzaAck::ref stanzaAck(std::dynamic_pointer_cast<StanzaAck>(element)); + assert(stanzaAck->isValid()); + XMLElement result("a", "urn:xmpp:sm:2"); + result.setAttribute("h", std::string(std::to_string(stanzaAck->getHandledStanzasCount()))); + return createSafeByteArray(result.serialize()); + } + }; } diff --git a/Swiften/Serializer/StanzaSerializer.cpp b/Swiften/Serializer/StanzaSerializer.cpp index 9a4fd2c..d4231c5 100644 --- a/Swiften/Serializer/StanzaSerializer.cpp +++ b/Swiften/Serializer/StanzaSerializer.cpp @@ -1,57 +1,67 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/StanzaSerializer.h> #include <sstream> #include <typeinfo> -#include <iostream> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Base/String.h> +#include <Swiften/Base/Log.h> +#include <Swiften/Elements/Stanza.h> #include <Swiften/Serializer/PayloadSerializer.h> #include <Swiften/Serializer/PayloadSerializerCollection.h> -#include <Swiften/Elements/Stanza.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> namespace Swift { -StanzaSerializer::StanzaSerializer(const std::string& tag, PayloadSerializerCollection* payloadSerializers) : tag_(tag), payloadSerializers_(payloadSerializers) { +StanzaSerializer::StanzaSerializer(const std::string& tag, PayloadSerializerCollection* payloadSerializers, const boost::optional<std::string>& explicitNS) : tag_(tag), payloadSerializers_(payloadSerializers), explicitDefaultNS_(explicitNS) { } -SafeByteArray StanzaSerializer::serialize(boost::shared_ptr<Element> element) const { - boost::shared_ptr<Stanza> stanza(boost::dynamic_pointer_cast<Stanza>(element)); - - XMLElement stanzaElement(tag_); - if (stanza->getFrom().isValid()) { - stanzaElement.setAttribute("from", stanza->getFrom()); - } - if (stanza->getTo().isValid()) { - stanzaElement.setAttribute("to", stanza->getTo()); - } - if (!stanza->getID().empty()) { - stanzaElement.setAttribute("id", stanza->getID()); - } - setStanzaSpecificAttributes(stanza, stanzaElement); - - std::string serializedPayloads; - foreach (const boost::shared_ptr<Payload>& payload, stanza->getPayloads()) { - PayloadSerializer* serializer = payloadSerializers_->getPayloadSerializer(payload); - if (serializer) { - serializedPayloads += serializer->serialize(payload); - } - else { - std::cerr << "Could not find serializer for " << typeid(*(payload.get())).name() << std::endl; - } - } - if (!serializedPayloads.empty()) { - stanzaElement.addNode(boost::shared_ptr<XMLNode>(new XMLRawTextNode(serializedPayloads))); - } - - return createSafeByteArray(stanzaElement.serialize()); +SafeByteArray StanzaSerializer::serialize(std::shared_ptr<ToplevelElement> element) const { + if (explicitDefaultNS_) { + return serialize(element, explicitDefaultNS_.get()); + } + else { + return serialize(element, ""); + } +} + +SafeByteArray StanzaSerializer::serialize(std::shared_ptr<ToplevelElement> element, const std::string& xmlns) const { + std::shared_ptr<Stanza> stanza(std::dynamic_pointer_cast<Stanza>(element)); + + XMLElement stanzaElement(tag_, explicitDefaultNS_ ? explicitDefaultNS_.get() : xmlns); + if (stanza->getFrom().isValid()) { + stanzaElement.setAttribute("from", stanza->getFrom()); + } + if (stanza->getTo().isValid()) { + stanzaElement.setAttribute("to", stanza->getTo()); + } + if (!stanza->getID().empty()) { + stanzaElement.setAttribute("id", stanza->getID()); + } + setStanzaSpecificAttributes(stanza, stanzaElement); + + std::string serializedPayloads; + for (const auto& payload : stanza->getPayloads()) { + PayloadSerializer* serializer = payloadSerializers_->getPayloadSerializer(payload); + if (serializer) { + serializedPayloads += serializer->serialize(payload); + } + else { + SWIFT_LOG(warning) << "Could not find serializer for " << typeid(*(payload.get())).name(); + } + } + serializedPayloads = String::sanitizeXMPPString(serializedPayloads); + if (!serializedPayloads.empty()) { + stanzaElement.addNode(std::make_shared<XMLRawTextNode>(serializedPayloads)); + } + + return createSafeByteArray(stanzaElement.serialize()); } } diff --git a/Swiften/Serializer/StanzaSerializer.h b/Swiften/Serializer/StanzaSerializer.h index db18aa2..b2e051c 100644 --- a/Swiften/Serializer/StanzaSerializer.h +++ b/Swiften/Serializer/StanzaSerializer.h @@ -1,28 +1,34 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <string> + +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Elements/Stanza.h> #include <Swiften/Serializer/ElementSerializer.h> -#include <string> namespace Swift { - class PayloadSerializerCollection; - class XMLElement; + class PayloadSerializerCollection; + class XMLElement; - class StanzaSerializer : public ElementSerializer { - public: - StanzaSerializer(const std::string& tag, PayloadSerializerCollection* payloadSerializers); + class SWIFTEN_API StanzaSerializer : public ElementSerializer { + public: + StanzaSerializer(const std::string& tag, PayloadSerializerCollection* payloadSerializers, const boost::optional<std::string>& explicitNS = boost::optional<std::string>()); - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const; - virtual void setStanzaSpecificAttributes(boost::shared_ptr<Element>, XMLElement&) const = 0; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element, const std::string& xmlns) const; + virtual void setStanzaSpecificAttributes(std::shared_ptr<ToplevelElement>, XMLElement&) const = 0; - private: - std::string tag_; - PayloadSerializerCollection* payloadSerializers_; - }; + private: + std::string tag_; + PayloadSerializerCollection* payloadSerializers_; + boost::optional<std::string> explicitDefaultNS_; + }; } diff --git a/Swiften/Serializer/StartTLSFailureSerializer.h b/Swiften/Serializer/StartTLSFailureSerializer.h index 779be92..77f904c 100644 --- a/Swiften/Serializer/StartTLSFailureSerializer.h +++ b/Swiften/Serializer/StartTLSFailureSerializer.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StartTLSFailure.h> #include <Swiften/Serializer/GenericElementSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class StartTLSFailureSerializer : public GenericElementSerializer<StartTLSFailure> { - public: - StartTLSFailureSerializer() : GenericElementSerializer<StartTLSFailure>() { - } + class SWIFTEN_API StartTLSFailureSerializer : public GenericElementSerializer<StartTLSFailure> { + public: + StartTLSFailureSerializer() : GenericElementSerializer<StartTLSFailure>() { + } - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const { - return createSafeByteArray(XMLElement("failure", "urn:ietf:params:xml:ns:xmpp-tls").serialize()); - } - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const { + return createSafeByteArray(XMLElement("failure", "urn:ietf:params:xml:ns:xmpp-tls").serialize()); + } + }; } diff --git a/Swiften/Serializer/StartTLSRequestSerializer.h b/Swiften/Serializer/StartTLSRequestSerializer.h index df914ce..ee2a76f 100644 --- a/Swiften/Serializer/StartTLSRequestSerializer.h +++ b/Swiften/Serializer/StartTLSRequestSerializer.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StartTLSRequest.h> #include <Swiften/Serializer/GenericElementSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class StartTLSRequestSerializer : public GenericElementSerializer<StartTLSRequest> { - public: - StartTLSRequestSerializer() : GenericElementSerializer<StartTLSRequest>() { - } + class SWIFTEN_API StartTLSRequestSerializer : public GenericElementSerializer<StartTLSRequest> { + public: + StartTLSRequestSerializer() : GenericElementSerializer<StartTLSRequest>() { + } - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const { - return createSafeByteArray(XMLElement("starttls", "urn:ietf:params:xml:ns:xmpp-tls").serialize()); - } - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const { + return createSafeByteArray(XMLElement("starttls", "urn:ietf:params:xml:ns:xmpp-tls").serialize()); + } + }; } diff --git a/Swiften/Serializer/StreamErrorSerializer.cpp b/Swiften/Serializer/StreamErrorSerializer.cpp index b3d62a0..684e8fe 100644 --- a/Swiften/Serializer/StreamErrorSerializer.cpp +++ b/Swiften/Serializer/StreamErrorSerializer.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/StreamErrorSerializer.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Serializer/XML/XMLElement.h> @@ -15,45 +15,45 @@ namespace Swift { StreamErrorSerializer::StreamErrorSerializer() : GenericElementSerializer<StreamError>() { } -SafeByteArray StreamErrorSerializer::serialize(boost::shared_ptr<Element> element) const { - StreamError::ref error = boost::dynamic_pointer_cast<StreamError>(element); - XMLElement errorElement("error", "http://etherx.jabber.org/streams"); - - std::string typeTag; - switch (error->getType()) { - case StreamError::BadFormat: typeTag = "bad-format"; break; - case StreamError::BadNamespacePrefix: typeTag = "bad-namespace-prefix"; break; - case StreamError::Conflict: typeTag = "conflict"; break; - case StreamError::ConnectionTimeout: typeTag = "connection-timeout"; break; - case StreamError::HostGone: typeTag = "host-gone"; break; - case StreamError::HostUnknown: typeTag = "host-unknown"; break; - case StreamError::ImproperAddressing: typeTag = "improper-addressing"; break; - case StreamError::InternalServerError: typeTag = "internal-server-error"; break; - case StreamError::InvalidFrom: typeTag = "invalid-from"; break; - case StreamError::InvalidID: typeTag = "invalid-id"; break; - case StreamError::InvalidNamespace: typeTag = "invalid-namespace"; break; - case StreamError::InvalidXML: typeTag = "invalid-xml"; break; - case StreamError::NotAuthorized: typeTag = "not-authorized"; break; - case StreamError::NotWellFormed: typeTag = "not-well-formed"; break; - case StreamError::PolicyViolation: typeTag = "policy-violation"; break; - case StreamError::RemoteConnectionFailed: typeTag = "remote-connection-failed"; break; - case StreamError::Reset: typeTag = "reset"; break; - case StreamError::ResourceConstraint: typeTag = "resource-constraint"; break; - case StreamError::RestrictedXML: typeTag = "restricted-xml"; break; - case StreamError::SeeOtherHost: typeTag = "see-other-host"; break; - case StreamError::SystemShutdown: typeTag = "system-shutdown"; break; - case StreamError::UndefinedCondition: typeTag = "undefined-condition"; break; - case StreamError::UnsupportedEncoding: typeTag = "unsupported-encoding"; break; - case StreamError::UnsupportedStanzaType: typeTag = "unsupported-stanza-type"; break; - case StreamError::UnsupportedVersion: typeTag = "unsupported-version"; break; - } - errorElement.addNode(boost::make_shared<XMLElement>(typeTag, "urn:ietf:params:xml:ns:xmpp-streams")); - - if (!error->getText().empty()) { - errorElement.addNode(boost::make_shared<XMLElement>("text", "urn:ietf:params:xml:ns:xmpp-streams", error->getText())); - } - - return createSafeByteArray(errorElement.serialize()); +SafeByteArray StreamErrorSerializer::serialize(std::shared_ptr<ToplevelElement> element) const { + StreamError::ref error = std::dynamic_pointer_cast<StreamError>(element); + XMLElement errorElement("error", "http://etherx.jabber.org/streams"); + + std::string typeTag; + switch (error->getType()) { + case StreamError::BadFormat: typeTag = "bad-format"; break; + case StreamError::BadNamespacePrefix: typeTag = "bad-namespace-prefix"; break; + case StreamError::Conflict: typeTag = "conflict"; break; + case StreamError::ConnectionTimeout: typeTag = "connection-timeout"; break; + case StreamError::HostGone: typeTag = "host-gone"; break; + case StreamError::HostUnknown: typeTag = "host-unknown"; break; + case StreamError::ImproperAddressing: typeTag = "improper-addressing"; break; + case StreamError::InternalServerError: typeTag = "internal-server-error"; break; + case StreamError::InvalidFrom: typeTag = "invalid-from"; break; + case StreamError::InvalidNamespace: typeTag = "invalid-namespace"; break; + case StreamError::InvalidXML: typeTag = "invalid-xml"; break; + case StreamError::NotAuthorized: typeTag = "not-authorized"; break; + case StreamError::NotWellFormed: typeTag = "not-well-formed"; break; + case StreamError::PolicyViolation: typeTag = "policy-violation"; break; + case StreamError::RemoteConnectionFailed: typeTag = "remote-connection-failed"; break; + case StreamError::Reset: typeTag = "reset"; break; + case StreamError::ResourceConstraint: typeTag = "resource-constraint"; break; + case StreamError::RestrictedXML: typeTag = "restricted-xml"; break; + case StreamError::SeeOtherHost: typeTag = "see-other-host"; break; + case StreamError::SystemShutdown: typeTag = "system-shutdown"; break; + case StreamError::UndefinedCondition: typeTag = "undefined-condition"; break; + case StreamError::UnsupportedEncoding: typeTag = "unsupported-encoding"; break; + case StreamError::UnsupportedFeature: typeTag = "unsupported-feature"; break; + case StreamError::UnsupportedStanzaType: typeTag = "unsupported-stanza-type"; break; + case StreamError::UnsupportedVersion: typeTag = "unsupported-version"; break; + } + errorElement.addNode(std::make_shared<XMLElement>(typeTag, "urn:ietf:params:xml:ns:xmpp-streams")); + + if (!error->getText().empty()) { + errorElement.addNode(std::make_shared<XMLElement>("text", "urn:ietf:params:xml:ns:xmpp-streams", error->getText())); + } + + return createSafeByteArray(errorElement.serialize()); } } diff --git a/Swiften/Serializer/StreamErrorSerializer.h b/Swiften/Serializer/StreamErrorSerializer.h index bdaa831..7277903 100644 --- a/Swiften/Serializer/StreamErrorSerializer.h +++ b/Swiften/Serializer/StreamErrorSerializer.h @@ -1,19 +1,20 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/GenericElementSerializer.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamError.h> +#include <Swiften/Serializer/GenericElementSerializer.h> namespace Swift { - class StreamErrorSerializer : public GenericElementSerializer<StreamError> { - public: - StreamErrorSerializer(); + class SWIFTEN_API StreamErrorSerializer : public GenericElementSerializer<StreamError> { + public: + StreamErrorSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element> error) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> error) const; + }; } diff --git a/Swiften/Serializer/StreamFeaturesSerializer.cpp b/Swiften/Serializer/StreamFeaturesSerializer.cpp index 2344349..2534db0 100644 --- a/Swiften/Serializer/StreamFeaturesSerializer.cpp +++ b/Swiften/Serializer/StreamFeaturesSerializer.cpp @@ -1,60 +1,59 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/StreamFeaturesSerializer.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> -#include <Swiften/Base/foreach.h> namespace Swift { StreamFeaturesSerializer::StreamFeaturesSerializer() { } -SafeByteArray StreamFeaturesSerializer::serialize(boost::shared_ptr<Element> element) const { - boost::shared_ptr<StreamFeatures> streamFeatures(boost::dynamic_pointer_cast<StreamFeatures>(element)); - - XMLElement streamFeaturesElement("stream:features"); - if (streamFeatures->hasStartTLS()) { - streamFeaturesElement.addNode(boost::make_shared<XMLElement>("starttls", "urn:ietf:params:xml:ns:xmpp-tls")); - } - if (!streamFeatures->getCompressionMethods().empty()) { - boost::shared_ptr<XMLElement> compressionElement(new XMLElement("compression", "http://jabber.org/features/compress")); - foreach(const std::string& method, streamFeatures->getCompressionMethods()) { - boost::shared_ptr<XMLElement> methodElement(new XMLElement("method")); - methodElement->addNode(boost::make_shared<XMLTextNode>(method)); - compressionElement->addNode(methodElement); - } - streamFeaturesElement.addNode(compressionElement); - } - if (!streamFeatures->getAuthenticationMechanisms().empty()) { - boost::shared_ptr<XMLElement> mechanismsElement(new XMLElement("mechanisms", "urn:ietf:params:xml:ns:xmpp-sasl")); - foreach(const std::string& mechanism, streamFeatures->getAuthenticationMechanisms()) { - boost::shared_ptr<XMLElement> mechanismElement(new XMLElement("mechanism")); - mechanismElement->addNode(boost::make_shared<XMLTextNode>(mechanism)); - mechanismsElement->addNode(mechanismElement); - } - streamFeaturesElement.addNode(mechanismsElement); - } - if (streamFeatures->hasResourceBind()) { - streamFeaturesElement.addNode(boost::make_shared<XMLElement>("bind", "urn:ietf:params:xml:ns:xmpp-bind")); - } - if (streamFeatures->hasSession()) { - streamFeaturesElement.addNode(boost::make_shared<XMLElement>("session", "urn:ietf:params:xml:ns:xmpp-session")); - } - if (streamFeatures->hasStreamManagement()) { - streamFeaturesElement.addNode(boost::make_shared<XMLElement>("sm", "urn:xmpp:sm:2")); - } - if (streamFeatures->hasRosterVersioning()) { - streamFeaturesElement.addNode(boost::make_shared<XMLElement>("ver", "urn:xmpp:features:rosterver")); - } - return createSafeByteArray(streamFeaturesElement.serialize()); +SafeByteArray StreamFeaturesSerializer::serialize(std::shared_ptr<ToplevelElement> element) const { + std::shared_ptr<StreamFeatures> streamFeatures(std::dynamic_pointer_cast<StreamFeatures>(element)); + + XMLElement streamFeaturesElement("stream:features"); + if (streamFeatures->hasStartTLS()) { + streamFeaturesElement.addNode(std::make_shared<XMLElement>("starttls", "urn:ietf:params:xml:ns:xmpp-tls")); + } + if (!streamFeatures->getCompressionMethods().empty()) { + std::shared_ptr<XMLElement> compressionElement(new XMLElement("compression", "http://jabber.org/features/compress")); + for (const auto& method : streamFeatures->getCompressionMethods()) { + std::shared_ptr<XMLElement> methodElement(new XMLElement("method")); + methodElement->addNode(std::make_shared<XMLTextNode>(method)); + compressionElement->addNode(methodElement); + } + streamFeaturesElement.addNode(compressionElement); + } + if (!streamFeatures->getAuthenticationMechanisms().empty()) { + std::shared_ptr<XMLElement> mechanismsElement(new XMLElement("mechanisms", "urn:ietf:params:xml:ns:xmpp-sasl")); + for (const auto& mechanism : streamFeatures->getAuthenticationMechanisms()) { + std::shared_ptr<XMLElement> mechanismElement(new XMLElement("mechanism")); + mechanismElement->addNode(std::make_shared<XMLTextNode>(mechanism)); + mechanismsElement->addNode(mechanismElement); + } + streamFeaturesElement.addNode(mechanismsElement); + } + if (streamFeatures->hasResourceBind()) { + streamFeaturesElement.addNode(std::make_shared<XMLElement>("bind", "urn:ietf:params:xml:ns:xmpp-bind")); + } + if (streamFeatures->hasSession()) { + streamFeaturesElement.addNode(std::make_shared<XMLElement>("session", "urn:ietf:params:xml:ns:xmpp-session")); + } + if (streamFeatures->hasStreamManagement()) { + streamFeaturesElement.addNode(std::make_shared<XMLElement>("sm", "urn:xmpp:sm:2")); + } + if (streamFeatures->hasRosterVersioning()) { + streamFeaturesElement.addNode(std::make_shared<XMLElement>("ver", "urn:xmpp:features:rosterver")); + } + return createSafeByteArray(streamFeaturesElement.serialize()); } } diff --git a/Swiften/Serializer/StreamFeaturesSerializer.h b/Swiften/Serializer/StreamFeaturesSerializer.h index 1bd1136..b1cc2f7 100644 --- a/Swiften/Serializer/StreamFeaturesSerializer.h +++ b/Swiften/Serializer/StreamFeaturesSerializer.h @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Elements/StreamFeatures.h> #include <Swiften/Serializer/GenericElementSerializer.h> namespace Swift { - class SWIFTEN_API StreamFeaturesSerializer : public GenericElementSerializer<StreamFeatures> { - public: - StreamFeaturesSerializer(); + class SWIFTEN_API StreamFeaturesSerializer : public GenericElementSerializer<StreamFeatures> { + public: + StreamFeaturesSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element> element) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement> element) const; + }; } diff --git a/Swiften/Serializer/StreamManagementEnabledSerializer.cpp b/Swiften/Serializer/StreamManagementEnabledSerializer.cpp index b559721..4f4ca2e 100644 --- a/Swiften/Serializer/StreamManagementEnabledSerializer.cpp +++ b/Swiften/Serializer/StreamManagementEnabledSerializer.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/StreamManagementEnabledSerializer.h> -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Elements/StreamManagementEnabled.h> #include <Swiften/Serializer/XML/XMLElement.h> @@ -16,14 +16,14 @@ using namespace Swift; StreamManagementEnabledSerializer::StreamManagementEnabledSerializer() : GenericElementSerializer<StreamManagementEnabled>() { } -SafeByteArray StreamManagementEnabledSerializer::serialize(boost::shared_ptr<Element> el) const { - boost::shared_ptr<StreamManagementEnabled> e(boost::dynamic_pointer_cast<StreamManagementEnabled>(el)); - XMLElement element("enabled", "urn:xmpp:sm:2"); - if (!e->getResumeID().empty()) { - element.setAttribute("id", e->getResumeID()); - } - if (e->getResumeSupported()) { - element.setAttribute("resume", "true"); - } - return createSafeByteArray(element.serialize()); +SafeByteArray StreamManagementEnabledSerializer::serialize(std::shared_ptr<ToplevelElement> el) const { + std::shared_ptr<StreamManagementEnabled> e(std::dynamic_pointer_cast<StreamManagementEnabled>(el)); + XMLElement element("enabled", "urn:xmpp:sm:2"); + if (!e->getResumeID().empty()) { + element.setAttribute("id", e->getResumeID()); + } + if (e->getResumeSupported()) { + element.setAttribute("resume", "true"); + } + return createSafeByteArray(element.serialize()); } diff --git a/Swiften/Serializer/StreamManagementEnabledSerializer.h b/Swiften/Serializer/StreamManagementEnabledSerializer.h index 5f28a2b..f139dc8 100644 --- a/Swiften/Serializer/StreamManagementEnabledSerializer.h +++ b/Swiften/Serializer/StreamManagementEnabledSerializer.h @@ -1,21 +1,22 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamManagementEnabled.h> #include <Swiften/Serializer/GenericElementSerializer.h> namespace Swift { - class StreamManagementEnabledSerializer : public GenericElementSerializer<StreamManagementEnabled> { - public: - StreamManagementEnabledSerializer(); + class SWIFTEN_API StreamManagementEnabledSerializer : public GenericElementSerializer<StreamManagementEnabled> { + public: + StreamManagementEnabledSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const; + }; } diff --git a/Swiften/Serializer/StreamManagementFailedSerializer.h b/Swiften/Serializer/StreamManagementFailedSerializer.h index f3dcce0..29dd0ab 100644 --- a/Swiften/Serializer/StreamManagementFailedSerializer.h +++ b/Swiften/Serializer/StreamManagementFailedSerializer.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamManagementFailed.h> #include <Swiften/Serializer/GenericElementSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class StreamManagementFailedSerializer : public GenericElementSerializer<StreamManagementFailed> { - public: - StreamManagementFailedSerializer() : GenericElementSerializer<StreamManagementFailed>() { - } + class SWIFTEN_API StreamManagementFailedSerializer : public GenericElementSerializer<StreamManagementFailed> { + public: + StreamManagementFailedSerializer() : GenericElementSerializer<StreamManagementFailed>() { + } - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const { - return createSafeByteArray(XMLElement("failed", "urn:xmpp:sm:2").serialize()); - } - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const { + return createSafeByteArray(XMLElement("failed", "urn:xmpp:sm:2").serialize()); + } + }; } diff --git a/Swiften/Serializer/StreamResumeSerializer.cpp b/Swiften/Serializer/StreamResumeSerializer.cpp index e9e520d..e4a40c9 100644 --- a/Swiften/Serializer/StreamResumeSerializer.cpp +++ b/Swiften/Serializer/StreamResumeSerializer.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/StreamResumeSerializer.h> -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/lexical_cast.hpp> #include <Swiften/Elements/StreamResume.h> @@ -17,12 +18,12 @@ using namespace Swift; StreamResumeSerializer::StreamResumeSerializer() : GenericElementSerializer<StreamResume>() { } -SafeByteArray StreamResumeSerializer::serialize(boost::shared_ptr<Element> el) const { - boost::shared_ptr<StreamResume> e(boost::dynamic_pointer_cast<StreamResume>(el)); - XMLElement element("resume", "urn:xmpp:sm:2"); - element.setAttribute("previd", e->getResumeID()); - if (e->getHandledStanzasCount()) { - element.setAttribute("h", boost::lexical_cast<std::string>(e->getHandledStanzasCount())); - } - return createSafeByteArray(element.serialize()); +SafeByteArray StreamResumeSerializer::serialize(std::shared_ptr<ToplevelElement> el) const { + std::shared_ptr<StreamResume> e(std::dynamic_pointer_cast<StreamResume>(el)); + XMLElement element("resume", "urn:xmpp:sm:2"); + element.setAttribute("previd", e->getResumeID()); + if (e->getHandledStanzasCount()) { + element.setAttribute("h", std::to_string(e->getHandledStanzasCount().get())); + } + return createSafeByteArray(element.serialize()); } diff --git a/Swiften/Serializer/StreamResumeSerializer.h b/Swiften/Serializer/StreamResumeSerializer.h index 501d8b6..ad13b2b 100644 --- a/Swiften/Serializer/StreamResumeSerializer.h +++ b/Swiften/Serializer/StreamResumeSerializer.h @@ -1,21 +1,22 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamResume.h> #include <Swiften/Serializer/GenericElementSerializer.h> namespace Swift { - class StreamResumeSerializer : public GenericElementSerializer<StreamResume> { - public: - StreamResumeSerializer(); + class SWIFTEN_API StreamResumeSerializer : public GenericElementSerializer<StreamResume> { + public: + StreamResumeSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const; + }; } diff --git a/Swiften/Serializer/StreamResumedSerializer.cpp b/Swiften/Serializer/StreamResumedSerializer.cpp index 7ae82d1..2398335 100644 --- a/Swiften/Serializer/StreamResumedSerializer.cpp +++ b/Swiften/Serializer/StreamResumedSerializer.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/StreamResumedSerializer.h> -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/lexical_cast.hpp> #include <Swiften/Elements/StreamResumed.h> @@ -17,12 +18,12 @@ using namespace Swift; StreamResumedSerializer::StreamResumedSerializer() : GenericElementSerializer<StreamResumed>() { } -SafeByteArray StreamResumedSerializer::serialize(boost::shared_ptr<Element> el) const { - boost::shared_ptr<StreamResumed> e(boost::dynamic_pointer_cast<StreamResumed>(el)); - XMLElement element("resumed", "urn:xmpp:sm:2"); - element.setAttribute("previd", e->getResumeID()); - if (e->getHandledStanzasCount()) { - element.setAttribute("h", boost::lexical_cast<std::string>(e->getHandledStanzasCount())); - } - return createSafeByteArray(element.serialize()); +SafeByteArray StreamResumedSerializer::serialize(std::shared_ptr<ToplevelElement> el) const { + std::shared_ptr<StreamResumed> e(std::dynamic_pointer_cast<StreamResumed>(el)); + XMLElement element("resumed", "urn:xmpp:sm:2"); + element.setAttribute("previd", e->getResumeID()); + if (e->getHandledStanzasCount()) { + element.setAttribute("h", std::to_string(e->getHandledStanzasCount().get())); + } + return createSafeByteArray(element.serialize()); } diff --git a/Swiften/Serializer/StreamResumedSerializer.h b/Swiften/Serializer/StreamResumedSerializer.h index 7828694..324282b 100644 --- a/Swiften/Serializer/StreamResumedSerializer.h +++ b/Swiften/Serializer/StreamResumedSerializer.h @@ -1,21 +1,22 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/StreamResumed.h> #include <Swiften/Serializer/GenericElementSerializer.h> namespace Swift { - class StreamResumedSerializer : public GenericElementSerializer<StreamResumed> { - public: - StreamResumedSerializer(); + class SWIFTEN_API StreamResumedSerializer : public GenericElementSerializer<StreamResumed> { + public: + StreamResumedSerializer(); - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const; - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const; + }; } diff --git a/Swiften/Serializer/TLSProceedSerializer.h b/Swiften/Serializer/TLSProceedSerializer.h index 21a8420..f99aefd 100644 --- a/Swiften/Serializer/TLSProceedSerializer.h +++ b/Swiften/Serializer/TLSProceedSerializer.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Elements/TLSProceed.h> #include <Swiften/Serializer/GenericElementSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> namespace Swift { - class TLSProceedSerializer : public GenericElementSerializer<TLSProceed> { - public: - TLSProceedSerializer() : GenericElementSerializer<TLSProceed>() { - } + class SWIFTEN_API TLSProceedSerializer : public GenericElementSerializer<TLSProceed> { + public: + TLSProceedSerializer() : GenericElementSerializer<TLSProceed>() { + } - virtual SafeByteArray serialize(boost::shared_ptr<Element>) const { - return createSafeByteArray(XMLElement("proceed", "urn:ietf:params:xml:ns:xmpp-tls").serialize()); - } - }; + virtual SafeByteArray serialize(std::shared_ptr<ToplevelElement>) const { + return createSafeByteArray(XMLElement("proceed", "urn:ietf:params:xml:ns:xmpp-tls").serialize()); + } + }; } diff --git a/Swiften/Serializer/UnitTest/AuthChallengeSerializerTest.cpp b/Swiften/Serializer/UnitTest/AuthChallengeSerializerTest.cpp index 5fb0a4e..d313b42 100644 --- a/Swiften/Serializer/UnitTest/AuthChallengeSerializerTest.cpp +++ b/Swiften/Serializer/UnitTest/AuthChallengeSerializerTest.cpp @@ -1,57 +1,57 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/AuthChallengeSerializer.h> -#include <Swiften/Elements/AuthChallenge.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/Elements/AuthChallenge.h> +#include <Swiften/Serializer/AuthChallengeSerializer.h> using namespace Swift; class AuthChallengeSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(AuthChallengeSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_NoMessage); - CPPUNIT_TEST(testSerialize_EmptyMessage); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerialize() { - AuthChallengeSerializer testling; - boost::shared_ptr<AuthChallenge> authChallenge(new AuthChallenge()); - authChallenge->setValue(createByteArray("foo")); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "Zm9v" - "</challenge>"), testling.serialize(authChallenge)); - } - - void testSerialize_NoMessage() { - AuthChallengeSerializer testling; - boost::shared_ptr<AuthChallenge> authChallenge(new AuthChallenge()); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "</challenge>"), testling.serialize(authChallenge)); - } - - void testSerialize_EmptyMessage() { - AuthChallengeSerializer testling; - boost::shared_ptr<AuthChallenge> authChallenge(new AuthChallenge()); - authChallenge->setValue(std::vector<unsigned char>()); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "=" - "</challenge>"), testling.serialize(authChallenge)); - } + CPPUNIT_TEST_SUITE(AuthChallengeSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_NoMessage); + CPPUNIT_TEST(testSerialize_EmptyMessage); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + AuthChallengeSerializer testling; + std::shared_ptr<AuthChallenge> authChallenge(new AuthChallenge()); + authChallenge->setValue(createByteArray("foo")); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "Zm9v" + "</challenge>"), testling.serialize(authChallenge)); + } + + void testSerialize_NoMessage() { + AuthChallengeSerializer testling; + std::shared_ptr<AuthChallenge> authChallenge(new AuthChallenge()); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "</challenge>"), testling.serialize(authChallenge)); + } + + void testSerialize_EmptyMessage() { + AuthChallengeSerializer testling; + std::shared_ptr<AuthChallenge> authChallenge(new AuthChallenge()); + authChallenge->setValue(std::vector<unsigned char>()); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "=" + "</challenge>"), testling.serialize(authChallenge)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(AuthChallengeSerializerTest); diff --git a/Swiften/Serializer/UnitTest/AuthRequestSerializerTest.cpp b/Swiften/Serializer/UnitTest/AuthRequestSerializerTest.cpp index db36de7..2dc71fb 100644 --- a/Swiften/Serializer/UnitTest/AuthRequestSerializerTest.cpp +++ b/Swiften/Serializer/UnitTest/AuthRequestSerializerTest.cpp @@ -1,57 +1,57 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/AuthRequestSerializer.h> -#include <Swiften/Elements/AuthRequest.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/Elements/AuthRequest.h> +#include <Swiften/Serializer/AuthRequestSerializer.h> using namespace Swift; class AuthRequestSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(AuthRequestSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_NoMessage); - CPPUNIT_TEST(testSerialize_EmptyMessage); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerialize() { - AuthRequestSerializer testling; - boost::shared_ptr<AuthRequest> authRequest(new AuthRequest("PLAIN")); - authRequest->setMessage(createSafeByteArray("foo")); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\">" - "Zm9v" - "</auth>"), testling.serialize(authRequest)); - } - - void testSerialize_NoMessage() { - AuthRequestSerializer testling; - boost::shared_ptr<AuthRequest> authRequest(new AuthRequest("PLAIN")); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\">" - "</auth>"), testling.serialize(authRequest)); - } - - void testSerialize_EmptyMessage() { - AuthRequestSerializer testling; - boost::shared_ptr<AuthRequest> authRequest(new AuthRequest("PLAIN")); - authRequest->setMessage(SafeByteArray()); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\">" - "=" - "</auth>"), testling.serialize(authRequest)); - } + CPPUNIT_TEST_SUITE(AuthRequestSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_NoMessage); + CPPUNIT_TEST(testSerialize_EmptyMessage); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + AuthRequestSerializer testling; + std::shared_ptr<AuthRequest> authRequest(new AuthRequest("PLAIN")); + authRequest->setMessage(createSafeByteArray("foo")); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\">" + "Zm9v" + "</auth>"), testling.serialize(authRequest)); + } + + void testSerialize_NoMessage() { + AuthRequestSerializer testling; + std::shared_ptr<AuthRequest> authRequest(new AuthRequest("PLAIN")); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\">" + "</auth>"), testling.serialize(authRequest)); + } + + void testSerialize_EmptyMessage() { + AuthRequestSerializer testling; + std::shared_ptr<AuthRequest> authRequest(new AuthRequest("PLAIN")); + authRequest->setMessage(SafeByteArray()); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\">" + "=" + "</auth>"), testling.serialize(authRequest)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(AuthRequestSerializerTest); diff --git a/Swiften/Serializer/UnitTest/AuthResponseSerializerTest.cpp b/Swiften/Serializer/UnitTest/AuthResponseSerializerTest.cpp index 4b846d7..1ee4b62 100644 --- a/Swiften/Serializer/UnitTest/AuthResponseSerializerTest.cpp +++ b/Swiften/Serializer/UnitTest/AuthResponseSerializerTest.cpp @@ -1,57 +1,57 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/AuthResponseSerializer.h> -#include <Swiften/Elements/AuthResponse.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/Elements/AuthResponse.h> +#include <Swiften/Serializer/AuthResponseSerializer.h> using namespace Swift; class AuthResponseSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(AuthResponseSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_NoMessage); - CPPUNIT_TEST(testSerialize_EmptyMessage); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerialize() { - AuthResponseSerializer testling; - boost::shared_ptr<AuthResponse> authResponse(new AuthResponse()); - authResponse->setValue(createSafeByteArray("foo")); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "Zm9v" - "</response>"), testling.serialize(authResponse)); - } - - void testSerialize_NoMessage() { - AuthResponseSerializer testling; - boost::shared_ptr<AuthResponse> authResponse(new AuthResponse()); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "</response>"), testling.serialize(authResponse)); - } - - void testSerialize_EmptyMessage() { - AuthResponseSerializer testling; - boost::shared_ptr<AuthResponse> authResponse(new AuthResponse()); - authResponse->setValue(SafeByteArray()); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "=" - "</response>"), testling.serialize(authResponse)); - } + CPPUNIT_TEST_SUITE(AuthResponseSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_NoMessage); + CPPUNIT_TEST(testSerialize_EmptyMessage); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + AuthResponseSerializer testling; + std::shared_ptr<AuthResponse> authResponse(new AuthResponse()); + authResponse->setValue(createSafeByteArray("foo")); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "Zm9v" + "</response>"), testling.serialize(authResponse)); + } + + void testSerialize_NoMessage() { + AuthResponseSerializer testling; + std::shared_ptr<AuthResponse> authResponse(new AuthResponse()); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "</response>"), testling.serialize(authResponse)); + } + + void testSerialize_EmptyMessage() { + AuthResponseSerializer testling; + std::shared_ptr<AuthResponse> authResponse(new AuthResponse()); + authResponse->setValue(SafeByteArray()); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "" + "</response>"), testling.serialize(authResponse)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(AuthResponseSerializerTest); diff --git a/Swiften/Serializer/UnitTest/AuthSuccessSerializerTest.cpp b/Swiften/Serializer/UnitTest/AuthSuccessSerializerTest.cpp index 86e01f5..3c4bb1b 100644 --- a/Swiften/Serializer/UnitTest/AuthSuccessSerializerTest.cpp +++ b/Swiften/Serializer/UnitTest/AuthSuccessSerializerTest.cpp @@ -1,57 +1,57 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/AuthSuccessSerializer.h> -#include <Swiften/Elements/AuthSuccess.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/Elements/AuthSuccess.h> +#include <Swiften/Serializer/AuthSuccessSerializer.h> using namespace Swift; class AuthSuccessSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(AuthSuccessSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_NoMessage); - CPPUNIT_TEST(testSerialize_EmptyMessage); - CPPUNIT_TEST_SUITE_END(); - - public: - void testSerialize() { - AuthSuccessSerializer testling; - boost::shared_ptr<AuthSuccess> authSuccess(new AuthSuccess()); - authSuccess->setValue(createByteArray("foo")); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "Zm9v" - "</success>"), testling.serialize(authSuccess)); - } - - void testSerialize_NoMessage() { - AuthSuccessSerializer testling; - boost::shared_ptr<AuthSuccess> authSuccess(new AuthSuccess()); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "</success>"), testling.serialize(authSuccess)); - } - - void testSerialize_EmptyMessage() { - AuthSuccessSerializer testling; - boost::shared_ptr<AuthSuccess> authSuccess(new AuthSuccess()); - authSuccess->setValue(std::vector<unsigned char>()); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "=" - "</success>"), testling.serialize(authSuccess)); - } + CPPUNIT_TEST_SUITE(AuthSuccessSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_NoMessage); + CPPUNIT_TEST(testSerialize_EmptyMessage); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize() { + AuthSuccessSerializer testling; + std::shared_ptr<AuthSuccess> authSuccess(new AuthSuccess()); + authSuccess->setValue(createByteArray("foo")); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "Zm9v" + "</success>"), testling.serialize(authSuccess)); + } + + void testSerialize_NoMessage() { + AuthSuccessSerializer testling; + std::shared_ptr<AuthSuccess> authSuccess(new AuthSuccess()); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "</success>"), testling.serialize(authSuccess)); + } + + void testSerialize_EmptyMessage() { + AuthSuccessSerializer testling; + std::shared_ptr<AuthSuccess> authSuccess(new AuthSuccess()); + authSuccess->setValue(std::vector<unsigned char>()); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "=" + "</success>"), testling.serialize(authSuccess)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(AuthSuccessSerializerTest); diff --git a/Swiften/Serializer/UnitTest/StreamFeaturesSerializerTest.cpp b/Swiften/Serializer/UnitTest/StreamFeaturesSerializerTest.cpp index 0abb32c..dd3d6c3 100644 --- a/Swiften/Serializer/UnitTest/StreamFeaturesSerializerTest.cpp +++ b/Swiften/Serializer/UnitTest/StreamFeaturesSerializerTest.cpp @@ -1,58 +1,57 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/StreamFeaturesSerializer.h> #include <Swiften/Elements/StreamFeatures.h> - +#include <Swiften/Serializer/StreamFeaturesSerializer.h> using namespace Swift; class StreamFeaturesSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StreamFeaturesSerializerTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST_SUITE_END(); - - public: - StreamFeaturesSerializerTest() {} - - void testSerialize() { - StreamFeaturesSerializer testling; - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->setHasStartTLS(); - streamFeatures->addCompressionMethod("zlib"); - streamFeatures->addCompressionMethod("lzw"); - streamFeatures->addAuthenticationMechanism("DIGEST-MD5"); - streamFeatures->addAuthenticationMechanism("PLAIN"); - streamFeatures->setHasResourceBind(); - streamFeatures->setHasSession(); - streamFeatures->setHasStreamManagement(); - streamFeatures->setHasRosterVersioning(); - - CPPUNIT_ASSERT_EQUAL(createSafeByteArray( - "<stream:features>" - "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>" - "<compression xmlns=\"http://jabber.org/features/compress\">" - "<method>zlib</method>" - "<method>lzw</method>" - "</compression>" - "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" - "<mechanism>DIGEST-MD5</mechanism>" - "<mechanism>PLAIN</mechanism>" - "</mechanisms>" - "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>" - "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>" - "<sm xmlns=\"urn:xmpp:sm:2\"/>" - "<ver xmlns=\"urn:xmpp:features:rosterver\"/>" - "</stream:features>"), testling.serialize(streamFeatures)); - } + CPPUNIT_TEST_SUITE(StreamFeaturesSerializerTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST_SUITE_END(); + + public: + StreamFeaturesSerializerTest() {} + + void testSerialize() { + StreamFeaturesSerializer testling; + std::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->setHasStartTLS(); + streamFeatures->addCompressionMethod("zlib"); + streamFeatures->addCompressionMethod("lzw"); + streamFeatures->addAuthenticationMechanism("DIGEST-MD5"); + streamFeatures->addAuthenticationMechanism("PLAIN"); + streamFeatures->setHasResourceBind(); + streamFeatures->setHasSession(); + streamFeatures->setHasStreamManagement(); + streamFeatures->setHasRosterVersioning(); + + CPPUNIT_ASSERT_EQUAL(createSafeByteArray( + "<stream:features>" + "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>" + "<compression xmlns=\"http://jabber.org/features/compress\">" + "<method>zlib</method>" + "<method>lzw</method>" + "</compression>" + "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">" + "<mechanism>DIGEST-MD5</mechanism>" + "<mechanism>PLAIN</mechanism>" + "</mechanisms>" + "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>" + "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>" + "<sm xmlns=\"urn:xmpp:sm:2\"/>" + "<ver xmlns=\"urn:xmpp:features:rosterver\"/>" + "</stream:features>"), testling.serialize(streamFeatures)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(StreamFeaturesSerializerTest); diff --git a/Swiften/Serializer/UnitTest/XMPPSerializerTest.cpp b/Swiften/Serializer/UnitTest/XMPPSerializerTest.cpp index c0ab841..93205fc 100644 --- a/Swiften/Serializer/UnitTest/XMPPSerializerTest.cpp +++ b/Swiften/Serializer/UnitTest/XMPPSerializerTest.cpp @@ -1,75 +1,75 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Serializer/XMPPSerializer.h> #include <Swiften/Elements/AuthChallenge.h> -#include <Swiften/Serializer/PayloadSerializerCollection.h> #include <Swiften/Elements/ProtocolHeader.h> +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/XMPPSerializer.h> using namespace Swift; class XMPPSerializerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(XMPPSerializerTest); - CPPUNIT_TEST(testSerializeHeader_Client); - CPPUNIT_TEST(testSerializeHeader_Component); - CPPUNIT_TEST(testSerializeHeader_Server); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(XMPPSerializerTest); + CPPUNIT_TEST(testSerializeHeader_Client); + CPPUNIT_TEST(testSerializeHeader_Component); + CPPUNIT_TEST(testSerializeHeader_Server); + CPPUNIT_TEST_SUITE_END(); - public: - void setUp() { - payloadSerializerCollection = new PayloadSerializerCollection(); - } + public: + void setUp() { + payloadSerializerCollection = new PayloadSerializerCollection(); + } - void tearDown() { - delete payloadSerializerCollection; - } + void tearDown() { + delete payloadSerializerCollection; + } - void testSerializeHeader_Client() { - boost::shared_ptr<XMPPSerializer> testling(createSerializer(ClientStreamType)); - ProtocolHeader protocolHeader; - protocolHeader.setFrom("bla@foo.com"); - protocolHeader.setTo("foo.com"); - protocolHeader.setID("myid"); - protocolHeader.setVersion("0.99"); + void testSerializeHeader_Client() { + std::shared_ptr<XMPPSerializer> testling(createSerializer(ClientStreamType)); + ProtocolHeader protocolHeader; + protocolHeader.setFrom("bla@foo.com"); + protocolHeader.setTo("foo.com"); + protocolHeader.setID("myid"); + protocolHeader.setVersion("0.99"); - CPPUNIT_ASSERT_EQUAL(std::string("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" from=\"bla@foo.com\" to=\"foo.com\" id=\"myid\" version=\"0.99\">"), testling->serializeHeader(protocolHeader)); - } + CPPUNIT_ASSERT_EQUAL(std::string("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" from=\"bla@foo.com\" to=\"foo.com\" id=\"myid\" version=\"0.99\">"), testling->serializeHeader(protocolHeader)); + } - void testSerializeHeader_Component() { - boost::shared_ptr<XMPPSerializer> testling(createSerializer(ComponentStreamType)); - ProtocolHeader protocolHeader; - protocolHeader.setFrom("bla@foo.com"); - protocolHeader.setTo("foo.com"); - protocolHeader.setID("myid"); - protocolHeader.setVersion("0.99"); + void testSerializeHeader_Component() { + std::shared_ptr<XMPPSerializer> testling(createSerializer(ComponentStreamType)); + ProtocolHeader protocolHeader; + protocolHeader.setFrom("bla@foo.com"); + protocolHeader.setTo("foo.com"); + protocolHeader.setID("myid"); + protocolHeader.setVersion("0.99"); - CPPUNIT_ASSERT_EQUAL(std::string("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:component:accept\" xmlns:stream=\"http://etherx.jabber.org/streams\" from=\"bla@foo.com\" to=\"foo.com\" id=\"myid\" version=\"0.99\">"), testling->serializeHeader(protocolHeader)); - } + CPPUNIT_ASSERT_EQUAL(std::string("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:component:accept\" xmlns:stream=\"http://etherx.jabber.org/streams\" from=\"bla@foo.com\" to=\"foo.com\" id=\"myid\" version=\"0.99\">"), testling->serializeHeader(protocolHeader)); + } - void testSerializeHeader_Server() { - boost::shared_ptr<XMPPSerializer> testling(createSerializer(ServerStreamType)); - ProtocolHeader protocolHeader; - protocolHeader.setFrom("bla@foo.com"); - protocolHeader.setTo("foo.com"); - protocolHeader.setID("myid"); - protocolHeader.setVersion("0.99"); + void testSerializeHeader_Server() { + std::shared_ptr<XMPPSerializer> testling(createSerializer(ServerStreamType)); + ProtocolHeader protocolHeader; + protocolHeader.setFrom("bla@foo.com"); + protocolHeader.setTo("foo.com"); + protocolHeader.setID("myid"); + protocolHeader.setVersion("0.99"); - CPPUNIT_ASSERT_EQUAL(std::string("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:server\" xmlns:stream=\"http://etherx.jabber.org/streams\" from=\"bla@foo.com\" to=\"foo.com\" id=\"myid\" version=\"0.99\">"), testling->serializeHeader(protocolHeader)); - } + CPPUNIT_ASSERT_EQUAL(std::string("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:server\" xmlns:stream=\"http://etherx.jabber.org/streams\" from=\"bla@foo.com\" to=\"foo.com\" id=\"myid\" version=\"0.99\">"), testling->serializeHeader(protocolHeader)); + } - private: - XMPPSerializer* createSerializer(StreamType type) { - return new XMPPSerializer(payloadSerializerCollection, type); - } + private: + XMPPSerializer* createSerializer(StreamType type) { + return new XMPPSerializer(payloadSerializerCollection, type, false); + } - private: - PayloadSerializerCollection* payloadSerializerCollection; + private: + PayloadSerializerCollection* payloadSerializerCollection; }; CPPUNIT_TEST_SUITE_REGISTRATION(XMPPSerializerTest); diff --git a/Swiften/Serializer/XML/UnitTest/XMLElementTest.cpp b/Swiften/Serializer/XML/UnitTest/XMLElementTest.cpp index a2197b0..ce6d7fa 100644 --- a/Swiften/Serializer/XML/UnitTest/XMLElementTest.cpp +++ b/Swiften/Serializer/XML/UnitTest/XMLElementTest.cpp @@ -1,14 +1,14 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <memory> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> - #include <Swiften/Serializer/XML/XMLElement.h> #include <Swiften/Serializer/XML/XMLTextNode.h> @@ -16,55 +16,62 @@ using namespace Swift; class XMLElementTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(XMLElementTest); - CPPUNIT_TEST(testSerialize); - CPPUNIT_TEST(testSerialize_NoChildren); - CPPUNIT_TEST(testSerialize_SpecialAttributeCharacters); - CPPUNIT_TEST(testSerialize_EmptyAttributeValue); - CPPUNIT_TEST_SUITE_END(); - - public: - XMLElementTest() {} - - void testSerialize() { - XMLElement testling("foo", "http://example.com"); - testling.setAttribute("myatt", "myval"); - boost::shared_ptr<XMLElement> barElement(new XMLElement("bar")); - barElement->addNode(boost::make_shared<XMLTextNode>("Blo")); - testling.addNode(barElement); - boost::shared_ptr<XMLElement> bazElement(new XMLElement("baz")); - bazElement->addNode(boost::make_shared<XMLTextNode>("Bli&</stream>")); - testling.addNode(bazElement); - - std::string result = testling.serialize(); - std::string expectedResult = - "<foo myatt=\"myval\" xmlns=\"http://example.com\">" - "<bar>Blo</bar>" - "<baz>Bli&</stream></baz>" - "</foo>"; - - CPPUNIT_ASSERT_EQUAL(expectedResult, result); - } - - void testSerialize_NoChildren() { - XMLElement testling("foo", "http://example.com"); - - CPPUNIT_ASSERT_EQUAL(std::string("<foo xmlns=\"http://example.com\"/>"), testling.serialize()); - } - - void testSerialize_SpecialAttributeCharacters() { - XMLElement testling("foo"); - testling.setAttribute("myatt", "<\"'&>"); - - CPPUNIT_ASSERT_EQUAL(std::string("<foo myatt=\"<"'&>\"/>"), testling.serialize()); - } - - void testSerialize_EmptyAttributeValue() { - XMLElement testling("foo"); - testling.setAttribute("myatt", ""); - - CPPUNIT_ASSERT_EQUAL(std::string("<foo myatt=\"\"/>"), testling.serialize()); - } + CPPUNIT_TEST_SUITE(XMLElementTest); + CPPUNIT_TEST(testSerialize); + CPPUNIT_TEST(testSerialize_NoChildren); + CPPUNIT_TEST(testSerialize_SpecialAttributeCharacters); + CPPUNIT_TEST(testSerialize_EmptyAttributeValue); + CPPUNIT_TEST_SUITE_END(); + + public: + XMLElementTest() {} + + void testSerialize() { + XMLElement testling("foo", "http://example.com"); + testling.setAttribute("myatt", "myval"); + std::shared_ptr<XMLElement> barElement(new XMLElement("bar")); + barElement->addNode(std::make_shared<XMLTextNode>("Blo")); + testling.addNode(barElement); + std::shared_ptr<XMLElement> bazElement(new XMLElement("baz")); + bazElement->addNode(std::make_shared<XMLTextNode>("Bli&</stream>")); + testling.addNode(bazElement); + + std::string result = testling.serialize(); + std::string expectedResult = + "<foo myatt=\"myval\" xmlns=\"http://example.com\">" + "<bar>Blo</bar>" + "<baz>Bli&</stream></baz>" + "</foo>"; + + CPPUNIT_ASSERT_EQUAL(expectedResult, result); + } + + void testSerialize_NoChildren() { + XMLElement testling("foo", "http://example.com"); + + CPPUNIT_ASSERT_EQUAL(std::string("<foo xmlns=\"http://example.com\"/>"), testling.serialize()); + } + + void testSerialize_SpecialAttributeCharacters() { + XMLElement testling("foo"); + testling.setAttribute("myatt", "<\"'&>"); + + CPPUNIT_ASSERT_EQUAL(std::string("<foo myatt=\"<"'&>\"/>"), testling.serialize()); + } + + void testSerialize_EmptyAttributeValue() { + XMLElement testling("foo"); + testling.setAttribute("myatt", ""); + + CPPUNIT_ASSERT_EQUAL(std::string("<foo myatt=\"\"/>"), testling.serialize()); + } + + void testEscape_SpecialAttributeCharacters() { + auto testling = XMLElement::escapeAttributeValue(R"(<"'&>not escaped.)"); + + CPPUNIT_ASSERT_EQUAL(std::string("<"'&>not escaped."), testling); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(XMLElementTest); diff --git a/Swiften/Serializer/XML/XMLElement.cpp b/Swiften/Serializer/XML/XMLElement.cpp index 42b602a..7515061 100644 --- a/Swiften/Serializer/XML/XMLElement.cpp +++ b/Swiften/Serializer/XML/XMLElement.cpp @@ -1,60 +1,61 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Serializer/XML/XMLTextNode.h> namespace Swift { XMLElement::XMLElement(const std::string& tag, const std::string& xmlns, const std::string& text) : tag_(tag) { - if (!xmlns.empty()) { - setAttribute("xmlns", xmlns); - } - if (!text.empty()) { - addNode(XMLTextNode::ref(new XMLTextNode(text))); - } + if (!xmlns.empty()) { + setAttribute("xmlns", xmlns); + } + if (!text.empty()) { + addNode(XMLTextNode::ref(new XMLTextNode(text))); + } } std::string XMLElement::serialize() { - std::string result; - result += "<" + tag_; - typedef std::pair<std::string,std::string> Pair; - foreach(const Pair& p, attributes_) { - result += " " + p.first + "=\"" + p.second + "\""; - } - - if (!childNodes_.empty()) { - result += ">"; - foreach (boost::shared_ptr<XMLNode> node, childNodes_) { - result += node->serialize(); - } - result += "</" + tag_ + ">"; - } - else { - result += "/>"; - } - return result; + std::string result; + result += "<" + tag_; + for (const auto& p : attributes_) { + result += " " + p.first + "=\"" + p.second + "\""; + } + + if (!childNodes_.empty()) { + result += ">"; + for (auto& node : childNodes_) { + result += node->serialize(); + } + result += "</" + tag_ + ">"; + } + else { + result += "/>"; + } + return result; +} + +std::string XMLElement::escapeAttributeValue(std::string value) { + String::replaceAll(value, '&', "&"); + String::replaceAll(value, '<', "<"); + String::replaceAll(value, '>', ">"); + String::replaceAll(value, '\'', "'"); + String::replaceAll(value, '"', """); + return value; } void XMLElement::setAttribute(const std::string& attribute, const std::string& value) { - std::string escapedValue(value); - String::replaceAll(escapedValue, '&', "&"); - String::replaceAll(escapedValue, '<', "<"); - String::replaceAll(escapedValue, '>', ">"); - String::replaceAll(escapedValue, '\'', "'"); - String::replaceAll(escapedValue, '"', """); - attributes_[attribute] = escapedValue; + attributes_[attribute] = escapeAttributeValue(value); } -void XMLElement::addNode(boost::shared_ptr<XMLNode> node) { - if (node) { - childNodes_.push_back(node); - } +void XMLElement::addNode(std::shared_ptr<XMLNode> node) { + if (node) { + childNodes_.push_back(node); + } } } diff --git a/Swiften/Serializer/XML/XMLElement.h b/Swiften/Serializer/XML/XMLElement.h index 305932a..db74626 100644 --- a/Swiften/Serializer/XML/XMLElement.h +++ b/Swiften/Serializer/XML/XMLElement.h @@ -1,35 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <vector> #include <map> - +#include <memory> #include <string> +#include <vector> #include <Swiften/Base/API.h> #include <Swiften/Serializer/XML/XMLNode.h> namespace Swift { - class SWIFTEN_API XMLElement : public XMLNode { - public: - typedef boost::shared_ptr<XMLElement> ref; + class SWIFTEN_API XMLElement : public XMLNode { + public: + typedef std::shared_ptr<XMLElement> ref; - XMLElement(const std::string& tag, const std::string& xmlns = "", const std::string& text = ""); + XMLElement(const std::string& tag, const std::string& xmlns = "", const std::string& text = ""); - void setAttribute(const std::string& attribute, const std::string& value); - void addNode(boost::shared_ptr<XMLNode> node); + static std::string escapeAttributeValue(std::string value); + void setAttribute(const std::string& attribute, const std::string& value); + void addNode(std::shared_ptr<XMLNode> node); - virtual std::string serialize(); + virtual std::string serialize(); - private: - std::string tag_; - std::map<std::string, std::string> attributes_; - std::vector< boost::shared_ptr<XMLNode> > childNodes_; - }; + private: + std::string tag_; + std::map<std::string, std::string> attributes_; + std::vector< std::shared_ptr<XMLNode> > childNodes_; + }; } diff --git a/Swiften/Serializer/XML/XMLNode.cpp b/Swiften/Serializer/XML/XMLNode.cpp index 7eedeff..9ee203b 100644 --- a/Swiften/Serializer/XML/XMLNode.cpp +++ b/Swiften/Serializer/XML/XMLNode.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/XML/XMLNode.h> diff --git a/Swiften/Serializer/XML/XMLNode.h b/Swiften/Serializer/XML/XMLNode.h index 9d9e1a0..8417b5c 100644 --- a/Swiften/Serializer/XML/XMLNode.h +++ b/Swiften/Serializer/XML/XMLNode.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,10 +11,10 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API XMLNode { - public: - virtual ~XMLNode(); + class SWIFTEN_API XMLNode { + public: + virtual ~XMLNode(); - virtual std::string serialize() = 0; - }; + virtual std::string serialize() = 0; + }; } diff --git a/Swiften/Serializer/XML/XMLRawTextNode.h b/Swiften/Serializer/XML/XMLRawTextNode.h index 9e222d5..fbd7754 100644 --- a/Swiften/Serializer/XML/XMLRawTextNode.h +++ b/Swiften/Serializer/XML/XMLRawTextNode.h @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Serializer/XML/XMLNode.h> namespace Swift { - class XMLRawTextNode : public XMLNode { - public: - XMLRawTextNode(const std::string& text) : text_(text) { - } + class SWIFTEN_API XMLRawTextNode : public XMLNode { + public: + XMLRawTextNode(const std::string& text) : text_(text) { + } - std::string serialize() { - return text_; - } + std::string serialize() { + return text_; + } - private: - std::string text_; - }; + private: + std::string text_; + }; } diff --git a/Swiften/Serializer/XML/XMLTextNode.h b/Swiften/Serializer/XML/XMLTextNode.h index 648854f..44970bf 100644 --- a/Swiften/Serializer/XML/XMLTextNode.h +++ b/Swiften/Serializer/XML/XMLTextNode.h @@ -1,34 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Serializer/XML/XMLNode.h> +#include <memory> + +#include <Swiften/Base/API.h> #include <Swiften/Base/String.h> +#include <Swiften/Serializer/XML/XMLNode.h> namespace Swift { - class XMLTextNode : public XMLNode { - public: - typedef boost::shared_ptr<XMLTextNode> ref; - - XMLTextNode(const std::string& text) : text_(text) { - String::replaceAll(text_, '&', "&"); // Should come first - String::replaceAll(text_, '<', "<"); - String::replaceAll(text_, '>', ">"); - } - - std::string serialize() { - return text_; - } - - static ref create(const std::string& text) { - return ref(new XMLTextNode(text)); - } - - private: - std::string text_; - }; + class SWIFTEN_API XMLTextNode : public XMLNode { + public: + typedef std::shared_ptr<XMLTextNode> ref; + + XMLTextNode(const std::string& text) : text_(text) { + String::replaceAll(text_, '&', "&"); // Should come first + String::replaceAll(text_, '<', "<"); + String::replaceAll(text_, '>', ">"); + } + + std::string serialize() { + return text_; + } + + static ref create(const std::string& text) { + return ref(new XMLTextNode(text)); + } + + private: + std::string text_; + }; } diff --git a/Swiften/Serializer/XMPPSerializer.cpp b/Swiften/Serializer/XMPPSerializer.cpp index 389f7cc..7a003fb 100644 --- a/Swiften/Serializer/XMPPSerializer.cpp +++ b/Swiften/Serializer/XMPPSerializer.cpp @@ -1,111 +1,111 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Serializer/XMPPSerializer.h> -#include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <iostream> #include <cassert> +#include <memory> + +#include <boost/bind.hpp> +#include <Swiften/Base/Log.h> #include <Swiften/Elements/ProtocolHeader.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/Serializer/CompressRequestSerializer.h> -#include <Swiften/Serializer/CompressFailureSerializer.h> -#include <Swiften/Serializer/StreamErrorSerializer.h> -#include <Swiften/Serializer/StreamFeaturesSerializer.h> -#include <Swiften/Serializer/AuthRequestSerializer.h> -#include <Swiften/Serializer/AuthFailureSerializer.h> -#include <Swiften/Serializer/AuthSuccessSerializer.h> #include <Swiften/Serializer/AuthChallengeSerializer.h> +#include <Swiften/Serializer/AuthFailureSerializer.h> +#include <Swiften/Serializer/AuthRequestSerializer.h> #include <Swiften/Serializer/AuthResponseSerializer.h> +#include <Swiften/Serializer/AuthSuccessSerializer.h> +#include <Swiften/Serializer/ComponentHandshakeSerializer.h> +#include <Swiften/Serializer/CompressFailureSerializer.h> +#include <Swiften/Serializer/CompressRequestSerializer.h> #include <Swiften/Serializer/EnableStreamManagementSerializer.h> +#include <Swiften/Serializer/IQSerializer.h> +#include <Swiften/Serializer/MessageSerializer.h> +#include <Swiften/Serializer/PresenceSerializer.h> +#include <Swiften/Serializer/StanzaAckRequestSerializer.h> +#include <Swiften/Serializer/StanzaAckSerializer.h> +#include <Swiften/Serializer/StartTLSFailureSerializer.h> +#include <Swiften/Serializer/StartTLSRequestSerializer.h> +#include <Swiften/Serializer/StreamErrorSerializer.h> +#include <Swiften/Serializer/StreamFeaturesSerializer.h> #include <Swiften/Serializer/StreamManagementEnabledSerializer.h> +#include <Swiften/Serializer/StreamManagementFailedSerializer.h> #include <Swiften/Serializer/StreamResumeSerializer.h> #include <Swiften/Serializer/StreamResumedSerializer.h> -#include <Swiften/Serializer/StreamManagementFailedSerializer.h> -#include <Swiften/Serializer/StanzaAckSerializer.h> -#include <Swiften/Serializer/StanzaAckRequestSerializer.h> -#include <Swiften/Serializer/StartTLSRequestSerializer.h> -#include <Swiften/Serializer/StartTLSFailureSerializer.h> #include <Swiften/Serializer/TLSProceedSerializer.h> -#include <Swiften/Serializer/MessageSerializer.h> -#include <Swiften/Serializer/PresenceSerializer.h> -#include <Swiften/Serializer/IQSerializer.h> -#include <Swiften/Serializer/ComponentHandshakeSerializer.h> namespace Swift { -XMPPSerializer::XMPPSerializer(PayloadSerializerCollection* payloadSerializers, StreamType type) : type_(type) { - serializers_.push_back(boost::make_shared<PresenceSerializer>(payloadSerializers)); - serializers_.push_back(boost::make_shared<IQSerializer>(payloadSerializers)); - serializers_.push_back(boost::make_shared<MessageSerializer>(payloadSerializers)); - serializers_.push_back(boost::make_shared<CompressRequestSerializer>()); - serializers_.push_back(boost::make_shared<CompressFailureSerializer>()); - serializers_.push_back(boost::make_shared<AuthRequestSerializer>()); - serializers_.push_back(boost::make_shared<AuthFailureSerializer>()); - serializers_.push_back(boost::make_shared<AuthSuccessSerializer>()); - serializers_.push_back(boost::make_shared<AuthChallengeSerializer>()); - serializers_.push_back(boost::make_shared<AuthResponseSerializer>()); - serializers_.push_back(boost::make_shared<StartTLSRequestSerializer>()); - serializers_.push_back(boost::make_shared<StartTLSFailureSerializer>()); - serializers_.push_back(boost::make_shared<TLSProceedSerializer>()); - serializers_.push_back(boost::make_shared<StreamFeaturesSerializer>()); - serializers_.push_back(boost::make_shared<StreamErrorSerializer>()); - serializers_.push_back(boost::make_shared<EnableStreamManagementSerializer>()); - serializers_.push_back(boost::make_shared<StreamManagementEnabledSerializer>()); - serializers_.push_back(boost::make_shared<StreamManagementFailedSerializer>()); - serializers_.push_back(boost::make_shared<StreamResumeSerializer>()); - serializers_.push_back(boost::make_shared<StreamResumedSerializer>()); - serializers_.push_back(boost::make_shared<StanzaAckSerializer>()); - serializers_.push_back(boost::make_shared<StanzaAckRequestSerializer>()); - serializers_.push_back(boost::make_shared<ComponentHandshakeSerializer>()); +XMPPSerializer::XMPPSerializer(PayloadSerializerCollection* payloadSerializers, StreamType type, bool setExplictNSonTopLevelElements) : type_(type) { + serializers_.push_back(std::make_shared<PresenceSerializer>(payloadSerializers, setExplictNSonTopLevelElements ? getDefaultNamespace() : boost::optional<std::string>())); + serializers_.push_back(std::make_shared<IQSerializer>(payloadSerializers, setExplictNSonTopLevelElements ? getDefaultNamespace() : boost::optional<std::string>())); + serializers_.push_back(std::make_shared<MessageSerializer>(payloadSerializers, setExplictNSonTopLevelElements ? getDefaultNamespace() : boost::optional<std::string>())); + serializers_.push_back(std::make_shared<CompressRequestSerializer>()); + serializers_.push_back(std::make_shared<CompressFailureSerializer>()); + serializers_.push_back(std::make_shared<AuthRequestSerializer>()); + serializers_.push_back(std::make_shared<AuthFailureSerializer>()); + serializers_.push_back(std::make_shared<AuthSuccessSerializer>()); + serializers_.push_back(std::make_shared<AuthChallengeSerializer>()); + serializers_.push_back(std::make_shared<AuthResponseSerializer>()); + serializers_.push_back(std::make_shared<StartTLSRequestSerializer>()); + serializers_.push_back(std::make_shared<StartTLSFailureSerializer>()); + serializers_.push_back(std::make_shared<TLSProceedSerializer>()); + serializers_.push_back(std::make_shared<StreamFeaturesSerializer>()); + serializers_.push_back(std::make_shared<StreamErrorSerializer>()); + serializers_.push_back(std::make_shared<EnableStreamManagementSerializer>()); + serializers_.push_back(std::make_shared<StreamManagementEnabledSerializer>()); + serializers_.push_back(std::make_shared<StreamManagementFailedSerializer>()); + serializers_.push_back(std::make_shared<StreamResumeSerializer>()); + serializers_.push_back(std::make_shared<StreamResumedSerializer>()); + serializers_.push_back(std::make_shared<StanzaAckSerializer>()); + serializers_.push_back(std::make_shared<StanzaAckRequestSerializer>()); + serializers_.push_back(std::make_shared<ComponentHandshakeSerializer>()); } std::string XMPPSerializer::serializeHeader(const ProtocolHeader& header) const { - std::string result = "<?xml version=\"1.0\"?><stream:stream xmlns=\"" + getDefaultNamespace() + "\" xmlns:stream=\"http://etherx.jabber.org/streams\""; - if (!header.getFrom().empty()) { - result += " from=\"" + header.getFrom() + "\""; - } - if (!header.getTo().empty()) { - result += " to=\"" + header.getTo() + "\""; - } - if (!header.getID().empty()) { - result += " id=\"" + header.getID() + "\""; - } - if (!header.getVersion().empty()) { - result += " version=\"" + header.getVersion() + "\""; - } - result += ">"; - return result; + std::string result = "<?xml version=\"1.0\"?><stream:stream xmlns=\"" + getDefaultNamespace() + "\" xmlns:stream=\"http://etherx.jabber.org/streams\""; + if (!header.getFrom().empty()) { + result += " from=\"" + header.getFrom() + "\""; + } + if (!header.getTo().empty()) { + result += " to=\"" + header.getTo() + "\""; + } + if (!header.getID().empty()) { + result += " id=\"" + header.getID() + "\""; + } + if (!header.getVersion().empty()) { + result += " version=\"" + header.getVersion() + "\""; + } + result += ">"; + return result; } -SafeByteArray XMPPSerializer::serializeElement(boost::shared_ptr<Element> element) const { - std::vector< boost::shared_ptr<ElementSerializer> >::const_iterator i = std::find_if(serializers_.begin(), serializers_.end(), boost::bind(&ElementSerializer::canSerialize, _1, element)); - if (i != serializers_.end()) { - return (*i)->serialize(element); - } - else { - std::cerr << "Could not find serializer for " << typeid(*(element.get())).name() << std::endl; - return createSafeByteArray(""); - } +SafeByteArray XMPPSerializer::serializeElement(std::shared_ptr<ToplevelElement> element) const { + std::vector< std::shared_ptr<ElementSerializer> >::const_iterator i = std::find_if(serializers_.begin(), serializers_.end(), boost::bind(&ElementSerializer::canSerialize, _1, element)); + if (i != serializers_.end()) { + return (*i)->serialize(element); + } + else { + SWIFT_LOG(warning) << "Could not find serializer for " << typeid(*(element.get())).name(); + return createSafeByteArray(""); + } } std::string XMPPSerializer::serializeFooter() const { - return "</stream:stream>"; + return "</stream:stream>"; } std::string XMPPSerializer::getDefaultNamespace() const { - switch (type_) { - case ClientStreamType: return "jabber:client"; - case ServerStreamType: return "jabber:server"; - case ComponentStreamType: return "jabber:component:accept"; - } - assert(false); - return ""; + switch (type_) { + case ClientStreamType: return "jabber:client"; + case ServerStreamType: return "jabber:server"; + case ComponentStreamType: return "jabber:component:accept"; + } + assert(false); + return ""; } } diff --git a/Swiften/Serializer/XMPPSerializer.h b/Swiften/Serializer/XMPPSerializer.h index 5b5c9d6..d328272 100644 --- a/Swiften/Serializer/XMPPSerializer.h +++ b/Swiften/Serializer/XMPPSerializer.h @@ -1,38 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> #include <vector> #include <Swiften/Base/API.h> -#include <Swiften/Elements/Element.h> #include <Swiften/Elements/StreamType.h> -#include <string> +#include <Swiften/Elements/ToplevelElement.h> #include <Swiften/Serializer/ElementSerializer.h> namespace Swift { - class PayloadSerializerCollection; - class CompressRequestSerializer; - class ProtocolHeader; - - class SWIFTEN_API XMPPSerializer { - public: - XMPPSerializer(PayloadSerializerCollection*, StreamType type); - - std::string serializeHeader(const ProtocolHeader&) const; - SafeByteArray serializeElement(boost::shared_ptr<Element> stanza) const; - std::string serializeFooter() const; - - private: - std::string getDefaultNamespace() const; - - private: - StreamType type_; - std::vector< boost::shared_ptr<ElementSerializer> > serializers_; - }; + class PayloadSerializerCollection; + class ProtocolHeader; + + class SWIFTEN_API XMPPSerializer { + public: + XMPPSerializer(PayloadSerializerCollection*, StreamType type, bool setExplictNSonTopLevelElements); + + std::string serializeHeader(const ProtocolHeader&) const; + SafeByteArray serializeElement(std::shared_ptr<ToplevelElement> stanza) const; + std::string serializeFooter() const; + + private: + std::string getDefaultNamespace() const; + + private: + StreamType type_; + std::vector< std::shared_ptr<ElementSerializer> > serializers_; + }; } diff --git a/Swiften/Session/BOSHSessionStream.cpp b/Swiften/Session/BOSHSessionStream.cpp index 62261d0..a335b93 100644 --- a/Swiften/Session/BOSHSessionStream.cpp +++ b/Swiften/Session/BOSHSessionStream.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ @@ -12,132 +12,138 @@ #include <boost/random/uniform_int.hpp> #include <boost/random/variate_generator.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/Elements/StreamType.h> -#include <Swiften/StreamStack/XMPPLayer.h> -#include <Swiften/StreamStack/StreamStack.h> -#include <Swiften/StreamStack/ConnectionLayer.h> -#include <Swiften/StreamStack/WhitespacePingLayer.h> +#include <Swiften/EventLoop/EventLoop.h> #include <Swiften/StreamStack/CompressionLayer.h> +#include <Swiften/StreamStack/ConnectionLayer.h> +#include <Swiften/StreamStack/StreamStack.h> #include <Swiften/StreamStack/TLSLayer.h> -#include <Swiften/TLS/TLSContextFactory.h> +#include <Swiften/StreamStack/WhitespacePingLayer.h> +#include <Swiften/StreamStack/XMPPLayer.h> #include <Swiften/TLS/TLSContext.h> -#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/TLS/TLSContextFactory.h> namespace Swift { -BOSHSessionStream::BOSHSessionStream( - const URL& boshURL, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - ConnectionFactory* connectionFactory, - TLSContextFactory* tlsContextFactory, - TimerFactory* timerFactory, - XMLParserFactory* xmlParserFactory, - EventLoop* eventLoop, - DomainNameResolver* resolver, - const std::string& to, - const URL& boshHTTPConnectProxyURL, - const SafeString& boshHTTPConnectProxyAuthID, - const SafeString& boshHTTPConnectProxyAuthPassword) : - available(false), - eventLoop(eventLoop), - firstHeader(true) { - - boost::mt19937 random; - boost::uniform_int<unsigned long long> dist(0, (1LL<<53) - 1); - random.seed(static_cast<unsigned int>(time(NULL))); - unsigned long long initialRID = boost::variate_generator<boost::mt19937&, boost::uniform_int<unsigned long long> >(random, dist)(); - - connectionPool = new BOSHConnectionPool(boshURL, resolver, connectionFactory, xmlParserFactory, tlsContextFactory, timerFactory, eventLoop, to, initialRID, boshHTTPConnectProxyURL, boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword); - connectionPool->onSessionTerminated.connect(boost::bind(&BOSHSessionStream::handlePoolSessionTerminated, this, _1)); - connectionPool->onSessionStarted.connect(boost::bind(&BOSHSessionStream::handlePoolSessionStarted, this)); - connectionPool->onXMPPDataRead.connect(boost::bind(&BOSHSessionStream::handlePoolXMPPDataRead, this, _1)); - connectionPool->onBOSHDataRead.connect(boost::bind(&BOSHSessionStream::handlePoolBOSHDataRead, this, _1)); - connectionPool->onBOSHDataWritten.connect(boost::bind(&BOSHSessionStream::handlePoolBOSHDataWritten, this, _1)); - - xmppLayer = new XMPPLayer(payloadParserFactories, payloadSerializers, xmlParserFactory, ClientStreamType); - xmppLayer->onStreamStart.connect(boost::bind(&BOSHSessionStream::handleStreamStartReceived, this, _1)); - xmppLayer->onElement.connect(boost::bind(&BOSHSessionStream::handleElementReceived, this, _1)); - xmppLayer->onError.connect(boost::bind(&BOSHSessionStream::handleXMPPError, this)); - xmppLayer->onWriteData.connect(boost::bind(&BOSHSessionStream::handleXMPPLayerDataWritten, this, _1)); - - available = true; +BOSHSessionStream::BOSHSessionStream(const URL& boshURL, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + ConnectionFactory* connectionFactory, + TLSContextFactory* tlsContextFactory, + TimerFactory* timerFactory, + XMLParserFactory* xmlParserFactory, + EventLoop* eventLoop, + DomainNameResolver* resolver, + const std::string& to, + const URL& boshHTTPConnectProxyURL, + const SafeString& boshHTTPConnectProxyAuthID, + const SafeString& boshHTTPConnectProxyAuthPassword, + const TLSOptions& tlsOptions, + std::shared_ptr<HTTPTrafficFilter> trafficFilter) : + available(false), + eventLoop(eventLoop), + firstHeader(true) { + + boost::mt19937 random; + boost::uniform_int<unsigned long long> dist(0, (1LL<<53) - 1); + random.seed(static_cast<unsigned int>(time(nullptr))); + unsigned long long initialRID = boost::variate_generator<boost::mt19937&, boost::uniform_int<unsigned long long> >(random, dist)(); + + connectionPool = new BOSHConnectionPool(boshURL, resolver, connectionFactory, xmlParserFactory, tlsContextFactory, timerFactory, eventLoop, to, initialRID, boshHTTPConnectProxyURL, boshHTTPConnectProxyAuthID, boshHTTPConnectProxyAuthPassword, tlsOptions, trafficFilter); + connectionPool->onSessionTerminated.connect(boost::bind(&BOSHSessionStream::handlePoolSessionTerminated, this, _1)); + connectionPool->onSessionStarted.connect(boost::bind(&BOSHSessionStream::handlePoolSessionStarted, this)); + connectionPool->onXMPPDataRead.connect(boost::bind(&BOSHSessionStream::handlePoolXMPPDataRead, this, _1)); + connectionPool->onBOSHDataRead.connect(boost::bind(&BOSHSessionStream::handlePoolBOSHDataRead, this, _1)); + connectionPool->onBOSHDataWritten.connect(boost::bind(&BOSHSessionStream::handlePoolBOSHDataWritten, this, _1)); + connectionPool->onTLSConnectionEstablished.connect(boost::bind(&BOSHSessionStream::handlePoolTLSEstablished, this)); + xmppLayer = new XMPPLayer(payloadParserFactories, payloadSerializers, xmlParserFactory, ClientStreamType, true); + xmppLayer->onStreamStart.connect(boost::bind(&BOSHSessionStream::handleStreamStartReceived, this, _1)); + xmppLayer->onElement.connect(boost::bind(&BOSHSessionStream::handleElementReceived, this, _1)); + xmppLayer->onError.connect(boost::bind(&BOSHSessionStream::handleXMPPError, this)); + xmppLayer->onWriteData.connect(boost::bind(&BOSHSessionStream::handleXMPPLayerDataWritten, this, _1)); + + available = true; } BOSHSessionStream::~BOSHSessionStream() { - close(); - connectionPool->onSessionTerminated.disconnect(boost::bind(&BOSHSessionStream::handlePoolSessionTerminated, this, _1)); - connectionPool->onSessionStarted.disconnect(boost::bind(&BOSHSessionStream::handlePoolSessionStarted, this)); - connectionPool->onXMPPDataRead.disconnect(boost::bind(&BOSHSessionStream::handlePoolXMPPDataRead, this, _1)); - connectionPool->onBOSHDataRead.disconnect(boost::bind(&BOSHSessionStream::handlePoolBOSHDataRead, this, _1)); - connectionPool->onBOSHDataWritten.disconnect(boost::bind(&BOSHSessionStream::handlePoolBOSHDataWritten, this, _1)); - delete connectionPool; - connectionPool = NULL; - xmppLayer->onStreamStart.disconnect(boost::bind(&BOSHSessionStream::handleStreamStartReceived, this, _1)); - xmppLayer->onElement.disconnect(boost::bind(&BOSHSessionStream::handleElementReceived, this, _1)); - xmppLayer->onError.disconnect(boost::bind(&BOSHSessionStream::handleXMPPError, this)); - xmppLayer->onWriteData.disconnect(boost::bind(&BOSHSessionStream::handleXMPPLayerDataWritten, this, _1)); - delete xmppLayer; - xmppLayer = NULL; + BOSHSessionStream::close(); + connectionPool->onSessionTerminated.disconnect(boost::bind(&BOSHSessionStream::handlePoolSessionTerminated, this, _1)); + connectionPool->onSessionStarted.disconnect(boost::bind(&BOSHSessionStream::handlePoolSessionStarted, this)); + connectionPool->onXMPPDataRead.disconnect(boost::bind(&BOSHSessionStream::handlePoolXMPPDataRead, this, _1)); + connectionPool->onBOSHDataRead.disconnect(boost::bind(&BOSHSessionStream::handlePoolBOSHDataRead, this, _1)); + connectionPool->onBOSHDataWritten.disconnect(boost::bind(&BOSHSessionStream::handlePoolBOSHDataWritten, this, _1)); + connectionPool->onTLSConnectionEstablished.disconnect(boost::bind(&BOSHSessionStream::handlePoolTLSEstablished, this)); + delete connectionPool; + connectionPool = nullptr; + xmppLayer->onStreamStart.disconnect(boost::bind(&BOSHSessionStream::handleStreamStartReceived, this, _1)); + xmppLayer->onElement.disconnect(boost::bind(&BOSHSessionStream::handleElementReceived, this, _1)); + xmppLayer->onError.disconnect(boost::bind(&BOSHSessionStream::handleXMPPError, this)); + xmppLayer->onWriteData.disconnect(boost::bind(&BOSHSessionStream::handleXMPPLayerDataWritten, this, _1)); + delete xmppLayer; + xmppLayer = nullptr; +} + +void BOSHSessionStream::open() { + connectionPool->setTLSCertificate(getTLSCertificate()); + connectionPool->open(); } void BOSHSessionStream::handlePoolXMPPDataRead(const SafeByteArray& data) { - xmppLayer->handleDataRead(data); + xmppLayer->handleDataRead(data); } -void BOSHSessionStream::writeElement(boost::shared_ptr<Element> element) { - assert(available); - xmppLayer->writeElement(element); +void BOSHSessionStream::writeElement(std::shared_ptr<ToplevelElement> element) { + assert(available); + xmppLayer->writeElement(element); } void BOSHSessionStream::writeFooter() { - connectionPool->writeFooter(); + connectionPool->writeFooter(); } void BOSHSessionStream::writeData(const std::string& data) { - assert(available); - xmppLayer->writeData(data); + assert(available); + xmppLayer->writeData(data); } void BOSHSessionStream::close() { - connectionPool->close(); + connectionPool->close(); } bool BOSHSessionStream::isOpen() { - return available; + return available; } bool BOSHSessionStream::supportsTLSEncryption() { - return false; + return false; } void BOSHSessionStream::addTLSEncryption() { - assert(available); + assert(available); } bool BOSHSessionStream::isTLSEncrypted() { - return false; + return connectionPool->isTLSEncrypted(); } Certificate::ref BOSHSessionStream::getPeerCertificate() const { - return Certificate::ref(); + return connectionPool->getPeerCertificate(); } std::vector<Certificate::ref> BOSHSessionStream::getPeerCertificateChain() const { - return std::vector<Certificate::ref>(); + return connectionPool->getPeerCertificateChain(); } -boost::shared_ptr<CertificateVerificationError> BOSHSessionStream::getPeerCertificateVerificationError() const { - return boost::shared_ptr<CertificateVerificationError>(); +std::shared_ptr<CertificateVerificationError> BOSHSessionStream::getPeerCertificateVerificationError() const { + return connectionPool->getPeerCertificateVerificationError(); } ByteArray BOSHSessionStream::getTLSFinishMessage() const { - return ByteArray(); + return ByteArray(); } bool BOSHSessionStream::supportsZLibCompression() { - return false; + return false; } void BOSHSessionStream::addZLibCompression() { @@ -145,71 +151,75 @@ void BOSHSessionStream::addZLibCompression() { } void BOSHSessionStream::setWhitespacePingEnabled(bool /*enabled*/) { - return; + return; } void BOSHSessionStream::resetXMPPParser() { - xmppLayer->resetParser(); + xmppLayer->resetParser(); } void BOSHSessionStream::handleStreamStartReceived(const ProtocolHeader& header) { - onStreamStartReceived(header); + onStreamStartReceived(header); } -void BOSHSessionStream::handleElementReceived(boost::shared_ptr<Element> element) { - onElementReceived(element); +void BOSHSessionStream::handleElementReceived(std::shared_ptr<ToplevelElement> element) { + onElementReceived(element); } void BOSHSessionStream::handleXMPPError() { - available = false; - onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::ParseError)); + available = false; + onClosed(std::make_shared<SessionStreamError>(SessionStreamError::ParseError)); } void BOSHSessionStream::handlePoolSessionStarted() { - fakeStreamHeaderReceipt(); + fakeStreamHeaderReceipt(); } void BOSHSessionStream::handlePoolSessionTerminated(BOSHError::ref error) { - eventLoop->postEvent(boost::bind(&BOSHSessionStream::fakeStreamFooterReceipt, this, error), shared_from_this()); + eventLoop->postEvent(boost::bind(&BOSHSessionStream::fakeStreamFooterReceipt, this, error), shared_from_this()); +} + +void BOSHSessionStream::handlePoolTLSEstablished() { + onTLSEncrypted(); } void BOSHSessionStream::writeHeader(const ProtocolHeader& header) { - streamHeader = header; - /*First time we're told to do this, don't (the sending of the initial header is handled on connect) - On subsequent requests we should restart the stream the BOSH way. - */ - if (!firstHeader) { - eventLoop->postEvent(boost::bind(&BOSHSessionStream::fakeStreamHeaderReceipt, this), shared_from_this()); - eventLoop->postEvent(boost::bind(&BOSHConnectionPool::restartStream, connectionPool), shared_from_this()); - } - firstHeader = false; + streamHeader = header; + /*First time we're told to do this, don't (the sending of the initial header is handled on connect) + On subsequent requests we should restart the stream the BOSH way. + */ + if (!firstHeader) { + eventLoop->postEvent(boost::bind(&BOSHSessionStream::fakeStreamHeaderReceipt, this), shared_from_this()); + eventLoop->postEvent(boost::bind(&BOSHConnectionPool::restartStream, connectionPool), shared_from_this()); + } + firstHeader = false; } void BOSHSessionStream::fakeStreamHeaderReceipt() { - std::stringstream header; - header << "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' from='"; - header << streamHeader.getTo() << "' id='dummy' version='1.0'>"; + std::stringstream header; + header << "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' from='"; + header << streamHeader.getTo() << "' id='dummy' version='1.0'>"; - xmppLayer->handleDataRead(createSafeByteArray(header.str())); + xmppLayer->handleDataRead(createSafeByteArray(header.str())); } void BOSHSessionStream::fakeStreamFooterReceipt(BOSHError::ref error) { - std::string footer("</stream:stream>"); - xmppLayer->handleDataRead(createSafeByteArray(footer)); - onClosed(error); + std::string footer("</stream:stream>"); + xmppLayer->handleDataRead(createSafeByteArray(footer)); + onClosed(error); } void BOSHSessionStream::handleXMPPLayerDataWritten(const SafeByteArray& data) { - eventLoop->postEvent(boost::bind(&BOSHConnectionPool::write, connectionPool, data), shared_from_this()); + eventLoop->postEvent(boost::bind(&BOSHConnectionPool::write, connectionPool, data), shared_from_this()); } void BOSHSessionStream::handlePoolBOSHDataRead(const SafeByteArray& data) { - onDataRead(data); + onDataRead(data); } void BOSHSessionStream::handlePoolBOSHDataWritten(const SafeByteArray& data) { - onDataWritten(data); + onDataWritten(data); } } diff --git a/Swiften/Session/BOSHSessionStream.h b/Swiften/Session/BOSHSessionStream.h index 290a4c5..5b730cf 100644 --- a/Swiften/Session/BOSHSessionStream.h +++ b/Swiften/Session/BOSHSessionStream.h @@ -1,96 +1,100 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/Base/SafeString.h> +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> -#include <Swiften/Network/BOSHConnectionPool.h> -#include <Swiften/Session/SessionStream.h> +#include <Swiften/Base/SafeString.h> #include <Swiften/Elements/StreamType.h> #include <Swiften/EventLoop/EventOwner.h> +#include <Swiften/Network/BOSHConnectionPool.h> +#include <Swiften/Session/SessionStream.h> +#include <Swiften/TLS/TLSOptions.h> namespace Swift { - class TimerFactory; - class PayloadParserFactoryCollection; - class PayloadSerializerCollection; - class StreamStack; - class XMPPLayer; - class ConnectionLayer; - class CompressionLayer; - class XMLParserFactory; - class TLSContextFactory; - class EventLoop; + class EventLoop; + class HTTPTrafficFilter; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + class TLSContextFactory; + class TimerFactory; + class XMLParserFactory; + class XMPPLayer; - class BOSHSessionStream : public SessionStream, public EventOwner, public boost::enable_shared_from_this<BOSHSessionStream> { - public: - BOSHSessionStream( - const URL& boshURL, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - ConnectionFactory* connectionFactory, - TLSContextFactory* tlsContextFactory, - TimerFactory* whitespacePingLayerFactory, - XMLParserFactory* xmlParserFactory, - EventLoop* eventLoop, - DomainNameResolver* resolver, - const std::string& to, - const URL& boshHTTPConnectProxyURL, - const SafeString& boshHTTPConnectProxyAuthID, - const SafeString& boshHTTPConnectProxyAuthPassword - ); - ~BOSHSessionStream(); + class SWIFTEN_API BOSHSessionStream : public SessionStream, public EventOwner, public std::enable_shared_from_this<BOSHSessionStream> { + public: + BOSHSessionStream( + const URL& boshURL, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + ConnectionFactory* connectionFactory, + TLSContextFactory* tlsContextFactory, + TimerFactory* whitespacePingLayerFactory, + XMLParserFactory* xmlParserFactory, + EventLoop* eventLoop, + DomainNameResolver* resolver, + const std::string& to, + const URL& boshHTTPConnectProxyURL, + const SafeString& boshHTTPConnectProxyAuthID, + const SafeString& boshHTTPConnectProxyAuthPassword, + const TLSOptions& tlsOptions, + std::shared_ptr<HTTPTrafficFilter> trafficFilter + ); + virtual ~BOSHSessionStream(); - virtual void close(); - virtual bool isOpen(); + void open(); + virtual void close(); + virtual bool isOpen(); - virtual void writeHeader(const ProtocolHeader& header); - virtual void writeElement(boost::shared_ptr<Element>); - virtual void writeFooter(); - virtual void writeData(const std::string& data); + virtual void writeHeader(const ProtocolHeader& header); + virtual void writeElement(std::shared_ptr<ToplevelElement>); + virtual void writeFooter(); + virtual void writeData(const std::string& data); - virtual bool supportsZLibCompression(); - virtual void addZLibCompression(); + virtual bool supportsZLibCompression(); + virtual void addZLibCompression(); - virtual bool supportsTLSEncryption(); - virtual void addTLSEncryption(); - virtual bool isTLSEncrypted(); - virtual Certificate::ref getPeerCertificate() const; - virtual std::vector<Certificate::ref> getPeerCertificateChain() const; - virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; - virtual ByteArray getTLSFinishMessage() const; + virtual bool supportsTLSEncryption(); + virtual void addTLSEncryption(); + virtual bool isTLSEncrypted(); + virtual Certificate::ref getPeerCertificate() const; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const; + virtual std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; + virtual ByteArray getTLSFinishMessage() const; - virtual void setWhitespacePingEnabled(bool); + virtual void setWhitespacePingEnabled(bool); - virtual void resetXMPPParser(); + virtual void resetXMPPParser(); - private: - void handleXMPPError(); - void handleStreamStartReceived(const ProtocolHeader&); - void handleElementReceived(boost::shared_ptr<Element>); - void handlePoolXMPPDataRead(const SafeByteArray& data); - void handleXMPPLayerDataWritten(const SafeByteArray& data); - void handlePoolSessionStarted(); - void handlePoolBOSHDataRead(const SafeByteArray& data); - void handlePoolBOSHDataWritten(const SafeByteArray& data); - void handlePoolSessionTerminated(BOSHError::ref condition); + private: + void handleXMPPError(); + void handleStreamStartReceived(const ProtocolHeader&); + void handleElementReceived(std::shared_ptr<ToplevelElement>); + void handlePoolXMPPDataRead(const SafeByteArray& data); + void handleXMPPLayerDataWritten(const SafeByteArray& data); + void handlePoolSessionStarted(); + void handlePoolBOSHDataRead(const SafeByteArray& data); + void handlePoolBOSHDataWritten(const SafeByteArray& data); + void handlePoolSessionTerminated(BOSHError::ref condition); + void handlePoolTLSEstablished(); - private: - void fakeStreamHeaderReceipt(); - void fakeStreamFooterReceipt(BOSHError::ref error); + private: + void fakeStreamHeaderReceipt(); + void fakeStreamFooterReceipt(BOSHError::ref error); - private: - BOSHConnectionPool* connectionPool; - bool available; - XMPPLayer* xmppLayer; - ProtocolHeader streamHeader; - EventLoop* eventLoop; - bool firstHeader; - }; + private: + BOSHConnectionPool* connectionPool; + bool available; + XMPPLayer* xmppLayer; + ProtocolHeader streamHeader; + EventLoop* eventLoop; + bool firstHeader; + }; } diff --git a/Swiften/Session/BasicSessionStream.cpp b/Swiften/Session/BasicSessionStream.cpp index 2bd8d66..c44961d 100644 --- a/Swiften/Session/BasicSessionStream.cpp +++ b/Swiften/Session/BasicSessionStream.cpp @@ -1,210 +1,216 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Session/BasicSessionStream.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/StreamStack/XMPPLayer.h> -#include <Swiften/StreamStack/StreamStack.h> -#include <Swiften/StreamStack/ConnectionLayer.h> -#include <Swiften/StreamStack/WhitespacePingLayer.h> #include <Swiften/StreamStack/CompressionLayer.h> +#include <Swiften/StreamStack/ConnectionLayer.h> +#include <Swiften/StreamStack/StreamStack.h> #include <Swiften/StreamStack/TLSLayer.h> -#include <Swiften/TLS/TLSContextFactory.h> +#include <Swiften/StreamStack/WhitespacePingLayer.h> +#include <Swiften/StreamStack/XMPPLayer.h> #include <Swiften/TLS/TLSContext.h> +#include <Swiften/TLS/TLSContextFactory.h> namespace Swift { BasicSessionStream::BasicSessionStream( - StreamType streamType, - boost::shared_ptr<Connection> connection, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - TLSContextFactory* tlsContextFactory, - TimerFactory* timerFactory, - XMLParserFactory* xmlParserFactory) : - available(false), - connection(connection), - tlsContextFactory(tlsContextFactory), - timerFactory(timerFactory), - compressionLayer(NULL), - tlsLayer(NULL), - whitespacePingLayer(NULL) { - xmppLayer = new XMPPLayer(payloadParserFactories, payloadSerializers, xmlParserFactory, streamType); - xmppLayer->onStreamStart.connect(boost::bind(&BasicSessionStream::handleStreamStartReceived, this, _1)); - xmppLayer->onElement.connect(boost::bind(&BasicSessionStream::handleElementReceived, this, _1)); - xmppLayer->onError.connect(boost::bind(&BasicSessionStream::handleXMPPError, this)); - xmppLayer->onDataRead.connect(boost::bind(&BasicSessionStream::handleDataRead, this, _1)); - xmppLayer->onWriteData.connect(boost::bind(&BasicSessionStream::handleDataWritten, this, _1)); - - connection->onDisconnected.connect(boost::bind(&BasicSessionStream::handleConnectionFinished, this, _1)); - connectionLayer = new ConnectionLayer(connection); - - streamStack = new StreamStack(xmppLayer, connectionLayer); - - available = true; + StreamType streamType, + std::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + TLSContextFactory* tlsContextFactory, + TimerFactory* timerFactory, + XMLParserFactory* xmlParserFactory, + const TLSOptions& tlsOptions) : + available(false), + connection(connection), + tlsContextFactory(tlsContextFactory), + timerFactory(timerFactory), + tlsOptions_(tlsOptions) { + auto xmppLayer = std::make_unique<XMPPLayer>(payloadParserFactories, payloadSerializers, xmlParserFactory, streamType); + xmppLayer->onStreamStart.connect(boost::bind(&BasicSessionStream::handleStreamStartReceived, this, _1)); + xmppLayer->onStreamEnd.connect(boost::bind(&BasicSessionStream::handleStreamEndReceived, this)); + xmppLayer->onElement.connect(boost::bind(&BasicSessionStream::handleElementReceived, this, _1)); + xmppLayer->onError.connect(boost::bind(&BasicSessionStream::handleXMPPError, this)); + xmppLayer->onDataRead.connect(boost::bind(&BasicSessionStream::handleDataRead, this, _1)); + xmppLayer->onWriteData.connect(boost::bind(&BasicSessionStream::handleDataWritten, this, _1)); + + connection->onDisconnected.connect(boost::bind(&BasicSessionStream::handleConnectionFinished, this, _1)); + + streamStack = std::make_unique<StreamStack>(std::move(xmppLayer), std::unique_ptr<ConnectionLayer>(new ConnectionLayer(connection))); + available = true; } BasicSessionStream::~BasicSessionStream() { - delete compressionLayer; - if (tlsLayer) { - tlsLayer->onError.disconnect(boost::bind(&BasicSessionStream::handleTLSError, this)); - tlsLayer->onConnected.disconnect(boost::bind(&BasicSessionStream::handleTLSConnected, this)); - delete tlsLayer; - } - delete whitespacePingLayer; - delete streamStack; + if (auto tlsLayer = streamStack->getLayer<TLSLayer>()) { + tlsLayer->onError.disconnect(boost::bind(&BasicSessionStream::handleTLSError, this, _1)); + tlsLayer->onConnected.disconnect(boost::bind(&BasicSessionStream::handleTLSConnected, this)); + } - connection->onDisconnected.disconnect(boost::bind(&BasicSessionStream::handleConnectionFinished, this, _1)); - delete connectionLayer; + connection->onDisconnected.disconnect(boost::bind(&BasicSessionStream::handleConnectionFinished, this, _1)); - xmppLayer->onStreamStart.disconnect(boost::bind(&BasicSessionStream::handleStreamStartReceived, this, _1)); - xmppLayer->onElement.disconnect(boost::bind(&BasicSessionStream::handleElementReceived, this, _1)); - xmppLayer->onError.disconnect(boost::bind(&BasicSessionStream::handleXMPPError, this)); - xmppLayer->onDataRead.disconnect(boost::bind(&BasicSessionStream::handleDataRead, this, _1)); - xmppLayer->onWriteData.disconnect(boost::bind(&BasicSessionStream::handleDataWritten, this, _1)); - delete xmppLayer; + auto xmppLayer = streamStack->getLayer<XMPPLayer>(); + xmppLayer->onStreamStart.disconnect(boost::bind(&BasicSessionStream::handleStreamStartReceived, this, _1)); + xmppLayer->onStreamEnd.disconnect(boost::bind(&BasicSessionStream::handleStreamEndReceived, this)); + xmppLayer->onElement.disconnect(boost::bind(&BasicSessionStream::handleElementReceived, this, _1)); + xmppLayer->onError.disconnect(boost::bind(&BasicSessionStream::handleXMPPError, this)); + xmppLayer->onDataRead.disconnect(boost::bind(&BasicSessionStream::handleDataRead, this, _1)); + xmppLayer->onWriteData.disconnect(boost::bind(&BasicSessionStream::handleDataWritten, this, _1)); } void BasicSessionStream::writeHeader(const ProtocolHeader& header) { - assert(available); - xmppLayer->writeHeader(header); + assert(available); + auto* xmppLayer = streamStack->getLayer<XMPPLayer>(); + xmppLayer->writeHeader(header); } -void BasicSessionStream::writeElement(boost::shared_ptr<Element> element) { - assert(available); - xmppLayer->writeElement(element); +void BasicSessionStream::writeElement(std::shared_ptr<ToplevelElement> element) { + assert(available); + auto* xmppLayer = streamStack->getLayer<XMPPLayer>(); + xmppLayer->writeElement(element); } void BasicSessionStream::writeFooter() { - assert(available); - xmppLayer->writeFooter(); + assert(available); + auto* xmppLayer = streamStack->getLayer<XMPPLayer>(); + xmppLayer->writeFooter(); } void BasicSessionStream::writeData(const std::string& data) { - assert(available); - xmppLayer->writeData(data); + assert(available); + auto* xmppLayer = streamStack->getLayer<XMPPLayer>(); + xmppLayer->writeData(data); } void BasicSessionStream::close() { - connection->disconnect(); + connection->disconnect(); } bool BasicSessionStream::isOpen() { - return available; + return available; } bool BasicSessionStream::supportsTLSEncryption() { - return tlsContextFactory && tlsContextFactory->canCreate(); + return tlsContextFactory && tlsContextFactory->canCreate(); } void BasicSessionStream::addTLSEncryption() { - assert(available); - tlsLayer = new TLSLayer(tlsContextFactory); - if (hasTLSCertificate() && !tlsLayer->setClientCertificate(getTLSCertificate())) { - onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::InvalidTLSCertificateError)); - } - else { - streamStack->addLayer(tlsLayer); - tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, this, _1)); - tlsLayer->onConnected.connect(boost::bind(&BasicSessionStream::handleTLSConnected, this)); - tlsLayer->connect(); - } + assert(available); + auto tlsContext = tlsContextFactory->createTLSContext(tlsOptions_); + auto tlsLayer = std::make_unique<TLSLayer>(std::move(tlsContext)); + if (hasTLSCertificate() && !tlsLayer->setClientCertificate(getTLSCertificate())) { + onClosed(std::make_shared<SessionStreamError>(SessionStreamError::InvalidTLSCertificateError)); + } + else { + streamStack->addLayer(std::move(tlsLayer)); + auto tlsLayer = streamStack->getLayer<TLSLayer>(); + tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, this, _1)); + tlsLayer->onConnected.connect(boost::bind(&BasicSessionStream::handleTLSConnected, this)); + tlsLayer->connect(); + } } bool BasicSessionStream::isTLSEncrypted() { - return tlsLayer; + return streamStack->getLayer<TLSLayer>(); } Certificate::ref BasicSessionStream::getPeerCertificate() const { - return tlsLayer->getPeerCertificate(); + return streamStack->getLayer<TLSLayer>()->getPeerCertificate(); } std::vector<Certificate::ref> BasicSessionStream::getPeerCertificateChain() const { - return tlsLayer->getPeerCertificateChain(); + return streamStack->getLayer<TLSLayer>()->getPeerCertificateChain(); } -boost::shared_ptr<CertificateVerificationError> BasicSessionStream::getPeerCertificateVerificationError() const { - return tlsLayer->getPeerCertificateVerificationError(); +std::shared_ptr<CertificateVerificationError> BasicSessionStream::getPeerCertificateVerificationError() const { + return streamStack->getLayer<TLSLayer>()->getPeerCertificateVerificationError(); } ByteArray BasicSessionStream::getTLSFinishMessage() const { - return tlsLayer->getContext()->getFinishMessage(); + return streamStack->getLayer<TLSLayer>()->getContext()->getFinishMessage(); } bool BasicSessionStream::supportsZLibCompression() { - return true; + return true; } void BasicSessionStream::addZLibCompression() { - compressionLayer = new CompressionLayer(); - streamStack->addLayer(compressionLayer); + streamStack->addLayer(std::make_unique<CompressionLayer>()); } void BasicSessionStream::setWhitespacePingEnabled(bool enabled) { - if (enabled) { - if (!whitespacePingLayer) { - whitespacePingLayer = new WhitespacePingLayer(timerFactory); - streamStack->addLayer(whitespacePingLayer); - } - whitespacePingLayer->setActive(); - } - else if (whitespacePingLayer) { - whitespacePingLayer->setInactive(); - } + auto whitespacePingLayer = streamStack->getLayer<WhitespacePingLayer>(); + if (enabled) { + if (!whitespacePingLayer) { + streamStack->addLayer(std::make_unique<WhitespacePingLayer>(timerFactory)); + whitespacePingLayer = streamStack->getLayer<WhitespacePingLayer>(); + } + whitespacePingLayer->setActive(); + } + else if (whitespacePingLayer) { + whitespacePingLayer->setInactive(); + } } void BasicSessionStream::resetXMPPParser() { - xmppLayer->resetParser(); + auto* xmppLayer = streamStack->getLayer<XMPPLayer>(); + xmppLayer->resetParser(); } void BasicSessionStream::handleStreamStartReceived(const ProtocolHeader& header) { - onStreamStartReceived(header); + onStreamStartReceived(header); +} + +void BasicSessionStream::handleStreamEndReceived() { + onStreamEndReceived(); } -void BasicSessionStream::handleElementReceived(boost::shared_ptr<Element> element) { - onElementReceived(element); +void BasicSessionStream::handleElementReceived(std::shared_ptr<ToplevelElement> element) { + onElementReceived(element); } void BasicSessionStream::handleXMPPError() { - available = false; - onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::ParseError)); + available = false; + onClosed(std::make_shared<SessionStreamError>(SessionStreamError::ParseError)); } void BasicSessionStream::handleTLSConnected() { - onTLSEncrypted(); + onTLSEncrypted(); } -void BasicSessionStream::handleTLSError(boost::shared_ptr<TLSError> error) { - available = false; - onClosed(error); +void BasicSessionStream::handleTLSError(std::shared_ptr<TLSError> error) { + available = false; + onClosed(error); } void BasicSessionStream::handleConnectionFinished(const boost::optional<Connection::Error>& error) { - available = false; - if (error == Connection::ReadError) { - onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::ConnectionReadError)); - } - else if (error) { - onClosed(boost::make_shared<SessionStreamError>(SessionStreamError::ConnectionWriteError)); - } - else { - onClosed(boost::shared_ptr<SessionStreamError>()); - } + available = false; + if (error == Connection::ReadError) { + onClosed(std::make_shared<SessionStreamError>(SessionStreamError::ConnectionReadError)); + } + else if (error) { + onClosed(std::make_shared<SessionStreamError>(SessionStreamError::ConnectionWriteError)); + } + else { + onClosed(std::shared_ptr<SessionStreamError>()); + } } void BasicSessionStream::handleDataRead(const SafeByteArray& data) { - onDataRead(data); + onDataRead(data); } void BasicSessionStream::handleDataWritten(const SafeByteArray& data) { - onDataWritten(data); + onDataWritten(data); } } diff --git a/Swiften/Session/BasicSessionStream.h b/Swiften/Session/BasicSessionStream.h index 389ecbe..30a7e3b 100644 --- a/Swiften/Session/BasicSessionStream.h +++ b/Swiften/Session/BasicSessionStream.h @@ -1,90 +1,90 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Elements/StreamType.h> #include <Swiften/Network/Connection.h> #include <Swiften/Session/SessionStream.h> -#include <Swiften/Elements/StreamType.h> #include <Swiften/TLS/TLSError.h> +#include <Swiften/TLS/TLSOptions.h> namespace Swift { - class TLSContextFactory; - class TLSLayer; - class TimerFactory; - class WhitespacePingLayer; - class PayloadParserFactoryCollection; - class PayloadSerializerCollection; - class StreamStack; - class XMPPLayer; - class ConnectionLayer; - class CompressionLayer; - class XMLParserFactory; + class TLSContextFactory; + class TLSLayer; + class TimerFactory; + class WhitespacePingLayer; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + class StreamStack; + class XMPPLayer; + class ConnectionLayer; + class CompressionLayer; + class XMLParserFactory; - class BasicSessionStream : public SessionStream { - public: - BasicSessionStream( - StreamType streamType, - boost::shared_ptr<Connection> connection, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - TLSContextFactory* tlsContextFactory, - TimerFactory* whitespacePingLayerFactory, - XMLParserFactory* xmlParserFactory - ); - ~BasicSessionStream(); + class SWIFTEN_API BasicSessionStream : public SessionStream { + public: + BasicSessionStream( + StreamType streamType, + std::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + TLSContextFactory* tlsContextFactory, + TimerFactory* whitespacePingLayerFactory, + XMLParserFactory* xmlParserFactory, + const TLSOptions& tlsOptions + ); + virtual ~BasicSessionStream(); - virtual void close(); - virtual bool isOpen(); + virtual void close(); + virtual bool isOpen(); - virtual void writeHeader(const ProtocolHeader& header); - virtual void writeElement(boost::shared_ptr<Element>); - virtual void writeFooter(); - virtual void writeData(const std::string& data); + virtual void writeHeader(const ProtocolHeader& header); + virtual void writeElement(std::shared_ptr<ToplevelElement>); + virtual void writeFooter(); + virtual void writeData(const std::string& data); - virtual bool supportsZLibCompression(); - virtual void addZLibCompression(); + virtual bool supportsZLibCompression(); + virtual void addZLibCompression(); - virtual bool supportsTLSEncryption(); - virtual void addTLSEncryption(); - virtual bool isTLSEncrypted(); - virtual Certificate::ref getPeerCertificate() const; - virtual std::vector<Certificate::ref> getPeerCertificateChain() const; + virtual bool supportsTLSEncryption(); + virtual void addTLSEncryption(); + virtual bool isTLSEncrypted(); + virtual Certificate::ref getPeerCertificate() const; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const; - virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; - virtual ByteArray getTLSFinishMessage() const; + virtual std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; + virtual ByteArray getTLSFinishMessage() const; - virtual void setWhitespacePingEnabled(bool); + virtual void setWhitespacePingEnabled(bool); - virtual void resetXMPPParser(); + virtual void resetXMPPParser(); - private: - void handleConnectionFinished(const boost::optional<Connection::Error>& error); - void handleXMPPError(); - void handleTLSConnected(); - void handleTLSError(boost::shared_ptr<TLSError>); - void handleStreamStartReceived(const ProtocolHeader&); - void handleElementReceived(boost::shared_ptr<Element>); - void handleDataRead(const SafeByteArray& data); - void handleDataWritten(const SafeByteArray& data); + private: + void handleConnectionFinished(const boost::optional<Connection::Error>& error); + void handleXMPPError(); + void handleTLSConnected(); + void handleTLSError(std::shared_ptr<TLSError>); + void handleStreamStartReceived(const ProtocolHeader&); + void handleStreamEndReceived(); + void handleElementReceived(std::shared_ptr<ToplevelElement>); + void handleDataRead(const SafeByteArray& data); + void handleDataWritten(const SafeByteArray& data); - private: - bool available; - boost::shared_ptr<Connection> connection; - TLSContextFactory* tlsContextFactory; - TimerFactory* timerFactory; - XMPPLayer* xmppLayer; - ConnectionLayer* connectionLayer; - CompressionLayer* compressionLayer; - TLSLayer* tlsLayer; - WhitespacePingLayer* whitespacePingLayer; - StreamStack* streamStack; - }; + private: + bool available; + std::shared_ptr<Connection> connection; + TLSContextFactory* tlsContextFactory; + TimerFactory* timerFactory; + std::unique_ptr<StreamStack> streamStack; + TLSOptions tlsOptions_; + }; } diff --git a/Swiften/Session/Session.cpp b/Swiften/Session/Session.cpp index acc73f1..b1525b8 100644 --- a/Swiften/Session/Session.cpp +++ b/Swiften/Session/Session.cpp @@ -1,105 +1,107 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Session/Session.h> #include <boost/bind.hpp> -#include <Swiften/StreamStack/XMPPLayer.h> #include <Swiften/StreamStack/StreamStack.h> +#include <Swiften/StreamStack/XMPPLayer.h> namespace Swift { Session::Session( - boost::shared_ptr<Connection> connection, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - XMLParserFactory* xmlParserFactory) : - connection(connection), - payloadParserFactories(payloadParserFactories), - payloadSerializers(payloadSerializers), - xmlParserFactory(xmlParserFactory), - xmppLayer(NULL), - connectionLayer(NULL), - streamStack(0), - finishing(false) { + std::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + XMLParserFactory* xmlParserFactory) : + connection(connection), + payloadParserFactories(payloadParserFactories), + payloadSerializers(payloadSerializers), + xmlParserFactory(xmlParserFactory), + finishing(false) { } Session::~Session() { - delete streamStack; - delete connectionLayer; - delete xmppLayer; } void Session::startSession() { - initializeStreamStack(); - handleSessionStarted(); + initializeStreamStack(); + handleSessionStarted(); } void Session::finishSession() { - if (finishing) { - return; - } - finishing = true; - if (xmppLayer) { - xmppLayer->writeFooter(); - } - connection->disconnect(); + if (finishing) { + return; + } + finishing = true; + if (auto xmppLayer = getXMPPLayer()) { + xmppLayer->writeFooter(); + } + connection->disconnect(); } void Session::finishSession(const SessionError& /*error*/) { - if (finishing) { - return; - } - finishing = true; - if (xmppLayer) { - xmppLayer->writeFooter(); - } - connection->disconnect(); + if (finishing) { + return; + } + finishing = true; + if (auto xmppLayer = getXMPPLayer()) { + xmppLayer->writeFooter(); + } + connection->disconnect(); } void Session::initializeStreamStack() { - xmppLayer = new XMPPLayer(payloadParserFactories, payloadSerializers, xmlParserFactory, ClientStreamType); - xmppLayer->onStreamStart.connect( - boost::bind(&Session::handleStreamStart, this, _1)); - xmppLayer->onElement.connect(boost::bind(&Session::handleElement, this, _1)); - xmppLayer->onError.connect( - boost::bind(&Session::finishSession, this, XMLError)); - xmppLayer->onDataRead.connect(boost::bind(boost::ref(onDataRead), _1)); - xmppLayer->onWriteData.connect(boost::bind(boost::ref(onDataWritten), _1)); - connection->onDisconnected.connect( - boost::bind(&Session::handleDisconnected, this, _1)); - connectionLayer = new ConnectionLayer(connection); - streamStack = new StreamStack(xmppLayer, connectionLayer); + auto xmppLayer = std::unique_ptr<XMPPLayer>(new XMPPLayer(payloadParserFactories, payloadSerializers, xmlParserFactory, ClientStreamType)); + xmppLayer->onStreamStart.connect( + boost::bind(&Session::handleStreamStart, this, _1)); + xmppLayer->onElement.connect(boost::bind(&Session::handleElement, this, _1)); + xmppLayer->onError.connect( + boost::bind(&Session::finishSession, this, XMLError)); + xmppLayer->onDataRead.connect(boost::bind(boost::ref(onDataRead), _1)); + xmppLayer->onWriteData.connect(boost::bind(boost::ref(onDataWritten), _1)); + connection->onDisconnected.connect( + boost::bind(&Session::handleDisconnected, this, _1)); + streamStack = std::unique_ptr<StreamStack>(new StreamStack(std::move(xmppLayer), std::unique_ptr<ConnectionLayer>(new ConnectionLayer(connection)))); +} + +XMPPLayer* Session::getXMPPLayer() const { + return dynamic_cast<XMPPLayer*>(streamStack->getTopLayer()); } -void Session::sendElement(boost::shared_ptr<Element> stanza) { - xmppLayer->writeElement(stanza); +StreamStack* Session::getStreamStack() const { + return streamStack.get(); +} + + +void Session::sendElement(std::shared_ptr<ToplevelElement> stanza) { + getXMPPLayer()->writeElement(stanza); } void Session::handleDisconnected(const boost::optional<Connection::Error>& connectionError) { - connection->onDisconnected.disconnect( - boost::bind(&Session::handleDisconnected, this, _1)); - if (connectionError) { - switch (*connectionError) { - case Connection::ReadError: - handleSessionFinished(ConnectionReadError); - onSessionFinished(ConnectionReadError); - break; - case Connection::WriteError: - handleSessionFinished(ConnectionWriteError); - onSessionFinished(ConnectionWriteError); - break; - } - } - else { - boost::optional<SessionError> error; - handleSessionFinished(error); - onSessionFinished(error); - } + connection->onDisconnected.disconnect( + boost::bind(&Session::handleDisconnected, this, _1)); + if (connectionError) { + switch (*connectionError) { + case Connection::ReadError: + handleSessionFinished(ConnectionReadError); + onSessionFinished(ConnectionReadError); + break; + case Connection::WriteError: + handleSessionFinished(ConnectionWriteError); + onSessionFinished(ConnectionWriteError); + break; + } + } + else { + boost::optional<SessionError> error; + handleSessionFinished(error); + onSessionFinished(error); + } } } diff --git a/Swiften/Session/Session.h b/Swiften/Session/Session.h index 4becebf..e6a0d53 100644 --- a/Swiften/Session/Session.h +++ b/Swiften/Session/Session.h @@ -1,115 +1,107 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> +#include <memory> + #include <boost/optional.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> +#include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Elements/ToplevelElement.h> #include <Swiften/JID/JID.h> -#include <Swiften/Elements/Element.h> #include <Swiften/Network/Connection.h> #include <Swiften/StreamStack/ConnectionLayer.h> -#include <Swiften/Base/SafeByteArray.h> namespace Swift { - class ProtocolHeader; - class StreamStack; - class JID; - class Element; - class PayloadParserFactoryCollection; - class PayloadSerializerCollection; - class XMPPLayer; - class XMLParserFactory; - - class SWIFTEN_API Session : public boost::enable_shared_from_this<Session> { - public: - enum SessionError { - ConnectionReadError, - ConnectionWriteError, - XMLError, - AuthenticationFailedError, - NoSupportedAuthMechanismsError, - UnexpectedElementError, - ResourceBindError, - SessionStartError, - TLSError, - ClientCertificateLoadError, - ClientCertificateError - }; - - Session( - boost::shared_ptr<Connection> connection, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - XMLParserFactory* xmlParserFactory); - virtual ~Session(); - - void startSession(); - void finishSession(); - - void sendElement(boost::shared_ptr<Element>); - - const JID& getLocalJID() const { - return localJID; - } - - const JID& getRemoteJID() const { - return remoteJID; - } - - boost::signal<void (boost::shared_ptr<Element>)> onElementReceived; - boost::signal<void (const boost::optional<SessionError>&)> onSessionFinished; - boost::signal<void (const SafeByteArray&)> onDataWritten; - boost::signal<void (const SafeByteArray&)> onDataRead; - - protected: - void setRemoteJID(const JID& j) { - remoteJID = j; - } - - void setLocalJID(const JID& j) { - localJID = j; - } - - void finishSession(const SessionError&); - - virtual void handleSessionStarted() {} - virtual void handleSessionFinished(const boost::optional<SessionError>&) {} - virtual void handleElement(boost::shared_ptr<Element>) = 0; - virtual void handleStreamStart(const ProtocolHeader&) = 0; - - void initializeStreamStack(); - - XMPPLayer* getXMPPLayer() const { - return xmppLayer; - } - - StreamStack* getStreamStack() const { - return streamStack; - } - - void setFinished(); - - private: - void handleDisconnected(const boost::optional<Connection::Error>& error); - - private: - JID localJID; - JID remoteJID; - boost::shared_ptr<Connection> connection; - PayloadParserFactoryCollection* payloadParserFactories; - PayloadSerializerCollection* payloadSerializers; - XMLParserFactory* xmlParserFactory; - XMPPLayer* xmppLayer; - ConnectionLayer* connectionLayer; - StreamStack* streamStack; - bool finishing; - }; + class ProtocolHeader; + class StreamStack; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + class XMPPLayer; + class XMLParserFactory; + + class SWIFTEN_API Session : public std::enable_shared_from_this<Session> { + public: + enum SessionError { + ConnectionReadError, + ConnectionWriteError, + XMLError, + AuthenticationFailedError, + NoSupportedAuthMechanismsError, + UnexpectedElementError, + ResourceBindError, + SessionStartError, + TLSError, + ClientCertificateLoadError, + ClientCertificateError + }; + + Session( + std::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + XMLParserFactory* xmlParserFactory); + virtual ~Session(); + + void startSession(); + void finishSession(); + + void sendElement(std::shared_ptr<ToplevelElement>); + + const JID& getLocalJID() const { + return localJID; + } + + const JID& getRemoteJID() const { + return remoteJID; + } + + boost::signals2::signal<void (std::shared_ptr<ToplevelElement>)> onElementReceived; + boost::signals2::signal<void (const boost::optional<SessionError>&)> onSessionFinished; + boost::signals2::signal<void (const SafeByteArray&)> onDataWritten; + boost::signals2::signal<void (const SafeByteArray&)> onDataRead; + + protected: + void setRemoteJID(const JID& j) { + remoteJID = j; + } + + void setLocalJID(const JID& j) { + localJID = j; + } + + void finishSession(const SessionError&); + + virtual void handleSessionStarted() {} + virtual void handleSessionFinished(const boost::optional<SessionError>&) {} + virtual void handleElement(std::shared_ptr<ToplevelElement>) = 0; + virtual void handleStreamStart(const ProtocolHeader&) = 0; + + void initializeStreamStack(); + + XMPPLayer* getXMPPLayer() const; + StreamStack* getStreamStack() const; + + void setFinished(); + + private: + void handleDisconnected(const boost::optional<Connection::Error>& error); + + private: + JID localJID; + JID remoteJID; + std::shared_ptr<Connection> connection; + PayloadParserFactoryCollection* payloadParserFactories; + PayloadSerializerCollection* payloadSerializers; + XMLParserFactory* xmlParserFactory; + + std::unique_ptr<StreamStack> streamStack; + bool finishing; + }; } diff --git a/Swiften/Session/SessionStream.cpp b/Swiften/Session/SessionStream.cpp index 7378680..54a7e82 100644 --- a/Swiften/Session/SessionStream.cpp +++ b/Swiften/Session/SessionStream.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Session/SessionStream.h> diff --git a/Swiften/Session/SessionStream.h b/Swiften/Session/SessionStream.h index 501f588..c5ec42a 100644 --- a/Swiften/Session/SessionStream.h +++ b/Swiften/Session/SessionStream.h @@ -1,91 +1,93 @@ /* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Elements/ProtocolHeader.h> -#include <Swiften/Elements/Element.h> #include <Swiften/Base/Error.h> #include <Swiften/Base/SafeByteArray.h> -#include <Swiften/TLS/CertificateWithKey.h> +#include <Swiften/Elements/ProtocolHeader.h> +#include <Swiften/Elements/ToplevelElement.h> #include <Swiften/TLS/Certificate.h> #include <Swiften/TLS/CertificateVerificationError.h> +#include <Swiften/TLS/CertificateWithKey.h> namespace Swift { - class SWIFTEN_API SessionStream { - public: - class SessionStreamError : public Swift::Error { - public: - enum Type { - ParseError, - TLSError, - InvalidTLSCertificateError, - ConnectionReadError, - ConnectionWriteError - }; - - SessionStreamError(Type type) : type(type) {} - - Type type; - }; - - SessionStream(): certificate() {} - - virtual ~SessionStream(); - - virtual void close() = 0; - virtual bool isOpen() = 0; - - virtual void writeHeader(const ProtocolHeader& header) = 0; - virtual void writeFooter() = 0; - virtual void writeElement(boost::shared_ptr<Element>) = 0; - virtual void writeData(const std::string& data) = 0; - - virtual bool supportsZLibCompression() = 0; - virtual void addZLibCompression() = 0; - - virtual bool supportsTLSEncryption() = 0; - virtual void addTLSEncryption() = 0; - virtual bool isTLSEncrypted() = 0; - virtual void setWhitespacePingEnabled(bool enabled) = 0; - - virtual void resetXMPPParser() = 0; - - void setTLSCertificate(CertificateWithKey::ref cert) { - certificate = cert; - } - - virtual bool hasTLSCertificate() { - return certificate && !certificate->isNull(); - } - - virtual Certificate::ref getPeerCertificate() const = 0; - virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; - virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const = 0; - - virtual ByteArray getTLSFinishMessage() const = 0; - - boost::signal<void (const ProtocolHeader&)> onStreamStartReceived; - boost::signal<void (boost::shared_ptr<Element>)> onElementReceived; - boost::signal<void (boost::shared_ptr<Error>)> onClosed; - boost::signal<void ()> onTLSEncrypted; - boost::signal<void (const SafeByteArray&)> onDataRead; - boost::signal<void (const SafeByteArray&)> onDataWritten; - - protected: - CertificateWithKey::ref getTLSCertificate() const { - return certificate; - } - - private: - CertificateWithKey::ref certificate; - }; + class SWIFTEN_API SessionStream { + public: + class SWIFTEN_API SessionStreamError : public Swift::Error { + public: + enum Type { + ParseError, + TLSError, + InvalidTLSCertificateError, + ConnectionReadError, + ConnectionWriteError + }; + + SessionStreamError(Type type) : type(type) {} + + Type type; + }; + + SessionStream(): certificate() {} + + virtual ~SessionStream(); + + virtual void close() = 0; + virtual bool isOpen() = 0; + + virtual void writeHeader(const ProtocolHeader& header) = 0; + virtual void writeFooter() = 0; + virtual void writeElement(std::shared_ptr<ToplevelElement>) = 0; + virtual void writeData(const std::string& data) = 0; + + virtual bool supportsZLibCompression() = 0; + virtual void addZLibCompression() = 0; + + virtual bool supportsTLSEncryption() = 0; + virtual void addTLSEncryption() = 0; + virtual bool isTLSEncrypted() = 0; + virtual void setWhitespacePingEnabled(bool enabled) = 0; + + virtual void resetXMPPParser() = 0; + + void setTLSCertificate(CertificateWithKey::ref cert) { + certificate = cert; + } + + virtual bool hasTLSCertificate() { + return certificate && !certificate->isNull(); + } + + virtual Certificate::ref getPeerCertificate() const = 0; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; + virtual std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const = 0; + + virtual ByteArray getTLSFinishMessage() const = 0; + + boost::signals2::signal<void (const ProtocolHeader&)> onStreamStartReceived; + boost::signals2::signal<void ()> onStreamEndReceived; + boost::signals2::signal<void (std::shared_ptr<ToplevelElement>)> onElementReceived; + boost::signals2::signal<void (std::shared_ptr<Error>)> onClosed; + boost::signals2::signal<void ()> onTLSEncrypted; + boost::signals2::signal<void (const SafeByteArray&)> onDataRead; + boost::signals2::signal<void (const SafeByteArray&)> onDataWritten; + + protected: + CertificateWithKey::ref getTLSCertificate() const { + return certificate; + } + + private: + CertificateWithKey::ref certificate; + }; } diff --git a/Swiften/Session/SessionTracer.cpp b/Swiften/Session/SessionTracer.cpp index e0a39bf..49b369d 100644 --- a/Swiften/Session/SessionTracer.cpp +++ b/Swiften/Session/SessionTracer.cpp @@ -1,28 +1,29 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Session/SessionTracer.h> #include <iostream> + #include <boost/bind.hpp> namespace Swift { -SessionTracer::SessionTracer(boost::shared_ptr<Session> session) : session(session) { - session->onDataRead.connect(boost::bind(&SessionTracer::printData, this, '<', _1)); - session->onDataWritten.connect(boost::bind(&SessionTracer::printData, this, '>', _1)); +SessionTracer::SessionTracer(std::shared_ptr<Session> session) : session(session) { + session->onDataRead.connect(boost::bind(&SessionTracer::printData, this, '<', _1)); + session->onDataWritten.connect(boost::bind(&SessionTracer::printData, this, '>', _1)); } void SessionTracer::printData(char direction, const SafeByteArray& data) { - std::cerr << direction << direction << " " << session->getLocalJID() << " "; - for (unsigned int i = 0; i < 72 - session->getLocalJID().toString().size() - session->getRemoteJID().toString().size(); ++i) { - std::cerr << direction; - } - std::cerr << " " << session->getRemoteJID()<< " " << direction << direction << std::endl; - std::cerr << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl; + std::cerr << direction << direction << " " << session->getLocalJID() << " "; + for (unsigned int i = 0; i < 72 - session->getLocalJID().toString().size() - session->getRemoteJID().toString().size(); ++i) { + std::cerr << direction; + } + std::cerr << " " << session->getRemoteJID()<< " " << direction << direction << std::endl; + std::cerr << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl; } } diff --git a/Swiften/Session/SessionTracer.h b/Swiften/Session/SessionTracer.h index 72c93b4..8e73c16 100644 --- a/Swiften/Session/SessionTracer.h +++ b/Swiften/Session/SessionTracer.h @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> -#include <Swiften/Session/Session.h> +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Session/Session.h> namespace Swift { - class SessionTracer { - public: - SessionTracer(boost::shared_ptr<Session> session); + class SWIFTEN_API SessionTracer { + public: + SessionTracer(std::shared_ptr<Session> session); - private: - void printData(char direction, const SafeByteArray& data); + private: + void printData(char direction, const SafeByteArray& data); - boost::shared_ptr<Session> session; - }; + std::shared_ptr<Session> session; + }; } diff --git a/Swiften/StreamManagement/SConscript b/Swiften/StreamManagement/SConscript index 4eaef67..8eab91b 100644 --- a/Swiften/StreamManagement/SConscript +++ b/Swiften/StreamManagement/SConscript @@ -1,8 +1,8 @@ Import("swiften_env") sources = [ - "StanzaAckRequester.cpp", - "StanzaAckResponder.cpp", - ] + "StanzaAckRequester.cpp", + "StanzaAckResponder.cpp", + ] -swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources))
\ No newline at end of file +swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources)) diff --git a/Swiften/StreamManagement/StanzaAckRequester.cpp b/Swiften/StreamManagement/StanzaAckRequester.cpp index b60b9b0..c71803a 100644 --- a/Swiften/StreamManagement/StanzaAckRequester.cpp +++ b/Swiften/StreamManagement/StanzaAckRequester.cpp @@ -1,44 +1,42 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StreamManagement/StanzaAckRequester.h> -#include <boost/numeric/conversion/cast.hpp> -#include <iostream> - +#include <Swiften/Base/Log.h> #include <Swiften/Elements/Message.h> namespace Swift { -static const unsigned int MAX_HANDLED_STANZA_COUNT = boost::numeric_cast<unsigned int>((1ULL<<32) - 1); +static const unsigned int MAX_HANDLED_STANZA_COUNT = static_cast<unsigned int>((1ULL<<32) - 1); StanzaAckRequester::StanzaAckRequester() : lastHandledStanzasCount(0) { } -void StanzaAckRequester::handleStanzaSent(boost::shared_ptr<Stanza> stanza) { - unackedStanzas.push_back(stanza); - if (boost::dynamic_pointer_cast<Message>(stanza)) { - onRequestAck(); - } +void StanzaAckRequester::handleStanzaSent(std::shared_ptr<Stanza> stanza) { + unackedStanzas.push_back(stanza); + if (std::dynamic_pointer_cast<Message>(stanza)) { + onRequestAck(); + } } void StanzaAckRequester::handleAckReceived(unsigned int handledStanzasCount) { - unsigned int i = lastHandledStanzasCount; - while (i != handledStanzasCount) { - if (unackedStanzas.empty()) { - std::cerr << "Warning: Server acked more stanzas than we sent" << std::endl; - break; - } - boost::shared_ptr<Stanza> ackedStanza = unackedStanzas.front(); - unackedStanzas.pop_front(); - onStanzaAcked(ackedStanza); - i = (i == MAX_HANDLED_STANZA_COUNT ? 0 : i + 1); - } - lastHandledStanzasCount = handledStanzasCount; + unsigned int i = lastHandledStanzasCount; + while (i != handledStanzasCount) { + if (unackedStanzas.empty()) { + SWIFT_LOG(warning) << "Server acked more stanzas than we sent"; + break; + } + std::shared_ptr<Stanza> ackedStanza = unackedStanzas.front(); + unackedStanzas.pop_front(); + onStanzaAcked(ackedStanza); + i = (i == MAX_HANDLED_STANZA_COUNT ? 0 : i + 1); + } + lastHandledStanzasCount = handledStanzasCount; } } diff --git a/Swiften/StreamManagement/StanzaAckRequester.h b/Swiften/StreamManagement/StanzaAckRequester.h index 591dc17..422efbd 100644 --- a/Swiften/StreamManagement/StanzaAckRequester.h +++ b/Swiften/StreamManagement/StanzaAckRequester.h @@ -1,34 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> #include <deque> +#include <memory> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> #include <Swiften/Elements/Stanza.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class SWIFTEN_API StanzaAckRequester { - public: - StanzaAckRequester(); - - void handleStanzaSent(boost::shared_ptr<Stanza> stanza); - void handleAckReceived(unsigned int handledStanzasCount); - - public: - boost::signal<void ()> onRequestAck; - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked; - - private: - friend class StanzaAckRequesterTest; - unsigned int lastHandledStanzasCount; - std::deque<boost::shared_ptr<Stanza> > unackedStanzas; - }; + class SWIFTEN_API StanzaAckRequester { + public: + StanzaAckRequester(); + + void handleStanzaSent(std::shared_ptr<Stanza> stanza); + void handleAckReceived(unsigned int handledStanzasCount); + + public: + boost::signals2::signal<void ()> onRequestAck; + boost::signals2::signal<void (std::shared_ptr<Stanza>)> onStanzaAcked; + + private: + friend class StanzaAckRequesterTest; + unsigned int lastHandledStanzasCount; + std::deque<std::shared_ptr<Stanza> > unackedStanzas; + }; } diff --git a/Swiften/StreamManagement/StanzaAckResponder.cpp b/Swiften/StreamManagement/StanzaAckResponder.cpp index 9295924..bfe6f4d 100644 --- a/Swiften/StreamManagement/StanzaAckResponder.cpp +++ b/Swiften/StreamManagement/StanzaAckResponder.cpp @@ -1,26 +1,24 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StreamManagement/StanzaAckResponder.h> -#include <boost/numeric/conversion/cast.hpp> - namespace Swift { -static const unsigned int MAX_HANDLED_STANZA_COUNT = boost::numeric_cast<unsigned int>((1ULL<<32) - 1); +static const unsigned int MAX_HANDLED_STANZA_COUNT = static_cast<unsigned int>((1ULL << 32) - 1); StanzaAckResponder::StanzaAckResponder() : handledStanzasCount(0) { } void StanzaAckResponder::handleStanzaReceived() { - handledStanzasCount = (handledStanzasCount == MAX_HANDLED_STANZA_COUNT ? 0 : handledStanzasCount + 1); + handledStanzasCount = (handledStanzasCount == MAX_HANDLED_STANZA_COUNT ? 0 : handledStanzasCount + 1); } void StanzaAckResponder::handleAckRequestReceived() { - onAck(handledStanzasCount); + onAck(handledStanzasCount); } } diff --git a/Swiften/StreamManagement/StanzaAckResponder.h b/Swiften/StreamManagement/StanzaAckResponder.h index d8edd2c..c90bbff 100644 --- a/Swiften/StreamManagement/StanzaAckResponder.h +++ b/Swiften/StreamManagement/StanzaAckResponder.h @@ -1,31 +1,32 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> #include <Swiften/Elements/Stanza.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class SWIFTEN_API StanzaAckResponder { - public: - StanzaAckResponder(); + class SWIFTEN_API StanzaAckResponder { + public: + StanzaAckResponder(); - void handleStanzaReceived(); - void handleAckRequestReceived(); + void handleStanzaReceived(); + void handleAckRequestReceived(); - public: - boost::signal<void (unsigned int /* handledStanzaCount */)> onAck; + public: + boost::signals2::signal<void (unsigned int /* handledStanzaCount */)> onAck; - private: - friend class StanzaAckResponderTest; - unsigned int handledStanzasCount; - }; + private: + friend class StanzaAckResponderTest; + unsigned int handledStanzasCount; + }; } diff --git a/Swiften/StreamManagement/UnitTest/StanzaAckRequesterTest.cpp b/Swiften/StreamManagement/UnitTest/StanzaAckRequesterTest.cpp index baccc41..e0ebefd 100644 --- a/Swiften/StreamManagement/UnitTest/StanzaAckRequesterTest.cpp +++ b/Swiften/StreamManagement/UnitTest/StanzaAckRequesterTest.cpp @@ -1,163 +1,165 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <cstdint> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> -#include <boost/numeric/conversion/cast.hpp> -#include <Swiften/StreamManagement/StanzaAckRequester.h> +#include <Swiften/Elements/IQ.h> #include <Swiften/Elements/Message.h> #include <Swiften/Elements/Presence.h> -#include <Swiften/Elements/IQ.h> +#include <Swiften/StreamManagement/StanzaAckRequester.h> using namespace Swift; namespace Swift { class StanzaAckRequesterTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StanzaAckRequesterTest); - CPPUNIT_TEST(testHandleStanzaSent_MessageRequestsAck); - CPPUNIT_TEST(testHandleStanzaSent_IQDoesNotRequestAck); - CPPUNIT_TEST(testHandleStanzaSent_PresenceDoesNotRequestAck); - CPPUNIT_TEST(testHandleAckReceived_AcksStanza); - CPPUNIT_TEST(testHandleAckReceived_AcksMultipleMessages); - CPPUNIT_TEST(testHandleAckReceived_AcksMultipleStanzas); - CPPUNIT_TEST(testHandleAckReceived_MultipleAcks); - CPPUNIT_TEST(testHandleAckReceived_WrapAround); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - acksRequested = 0; - } - - void testHandleStanzaSent_MessageRequestsAck() { - boost::shared_ptr<StanzaAckRequester> testling(createRequester()); - testling->handleStanzaSent(createMessage("m1")); - - CPPUNIT_ASSERT_EQUAL(1, acksRequested); - } - - void testHandleStanzaSent_IQDoesNotRequestAck() { - boost::shared_ptr<StanzaAckRequester> testling(createRequester()); - testling->handleStanzaSent(createIQ("iq1")); - - CPPUNIT_ASSERT_EQUAL(0, acksRequested); - } - - void testHandleStanzaSent_PresenceDoesNotRequestAck() { - boost::shared_ptr<StanzaAckRequester> testling(createRequester()); - testling->handleStanzaSent(createPresence("p1")); - - CPPUNIT_ASSERT_EQUAL(0, acksRequested); - } - - void testHandleAckReceived_AcksStanza() { - boost::shared_ptr<StanzaAckRequester> testling(createRequester()); - testling->handleStanzaSent(createMessage("m1")); - - testling->handleAckReceived(1); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(ackedStanzas.size())); - CPPUNIT_ASSERT_EQUAL(std::string("m1"), ackedStanzas[0]->getID()); - } - - void testHandleAckReceived_AcksMultipleMessages() { - boost::shared_ptr<StanzaAckRequester> testling(createRequester()); - testling->handleStanzaSent(createMessage("m1")); - testling->handleStanzaSent(createMessage("m2")); - - testling->handleAckReceived(2); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(ackedStanzas.size())); - CPPUNIT_ASSERT_EQUAL(std::string("m1"), ackedStanzas[0]->getID()); - CPPUNIT_ASSERT_EQUAL(std::string("m2"), ackedStanzas[1]->getID()); - } - - void testHandleAckReceived_AcksMultipleStanzas() { - boost::shared_ptr<StanzaAckRequester> testling(createRequester()); - testling->handleStanzaSent(createIQ("iq1")); - testling->handleStanzaSent(createPresence("p1")); - testling->handleStanzaSent(createMessage("m1")); - - testling->handleAckReceived(3); - - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(ackedStanzas.size())); - CPPUNIT_ASSERT_EQUAL(std::string("iq1"), ackedStanzas[0]->getID()); - CPPUNIT_ASSERT_EQUAL(std::string("p1"), ackedStanzas[1]->getID()); - CPPUNIT_ASSERT_EQUAL(std::string("m1"), ackedStanzas[2]->getID()); - } - - void testHandleAckReceived_MultipleAcks() { - boost::shared_ptr<StanzaAckRequester> testling(createRequester()); - testling->handleStanzaSent(createMessage("m1")); - testling->handleAckReceived(1); - - testling->handleStanzaSent(createMessage("m2")); - testling->handleStanzaSent(createMessage("m3")); - testling->handleAckReceived(3); - - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(ackedStanzas.size())); - CPPUNIT_ASSERT_EQUAL(std::string("m1"), ackedStanzas[0]->getID()); - CPPUNIT_ASSERT_EQUAL(std::string("m2"), ackedStanzas[1]->getID()); - CPPUNIT_ASSERT_EQUAL(std::string("m3"), ackedStanzas[2]->getID()); - } - - // Handle stanza ack count wrapping, as per the XEP - void testHandleAckReceived_WrapAround() { - boost::shared_ptr<StanzaAckRequester> testling(createRequester()); - testling->lastHandledStanzasCount = boost::numeric_cast<unsigned int>((1ULL<<32) - 1); - testling->handleStanzaSent(createMessage("m1")); - testling->handleStanzaSent(createMessage("m2")); - - testling->handleAckReceived(1); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(ackedStanzas.size())); - CPPUNIT_ASSERT_EQUAL(std::string("m1"), ackedStanzas[0]->getID()); - CPPUNIT_ASSERT_EQUAL(std::string("m2"), ackedStanzas[1]->getID()); - } - - private: - Message::ref createMessage(const std::string& id) { - Message::ref result(new Message()); - result->setID(id); - return result; - } - - IQ::ref createIQ(const std::string& id) { - IQ::ref result(new IQ()); - result->setID(id); - return result; - } - - Presence::ref createPresence(const std::string& id) { - Presence::ref result(new Presence()); - result->setID(id); - return result; - } - - StanzaAckRequester* createRequester() { - StanzaAckRequester* requester = new StanzaAckRequester(); - requester->onRequestAck.connect(boost::bind(&StanzaAckRequesterTest::handleRequestAck, this)); - requester->onStanzaAcked.connect(boost::bind(&StanzaAckRequesterTest::handleStanzaAcked, this, _1)); - return requester; - } - - void handleRequestAck() { - acksRequested++; - } - - void handleStanzaAcked(boost::shared_ptr<Stanza> stanza) { - ackedStanzas.push_back(stanza); - } - - private: - int acksRequested; - std::vector< boost::shared_ptr<Stanza> > ackedStanzas; + CPPUNIT_TEST_SUITE(StanzaAckRequesterTest); + CPPUNIT_TEST(testHandleStanzaSent_MessageRequestsAck); + CPPUNIT_TEST(testHandleStanzaSent_IQDoesNotRequestAck); + CPPUNIT_TEST(testHandleStanzaSent_PresenceDoesNotRequestAck); + CPPUNIT_TEST(testHandleAckReceived_AcksStanza); + CPPUNIT_TEST(testHandleAckReceived_AcksMultipleMessages); + CPPUNIT_TEST(testHandleAckReceived_AcksMultipleStanzas); + CPPUNIT_TEST(testHandleAckReceived_MultipleAcks); + CPPUNIT_TEST(testHandleAckReceived_WrapAround); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + acksRequested = 0; + } + + void testHandleStanzaSent_MessageRequestsAck() { + std::shared_ptr<StanzaAckRequester> testling(createRequester()); + testling->handleStanzaSent(createMessage("m1")); + + CPPUNIT_ASSERT_EQUAL(1, acksRequested); + } + + void testHandleStanzaSent_IQDoesNotRequestAck() { + std::shared_ptr<StanzaAckRequester> testling(createRequester()); + testling->handleStanzaSent(createIQ("iq1")); + + CPPUNIT_ASSERT_EQUAL(0, acksRequested); + } + + void testHandleStanzaSent_PresenceDoesNotRequestAck() { + std::shared_ptr<StanzaAckRequester> testling(createRequester()); + testling->handleStanzaSent(createPresence("p1")); + + CPPUNIT_ASSERT_EQUAL(0, acksRequested); + } + + void testHandleAckReceived_AcksStanza() { + std::shared_ptr<StanzaAckRequester> testling(createRequester()); + testling->handleStanzaSent(createMessage("m1")); + + testling->handleAckReceived(1); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(ackedStanzas.size())); + CPPUNIT_ASSERT_EQUAL(std::string("m1"), ackedStanzas[0]->getID()); + } + + void testHandleAckReceived_AcksMultipleMessages() { + std::shared_ptr<StanzaAckRequester> testling(createRequester()); + testling->handleStanzaSent(createMessage("m1")); + testling->handleStanzaSent(createMessage("m2")); + + testling->handleAckReceived(2); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(ackedStanzas.size())); + CPPUNIT_ASSERT_EQUAL(std::string("m1"), ackedStanzas[0]->getID()); + CPPUNIT_ASSERT_EQUAL(std::string("m2"), ackedStanzas[1]->getID()); + } + + void testHandleAckReceived_AcksMultipleStanzas() { + std::shared_ptr<StanzaAckRequester> testling(createRequester()); + testling->handleStanzaSent(createIQ("iq1")); + testling->handleStanzaSent(createPresence("p1")); + testling->handleStanzaSent(createMessage("m1")); + + testling->handleAckReceived(3); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(ackedStanzas.size())); + CPPUNIT_ASSERT_EQUAL(std::string("iq1"), ackedStanzas[0]->getID()); + CPPUNIT_ASSERT_EQUAL(std::string("p1"), ackedStanzas[1]->getID()); + CPPUNIT_ASSERT_EQUAL(std::string("m1"), ackedStanzas[2]->getID()); + } + + void testHandleAckReceived_MultipleAcks() { + std::shared_ptr<StanzaAckRequester> testling(createRequester()); + testling->handleStanzaSent(createMessage("m1")); + testling->handleAckReceived(1); + + testling->handleStanzaSent(createMessage("m2")); + testling->handleStanzaSent(createMessage("m3")); + testling->handleAckReceived(3); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(ackedStanzas.size())); + CPPUNIT_ASSERT_EQUAL(std::string("m1"), ackedStanzas[0]->getID()); + CPPUNIT_ASSERT_EQUAL(std::string("m2"), ackedStanzas[1]->getID()); + CPPUNIT_ASSERT_EQUAL(std::string("m3"), ackedStanzas[2]->getID()); + } + + // Handle stanza ack count wrapping, as per the XEP + void testHandleAckReceived_WrapAround() { + std::shared_ptr<StanzaAckRequester> testling(createRequester()); + testling->lastHandledStanzasCount = UINT32_MAX; + testling->handleStanzaSent(createMessage("m1")); + testling->handleStanzaSent(createMessage("m2")); + + testling->handleAckReceived(1); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(ackedStanzas.size())); + CPPUNIT_ASSERT_EQUAL(std::string("m1"), ackedStanzas[0]->getID()); + CPPUNIT_ASSERT_EQUAL(std::string("m2"), ackedStanzas[1]->getID()); + } + + private: + Message::ref createMessage(const std::string& id) { + Message::ref result(new Message()); + result->setID(id); + return result; + } + + IQ::ref createIQ(const std::string& id) { + IQ::ref result(new IQ()); + result->setID(id); + return result; + } + + Presence::ref createPresence(const std::string& id) { + Presence::ref result(new Presence()); + result->setID(id); + return result; + } + + StanzaAckRequester* createRequester() { + StanzaAckRequester* requester = new StanzaAckRequester(); + requester->onRequestAck.connect(boost::bind(&StanzaAckRequesterTest::handleRequestAck, this)); + requester->onStanzaAcked.connect(boost::bind(&StanzaAckRequesterTest::handleStanzaAcked, this, _1)); + return requester; + } + + void handleRequestAck() { + acksRequested++; + } + + void handleStanzaAcked(std::shared_ptr<Stanza> stanza) { + ackedStanzas.push_back(stanza); + } + + private: + int acksRequested = 0; + std::vector< std::shared_ptr<Stanza> > ackedStanzas; }; } diff --git a/Swiften/StreamManagement/UnitTest/StanzaAckResponderTest.cpp b/Swiften/StreamManagement/UnitTest/StanzaAckResponderTest.cpp index 71a7f94..ee4b913 100644 --- a/Swiften/StreamManagement/UnitTest/StanzaAckResponderTest.cpp +++ b/Swiften/StreamManagement/UnitTest/StanzaAckResponderTest.cpp @@ -1,96 +1,98 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <cstdint> + +#include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> -#include <boost/numeric/conversion/cast.hpp> -#include <Swiften/StreamManagement/StanzaAckResponder.h> #include <Swiften/Elements/Message.h> +#include <Swiften/StreamManagement/StanzaAckResponder.h> using namespace Swift; namespace Swift { class StanzaAckResponderTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StanzaAckResponderTest); - CPPUNIT_TEST(testHandleAckRequestReceived_AcksStanza); - CPPUNIT_TEST(testHandleAckRequestReceived_AcksMultipleStanzas); - CPPUNIT_TEST(testHandleAckRequestReceived_MultipleAcks); - CPPUNIT_TEST(testHandleAckRequestReceived_WrapAround); - CPPUNIT_TEST_SUITE_END(); - - public: - void testHandleAckRequestReceived_AcksStanza() { - boost::shared_ptr<StanzaAckResponder> testling(createResponder()); - testling->handleStanzaReceived(); - - testling->handleAckRequestReceived(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(acks.size())); - CPPUNIT_ASSERT_EQUAL(1U, acks[0]); - } - - void testHandleAckRequestReceived_AcksMultipleStanzas() { - boost::shared_ptr<StanzaAckResponder> testling(createResponder()); - testling->handleStanzaReceived(); - testling->handleStanzaReceived(); - - testling->handleAckRequestReceived(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(acks.size())); - CPPUNIT_ASSERT_EQUAL(2U, acks[0]); - } - - void testHandleAckRequestReceived_MultipleAcks() { - boost::shared_ptr<StanzaAckResponder> testling(createResponder()); - testling->handleStanzaReceived(); - testling->handleAckRequestReceived(); - - testling->handleStanzaReceived(); - testling->handleAckRequestReceived(); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(acks.size())); - CPPUNIT_ASSERT_EQUAL(1U, acks[0]); - CPPUNIT_ASSERT_EQUAL(2U, acks[1]); - } - - // Handle stanza ack count wrapping, as per the XEP - void testHandleAckRequestReceived_WrapAround() { - boost::shared_ptr<StanzaAckResponder> testling(createResponder()); - testling->handledStanzasCount = boost::numeric_cast<unsigned int>((1ULL<<32) - 1); - testling->handleStanzaReceived(); - testling->handleStanzaReceived(); - - testling->handleAckRequestReceived(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(acks.size())); - CPPUNIT_ASSERT_EQUAL(1U, acks[0]); - } - - private: - Message::ref createMessage(const std::string& id) { - Message::ref result(new Message()); - result->setID(id); - return result; - } - - StanzaAckResponder* createResponder() { - StanzaAckResponder* responder = new StanzaAckResponder(); - responder->onAck.connect(boost::bind(&StanzaAckResponderTest::handleAck, this, _1)); - return responder; - } - - void handleAck(unsigned int h) { - acks.push_back(h); - } - - private: - std::vector<unsigned int> acks; + CPPUNIT_TEST_SUITE(StanzaAckResponderTest); + CPPUNIT_TEST(testHandleAckRequestReceived_AcksStanza); + CPPUNIT_TEST(testHandleAckRequestReceived_AcksMultipleStanzas); + CPPUNIT_TEST(testHandleAckRequestReceived_MultipleAcks); + CPPUNIT_TEST(testHandleAckRequestReceived_WrapAround); + CPPUNIT_TEST_SUITE_END(); + + public: + void testHandleAckRequestReceived_AcksStanza() { + std::shared_ptr<StanzaAckResponder> testling(createResponder()); + testling->handleStanzaReceived(); + + testling->handleAckRequestReceived(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(acks.size())); + CPPUNIT_ASSERT_EQUAL(1U, acks[0]); + } + + void testHandleAckRequestReceived_AcksMultipleStanzas() { + std::shared_ptr<StanzaAckResponder> testling(createResponder()); + testling->handleStanzaReceived(); + testling->handleStanzaReceived(); + + testling->handleAckRequestReceived(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(acks.size())); + CPPUNIT_ASSERT_EQUAL(2U, acks[0]); + } + + void testHandleAckRequestReceived_MultipleAcks() { + std::shared_ptr<StanzaAckResponder> testling(createResponder()); + testling->handleStanzaReceived(); + testling->handleAckRequestReceived(); + + testling->handleStanzaReceived(); + testling->handleAckRequestReceived(); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(acks.size())); + CPPUNIT_ASSERT_EQUAL(1U, acks[0]); + CPPUNIT_ASSERT_EQUAL(2U, acks[1]); + } + + // Handle stanza ack count wrapping, as per the XEP + void testHandleAckRequestReceived_WrapAround() { + std::shared_ptr<StanzaAckResponder> testling(createResponder()); + testling->handledStanzasCount = UINT32_MAX; + testling->handleStanzaReceived(); + testling->handleStanzaReceived(); + + testling->handleAckRequestReceived(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(acks.size())); + CPPUNIT_ASSERT_EQUAL(1U, acks[0]); + } + + private: + Message::ref createMessage(const std::string& id) { + Message::ref result(new Message()); + result->setID(id); + return result; + } + + StanzaAckResponder* createResponder() { + StanzaAckResponder* responder = new StanzaAckResponder(); + responder->onAck.connect(boost::bind(&StanzaAckResponderTest::handleAck, this, _1)); + return responder; + } + + void handleAck(unsigned int h) { + acks.push_back(h); + } + + private: + std::vector<unsigned int> acks; }; } diff --git a/Swiften/StreamStack/CompressionLayer.h b/Swiften/StreamStack/CompressionLayer.h index 783cfca..04a9251 100644 --- a/Swiften/StreamStack/CompressionLayer.h +++ b/Swiften/StreamStack/CompressionLayer.h @@ -1,51 +1,52 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <boost/noncopyable.hpp> -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> -#include <Swiften/StreamStack/StreamLayer.h> -#include <Swiften/Compress/ZLibException.h> #include <Swiften/Compress/ZLibCompressor.h> #include <Swiften/Compress/ZLibDecompressor.h> +#include <Swiften/Compress/ZLibException.h> +#include <Swiften/StreamStack/StreamLayer.h> namespace Swift { - class ZLibCompressor; - class ZLibDecompressor; - - class CompressionLayer : public StreamLayer, boost::noncopyable { - public: - CompressionLayer() {} - - virtual void writeData(const SafeByteArray& data) { - try { - writeDataToChildLayer(compressor_.process(data)); - } - catch (const ZLibException&) { - onError(); - } - } - - virtual void handleDataRead(const SafeByteArray& data) { - try { - writeDataToParentLayer(decompressor_.process(data)); - } - catch (const ZLibException&) { - onError(); - } - } - - public: - boost::signal<void ()> onError; - - private: - ZLibCompressor compressor_; - ZLibDecompressor decompressor_; - }; + class ZLibCompressor; + class ZLibDecompressor; + + class SWIFTEN_API CompressionLayer : public StreamLayer, boost::noncopyable { + public: + CompressionLayer() {} + + virtual void writeData(const SafeByteArray& data) { + try { + writeDataToChildLayer(compressor_.process(data)); + } + catch (const ZLibException&) { + onError(); + } + } + + virtual void handleDataRead(const SafeByteArray& data) { + try { + writeDataToParentLayer(decompressor_.process(data)); + } + catch (const ZLibException&) { + onError(); + } + } + + public: + boost::signals2::signal<void ()> onError; + + private: + ZLibCompressor compressor_; + ZLibDecompressor decompressor_; + }; } diff --git a/Swiften/StreamStack/ConnectionLayer.cpp b/Swiften/StreamStack/ConnectionLayer.cpp index 5ea06eb..b0c4deb 100644 --- a/Swiften/StreamStack/ConnectionLayer.cpp +++ b/Swiften/StreamStack/ConnectionLayer.cpp @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StreamStack/ConnectionLayer.h> + #include <boost/bind.hpp> namespace Swift { -ConnectionLayer::ConnectionLayer(boost::shared_ptr<Connection> connection) : connection(connection) { - connection->onDataRead.connect(boost::bind(&ConnectionLayer::handleDataRead, this, _1)); +ConnectionLayer::ConnectionLayer(std::shared_ptr<Connection> connection) : connection(connection) { + connection->onDataRead.connect(boost::bind(&ConnectionLayer::handleDataRead, this, _1)); } ConnectionLayer::~ConnectionLayer() { - connection->onDataRead.disconnect(boost::bind(&ConnectionLayer::writeDataToParentLayer, this, _1)); + connection->onDataRead.disconnect(boost::bind(&ConnectionLayer::handleDataRead, this, _1)); } -void ConnectionLayer::handleDataRead(boost::shared_ptr<SafeByteArray> data) { - writeDataToParentLayer(*data); +void ConnectionLayer::handleDataRead(std::shared_ptr<SafeByteArray> data) { + writeDataToParentLayer(*data); } diff --git a/Swiften/StreamStack/ConnectionLayer.h b/Swiften/StreamStack/ConnectionLayer.h index 6776751..d1775ee 100644 --- a/Swiften/StreamStack/ConnectionLayer.h +++ b/Swiften/StreamStack/ConnectionLayer.h @@ -1,30 +1,31 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include <Swiften/StreamStack/LowLayer.h> +#include <Swiften/Base/API.h> #include <Swiften/Network/Connection.h> +#include <Swiften/StreamStack/LowLayer.h> namespace Swift { - class ConnectionLayer : public LowLayer { - public: - ConnectionLayer(boost::shared_ptr<Connection> connection); - ~ConnectionLayer(); + class SWIFTEN_API ConnectionLayer : public LowLayer { + public: + ConnectionLayer(std::shared_ptr<Connection> connection); + virtual ~ConnectionLayer(); - void writeData(const SafeByteArray& data) { - connection->write(data); - } + void writeData(const SafeByteArray& data) { + connection->write(data); + } - private: - void handleDataRead(boost::shared_ptr<SafeByteArray>); + private: + void handleDataRead(std::shared_ptr<SafeByteArray>); - private: - boost::shared_ptr<Connection> connection; - }; + private: + std::shared_ptr<Connection> connection; + }; } diff --git a/Swiften/StreamStack/DummyStreamLayer.h b/Swiften/StreamStack/DummyStreamLayer.h new file mode 100644 index 0000000..5a93b7f --- /dev/null +++ b/Swiften/StreamStack/DummyStreamLayer.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/StreamStack/HighLayer.h> +#include <Swiften/StreamStack/LowLayer.h> + +namespace Swift { + /** + * The \ref DummyStreamLayer can be used to use a \ref LowLayer on its own, without a functioning parent layer. + * The \ref DummyStreamLayer will serve as the parent layer to the \ref LowLayer and is called when the \ref LowLayer + * wants to write data to its parent layer. + */ + class SWIFTEN_API DummyStreamLayer : public HighLayer { + public: + DummyStreamLayer(LowLayer* lowLayer) { + setChildLayer(lowLayer); + lowLayer->setParentLayer(this); + } + + virtual void handleDataRead(const SafeByteArray& /* data */) { + + } + }; +} diff --git a/Swiften/StreamStack/HighLayer.cpp b/Swiften/StreamStack/HighLayer.cpp index 0f76f22..8e7ba02 100644 --- a/Swiften/StreamStack/HighLayer.cpp +++ b/Swiften/StreamStack/HighLayer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StreamStack/HighLayer.h> @@ -12,17 +12,17 @@ namespace Swift { -HighLayer::HighLayer() : childLayer(NULL) { +HighLayer::HighLayer() : childLayer(nullptr) { } HighLayer::~HighLayer() { } void HighLayer::writeDataToChildLayer(const SafeByteArray& data) { - //assert(childLayer); - if (childLayer) { - childLayer->writeData(data); - } + //assert(childLayer); + if (childLayer) { + childLayer->writeData(data); + } } } diff --git a/Swiften/StreamStack/HighLayer.h b/Swiften/StreamStack/HighLayer.h index 5669592..a877d8d 100644 --- a/Swiften/StreamStack/HighLayer.h +++ b/Swiften/StreamStack/HighLayer.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,29 +10,29 @@ #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class LowLayer; + class LowLayer; - class SWIFTEN_API HighLayer { - friend class StreamStack; + class SWIFTEN_API HighLayer { + friend class StreamStack; - public: - HighLayer(); - virtual ~HighLayer(); + public: + HighLayer(); + virtual ~HighLayer(); - virtual void handleDataRead(const SafeByteArray& data) = 0; - - protected: - LowLayer* getChildLayer() { - return childLayer; - } + virtual void handleDataRead(const SafeByteArray& data) = 0; - void setChildLayer(LowLayer* childLayer) { - this->childLayer = childLayer; - } + protected: + LowLayer* getChildLayer() { + return childLayer; + } - void writeDataToChildLayer(const SafeByteArray& data); + void setChildLayer(LowLayer* childLayer) { + this->childLayer = childLayer; + } - private: - LowLayer* childLayer; - }; + void writeDataToChildLayer(const SafeByteArray& data); + + private: + LowLayer* childLayer; + }; } diff --git a/Swiften/StreamStack/LowLayer.cpp b/Swiften/StreamStack/LowLayer.cpp index ff4ca17..c94dafe 100644 --- a/Swiften/StreamStack/LowLayer.cpp +++ b/Swiften/StreamStack/LowLayer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StreamStack/LowLayer.h> @@ -12,15 +12,15 @@ namespace Swift { -LowLayer::LowLayer() : parentLayer(NULL) { +LowLayer::LowLayer() : parentLayer(nullptr) { } LowLayer::~LowLayer() { } void LowLayer::writeDataToParentLayer(const SafeByteArray& data) { - assert(parentLayer); - parentLayer->handleDataRead(data); + assert(parentLayer); + parentLayer->handleDataRead(data); } } diff --git a/Swiften/StreamStack/LowLayer.h b/Swiften/StreamStack/LowLayer.h index ee3f7d3..83cc190 100644 --- a/Swiften/StreamStack/LowLayer.h +++ b/Swiften/StreamStack/LowLayer.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,29 +10,30 @@ #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class HighLayer; + class HighLayer; - class SWIFTEN_API LowLayer { - friend class StreamStack; + class SWIFTEN_API LowLayer { + friend class StreamStack; + friend class DummyStreamLayer; - public: - LowLayer(); - virtual ~LowLayer(); + public: + LowLayer(); + virtual ~LowLayer(); - virtual void writeData(const SafeByteArray& data) = 0; - - protected: - HighLayer* getParentLayer() { - return parentLayer; - } + virtual void writeData(const SafeByteArray& data) = 0; - void setParentLayer(HighLayer* parentLayer) { - this->parentLayer = parentLayer; - } + protected: + HighLayer* getParentLayer() { + return parentLayer; + } - void writeDataToParentLayer(const SafeByteArray& data); + void setParentLayer(HighLayer* parentLayer) { + this->parentLayer = parentLayer; + } - private: - HighLayer* parentLayer; - }; + void writeDataToParentLayer(const SafeByteArray& data); + + private: + HighLayer* parentLayer; + }; } diff --git a/Swiften/StreamStack/SConscript b/Swiften/StreamStack/SConscript index 06fcc03..0a8bab1 100644 --- a/Swiften/StreamStack/SConscript +++ b/Swiften/StreamStack/SConscript @@ -3,14 +3,14 @@ Import("swiften_env") myenv = swiften_env.Clone() sources = [ - "HighLayer.cpp", - "LowLayer.cpp", - "StreamStack.cpp", - "ConnectionLayer.cpp", - "TLSLayer.cpp", - "WhitespacePingLayer.cpp", - "XMPPLayer.cpp", - ] + "HighLayer.cpp", + "LowLayer.cpp", + "StreamStack.cpp", + "ConnectionLayer.cpp", + "TLSLayer.cpp", + "WhitespacePingLayer.cpp", + "XMPPLayer.cpp", + ] objects = myenv.SwiftenObject(sources) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/StreamStack/StreamLayer.h b/Swiften/StreamStack/StreamLayer.h index 09bb5b3..14a1ea6 100644 --- a/Swiften/StreamStack/StreamLayer.h +++ b/Swiften/StreamStack/StreamLayer.h @@ -1,17 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/StreamStack/LowLayer.h> +#include <Swiften/Base/API.h> #include <Swiften/StreamStack/HighLayer.h> +#include <Swiften/StreamStack/LowLayer.h> namespace Swift { - class StreamLayer : public LowLayer, public HighLayer { - public: - StreamLayer() {} - }; + class SWIFTEN_API StreamLayer : public LowLayer, public HighLayer { + public: + StreamLayer() {} + }; } diff --git a/Swiften/StreamStack/StreamStack.cpp b/Swiften/StreamStack/StreamStack.cpp index 78409f7..cf80fb1 100644 --- a/Swiften/StreamStack/StreamStack.cpp +++ b/Swiften/StreamStack/StreamStack.cpp @@ -1,38 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StreamStack/StreamStack.h> #include <boost/bind.hpp> -#include <Swiften/Base/foreach.h> -#include <Swiften/StreamStack/XMPPLayer.h> +#include <Swiften/StreamStack/HighLayer.h> #include <Swiften/StreamStack/LowLayer.h> #include <Swiften/StreamStack/StreamLayer.h> namespace Swift { -StreamStack::StreamStack(XMPPLayer* xmppLayer, LowLayer* physicalLayer) : xmppLayer_(xmppLayer), physicalLayer_(physicalLayer) { - physicalLayer_->setParentLayer(xmppLayer_); - xmppLayer_->setChildLayer(physicalLayer_); +StreamStack::StreamStack(std::unique_ptr<HighLayer> topLayer, std::unique_ptr<LowLayer> bottomLayer) : topLayer_(std::move(topLayer)), bottomLayer_(std::move(bottomLayer)) { + bottomLayer_->setParentLayer(topLayer_.get()); + topLayer_->setChildLayer(bottomLayer_.get()); } StreamStack::~StreamStack() { } -void StreamStack::addLayer(StreamLayer* newLayer) { - LowLayer* lowLayer = layers_.empty() ? physicalLayer_ : *layers_.rbegin(); +void StreamStack::addLayer(std::unique_ptr<StreamLayer> streamLayer) { + auto* lowLayer = layers_.empty() ? bottomLayer_.get() : layers_.rbegin()->get(); - xmppLayer_->setChildLayer(newLayer); - newLayer->setParentLayer(xmppLayer_); - - lowLayer->setParentLayer(newLayer); - newLayer->setChildLayer(lowLayer); + topLayer_->setChildLayer(streamLayer.get()); + streamLayer->setParentLayer(topLayer_.get()); - layers_.push_back(newLayer); + lowLayer->setParentLayer(streamLayer.get()); + streamLayer->setChildLayer(lowLayer); + + layers_.emplace_back(std::move(streamLayer)); } } diff --git a/Swiften/StreamStack/StreamStack.h b/Swiften/StreamStack/StreamStack.h index 8bbb235..263b1f5 100644 --- a/Swiften/StreamStack/StreamStack.h +++ b/Swiften/StreamStack/StreamStack.h @@ -1,47 +1,54 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> +#include <memory> #include <vector> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> #include <Swiften/Elements/Stanza.h> namespace Swift { - class XMPPLayer; - class LowLayer; - class StreamLayer; - - class SWIFTEN_API StreamStack { - public: - StreamStack(XMPPLayer* xmppLayer, LowLayer* physicalLayer); - ~StreamStack(); - - void addLayer(StreamLayer*); - - XMPPLayer* getXMPPLayer() const { - return xmppLayer_; - } - - template<typename T> T* getLayer() { - for (size_t i = 0; i < layers_.size(); ++i) { - T* layer = dynamic_cast<T*>(layers_[i]); - if (layer) { - return layer; - } - } - return NULL; - } - - private: - XMPPLayer* xmppLayer_; - LowLayer* physicalLayer_; - std::vector<StreamLayer*> layers_; - }; + class HighLayer; + class LowLayer; + class StreamLayer; + + class SWIFTEN_API StreamStack { + public: + StreamStack(std::unique_ptr<HighLayer> topLayer, std::unique_ptr<LowLayer> bottomLayer); + ~StreamStack(); + + void addLayer(std::unique_ptr<StreamLayer> /* streamLayer */); + + HighLayer* getTopLayer() const { + return topLayer_.get(); + } + + template<typename T> T* getLayer() const { + for (const auto& i : layers_) { + T* layer = dynamic_cast<T*>(i.get()); + if (layer) { + return layer; + } + } + if (T* layer = dynamic_cast<T*>(topLayer_.get())) { + return layer; + } + if (T* layer = dynamic_cast<T*>(bottomLayer_.get())) { + return layer; + } + return nullptr; + } + + private: + std::unique_ptr<HighLayer> topLayer_; + std::unique_ptr<LowLayer> bottomLayer_; + std::vector<std::unique_ptr<StreamLayer>> layers_; + }; } diff --git a/Swiften/StreamStack/TLSLayer.cpp b/Swiften/StreamStack/TLSLayer.cpp index 86221ea..9f84889 100644 --- a/Swiften/StreamStack/TLSLayer.cpp +++ b/Swiften/StreamStack/TLSLayer.cpp @@ -1,56 +1,56 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StreamStack/TLSLayer.h> +#include <memory> + #include <boost/bind.hpp> -#include <Swiften/TLS/TLSContextFactory.h> #include <Swiften/TLS/TLSContext.h> +#include <Swiften/TLS/TLSContextFactory.h> namespace Swift { -TLSLayer::TLSLayer(TLSContextFactory* factory) { - context = factory->createTLSContext(); - context->onDataForNetwork.connect(boost::bind(&TLSLayer::writeDataToChildLayer, this, _1)); - context->onDataForApplication.connect(boost::bind(&TLSLayer::writeDataToParentLayer, this, _1)); - context->onConnected.connect(onConnected); - context->onError.connect(onError); +TLSLayer::TLSLayer(std::unique_ptr<TLSContext> tlsContext) : context_(std::move(tlsContext)) { + context_->onDataForNetwork.connect(boost::bind(&TLSLayer::writeDataToChildLayer, this, _1)); + context_->onDataForApplication.connect(boost::bind(&TLSLayer::writeDataToParentLayer, this, _1)); + context_->onConnected.connect(onConnected); + context_->onError.connect(onError); } TLSLayer::~TLSLayer() { - delete context; } void TLSLayer::connect() { - context->connect(); + context_->connect(); } void TLSLayer::writeData(const SafeByteArray& data) { - context->handleDataFromApplication(data); + context_->handleDataFromApplication(data); } void TLSLayer::handleDataRead(const SafeByteArray& data) { - context->handleDataFromNetwork(data); + context_->handleDataFromNetwork(data); } bool TLSLayer::setClientCertificate(CertificateWithKey::ref certificate) { - return context->setClientCertificate(certificate); + return context_->setClientCertificate(certificate); } Certificate::ref TLSLayer::getPeerCertificate() const { - return context->getPeerCertificate(); + return context_->getPeerCertificate(); } std::vector<Certificate::ref> TLSLayer::getPeerCertificateChain() const { - return context->getPeerCertificateChain(); + return context_->getPeerCertificateChain(); } -boost::shared_ptr<CertificateVerificationError> TLSLayer::getPeerCertificateVerificationError() const { - return context->getPeerCertificateVerificationError(); +std::shared_ptr<CertificateVerificationError> TLSLayer::getPeerCertificateVerificationError() const { + return context_->getPeerCertificateVerificationError(); } } diff --git a/Swiften/StreamStack/TLSLayer.h b/Swiften/StreamStack/TLSLayer.h index 24978e0..89588e3 100644 --- a/Swiften/StreamStack/TLSLayer.h +++ b/Swiften/StreamStack/TLSLayer.h @@ -1,46 +1,50 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/boost_bsignals.h> +#pragma once +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> #include <Swiften/StreamStack/StreamLayer.h> #include <Swiften/TLS/Certificate.h> -#include <Swiften/TLS/CertificateWithKey.h> #include <Swiften/TLS/CertificateVerificationError.h> +#include <Swiften/TLS/CertificateWithKey.h> #include <Swiften/TLS/TLSError.h> +#include <Swiften/TLS/TLSOptions.h> namespace Swift { - class TLSContext; - class TLSContextFactory; + class TLSContext; + class TLSContextFactory; - class TLSLayer : public StreamLayer { - public: - TLSLayer(TLSContextFactory*); - ~TLSLayer(); + class SWIFTEN_API TLSLayer : public StreamLayer { + public: + TLSLayer(std::unique_ptr<TLSContext> tlsContext); + virtual ~TLSLayer(); - void connect(); - bool setClientCertificate(CertificateWithKey::ref cert); + void connect(); + bool setClientCertificate(CertificateWithKey::ref cert); - Certificate::ref getPeerCertificate() const; - std::vector<Certificate::ref> getPeerCertificateChain() const; - boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; + Certificate::ref getPeerCertificate() const; + std::vector<Certificate::ref> getPeerCertificateChain() const; + std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; - void writeData(const SafeByteArray& data); - void handleDataRead(const SafeByteArray& data); + void writeData(const SafeByteArray& data); + void handleDataRead(const SafeByteArray& data); - TLSContext* getContext() const { - return context; - } + TLSContext* getContext() const { + return context_.get(); + } - public: - boost::signal<void (boost::shared_ptr<TLSError>)> onError; - boost::signal<void ()> onConnected; + public: + boost::signals2::signal<void (std::shared_ptr<TLSError>)> onError; + boost::signals2::signal<void ()> onConnected; - private: - TLSContext* context; - }; + private: + std::unique_ptr<TLSContext> context_; + }; } diff --git a/Swiften/StreamStack/UnitTest/StreamStackTest.cpp b/Swiften/StreamStack/UnitTest/StreamStackTest.cpp index 213948a..b074736 100644 --- a/Swiften/StreamStack/UnitTest/StreamStackTest.cpp +++ b/Swiften/StreamStack/UnitTest/StreamStackTest.cpp @@ -1,182 +1,176 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> -#include <QA/Checker/IO.h> - +#include <memory> #include <vector> + #include <boost/bind.hpp> -#include <boost/smart_ptr.hpp> + +#include <QA/Checker/IO.h> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Concat.h> -#include <Swiften/StreamStack/StreamStack.h> -#include <Swiften/StreamStack/LowLayer.h> -#include <Swiften/StreamStack/XMPPLayer.h> -#include <Swiften/StreamStack/StreamLayer.h> -#include <Swiften/Parser/PlatformXMLParserFactory.h> #include <Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h> +#include <Swiften/Parser/PlatformXMLParserFactory.h> #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/StreamStack/LowLayer.h> +#include <Swiften/StreamStack/StreamLayer.h> +#include <Swiften/StreamStack/StreamStack.h> +#include <Swiften/StreamStack/XMPPLayer.h> using namespace Swift; class StreamStackTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StreamStackTest); - CPPUNIT_TEST(testWriteData_NoIntermediateStreamStack); - CPPUNIT_TEST(testWriteData_OneIntermediateStream); - CPPUNIT_TEST(testWriteData_TwoIntermediateStreamStack); - CPPUNIT_TEST(testReadData_NoIntermediateStreamStack); - CPPUNIT_TEST(testReadData_OneIntermediateStream); - CPPUNIT_TEST(testReadData_TwoIntermediateStreamStack); - CPPUNIT_TEST(testAddLayer_ExistingOnWriteDataSlot); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - physicalStream_ = new TestLowLayer(); - xmppStream_ = new XMPPLayer(&parserFactories_, &serializers_, &xmlParserFactory_, ClientStreamType); - elementsReceived_ = 0; - dataWriteReceived_ = 0; - } - - void tearDown() { - delete physicalStream_; - delete xmppStream_; - } - - void testWriteData_NoIntermediateStreamStack() { - StreamStack testling(xmppStream_, physicalStream_); - - xmppStream_->writeData("foo"); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), physicalStream_->data_.size()); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("foo"), physicalStream_->data_[0]); - } - - void testWriteData_OneIntermediateStream() { - StreamStack testling(xmppStream_, physicalStream_); - boost::shared_ptr<MyStreamLayer> xStream(new MyStreamLayer("X")); - testling.addLayer(xStream.get()); - - xmppStream_->writeData("foo"); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), physicalStream_->data_.size()); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("Xfoo"), physicalStream_->data_[0]); - } - - void testWriteData_TwoIntermediateStreamStack() { - StreamStack testling(xmppStream_, physicalStream_); - boost::shared_ptr<MyStreamLayer> xStream(new MyStreamLayer("X")); - boost::shared_ptr<MyStreamLayer> yStream(new MyStreamLayer("Y")); - testling.addLayer(xStream.get()); - testling.addLayer(yStream.get()); - - xmppStream_->writeData("foo"); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), physicalStream_->data_.size()); - CPPUNIT_ASSERT_EQUAL(createSafeByteArray("XYfoo"), physicalStream_->data_[0]); - } - - void testReadData_NoIntermediateStreamStack() { - StreamStack testling(xmppStream_, physicalStream_); - xmppStream_->onElement.connect(boost::bind(&StreamStackTest::handleElement, this, _1)); - - physicalStream_->onDataRead(createSafeByteArray("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'><presence/>")); - - CPPUNIT_ASSERT_EQUAL(1, elementsReceived_); - } - - void testReadData_OneIntermediateStream() { - StreamStack testling(xmppStream_, physicalStream_); - xmppStream_->onElement.connect(boost::bind(&StreamStackTest::handleElement, this, _1)); - boost::shared_ptr<MyStreamLayer> xStream(new MyStreamLayer("<")); - testling.addLayer(xStream.get()); - - physicalStream_->onDataRead(createSafeByteArray("stream:stream xmlns:stream='http://etherx.jabber.org/streams'><presence/>")); - - CPPUNIT_ASSERT_EQUAL(1, elementsReceived_); - } - - void testReadData_TwoIntermediateStreamStack() { - StreamStack testling(xmppStream_, physicalStream_); - xmppStream_->onElement.connect(boost::bind(&StreamStackTest::handleElement, this, _1)); - boost::shared_ptr<MyStreamLayer> xStream(new MyStreamLayer("s")); - boost::shared_ptr<MyStreamLayer> yStream(new MyStreamLayer("<")); - testling.addLayer(xStream.get()); - testling.addLayer(yStream.get()); - - physicalStream_->onDataRead(createSafeByteArray("tream:stream xmlns:stream='http://etherx.jabber.org/streams'><presence/>")); - - CPPUNIT_ASSERT_EQUAL(1, elementsReceived_); - } - - void testAddLayer_ExistingOnWriteDataSlot() { - StreamStack testling(xmppStream_, physicalStream_); - xmppStream_->onWriteData.connect(boost::bind(&StreamStackTest::handleWriteData, this, _1)); - boost::shared_ptr<MyStreamLayer> xStream(new MyStreamLayer("X")); - testling.addLayer(xStream.get()); - - xmppStream_->writeData("foo"); - - CPPUNIT_ASSERT_EQUAL(1, dataWriteReceived_); - } - - void handleElement(boost::shared_ptr<Element>) { - ++elementsReceived_; - } - - void handleWriteData(const SafeByteArray&) { - ++dataWriteReceived_; - } - - private: - class MyStreamLayer : public StreamLayer { - public: - MyStreamLayer(const std::string& prepend) : prepend_(prepend) { - } - - virtual void writeData(const SafeByteArray& data) { - writeDataToChildLayer(concat(createSafeByteArray(prepend_), data)); - } - - virtual void handleDataRead(const SafeByteArray& data) { - writeDataToParentLayer(concat(createSafeByteArray(prepend_), data)); - } - - private: - std::string prepend_; - }; - - class TestLowLayer : public LowLayer { - public: - TestLowLayer() { - } - - virtual void writeData(const SafeByteArray& data) { - data_.push_back(data); - } - - void onDataRead(const SafeByteArray& data) { - writeDataToParentLayer(data); - } - - std::vector<SafeByteArray> data_; - }; - - - private: - FullPayloadParserFactoryCollection parserFactories_; - FullPayloadSerializerCollection serializers_; - TestLowLayer* physicalStream_; - PlatformXMLParserFactory xmlParserFactory_; - XMPPLayer* xmppStream_; - int elementsReceived_; - int dataWriteReceived_; + CPPUNIT_TEST_SUITE(StreamStackTest); + CPPUNIT_TEST(testWriteData_NoIntermediateStreamStack); + CPPUNIT_TEST(testWriteData_OneIntermediateStream); + CPPUNIT_TEST(testWriteData_TwoIntermediateStreamStack); + CPPUNIT_TEST(testReadData_NoIntermediateStreamStack); + CPPUNIT_TEST(testReadData_OneIntermediateStream); + CPPUNIT_TEST(testReadData_TwoIntermediateStreamStack); + CPPUNIT_TEST(testAddLayer_ExistingOnWriteDataSlot); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + testling_ = std::make_unique<StreamStack>(std::make_unique<XMPPLayer>(&parserFactories_, &serializers_, &xmlParserFactory_, ClientStreamType), std::make_unique<TestLowLayer>()); + physicalStream_ = testling_->getLayer<TestLowLayer>(); + xmppStream_ = testling_->getLayer<XMPPLayer>(); + elementsReceived_ = 0; + dataWriteReceived_ = 0; + } + + void tearDown() { + } + + void testWriteData_NoIntermediateStreamStack() { + + xmppStream_->writeData("foo"); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), physicalStream_->data_.size()); + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("foo"), physicalStream_->data_[0]); + } + + void testWriteData_OneIntermediateStream() { + std::unique_ptr<MyStreamLayer> xStream(new MyStreamLayer("X")); + testling_->addLayer(std::move(xStream)); + + xmppStream_->writeData("foo"); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), physicalStream_->data_.size()); + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("Xfoo"), physicalStream_->data_[0]); + } + + void testWriteData_TwoIntermediateStreamStack() { + std::unique_ptr<MyStreamLayer> xStream(new MyStreamLayer("X")); + std::unique_ptr<MyStreamLayer> yStream(new MyStreamLayer("Y")); + testling_->addLayer(std::move(xStream)); + testling_->addLayer(std::move(yStream)); + + xmppStream_->writeData("foo"); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), physicalStream_->data_.size()); + CPPUNIT_ASSERT_EQUAL(createSafeByteArray("XYfoo"), physicalStream_->data_[0]); + } + + void testReadData_NoIntermediateStreamStack() { + xmppStream_->onElement.connect(boost::bind(&StreamStackTest::handleElement, this, _1)); + + physicalStream_->onDataRead(createSafeByteArray("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'><presence/>")); + + CPPUNIT_ASSERT_EQUAL(1, elementsReceived_); + } + + void testReadData_OneIntermediateStream() { + xmppStream_->onElement.connect(boost::bind(&StreamStackTest::handleElement, this, _1)); + std::unique_ptr<MyStreamLayer> xStream(new MyStreamLayer("<")); + testling_->addLayer(std::move(xStream)); + + physicalStream_->onDataRead(createSafeByteArray("stream:stream xmlns:stream='http://etherx.jabber.org/streams'><presence/>")); + + CPPUNIT_ASSERT_EQUAL(1, elementsReceived_); + } + + void testReadData_TwoIntermediateStreamStack() { + xmppStream_->onElement.connect(boost::bind(&StreamStackTest::handleElement, this, _1)); + std::unique_ptr<MyStreamLayer> xStream(new MyStreamLayer("s")); + std::unique_ptr<MyStreamLayer> yStream(new MyStreamLayer("<")); + testling_->addLayer(std::move(xStream)); + testling_->addLayer(std::move(yStream)); + + physicalStream_->onDataRead(createSafeByteArray("tream:stream xmlns:stream='http://etherx.jabber.org/streams'><presence/>")); + + CPPUNIT_ASSERT_EQUAL(1, elementsReceived_); + } + + void testAddLayer_ExistingOnWriteDataSlot() { + xmppStream_->onWriteData.connect(boost::bind(&StreamStackTest::handleWriteData, this, _1)); + std::unique_ptr<MyStreamLayer> xStream(new MyStreamLayer("X")); + testling_->addLayer(std::move(xStream)); + + xmppStream_->writeData("foo"); + + CPPUNIT_ASSERT_EQUAL(1, dataWriteReceived_); + } + + void handleElement(std::shared_ptr<ToplevelElement>) { + ++elementsReceived_; + } + + void handleWriteData(const SafeByteArray&) { + ++dataWriteReceived_; + } + + private: + class MyStreamLayer : public StreamLayer { + public: + MyStreamLayer(const std::string& prepend) : prepend_(prepend) { + } + + virtual void writeData(const SafeByteArray& data) { + writeDataToChildLayer(concat(createSafeByteArray(prepend_), data)); + } + + virtual void handleDataRead(const SafeByteArray& data) { + writeDataToParentLayer(concat(createSafeByteArray(prepend_), data)); + } + + private: + std::string prepend_; + }; + + class TestLowLayer : public LowLayer { + public: + TestLowLayer() { + } + + virtual void writeData(const SafeByteArray& data) { + data_.push_back(data); + } + + void onDataRead(const SafeByteArray& data) { + writeDataToParentLayer(data); + } + + std::vector<SafeByteArray> data_; + }; + + + private: + FullPayloadParserFactoryCollection parserFactories_; + FullPayloadSerializerCollection serializers_; + TestLowLayer* physicalStream_; + PlatformXMLParserFactory xmlParserFactory_; + XMPPLayer* xmppStream_; + std::unique_ptr<StreamStack> testling_; + int elementsReceived_; + int dataWriteReceived_; }; CPPUNIT_TEST_SUITE_REGISTRATION(StreamStackTest); diff --git a/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp b/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp index a6098f1..6d1d537 100644 --- a/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp +++ b/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp @@ -1,141 +1,143 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <vector> + #include <boost/bind.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/Elements/ProtocolHeader.h> -#include <Swiften/Elements/Presence.h> #include <Swiften/Base/ByteArray.h> -#include <Swiften/StreamStack/XMPPLayer.h> -#include <Swiften/StreamStack/LowLayer.h> -#include <Swiften/Parser/PlatformXMLParserFactory.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/ProtocolHeader.h> #include <Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h> +#include <Swiften/Parser/PlatformXMLParserFactory.h> #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/StreamStack/LowLayer.h> +#include <Swiften/StreamStack/XMPPLayer.h> using namespace Swift; class XMPPLayerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(XMPPLayerTest); - CPPUNIT_TEST(testParseData_Error); - CPPUNIT_TEST(testResetParser); - CPPUNIT_TEST(testResetParser_FromSlot); - CPPUNIT_TEST(testWriteHeader); - CPPUNIT_TEST(testWriteElement); - CPPUNIT_TEST(testWriteFooter); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - lowLayer_ = new DummyLowLayer(); - testling_ = new XMPPLayerExposed(&parserFactories_, &serializers_, &xmlParserFactory_, ClientStreamType); - testling_->setChildLayer(lowLayer_); - elementsReceived_ = 0; - errorReceived_ = 0; - } - - void tearDown() { - delete testling_; - delete lowLayer_; - } - - void testParseData_Error() { - testling_->onError.connect(boost::bind(&XMPPLayerTest::handleError, this)); - - testling_->handleDataRead(createSafeByteArray("<iq>")); - - CPPUNIT_ASSERT_EQUAL(1, errorReceived_); - } - - void testResetParser() { - testling_->onElement.connect(boost::bind(&XMPPLayerTest::handleElement, this, _1)); - testling_->onError.connect(boost::bind(&XMPPLayerTest::handleError, this)); - - testling_->handleDataRead(createSafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" >")); - testling_->resetParser(); - testling_->handleDataRead(createSafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" >")); - testling_->handleDataRead(createSafeByteArray("<presence/>")); - - CPPUNIT_ASSERT_EQUAL(1, elementsReceived_); - CPPUNIT_ASSERT_EQUAL(0, errorReceived_); - } - - void testResetParser_FromSlot() { - testling_->onElement.connect(boost::bind(&XMPPLayerTest::handleElementAndReset, this, _1)); - testling_->handleDataRead(createSafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" ><presence/>")); - testling_->handleDataRead(createSafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" ><presence/>")); - - CPPUNIT_ASSERT_EQUAL(2, elementsReceived_); - CPPUNIT_ASSERT_EQUAL(0, errorReceived_); - } - - void testWriteHeader() { - ProtocolHeader header; - header.setTo("example.com"); - testling_->writeHeader(header); - - CPPUNIT_ASSERT_EQUAL(std::string("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" to=\"example.com\" version=\"1.0\">"), lowLayer_->writtenData); - } - - void testWriteElement() { - testling_->writeElement(boost::make_shared<Presence>()); - - CPPUNIT_ASSERT_EQUAL(std::string("<presence/>"), lowLayer_->writtenData); - } - - void testWriteFooter() { - testling_->writeFooter(); - - CPPUNIT_ASSERT_EQUAL(std::string("</stream:stream>"), lowLayer_->writtenData); - } - - void handleElement(boost::shared_ptr<Element>) { - ++elementsReceived_; - } - - void handleElementAndReset(boost::shared_ptr<Element>) { - ++elementsReceived_; - testling_->resetParser(); - } - - void handleError() { - ++errorReceived_; - } - - private: - class XMPPLayerExposed : public XMPPLayer { - public: - XMPPLayerExposed( - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - XMLParserFactory* xmlParserFactory, - StreamType streamType) : XMPPLayer(payloadParserFactories, payloadSerializers, xmlParserFactory, streamType) {} - - using XMPPLayer::handleDataRead; - using HighLayer::setChildLayer; - }; - - class DummyLowLayer : public LowLayer { - public: - virtual void writeData(const SafeByteArray& data) { - writtenData += byteArrayToString(ByteArray(data.begin(), data.end())); - } - - std::string writtenData; - }; - - FullPayloadParserFactoryCollection parserFactories_; - FullPayloadSerializerCollection serializers_; - DummyLowLayer* lowLayer_; - XMPPLayerExposed* testling_; - PlatformXMLParserFactory xmlParserFactory_; - int elementsReceived_; - int errorReceived_; + CPPUNIT_TEST_SUITE(XMPPLayerTest); + CPPUNIT_TEST(testParseData_Error); + CPPUNIT_TEST(testResetParser); + CPPUNIT_TEST(testResetParser_FromSlot); + CPPUNIT_TEST(testWriteHeader); + CPPUNIT_TEST(testWriteElement); + CPPUNIT_TEST(testWriteFooter); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + lowLayer_ = new DummyLowLayer(); + testling_ = new XMPPLayerExposed(&parserFactories_, &serializers_, &xmlParserFactory_, ClientStreamType); + testling_->setChildLayer(lowLayer_); + elementsReceived_ = 0; + errorReceived_ = 0; + } + + void tearDown() { + delete testling_; + delete lowLayer_; + } + + void testParseData_Error() { + testling_->onError.connect(boost::bind(&XMPPLayerTest::handleError, this)); + + testling_->handleDataRead(createSafeByteArray("<iq>")); + + CPPUNIT_ASSERT_EQUAL(1, errorReceived_); + } + + void testResetParser() { + testling_->onElement.connect(boost::bind(&XMPPLayerTest::handleElement, this, _1)); + testling_->onError.connect(boost::bind(&XMPPLayerTest::handleError, this)); + + testling_->handleDataRead(createSafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" >")); + testling_->resetParser(); + testling_->handleDataRead(createSafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" >")); + testling_->handleDataRead(createSafeByteArray("<presence/>")); + + CPPUNIT_ASSERT_EQUAL(1, elementsReceived_); + CPPUNIT_ASSERT_EQUAL(0, errorReceived_); + } + + void testResetParser_FromSlot() { + testling_->onElement.connect(boost::bind(&XMPPLayerTest::handleElementAndReset, this, _1)); + testling_->handleDataRead(createSafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" ><presence/>")); + testling_->handleDataRead(createSafeByteArray("<stream:stream to=\"example.com\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" ><presence/>")); + + CPPUNIT_ASSERT_EQUAL(2, elementsReceived_); + CPPUNIT_ASSERT_EQUAL(0, errorReceived_); + } + + void testWriteHeader() { + ProtocolHeader header; + header.setTo("example.com"); + testling_->writeHeader(header); + + CPPUNIT_ASSERT_EQUAL(std::string("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" to=\"example.com\" version=\"1.0\">"), lowLayer_->writtenData); + } + + void testWriteElement() { + testling_->writeElement(std::make_shared<Presence>()); + + CPPUNIT_ASSERT_EQUAL(std::string("<presence/>"), lowLayer_->writtenData); + } + + void testWriteFooter() { + testling_->writeFooter(); + + CPPUNIT_ASSERT_EQUAL(std::string("</stream:stream>"), lowLayer_->writtenData); + } + + void handleElement(std::shared_ptr<ToplevelElement>) { + ++elementsReceived_; + } + + void handleElementAndReset(std::shared_ptr<ToplevelElement>) { + ++elementsReceived_; + testling_->resetParser(); + } + + void handleError() { + ++errorReceived_; + } + + private: + class XMPPLayerExposed : public XMPPLayer { + public: + XMPPLayerExposed( + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + XMLParserFactory* xmlParserFactory, + StreamType streamType) : XMPPLayer(payloadParserFactories, payloadSerializers, xmlParserFactory, streamType) {} + + using XMPPLayer::handleDataRead; + using HighLayer::setChildLayer; + }; + + class DummyLowLayer : public LowLayer { + public: + virtual void writeData(const SafeByteArray& data) { + writtenData += byteArrayToString(ByteArray(data.begin(), data.end())); + } + + std::string writtenData; + }; + + FullPayloadParserFactoryCollection parserFactories_; + FullPayloadSerializerCollection serializers_; + DummyLowLayer* lowLayer_; + XMPPLayerExposed* testling_; + PlatformXMLParserFactory xmlParserFactory_; + int elementsReceived_; + int errorReceived_; }; CPPUNIT_TEST_SUITE_REGISTRATION(XMPPLayerTest); diff --git a/Swiften/StreamStack/WhitespacePingLayer.cpp b/Swiften/StreamStack/WhitespacePingLayer.cpp index b14f3a2..7c8301e 100644 --- a/Swiften/StreamStack/WhitespacePingLayer.cpp +++ b/Swiften/StreamStack/WhitespacePingLayer.cpp @@ -1,47 +1,56 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StreamStack/WhitespacePingLayer.h> #include <boost/bind.hpp> -#include <Swiften/Network/TimerFactory.h> +#include <Swiften/Base/Log.h> #include <Swiften/Network/Timer.h> +#include <Swiften/Network/TimerFactory.h> namespace Swift { static const int TIMEOUT_MILLISECONDS = 60000; WhitespacePingLayer::WhitespacePingLayer(TimerFactory* timerFactory) : isActive(false) { - timer = timerFactory->createTimer(TIMEOUT_MILLISECONDS); - timer->onTick.connect(boost::bind(&WhitespacePingLayer::handleTimerTick, this)); + timer = timerFactory->createTimer(TIMEOUT_MILLISECONDS); + timer->onTick.connect(boost::bind(&WhitespacePingLayer::handleTimerTick, this)); +} + +WhitespacePingLayer::~WhitespacePingLayer() { + SWIFT_LOG_ASSERT(!isActive, debug) << "WhitespacePingLayer still active at destruction."; + if (isActive) { + timer->stop(); + } + timer->onTick.disconnect(boost::bind(&WhitespacePingLayer::handleTimerTick, this)); } void WhitespacePingLayer::writeData(const SafeByteArray& data) { - writeDataToChildLayer(data); + writeDataToChildLayer(data); } void WhitespacePingLayer::handleDataRead(const SafeByteArray& data) { - writeDataToParentLayer(data); + writeDataToParentLayer(data); } void WhitespacePingLayer::handleTimerTick() { - timer->stop(); - writeDataToChildLayer(createSafeByteArray(" ")); - timer->start(); + timer->stop(); + writeDataToChildLayer(createSafeByteArray(" ")); + timer->start(); } void WhitespacePingLayer::setActive() { - isActive = true; - timer->start(); + isActive = true; + timer->start(); } void WhitespacePingLayer::setInactive() { - timer->stop(); - isActive = false; + timer->stop(); + isActive = false; } } diff --git a/Swiften/StreamStack/WhitespacePingLayer.h b/Swiften/StreamStack/WhitespacePingLayer.h index 1435842..c9ffe92 100644 --- a/Swiften/StreamStack/WhitespacePingLayer.h +++ b/Swiften/StreamStack/WhitespacePingLayer.h @@ -1,38 +1,41 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> +#include <Swiften/Base/API.h> #include <Swiften/StreamStack/StreamLayer.h> namespace Swift { - class Timer; - class TimerFactory; - - class WhitespacePingLayer : public StreamLayer, boost::noncopyable { - public: - WhitespacePingLayer(TimerFactory* timerFactory); - - void setActive(); - void setInactive(); - void writeData(const SafeByteArray& data); - void handleDataRead(const SafeByteArray& data); - - bool getIsActive() const { - return isActive; - } - - private: - void handleTimerTick(); - - private: - bool isActive; - boost::shared_ptr<Timer> timer; - }; + class Timer; + class TimerFactory; + + class SWIFTEN_API WhitespacePingLayer : public StreamLayer, boost::noncopyable { + public: + WhitespacePingLayer(TimerFactory* timerFactory); + virtual ~WhitespacePingLayer(); + + void setActive(); + void setInactive(); + void writeData(const SafeByteArray& data); + void handleDataRead(const SafeByteArray& data); + + bool getIsActive() const { + return isActive; + } + + private: + void handleTimerTick(); + + private: + bool isActive; + std::shared_ptr<Timer> timer; + }; } diff --git a/Swiften/StreamStack/XMPPLayer.cpp b/Swiften/StreamStack/XMPPLayer.cpp index 94afcf9..982d13f 100644 --- a/Swiften/StreamStack/XMPPLayer.cpp +++ b/Swiften/StreamStack/XMPPLayer.cpp @@ -1,97 +1,101 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StreamStack/XMPPLayer.h> + +#include <Swiften/Elements/ProtocolHeader.h> #include <Swiften/Parser/XMPPParser.h> #include <Swiften/Serializer/XMPPSerializer.h> -#include <Swiften/Elements/ProtocolHeader.h> namespace Swift { XMPPLayer::XMPPLayer( - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - XMLParserFactory* xmlParserFactory, - StreamType streamType) : - payloadParserFactories_(payloadParserFactories), - payloadSerializers_(payloadSerializers), - xmlParserFactory_(xmlParserFactory), - resetParserAfterParse_(false), - inParser_(false) { - xmppParser_ = new XMPPParser(this, payloadParserFactories_, xmlParserFactory); - xmppSerializer_ = new XMPPSerializer(payloadSerializers_, streamType); + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + XMLParserFactory* xmlParserFactory, + StreamType streamType, + bool setExplictNSonTopLevelElements) : + payloadParserFactories_(payloadParserFactories), + payloadSerializers_(payloadSerializers), + xmlParserFactory_(xmlParserFactory), + setExplictNSonTopLevelElements_(setExplictNSonTopLevelElements), + resetParserAfterParse_(false), + inParser_(false) { + xmppParser_ = new XMPPParser(this, payloadParserFactories_, xmlParserFactory); + xmppSerializer_ = new XMPPSerializer(payloadSerializers_, streamType, setExplictNSonTopLevelElements); } XMPPLayer::~XMPPLayer() { - delete xmppSerializer_; - delete xmppParser_; + delete xmppSerializer_; + delete xmppParser_; } void XMPPLayer::writeHeader(const ProtocolHeader& header) { - writeDataInternal(createSafeByteArray(xmppSerializer_->serializeHeader(header))); + writeDataInternal(createSafeByteArray(xmppSerializer_->serializeHeader(header))); } void XMPPLayer::writeFooter() { - writeDataInternal(createSafeByteArray(xmppSerializer_->serializeFooter())); + writeDataInternal(createSafeByteArray(xmppSerializer_->serializeFooter())); } -void XMPPLayer::writeElement(boost::shared_ptr<Element> element) { - writeDataInternal(xmppSerializer_->serializeElement(element)); +void XMPPLayer::writeElement(std::shared_ptr<ToplevelElement> element) { + writeDataInternal(xmppSerializer_->serializeElement(element)); } void XMPPLayer::writeData(const std::string& data) { - writeDataInternal(createSafeByteArray(data)); + writeDataInternal(createSafeByteArray(data)); } void XMPPLayer::writeDataInternal(const SafeByteArray& data) { - onWriteData(data); - writeDataToChildLayer(data); + onWriteData(data); + writeDataToChildLayer(data); } void XMPPLayer::handleDataRead(const SafeByteArray& data) { - onDataRead(data); - inParser_ = true; - // FIXME: Converting to unsafe string. Should be ok, since we don't take passwords - // from the stream in clients. If servers start using this, and require safe storage, - // we need to fix this. - if (!xmppParser_->parse(byteArrayToString(ByteArray(data.begin(), data.end())))) { - inParser_ = false; - onError(); - return; - } - inParser_ = false; - if (resetParserAfterParse_) { - doResetParser(); - } + onDataRead(data); + inParser_ = true; + // FIXME: Converting to unsafe string. Should be ok, since we don't take passwords + // from the stream in clients. If servers start using this, and require safe storage, + // we need to fix this. + if (!xmppParser_->parse(byteArrayToString(ByteArray(data.begin(), data.end())))) { + inParser_ = false; + onError(); + return; + } + inParser_ = false; + if (resetParserAfterParse_) { + doResetParser(); + } } void XMPPLayer::doResetParser() { - delete xmppParser_; - xmppParser_ = new XMPPParser(this, payloadParserFactories_, xmlParserFactory_); - resetParserAfterParse_ = false; + delete xmppParser_; + xmppParser_ = new XMPPParser(this, payloadParserFactories_, xmlParserFactory_); + resetParserAfterParse_ = false; } void XMPPLayer::handleStreamStart(const ProtocolHeader& header) { - onStreamStart(header); + onStreamStart(header); } -void XMPPLayer::handleElement(boost::shared_ptr<Element> stanza) { - onElement(stanza); +void XMPPLayer::handleElement(std::shared_ptr<ToplevelElement> stanza) { + onElement(stanza); } void XMPPLayer::handleStreamEnd() { + onStreamEnd(); } void XMPPLayer::resetParser() { - if (inParser_) { - resetParserAfterParse_ = true; - } - else { - doResetParser(); - } + if (inParser_) { + resetParserAfterParse_ = true; + } + else { + doResetParser(); + } } } diff --git a/Swiften/StreamStack/XMPPLayer.h b/Swiften/StreamStack/XMPPLayer.h index f0e88aa..f0b5afb 100644 --- a/Swiften/StreamStack/XMPPLayer.h +++ b/Swiften/StreamStack/XMPPLayer.h @@ -1,73 +1,77 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <Swiften/Base/boost_bsignals.h> +#include <memory> + #include <boost/noncopyable.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/StreamStack/HighLayer.h> #include <Swiften/Base/SafeByteArray.h> -#include <Swiften/Elements/Element.h> #include <Swiften/Elements/StreamType.h> +#include <Swiften/Elements/ToplevelElement.h> #include <Swiften/Parser/XMPPParserClient.h> +#include <Swiften/StreamStack/HighLayer.h> namespace Swift { - class ProtocolHeader; - class XMPPParser; - class PayloadParserFactoryCollection; - class XMPPSerializer; - class PayloadSerializerCollection; - class XMLParserFactory; - class BOSHSessionStream; + class ProtocolHeader; + class XMPPParser; + class PayloadParserFactoryCollection; + class XMPPSerializer; + class PayloadSerializerCollection; + class XMLParserFactory; + class BOSHSessionStream; - class SWIFTEN_API XMPPLayer : public XMPPParserClient, public HighLayer, boost::noncopyable { - friend class BOSHSessionStream; - public: - XMPPLayer( - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers, - XMLParserFactory* xmlParserFactory, - StreamType streamType); - ~XMPPLayer(); + class SWIFTEN_API XMPPLayer : public XMPPParserClient, public HighLayer, boost::noncopyable { + friend class BOSHSessionStream; + public: + XMPPLayer( + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + XMLParserFactory* xmlParserFactory, + StreamType streamType, + bool setExplictNSonTopLevelElements = false); + virtual ~XMPPLayer(); - void writeHeader(const ProtocolHeader& header); - void writeFooter(); - void writeElement(boost::shared_ptr<Element>); - void writeData(const std::string& data); + void writeHeader(const ProtocolHeader& header); + void writeFooter(); + void writeElement(std::shared_ptr<ToplevelElement>); + void writeData(const std::string& data); - void resetParser(); + void resetParser(); - protected: - void handleDataRead(const SafeByteArray& data); - void writeDataInternal(const SafeByteArray& data); + protected: + void handleDataRead(const SafeByteArray& data); + void writeDataInternal(const SafeByteArray& data); - public: - boost::signal<void (const ProtocolHeader&)> onStreamStart; - boost::signal<void (boost::shared_ptr<Element>)> onElement; - boost::signal<void (const SafeByteArray&)> onWriteData; - boost::signal<void (const SafeByteArray&)> onDataRead; - boost::signal<void ()> onError; + public: + boost::signals2::signal<void (const ProtocolHeader&)> onStreamStart; + boost::signals2::signal<void ()> onStreamEnd; + boost::signals2::signal<void (std::shared_ptr<ToplevelElement>)> onElement; + boost::signals2::signal<void (const SafeByteArray&)> onWriteData; + boost::signals2::signal<void (const SafeByteArray&)> onDataRead; + boost::signals2::signal<void ()> onError; - private: - void handleStreamStart(const ProtocolHeader&); - void handleElement(boost::shared_ptr<Element>); - void handleStreamEnd(); + private: + void handleStreamStart(const ProtocolHeader&); + void handleElement(std::shared_ptr<ToplevelElement>); + void handleStreamEnd(); - void doResetParser(); + void doResetParser(); - private: - PayloadParserFactoryCollection* payloadParserFactories_; - XMPPParser* xmppParser_; - PayloadSerializerCollection* payloadSerializers_; - XMLParserFactory* xmlParserFactory_; - XMPPSerializer* xmppSerializer_; - bool resetParserAfterParse_; - bool inParser_; - }; + private: + PayloadParserFactoryCollection* payloadParserFactories_; + XMPPParser* xmppParser_; + PayloadSerializerCollection* payloadSerializers_; + XMLParserFactory* xmlParserFactory_; + XMPPSerializer* xmppSerializer_; + bool setExplictNSonTopLevelElements_; + bool resetParserAfterParse_; + bool inParser_; + }; } diff --git a/Swiften/StringCodecs/Base64.cpp b/Swiften/StringCodecs/Base64.cpp index e1d70a0..7b5f402 100644 --- a/Swiften/StringCodecs/Base64.cpp +++ b/Swiften/StringCodecs/Base64.cpp @@ -1,101 +1,106 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StringCodecs/Base64.h> +#include <stddef.h> + +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/SafeByteArray.h> + #pragma clang diagnostic ignored "-Wconversion" using namespace Swift; namespace { - const char* encodeMap = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - const unsigned char decodeMap[255] = { - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 62, 255, 255, 255, 63, - 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 255, 255, 255, 255, 255, 255, - 255, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 255, 255, 255, 255, 255, - 255, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 255, 255, 255, 255, 255 - }; + const char* encodeMap = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const unsigned char decodeMap[255] = { + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 62, 255, 255, 255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 255, 255, 255, 255, 255, 255, + 255, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 255, 255, 255, 255, 255, + 255, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 255, 255, 255, 255, 255 + }; - template<typename ResultType, typename InputType> - ResultType encodeDetail(const InputType& input) { - ResultType result; - size_t i = 0; - for (; i < (input.size()/3)*3; i += 3) { - unsigned int c = input[i+2] | (input[i+1]<<8) | (input[i]<<16); - result.push_back(encodeMap[(c&0xFC0000)>>18]); - result.push_back(encodeMap[(c&0x3F000)>>12]); - result.push_back(encodeMap[(c&0xFC0)>>6]); - result.push_back(encodeMap[c&0x3F]); - } - if (input.size() % 3 == 2) { - unsigned int c = (input[i+1]<<8) | (input[i]<<16); - result.push_back(encodeMap[(c&0xFC0000)>>18]); - result.push_back(encodeMap[(c&0x3F000)>>12]); - result.push_back(encodeMap[(c&0xFC0)>>6]); - result.push_back('='); - } - else if (input.size() % 3 == 1) { - unsigned int c = input[i]<<16; - result.push_back(encodeMap[(c&0xFC0000)>>18]); - result.push_back(encodeMap[(c&0x3F000)>>12]); - result.push_back('='); - result.push_back('='); - } - return result; - } + template<typename ResultType, typename InputType> + ResultType encodeDetail(const InputType& input) { + ResultType result; + size_t i = 0; + for (; i < (input.size()/3)*3; i += 3) { + unsigned int c = input[i+2] | (input[i+1]<<8) | (input[i]<<16); + result.push_back(encodeMap[(c&0xFC0000)>>18]); + result.push_back(encodeMap[(c&0x3F000)>>12]); + result.push_back(encodeMap[(c&0xFC0)>>6]); + result.push_back(encodeMap[c&0x3F]); + } + if (input.size() % 3 == 2) { + unsigned int c = (input[i+1]<<8) | (input[i]<<16); + result.push_back(encodeMap[(c&0xFC0000)>>18]); + result.push_back(encodeMap[(c&0x3F000)>>12]); + result.push_back(encodeMap[(c&0xFC0)>>6]); + result.push_back('='); + } + else if (input.size() % 3 == 1) { + unsigned int c = input[i]<<16; + result.push_back(encodeMap[(c&0xFC0000)>>18]); + result.push_back(encodeMap[(c&0x3F000)>>12]); + result.push_back('='); + result.push_back('='); + } + return result; + } } std::string Base64::encode(const ByteArray& s) { - return encodeDetail<std::string>(s); + return encodeDetail<std::string>(s); } SafeByteArray Base64::encode(const SafeByteArray& s) { - return encodeDetail<SafeByteArray>(s); + return encodeDetail<SafeByteArray>(s); } ByteArray Base64::decode(const std::string& input) { - ByteArray result; + ByteArray result; - if (input.size() % 4) { - return ByteArray(); - } - for (size_t i = 0; i < input.size(); i += 4) { - unsigned char c1 = input[i+0]; - unsigned char c2 = input[i+1]; - unsigned char c3 = input[i+2]; - unsigned char c4 = input[i+3]; - if (c3 == '=') { - unsigned int c = (((decodeMap[c1]<<6)|decodeMap[c2])&0xFF0)>>4; - result.push_back(c); - } - else if (c4 == '=') { - unsigned int c = (((decodeMap[c1]<<12)|(decodeMap[c2]<<6)|decodeMap[c3])&0x3FFFC)>>2; - result.push_back((c&0xFF00) >> 8); - result.push_back(c&0xFF); - } - else { - unsigned int c = (decodeMap[c1]<<18) | (decodeMap[c2]<<12) | (decodeMap[c3]<<6) | decodeMap[c4]; - result.push_back((c&0xFF0000) >> 16); - result.push_back((c&0xFF00) >> 8); - result.push_back(c&0xFF); - } - } - return result; + if (input.size() % 4) { + return ByteArray(); + } + for (size_t i = 0; i < input.size(); i += 4) { + unsigned char c1 = input[i+0]; + unsigned char c2 = input[i+1]; + unsigned char c3 = input[i+2]; + unsigned char c4 = input[i+3]; + if (c3 == '=') { + unsigned int c = (((decodeMap[c1]<<6)|decodeMap[c2])&0xFF0)>>4; + result.push_back(c); + } + else if (c4 == '=') { + unsigned int c = (((decodeMap[c1]<<12)|(decodeMap[c2]<<6)|decodeMap[c3])&0x3FFFC)>>2; + result.push_back((c&0xFF00) >> 8); + result.push_back(c&0xFF); + } + else { + unsigned int c = (decodeMap[c1]<<18) | (decodeMap[c2]<<12) | (decodeMap[c3]<<6) | decodeMap[c4]; + result.push_back((c&0xFF0000) >> 16); + result.push_back((c&0xFF00) >> 8); + result.push_back(c&0xFF); + } + } + return result; } diff --git a/Swiften/StringCodecs/Base64.h b/Swiften/StringCodecs/Base64.h index 7d5ab51..fde27c0 100644 --- a/Swiften/StringCodecs/Base64.h +++ b/Swiften/StringCodecs/Base64.h @@ -1,12 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <string> #include <Swiften/Base/API.h> @@ -14,11 +13,11 @@ #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class SWIFTEN_API Base64 { - public: - static std::string encode(const ByteArray& s); - static SafeByteArray encode(const SafeByteArray& s); + class SWIFTEN_API Base64 { + public: + static std::string encode(const ByteArray& s); + static SafeByteArray encode(const SafeByteArray& s); - static ByteArray decode(const std::string &s); - }; + static ByteArray decode(const std::string &s); + }; } diff --git a/Swiften/StringCodecs/Hexify.cpp b/Swiften/StringCodecs/Hexify.cpp index ed2b2a3..907c240 100644 --- a/Swiften/StringCodecs/Hexify.cpp +++ b/Swiften/StringCodecs/Hexify.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/StringCodecs/Hexify.h> @@ -18,56 +18,56 @@ namespace Swift { std::string Hexify::hexify(unsigned char byte) { - std::ostringstream result; - result << std::hex << std::setw(2) << std::setfill('0') << boost::numeric_cast<unsigned int>(byte); - return std::string(result.str()); + std::ostringstream result; + result << std::hex << std::setw(2) << std::setfill('0') << boost::numeric_cast<unsigned int>(byte); + return std::string(result.str()); } std::string Hexify::hexify(const ByteArray& data) { - std::ostringstream result; - result << std::hex; + std::ostringstream result; + result << std::hex; - for (unsigned int i = 0; i < data.size(); ++i) { - result << std::setw(2) << std::setfill('0') << boost::numeric_cast<unsigned int>(static_cast<unsigned char>(data[i])); - } - return std::string(result.str()); + for (unsigned char i : data) { + result << std::setw(2) << std::setfill('0') << boost::numeric_cast<unsigned int>(static_cast<unsigned char>(i)); + } + return std::string(result.str()); } static const unsigned char map[256] = { - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 255, 255, 255, 255, 255, 255, - 255, 10, 11, 12, 13, 14, 15, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 10, 11, 12, 13, 14, 15, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255 + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255 }; ByteArray Hexify::unhexify(const std::string& in) { - if (in.size() % 2) { - return ByteArray(); - } + if (in.size() % 2) { + return ByteArray(); + } - ByteArray result(in.size() / 2); - for (size_t pos = 0; pos < in.size() - 1; pos += 2) { - unsigned char a = map[static_cast<size_t>(in[pos])]; - unsigned char b = map[static_cast<size_t>(in[pos+1])]; - if (a == 255 || b == 255) { - return ByteArray(); - } - result[pos/2] = (a<<4) | b; - } - return result; + ByteArray result(in.size() / 2); + for (size_t pos = 0; pos < in.size() - 1; pos += 2) { + unsigned char a = map[static_cast<size_t>(in[pos])]; + unsigned char b = map[static_cast<size_t>(in[pos+1])]; + if (a == 255 || b == 255) { + return ByteArray(); + } + result[pos/2] = (a<<4) | b; + } + return result; } } diff --git a/Swiften/StringCodecs/Hexify.h b/Swiften/StringCodecs/Hexify.h index 3b9a751..20027d3 100644 --- a/Swiften/StringCodecs/Hexify.h +++ b/Swiften/StringCodecs/Hexify.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,10 +10,10 @@ #include <Swiften/Base/ByteArray.h> namespace Swift { - class SWIFTEN_API Hexify { - public: - static std::string hexify(unsigned char byte); - static std::string hexify(const ByteArray& data); - static ByteArray unhexify(const std::string& hexstring); - }; + class SWIFTEN_API Hexify { + public: + static std::string hexify(unsigned char byte); + static std::string hexify(const ByteArray& data); + static ByteArray unhexify(const std::string& hexstring); + }; } diff --git a/Swiften/StringCodecs/PBKDF2.h b/Swiften/StringCodecs/PBKDF2.h index ae0bb17..2177b5f 100644 --- a/Swiften/StringCodecs/PBKDF2.h +++ b/Swiften/StringCodecs/PBKDF2.h @@ -1,30 +1,31 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Base/API.h> #include <Swiften/Base/Concat.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/Crypto/CryptoProvider.h> namespace Swift { - class PBKDF2 { - public: - static ByteArray encode(const SafeByteArray& password, const ByteArray& salt, int iterations, CryptoProvider* crypto) { - ByteArray u = crypto->getHMACSHA1(password, concat(salt, createByteArray("\0\0\0\1", 4))); - ByteArray result(u); - int i = 1; - while (i < iterations) { - u = crypto->getHMACSHA1(password, u); - for (unsigned int j = 0; j < u.size(); ++j) { - result[j] ^= u[j]; - } - ++i; - } - return result; - } - }; + class SWIFTEN_API PBKDF2 { + public: + static ByteArray encode(const SafeByteArray& password, const ByteArray& salt, int iterations, CryptoProvider* crypto) { + ByteArray u = crypto->getHMACSHA1(password, concat(salt, createByteArray("\0\0\0\1", 4))); + ByteArray result(u); + int i = 1; + while (i < iterations) { + u = crypto->getHMACSHA1(password, u); + for (unsigned int j = 0; j < u.size(); ++j) { + result[j] ^= u[j]; + } + ++i; + } + return result; + } + }; } diff --git a/Swiften/StringCodecs/SHA1_Windows.cpp b/Swiften/StringCodecs/SHA1_Windows.cpp index fef415a..ff02012 100644 --- a/Swiften/StringCodecs/SHA1_Windows.cpp +++ b/Swiften/StringCodecs/SHA1_Windows.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ @@ -10,95 +10,95 @@ #include <Swiften/StringCodecs/SHA1_Windows.h> namespace { - HCRYPTPROV context = 0; - - struct ContextDeleter { - ~ContextDeleter() { - if (context) { - CryptReleaseContext(context, 0); - context = 0; - } - } - } contextDeleter; + HCRYPTPROV context = 0; + + struct ContextDeleter { + ~ContextDeleter() { + if (context) { + CryptReleaseContext(context, 0); + context = 0; + } + } + } contextDeleter; } namespace Swift { SHA1::SHA1() : hash(NULL) { - if (!context) { - if (!CryptAcquireContext(&context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { -// DWORD error = GetLastError(); -// switch (error) { -// std::cerr << (long)error << std::endl; -// } -// assert(false); - context = 0; - } - } - - if (!CryptCreateHash(context, CALG_SHA1, 0, 0, &hash)) { - hash = NULL; - } + if (!context) { + if (!CryptAcquireContext(&context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { +// DWORD error = GetLastError(); +// switch (error) { +// std::cerr << (long)error << std::endl; +// } +// assert(false); + context = 0; + } + } + + if (!CryptCreateHash(context, CALG_SHA1, 0, 0, &hash)) { + hash = NULL; + } } SHA1::~SHA1() { - if (hash) { - CryptDestroyHash(hash); - } + if (hash) { + CryptDestroyHash(hash); + } } SHA1& SHA1::update(const std::vector<unsigned char>& data) { - return update(vecptr(data), data.size()); + return update(vecptr(data), data.size()); } SHA1& SHA1::update(const unsigned char* data, size_t dataSize) { - if (!hash || !context) { - return *this; - } - if (!CryptHashData(hash, const_cast<BYTE*>(data), dataSize, 0)) { -// DWORD error = GetLastError(); -// switch (error) { -// std::cerr << (long)error << std::endl; -// } -// assert(false); -// } - } - return *this; + if (!hash || !context) { + return *this; + } + if (!CryptHashData(hash, const_cast<BYTE*>(data), dataSize, 0)) { +// DWORD error = GetLastError(); +// switch (error) { +// std::cerr << (long)error << std::endl; +// } +// assert(false); +// } + } + return *this; } std::vector<unsigned char> SHA1::getHash() const { - if (!hash || !context) { - return std::vector<unsigned char>(); - } - std::vector<unsigned char> result; - DWORD hashLength = sizeof(DWORD); - DWORD hashSize; - CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0); - result.resize(static_cast<size_t>(hashSize)); - if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) { -// DWORD error = GetLastError(); -// switch (error) { -// std::cerr << (long)error << std::endl; -// } -// assert(false); - return std::vector<unsigned char>(); - } - result.resize(static_cast<size_t>(hashSize)); - return result; + if (!hash || !context) { + return std::vector<unsigned char>(); + } + std::vector<unsigned char> result; + DWORD hashLength = sizeof(DWORD); + DWORD hashSize; + CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0); + result.resize(static_cast<size_t>(hashSize)); + if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) { +// DWORD error = GetLastError(); +// switch (error) { +// std::cerr << (long)error << std::endl; +// } +// assert(false); + return std::vector<unsigned char>(); + } + result.resize(static_cast<size_t>(hashSize)); + return result; } ByteArray SHA1::getHash(const ByteArray& data) { - SHA1 hash; - hash.update(vecptr(data), data.size()); - return hash.getHash(); + SHA1 hash; + hash.update(vecptr(data), data.size()); + return hash.getHash(); } ByteArray SHA1::getHash(const SafeByteArray& data) { - SHA1 hash; - hash.update(vecptr(data), data.size()); - return hash.getHash(); + SHA1 hash; + hash.update(vecptr(data), data.size()); + return hash.getHash(); } } diff --git a/Swiften/StringCodecs/SHA1_Windows.h b/Swiften/StringCodecs/SHA1_Windows.h index 51786ca..b94de21 100644 --- a/Swiften/StringCodecs/SHA1_Windows.h +++ b/Swiften/StringCodecs/SHA1_Windows.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -16,29 +16,29 @@ #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class SWIFTEN_API SHA1 { - public: - SHA1(); - ~SHA1(); + class SWIFTEN_API SHA1 { + public: + SHA1(); + ~SHA1(); - SHA1& update(const std::vector<unsigned char>& data); - std::vector<unsigned char> getHash() const; + SHA1& update(const std::vector<unsigned char>& data); + std::vector<unsigned char> getHash() const; - static ByteArray getHash(const ByteArray& data); - static ByteArray getHash(const SafeByteArray& data); + static ByteArray getHash(const ByteArray& data); + static ByteArray getHash(const SafeByteArray& data); - ByteArray operator()(const SafeByteArray& data) { - return getHash(data); - } + ByteArray operator()(const SafeByteArray& data) { + return getHash(data); + } - ByteArray operator()(const ByteArray& data) { - return getHash(data); - } + ByteArray operator()(const ByteArray& data) { + return getHash(data); + } - private: - SHA1& update(const unsigned char* data, size_t dataSize); + private: + SHA1& update(const unsigned char* data, size_t dataSize); - private: - HCRYPTHASH hash; - }; + private: + HCRYPTHASH hash; + }; } diff --git a/Swiften/StringCodecs/UnitTest/Base64Test.cpp b/Swiften/StringCodecs/UnitTest/Base64Test.cpp index 4005047..272514f 100644 --- a/Swiften/StringCodecs/UnitTest/Base64Test.cpp +++ b/Swiften/StringCodecs/UnitTest/Base64Test.cpp @@ -1,67 +1,67 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/StringCodecs/Base64.h> using namespace Swift; class Base64Test : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(Base64Test); - CPPUNIT_TEST(testEncodeDecodeAllChars); - CPPUNIT_TEST(testEncodeDecodeOneBytePadding); - CPPUNIT_TEST(testEncodeDecodeTwoBytesPadding); - CPPUNIT_TEST(testEncode_NoData); - CPPUNIT_TEST(testDecode_NoData); - CPPUNIT_TEST_SUITE_END(); - - public: - void testEncodeDecodeAllChars() { - ByteArray input; - for (unsigned char i = 0; i < 255; ++i) { - input.push_back(i); - } - std::string result(Base64::encode(input)); - - CPPUNIT_ASSERT_EQUAL(std::string("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+"), result); - CPPUNIT_ASSERT_EQUAL(input, Base64::decode(result)); - } - - void testEncodeDecodeOneBytePadding() { - ByteArray input = createByteArray("ABCDE", 5); - - std::string result = Base64::encode(input); - - CPPUNIT_ASSERT_EQUAL(std::string("QUJDREU="), result); - CPPUNIT_ASSERT_EQUAL(input, Base64::decode(result)); - } - - void testEncodeDecodeTwoBytesPadding() { - ByteArray input = createByteArray("ABCD", 4); - - std::string result = Base64::encode(input); - - CPPUNIT_ASSERT_EQUAL(std::string("QUJDRA=="), result); - CPPUNIT_ASSERT_EQUAL(input, Base64::decode(result)); - } - - void testEncode_NoData() { - std::string result(Base64::encode(ByteArray())); - CPPUNIT_ASSERT_EQUAL(std::string(""), result); - } - - void testDecode_NoData() { - ByteArray result(Base64::decode("")); - CPPUNIT_ASSERT_EQUAL(ByteArray(), result); - } + CPPUNIT_TEST_SUITE(Base64Test); + CPPUNIT_TEST(testEncodeDecodeAllChars); + CPPUNIT_TEST(testEncodeDecodeOneBytePadding); + CPPUNIT_TEST(testEncodeDecodeTwoBytesPadding); + CPPUNIT_TEST(testEncode_NoData); + CPPUNIT_TEST(testDecode_NoData); + CPPUNIT_TEST_SUITE_END(); + + public: + void testEncodeDecodeAllChars() { + ByteArray input; + for (unsigned char i = 0; i < 255; ++i) { + input.push_back(i); + } + std::string result(Base64::encode(input)); + + CPPUNIT_ASSERT_EQUAL(std::string("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+"), result); + CPPUNIT_ASSERT_EQUAL(input, Base64::decode(result)); + } + + void testEncodeDecodeOneBytePadding() { + ByteArray input = createByteArray("ABCDE", 5); + + std::string result = Base64::encode(input); + + CPPUNIT_ASSERT_EQUAL(std::string("QUJDREU="), result); + CPPUNIT_ASSERT_EQUAL(input, Base64::decode(result)); + } + + void testEncodeDecodeTwoBytesPadding() { + ByteArray input = createByteArray("ABCD", 4); + + std::string result = Base64::encode(input); + + CPPUNIT_ASSERT_EQUAL(std::string("QUJDRA=="), result); + CPPUNIT_ASSERT_EQUAL(input, Base64::decode(result)); + } + + void testEncode_NoData() { + std::string result(Base64::encode(ByteArray())); + CPPUNIT_ASSERT_EQUAL(std::string(""), result); + } + + void testDecode_NoData() { + ByteArray result(Base64::decode("")); + CPPUNIT_ASSERT_EQUAL(ByteArray(), result); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(Base64Test); diff --git a/Swiften/StringCodecs/UnitTest/HexifyTest.cpp b/Swiften/StringCodecs/UnitTest/HexifyTest.cpp index 38233f9..7d349fa 100644 --- a/Swiften/StringCodecs/UnitTest/HexifyTest.cpp +++ b/Swiften/StringCodecs/UnitTest/HexifyTest.cpp @@ -1,38 +1,39 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <string> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <Swiften/StringCodecs/Hexify.h> -#include <string> #include <Swiften/Base/ByteArray.h> +#include <Swiften/StringCodecs/Hexify.h> using namespace Swift; class HexifyTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(HexifyTest); - CPPUNIT_TEST(testHexify); - CPPUNIT_TEST(testHexify_Byte); - CPPUNIT_TEST(testUnhexify); - CPPUNIT_TEST_SUITE_END(); - - public: - void testHexify() { - CPPUNIT_ASSERT_EQUAL(std::string("4206b23ca6b0a643d20d89b04ff58cf78b8096ed"), Hexify::hexify(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"))); - } - - void testHexify_Byte() { - CPPUNIT_ASSERT_EQUAL(std::string("b2"), Hexify::hexify(0xb2)); - } - - void testUnhexify() { - CPPUNIT_ASSERT_EQUAL(std::string("ffaf02"), Hexify::hexify(Hexify::unhexify("ffaf02"))); - CPPUNIT_ASSERT(createByteArray("\x01\x23\xf2", 3) == Hexify::unhexify("0123f2")); - } + CPPUNIT_TEST_SUITE(HexifyTest); + CPPUNIT_TEST(testHexify); + CPPUNIT_TEST(testHexify_Byte); + CPPUNIT_TEST(testUnhexify); + CPPUNIT_TEST_SUITE_END(); + + public: + void testHexify() { + CPPUNIT_ASSERT_EQUAL(std::string("4206b23ca6b0a643d20d89b04ff58cf78b8096ed"), Hexify::hexify(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"))); + } + + void testHexify_Byte() { + CPPUNIT_ASSERT_EQUAL(std::string("b2"), Hexify::hexify(0xb2)); + } + + void testUnhexify() { + CPPUNIT_ASSERT_EQUAL(std::string("ffaf02"), Hexify::hexify(Hexify::unhexify("ffaf02"))); + CPPUNIT_ASSERT(createByteArray("\x01\x23\xf2", 3) == Hexify::unhexify("0123f2")); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(HexifyTest); diff --git a/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp b/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp index 1172679..43866cb 100644 --- a/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp +++ b/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp @@ -1,54 +1,53 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> #include <QA/Checker/IO.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Base/ByteArray.h> -#include <Swiften/StringCodecs/PBKDF2.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/StringCodecs/PBKDF2.h> using namespace Swift; class PBKDF2Test : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PBKDF2Test); - CPPUNIT_TEST(testGetResult_I1); - CPPUNIT_TEST(testGetResult_I2); - CPPUNIT_TEST(testGetResult_I4096); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(PBKDF2Test); + CPPUNIT_TEST(testGetResult_I1); + CPPUNIT_TEST(testGetResult_I2); + CPPUNIT_TEST(testGetResult_I4096); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - } + void testGetResult_I1() { + ByteArray result(PBKDF2::encode(createSafeByteArray("password"), createByteArray("salt"), 1, crypto.get())); - void testGetResult_I1() { - ByteArray result(PBKDF2::encode(createSafeByteArray("password"), createByteArray("salt"), 1, crypto.get())); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6"), result); + } - CPPUNIT_ASSERT_EQUAL(createByteArray("\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6"), result); - } + void testGetResult_I2() { + ByteArray result(PBKDF2::encode(createSafeByteArray("password"), createByteArray("salt"), 2, crypto.get())); - void testGetResult_I2() { - ByteArray result(PBKDF2::encode(createSafeByteArray("password"), createByteArray("salt"), 2, crypto.get())); + CPPUNIT_ASSERT_EQUAL(createByteArray("\xea\x6c\x1\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57"), result); + } - CPPUNIT_ASSERT_EQUAL(createByteArray("\xea\x6c\x1\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57"), result); - } + void testGetResult_I4096() { + ByteArray result(PBKDF2::encode(createSafeByteArray("password"), createByteArray("salt"), 4096, crypto.get())); - void testGetResult_I4096() { - ByteArray result(PBKDF2::encode(createSafeByteArray("password"), createByteArray("salt"), 4096, crypto.get())); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x4b\x00\x79\x1\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20), result); + } - CPPUNIT_ASSERT_EQUAL(createByteArray("\x4b\x00\x79\x1\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20), result); - } - - private: - boost::shared_ptr<CryptoProvider> crypto; + private: + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(PBKDF2Test); diff --git a/Swiften/TLS/BlindCertificateTrustChecker.h b/Swiften/TLS/BlindCertificateTrustChecker.h index d91ec25..76a7a02 100644 --- a/Swiften/TLS/BlindCertificateTrustChecker.h +++ b/Swiften/TLS/BlindCertificateTrustChecker.h @@ -1,26 +1,27 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/TLS/CertificateTrustChecker.h> namespace Swift { - /** - * A certificate trust checker that trusts any ceritficate. - * - * This can be used to ignore any TLS certificate errors occurring - * during connection. - * - * \see Client::setAlwaysTrustCertificates() - */ - class BlindCertificateTrustChecker : public CertificateTrustChecker { - public: - virtual bool isCertificateTrusted(const std::vector<Certificate::ref>&) { - return true; - } - }; + /** + * A certificate trust checker that trusts any ceritficate. + * + * This can be used to ignore any TLS certificate errors occurring + * during connection. + * + * \see Client::setAlwaysTrustCertificates() + */ + class SWIFTEN_API BlindCertificateTrustChecker : public CertificateTrustChecker { + public: + virtual bool isCertificateTrusted(const std::vector<Certificate::ref>&) { + return true; + } + }; } diff --git a/Swiften/TLS/CAPICertificate.cpp b/Swiften/TLS/CAPICertificate.cpp index d10ae6d..526b535 100644 --- a/Swiften/TLS/CAPICertificate.cpp +++ b/Swiften/TLS/CAPICertificate.cpp @@ -1,332 +1,342 @@ /* - * Copyright (c) 2012 Isode Limited, London, England. - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. + * Copyright (c) 2012-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Network/TimerFactory.h> #include <Swiften/TLS/CAPICertificate.h> -#include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/Base/Log.h> -#include <boost/bind.hpp> #include <boost/algorithm/string/predicate.hpp> +#include <boost/bind.hpp> + +#include <Swiften/Base/Log.h> +#include <Swiften/Network/TimerFactory.h> +#include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/TLS/Schannel/SchannelUtil.h> // Size of the SHA1 hash #define SHA1_HASH_LEN 20 +#define DEBUG_SCARD_STATUS(function, status) \ +{ \ + std::shared_ptr<boost::system::error_code> errorCode = std::make_shared<boost::system::error_code>(status, boost::system::system_category()); \ + SWIFT_LOG(debug) << std::hex << function << ": status: 0x" << status << ": " << errorCode->message(); \ +} namespace Swift { -CAPICertificate::CAPICertificate(const std::string& capiUri, TimerFactory* timerFactory) : - valid_(false), - uri_(capiUri), - certStoreHandle_(0), - scardContext_(0), - cardHandle_(0), - certStore_(), - certName_(), - smartCardReaderName_(), - timerFactory_(timerFactory), - lastPollingResult_(true) { - assert(timerFactory_); - - setUri(capiUri); +CAPICertificate::CAPICertificate(const std::string& capiUri, TimerFactory* timerFactory) : + valid_(false), + uri_(capiUri), + certStoreHandle_(0), + scardContext_(0), + cardHandle_(0), + certStore_(), + certName_(), + smartCardReaderName_(), + timerFactory_(timerFactory), + lastPollingResult_(true) { + assert(timerFactory_); + + setUri(capiUri); } CAPICertificate::~CAPICertificate() { - if (smartCardTimer_) { - smartCardTimer_->stop(); - smartCardTimer_->onTick.disconnect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this)); - smartCardTimer_.reset(); - } - - if (certStoreHandle_) { - CertCloseStore(certStoreHandle_, 0); - } - - if (cardHandle_) { - (void) SCardDisconnect(cardHandle_, SCARD_LEAVE_CARD); - } - - if (scardContext_) { - SCardReleaseContext(scardContext_); - } + SWIFT_LOG(debug) << "Destroying the CAPICertificate"; + if (smartCardTimer_) { + smartCardTimer_->stop(); + smartCardTimer_->onTick.disconnect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this)); + smartCardTimer_.reset(); + } + + if (certStoreHandle_) { + if (CertCloseStore(certStoreHandle_, 0) == FALSE) { + SWIFT_LOG(debug) << "Failed to close the certificate store handle"; + } + } + + if (cardHandle_) { + LONG result = SCardDisconnect(cardHandle_, SCARD_LEAVE_CARD); + DEBUG_SCARD_STATUS("SCardDisconnect", result); + } + + if (scardContext_) { + LONG result = SCardReleaseContext(scardContext_); + DEBUG_SCARD_STATUS("SCardReleaseContext", result); + } } bool CAPICertificate::isNull() const { - return uri_.empty() || !valid_; + return uri_.empty() || !valid_; } const std::string& CAPICertificate::getCertStoreName() const { - return certStore_; + return certStore_; } const std::string& CAPICertificate::getCertName() const { - return certName_; + return certName_; } const std::string& CAPICertificate::getSmartCardReaderName() const { - return smartCardReaderName_; + return smartCardReaderName_; } -PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::string &certName) { - if (!boost::iequals(certName.substr(0, 5), "sha1:")) { +PCCERT_CONTEXT findCertificateInStore(HCERTSTORE certStoreHandle, const std::string &certName) { + if (!boost::iequals(certName.substr(0, 5), "sha1:")) { - // Find client certificate. Note that this sample just searches for a - // certificate that contains the user name somewhere in the subject name. - return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /*dwFindFlags*/ 0, CERT_FIND_SUBJECT_STR_A, /* *pvFindPara*/certName.c_str(), /*pPrevCertContext*/ NULL); - } + // Find client certificate. Note that this sample just searches for a + // certificate that contains the user name somewhere in the subject name. + return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /*dwFindFlags*/ 0, CERT_FIND_SUBJECT_STR_A, /* *pvFindPara*/certName.c_str(), /*pPrevCertContext*/ NULL); + } - std::string hexstring = certName.substr(5); - ByteArray byteArray = Hexify::unhexify(hexstring); - CRYPT_HASH_BLOB HashBlob; + std::string hexstring = certName.substr(5); + ByteArray byteArray = Hexify::unhexify(hexstring); + CRYPT_HASH_BLOB HashBlob; - if (byteArray.size() != SHA1_HASH_LEN) { - return NULL; - } - HashBlob.cbData = SHA1_HASH_LEN; - HashBlob.pbData = static_cast<BYTE *>(vecptr(byteArray)); + if (byteArray.size() != SHA1_HASH_LEN) { + return NULL; + } + HashBlob.cbData = SHA1_HASH_LEN; + HashBlob.pbData = static_cast<BYTE *>(vecptr(byteArray)); - // Find client certificate. Note that this sample just searches for a - // certificate that contains the user name somewhere in the subject name. - return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /* dwFindFlags */ 0, CERT_FIND_HASH, &HashBlob, /* pPrevCertContext */ NULL); + // Find client certificate. Note that this sample just searches for a + // certificate that contains the user name somewhere in the subject name. + return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /* dwFindFlags */ 0, CERT_FIND_HASH, &HashBlob, /* pPrevCertContext */ NULL); } - -void CAPICertificate::setUri (const std::string& capiUri) { - valid_ = false; - - /* Syntax: "certstore:" <cert_store> ":" <hash> ":" <hash_of_cert> */ - - if (!boost::iequals(capiUri.substr(0, 10), "certstore:")) { - return; - } - - /* Substring of subject: uses "storename" */ - std::string capiIdentity = capiUri.substr(10); - std::string newCertStoreName; - size_t pos = capiIdentity.find_first_of (':'); - - if (pos == std::string::npos) { - /* Using the default certificate store */ - newCertStoreName = "MY"; - certName_ = capiIdentity; - } - else { - newCertStoreName = capiIdentity.substr(0, pos); - certName_ = capiIdentity.substr(pos + 1); - } - - if (certStoreHandle_ != NULL) { - if (newCertStoreName != certStore_) { - CertCloseStore(certStoreHandle_, 0); - certStoreHandle_ = NULL; - } - } - - if (certStoreHandle_ == NULL) { - certStoreHandle_ = CertOpenSystemStore(0, newCertStoreName.c_str()); - if (!certStoreHandle_) { - return; - } - } - - certStore_ = newCertStoreName; - - PCCERT_CONTEXT certContext = findCertificateInStore (certStoreHandle_, certName_); - - if (!certContext) { - return; - } - - - /* Now verify that we can have access to the corresponding private key */ - - DWORD len; - CRYPT_KEY_PROV_INFO *pinfo; - HCRYPTPROV hprov; - HCRYPTKEY key; - - if (!CertGetCertificateContextProperty(certContext, - CERT_KEY_PROV_INFO_PROP_ID, - NULL, - &len)) { - CertFreeCertificateContext(certContext); - return; - } - - pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len)); - if (!pinfo) { - CertFreeCertificateContext(certContext); - return; - } - - if (!CertGetCertificateContextProperty(certContext, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) { - CertFreeCertificateContext(certContext); - free(pinfo); - return; - } - - CertFreeCertificateContext(certContext); - - // Now verify if we have access to the private key - if (!CryptAcquireContextW(&hprov, pinfo->pwszContainerName, pinfo->pwszProvName, pinfo->dwProvType, 0)) { - free(pinfo); - return; - } - - - char smartCardReader[1024]; - DWORD bufferLength = sizeof(smartCardReader); - if (!CryptGetProvParam(hprov, PP_SMARTCARD_READER, (BYTE *)&smartCardReader, &bufferLength, 0)) { - DWORD error = GetLastError(); - smartCardReaderName_ = ""; - } - else { - smartCardReaderName_ = smartCardReader; - - LONG result = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &scardContext_); - if (SCARD_S_SUCCESS == result) { - // Initiate monitoring for smartcard ejection - smartCardTimer_ = timerFactory_->createTimer(SMARTCARD_EJECTION_CHECK_FREQUENCY_MILLISECONDS); - } - else { - ///Need to handle an error here - } - } - - if (!CryptGetUserKey(hprov, pinfo->dwKeySpec, &key)) { - CryptReleaseContext(hprov, 0); - free(pinfo); - return; - } - - CryptDestroyKey(key); - CryptReleaseContext(hprov, 0); - free(pinfo); - - if (smartCardTimer_) { - smartCardTimer_->onTick.connect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this)); - smartCardTimer_->start(); - } - - valid_ = true; +void CAPICertificate::setUri(const std::string& capiUri) { + valid_ = false; + + /* Syntax: "certstore:" <cert_store> ":" <hash> ":" <hash_of_cert> */ + + if (!boost::iequals(capiUri.substr(0, 10), "certstore:")) { + return; + } + + /* Substring of subject: uses "storename" */ + std::string capiIdentity = capiUri.substr(10); + std::string newCertStoreName; + size_t pos = capiIdentity.find_first_of(':'); + + if (pos == std::string::npos) { + /* Using the default certificate store */ + newCertStoreName = "MY"; + certName_ = capiIdentity; + } + else { + newCertStoreName = capiIdentity.substr(0, pos); + certName_ = capiIdentity.substr(pos + 1); + } + + if (certStoreHandle_ != NULL) { + if (newCertStoreName != certStore_) { + CertCloseStore(certStoreHandle_, 0); + certStoreHandle_ = NULL; + } + } + + if (certStoreHandle_ == NULL) { + certStoreHandle_ = CertOpenSystemStore(0, newCertStoreName.c_str()); + if (!certStoreHandle_) { + return; + } + } + + certStore_ = newCertStoreName; + + ScopedCertContext certContext(findCertificateInStore(certStoreHandle_, certName_)); + if (!certContext) { + return; + } + + /* Now verify that we can have access to the corresponding private key */ + + DWORD len; + if (!CertGetCertificateContextProperty(certContext, + CERT_KEY_PROV_INFO_PROP_ID, + NULL, + &len)) { + SWIFT_LOG(error) << "Error while retrieving context properties"; + return; + } + + std::shared_ptr<CRYPT_KEY_PROV_INFO> pinfo(static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len)), free); + if (!pinfo) { + return; + } + + if (!CertGetCertificateContextProperty(certContext, CERT_KEY_PROV_INFO_PROP_ID, pinfo.get(), &len)) { + return; + } + certContext.FreeContext(); + + HCRYPTPROV hprov; + // Now verify if we have access to the private key + if (!CryptAcquireContextW(&hprov, pinfo->pwszContainerName, pinfo->pwszProvName, pinfo->dwProvType, 0)) { + return; + } + + char smartCardReader[1024]; + DWORD bufferLength = sizeof(smartCardReader); + if (!CryptGetProvParam(hprov, PP_SMARTCARD_READER, (BYTE *)&smartCardReader, &bufferLength, 0)) { + DWORD error = GetLastError(); + smartCardReaderName_ = ""; + } + else { + smartCardReaderName_ = smartCardReader; + + LONG result = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &scardContext_); + DEBUG_SCARD_STATUS("SCardEstablishContext", result); + if (SCARD_S_SUCCESS == result) { + // Initiate monitoring for smartcard ejection + smartCardTimer_ = timerFactory_->createTimer(SMARTCARD_EJECTION_CHECK_FREQUENCY_MILLISECONDS); + } + else { + CryptReleaseContext(hprov, 0); + return; + } + } + + HCRYPTKEY key; + if (!CryptGetUserKey(hprov, pinfo->dwKeySpec, &key)) { + CryptReleaseContext(hprov, 0); + return; + } + + CryptDestroyKey(key); + CryptReleaseContext(hprov, 0); + + if (smartCardTimer_) { + smartCardTimer_->onTick.connect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this)); + smartCardTimer_->start(); + } + + valid_ = true; } -static void smartcard_check_status (SCARDCONTEXT hContext, - const char* pReader, - SCARDHANDLE hCardHandle, /* Can be 0 on the first call */ - SCARDHANDLE* newCardHandle, /* The handle returned */ - DWORD* pdwState) { - if (hCardHandle == 0) { - DWORD dwAP; - LONG result = SCardConnect(hContext, pReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCardHandle, &dwAP); - if (SCARD_S_SUCCESS != result) { - hCardHandle = 0; - if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) { - *pdwState = SCARD_ABSENT; - } - else { - *pdwState = SCARD_UNKNOWN; - } - - if (newCardHandle == NULL) { - (void) SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); - hCardHandle = 0; - } - else { - *newCardHandle = hCardHandle; - } - } - } - - char szReader[200]; - DWORD cch = sizeof(szReader); - BYTE bAttr[32]; - DWORD cByte = 32; - LONG result = SCardStatus(hCardHandle, /* Unfortunately we can't use NULL here */ szReader, &cch, pdwState, NULL, (LPBYTE)&bAttr, &cByte); - - if (SCARD_S_SUCCESS != result) { - if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) { - *pdwState = SCARD_ABSENT; - } - else { - *pdwState = SCARD_UNKNOWN; - } - } - - if (newCardHandle == NULL) { - (void) SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); - hCardHandle = 0; - } - else { - *newCardHandle = hCardHandle; - } +static void smartcard_check_status(SCARDCONTEXT hContext, + const char* pReader, + SCARDHANDLE hCardHandle, /* Can be 0 on the first call */ + SCARDHANDLE* newCardHandle, /* The handle returned */ + DWORD* pdwState) { + DWORD shareMode = SCARD_SHARE_SHARED; + DWORD preferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1; + DWORD dwAP; + LONG result; + + if (hCardHandle == 0) { + result = SCardConnect(hContext, pReader, shareMode, preferredProtocols, &hCardHandle, &dwAP); + DEBUG_SCARD_STATUS("SCardConnect", result); + if (SCARD_S_SUCCESS != result) { + hCardHandle = 0; + } + } + + char szReader[200]; + DWORD cch = sizeof(szReader); + BYTE bAttr[32]; + DWORD cByte = 32; + size_t countStatusAttempts = 0; + + while (hCardHandle && (countStatusAttempts < 2)) { + *pdwState = SCARD_UNKNOWN; + + result = SCardStatus(hCardHandle, /* Unfortunately we can't use NULL here */ szReader, &cch, pdwState, NULL, (LPBYTE)&bAttr, &cByte); + DEBUG_SCARD_STATUS("SCardStatus", result); + countStatusAttempts++; + + if ((SCARD_W_RESET_CARD == result) && (countStatusAttempts < 2)) { + result = SCardReconnect(hCardHandle, shareMode, preferredProtocols, SCARD_RESET_CARD, &dwAP); + DEBUG_SCARD_STATUS("SCardReconnect", result); + if (SCARD_S_SUCCESS != result) { + break; + } + } + else { + break; + } + } + + if (SCARD_S_SUCCESS != result) { + if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) { + *pdwState = SCARD_ABSENT; + } + else { + *pdwState = SCARD_UNKNOWN; + } + } + + if (newCardHandle == NULL) { + result = SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); + DEBUG_SCARD_STATUS("SCardDisconnect", result); + } + else { + *newCardHandle = hCardHandle; + } } -bool CAPICertificate::checkIfSmartCardPresent () { - if (!smartCardReaderName_.empty()) { - DWORD dwState; - smartcard_check_status(scardContext_, smartCardReaderName_.c_str(), cardHandle_, &cardHandle_, &dwState); - - switch (dwState) { - case SCARD_ABSENT: - SWIFT_LOG(debug) << "Card absent." << std::endl; - break; - case SCARD_PRESENT: - SWIFT_LOG(debug) << "Card present." << std::endl; - break; - case SCARD_SWALLOWED: - SWIFT_LOG(debug) << "Card swallowed." << std::endl; - break; - case SCARD_POWERED: - SWIFT_LOG(debug) << "Card has power." << std::endl; - break; - case SCARD_NEGOTIABLE: - SWIFT_LOG(debug) << "Card reset and waiting PTS negotiation." << std::endl; - break; - case SCARD_SPECIFIC: - SWIFT_LOG(debug) << "Card has specific communication protocols set." << std::endl; - break; - default: - SWIFT_LOG(debug) << "Unknown or unexpected card state." << std::endl; - break; - } - - - - switch (dwState) { - case SCARD_ABSENT: - return false; - - case SCARD_PRESENT: - case SCARD_SWALLOWED: - case SCARD_POWERED: - case SCARD_NEGOTIABLE: - case SCARD_SPECIFIC: - return true; - - default: - return false; - } - } - else { - return false; - } +bool CAPICertificate::checkIfSmartCardPresent() { + if (!smartCardReaderName_.empty()) { + DWORD dwState; + smartcard_check_status(scardContext_, smartCardReaderName_.c_str(), cardHandle_, &cardHandle_, &dwState); + + switch (dwState) { + case SCARD_ABSENT: + SWIFT_LOG(debug) << "Card absent."; + break; + case SCARD_PRESENT: + SWIFT_LOG(debug) << "Card present."; + break; + case SCARD_SWALLOWED: + SWIFT_LOG(debug) << "Card swallowed."; + break; + case SCARD_POWERED: + SWIFT_LOG(debug) << "Card has power."; + break; + case SCARD_NEGOTIABLE: + SWIFT_LOG(debug) << "Card reset and waiting PTS negotiation."; + break; + case SCARD_SPECIFIC: + SWIFT_LOG(debug) << "Card has specific communication protocols set."; + break; + default: + SWIFT_LOG(debug) << "Unknown or unexpected card state."; + break; + } + + switch (dwState) { + case SCARD_ABSENT: + return false; + + case SCARD_PRESENT: + case SCARD_SWALLOWED: + case SCARD_POWERED: + case SCARD_NEGOTIABLE: + case SCARD_SPECIFIC: + return true; + + default: + return false; + } + } + else { + return false; + } } void CAPICertificate::handleSmartCardTimerTick() { - bool poll = checkIfSmartCardPresent(); - if (lastPollingResult_ && !poll) { - onCertificateCardRemoved(); - } - lastPollingResult_ = poll; - smartCardTimer_->start(); + bool poll = checkIfSmartCardPresent(); + if (lastPollingResult_ && !poll) { + SWIFT_LOG(debug) << "CAPI Certificate detected that the certificate card was removed"; + onCertificateCardRemoved(); + } + lastPollingResult_ = poll; + smartCardTimer_->start(); } } diff --git a/Swiften/TLS/CAPICertificate.h b/Swiften/TLS/CAPICertificate.h index aebfb41..0259db5 100644 --- a/Swiften/TLS/CAPICertificate.h +++ b/Swiften/TLS/CAPICertificate.h @@ -4,10 +4,16 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> #include <Swiften/Base/SafeByteArray.h> #include <Swiften/TLS/CertificateWithKey.h> #include <Swiften/Network/Timer.h> @@ -17,52 +23,52 @@ #include <WinCrypt.h> #include <Winscard.h> -#define SMARTCARD_EJECTION_CHECK_FREQUENCY_MILLISECONDS 1000 +#define SMARTCARD_EJECTION_CHECK_FREQUENCY_MILLISECONDS 1000 namespace Swift { - class TimerFactory; + class TimerFactory; - class SWIFTEN_API CAPICertificate : public Swift::CertificateWithKey { - public: - CAPICertificate(const std::string& capiUri, TimerFactory* timerFactory); + class SWIFTEN_API CAPICertificate : public Swift::CertificateWithKey { + public: + CAPICertificate(const std::string& capiUri, TimerFactory* timerFactory); - virtual ~CAPICertificate(); + virtual ~CAPICertificate(); - virtual bool isNull() const; + virtual bool isNull() const; - const std::string& getCertStoreName() const; + const std::string& getCertStoreName() const; - const std::string& getCertName() const; + const std::string& getCertName() const; - const std::string& getSmartCardReaderName() const; + const std::string& getSmartCardReaderName() const; - public: - boost::signal<void ()> onCertificateCardRemoved; + public: + boost::signals2::signal<void ()> onCertificateCardRemoved; - private: - void setUri (const std::string& capiUri); + private: + void setUri (const std::string& capiUri); - void handleSmartCardTimerTick(); + void handleSmartCardTimerTick(); - bool checkIfSmartCardPresent(); + bool checkIfSmartCardPresent(); - private: - bool valid_; - std::string uri_; + private: + bool valid_; + std::string uri_; - HCERTSTORE certStoreHandle_; - SCARDCONTEXT scardContext_; - SCARDHANDLE cardHandle_; + HCERTSTORE certStoreHandle_; + SCARDCONTEXT scardContext_; + SCARDHANDLE cardHandle_; - /* Parsed components of the uri_ */ - std::string certStore_; - std::string certName_; - std::string smartCardReaderName_; - boost::shared_ptr<Timer> smartCardTimer_; - TimerFactory* timerFactory_; + /* Parsed components of the uri_ */ + std::string certStore_; + std::string certName_; + std::string smartCardReaderName_; + std::shared_ptr<Timer> smartCardTimer_; + TimerFactory* timerFactory_; - bool lastPollingResult_; - }; + bool lastPollingResult_; + }; PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::string &certName); diff --git a/Swiften/TLS/Certificate.cpp b/Swiften/TLS/Certificate.cpp index ec268c8..c7d48b2 100644 --- a/Swiften/TLS/Certificate.cpp +++ b/Swiften/TLS/Certificate.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/TLS/Certificate.h> @@ -20,15 +20,15 @@ Certificate::~Certificate() { } std::string Certificate::getSHA1Fingerprint(Certificate::ref certificate, CryptoProvider* crypto) { - ByteArray hash = crypto->getSHA1Hash(certificate->toDER()); - std::ostringstream s; - for (size_t i = 0; i < hash.size(); ++i) { - if (i > 0) { - s << ":"; - } - s << Hexify::hexify(hash[i]); - } - return std::string(s.str()); + ByteArray hash = crypto->getSHA1Hash(certificate->toDER()); + std::ostringstream s; + for (size_t i = 0; i < hash.size(); ++i) { + if (i > 0) { + s << ":"; + } + s << Hexify::hexify(hash[i]); + } + return std::string(s.str()); } } diff --git a/Swiften/TLS/Certificate.h b/Swiften/TLS/Certificate.h index f558c12..dbc61ad 100644 --- a/Swiften/TLS/Certificate.h +++ b/Swiften/TLS/Certificate.h @@ -1,44 +1,45 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> - +#include <memory> #include <string> +#include <vector> + #include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> namespace Swift { - class CryptoProvider; + class CryptoProvider; - class SWIFTEN_API Certificate { - public: - typedef boost::shared_ptr<Certificate> ref; + class SWIFTEN_API Certificate { + public: + typedef std::shared_ptr<Certificate> ref; - virtual ~Certificate(); + virtual ~Certificate(); - /** - * Returns the textual representation of the full Subject - * name. - */ - virtual std::string getSubjectName() const = 0; + /** + * Returns the textual representation of the full Subject + * name. + */ + virtual std::string getSubjectName() const = 0; - virtual std::vector<std::string> getCommonNames() const = 0; - virtual std::vector<std::string> getSRVNames() const = 0; - virtual std::vector<std::string> getDNSNames() const = 0; - virtual std::vector<std::string> getXMPPAddresses() const = 0; + virtual std::vector<std::string> getCommonNames() const = 0; + virtual std::vector<std::string> getSRVNames() const = 0; + virtual std::vector<std::string> getDNSNames() const = 0; + virtual std::vector<std::string> getXMPPAddresses() const = 0; - virtual ByteArray toDER() const = 0; + virtual ByteArray toDER() const = 0; - static std::string getSHA1Fingerprint(Certificate::ref, CryptoProvider* crypto); + static std::string getSHA1Fingerprint(Certificate::ref, CryptoProvider* crypto); - protected: - static const char* ID_ON_XMPPADDR_OID; - static const char* ID_ON_DNSSRV_OID; + protected: + static const char* ID_ON_XMPPADDR_OID; + static const char* ID_ON_DNSSRV_OID; - }; + }; } diff --git a/Swiften/TLS/CertificateFactory.cpp b/Swiften/TLS/CertificateFactory.cpp index df01090..d4db3f4 100644 --- a/Swiften/TLS/CertificateFactory.cpp +++ b/Swiften/TLS/CertificateFactory.cpp @@ -1,14 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/TLS/CertificateFactory.h> +#include <cassert> +#include <memory> +#include <sstream> +#include <string> + +#include <boost/algorithm/string/predicate.hpp> +#include <boost/optional.hpp> + +#include <Swiften/Base/Log.h> +#include <Swiften/StringCodecs/Base64.h> +#include <Swiften/TLS/PrivateKey.h> + namespace Swift { CertificateFactory::~CertificateFactory() { } +std::vector<std::shared_ptr<Certificate>> CertificateFactory::createCertificateChain(const ByteArray& /* data */) { + assert(false); + return std::vector<std::shared_ptr<Certificate>>(); +} + +PrivateKey::ref CertificateFactory::createPrivateKey(const SafeByteArray& data, boost::optional<SafeByteArray> password) { + return std::make_shared<PrivateKey>(data, password); +} + } diff --git a/Swiften/TLS/CertificateFactory.h b/Swiften/TLS/CertificateFactory.h index 3e94082..873c36b 100644 --- a/Swiften/TLS/CertificateFactory.h +++ b/Swiften/TLS/CertificateFactory.h @@ -1,18 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <boost/optional.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/TLS/Certificate.h> +#include <Swiften/TLS/PrivateKey.h> namespace Swift { - class CertificateFactory { - public: - virtual ~CertificateFactory(); + class SWIFTEN_API CertificateFactory { + public: + virtual ~CertificateFactory(); - virtual Certificate::ref createCertificateFromDER(const ByteArray& der) = 0; - }; + virtual Certificate* createCertificateFromDER(const ByteArray& der) = 0; + virtual std::vector<std::shared_ptr<Certificate>> createCertificateChain(const ByteArray& data); + PrivateKey::ref createPrivateKey(const SafeByteArray& data, boost::optional<SafeByteArray> password = boost::optional<SafeByteArray>()); + }; } diff --git a/Swiften/TLS/CertificateTrustChecker.cpp b/Swiften/TLS/CertificateTrustChecker.cpp index 42e24a1..fa3761a 100644 --- a/Swiften/TLS/CertificateTrustChecker.cpp +++ b/Swiften/TLS/CertificateTrustChecker.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/TLS/CertificateTrustChecker.h> diff --git a/Swiften/TLS/CertificateTrustChecker.h b/Swiften/TLS/CertificateTrustChecker.h index 4ec0b39..dd2b3ec 100644 --- a/Swiften/TLS/CertificateTrustChecker.h +++ b/Swiften/TLS/CertificateTrustChecker.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <string> #include <vector> @@ -14,21 +14,21 @@ #include <Swiften/TLS/Certificate.h> namespace Swift { - /** - * A class to implement a check for certificate trust. - */ - class SWIFTEN_API CertificateTrustChecker { - public: - virtual ~CertificateTrustChecker(); + /** + * A class to implement a check for certificate trust. + */ + class SWIFTEN_API CertificateTrustChecker { + public: + virtual ~CertificateTrustChecker(); - /** - * This method is called to find out whether a certificate (chain) is - * trusted. This usually happens when a certificate's validation - * fails, to check whether to proceed with the connection or not. - * - * certificateChain contains the chain of certificates. The first certificate - * is the subject certificate. - */ - virtual bool isCertificateTrusted(const std::vector<Certificate::ref>& certificateChain) = 0; - }; + /** + * This method is called to find out whether a certificate (chain) is + * trusted. This usually happens when a certificate's validation + * fails, to check whether to proceed with the connection or not. + * + * certificateChain contains the chain of certificates. The first certificate + * is the subject certificate. + */ + virtual bool isCertificateTrusted(const std::vector<Certificate::ref>& certificateChain) = 0; + }; } diff --git a/Swiften/TLS/CertificateVerificationError.h b/Swiften/TLS/CertificateVerificationError.h index b17f5df..02b4cca 100644 --- a/Swiften/TLS/CertificateVerificationError.h +++ b/Swiften/TLS/CertificateVerificationError.h @@ -1,42 +1,44 @@ /* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <Swiften/Base/API.h> #include <Swiften/Base/Error.h> namespace Swift { - class CertificateVerificationError : public Error { - public: - typedef boost::shared_ptr<CertificateVerificationError> ref; - - enum Type { - UnknownError, - Expired, - NotYetValid, - SelfSigned, - Rejected, - Untrusted, - InvalidPurpose, - PathLengthExceeded, - InvalidSignature, - InvalidCA, - InvalidServerIdentity, - Revoked, - RevocationCheckFailed - }; - - CertificateVerificationError(Type type = UnknownError) : type(type) {} - - Type getType() const { - return type; - } - - private: - Type type; - }; + class SWIFTEN_API CertificateVerificationError : public Error { + public: + typedef std::shared_ptr<CertificateVerificationError> ref; + + enum Type { + UnknownError, + Expired, + NotYetValid, + SelfSigned, + Rejected, + Untrusted, + InvalidPurpose, + PathLengthExceeded, + InvalidSignature, + InvalidCA, + InvalidServerIdentity, + Revoked, + RevocationCheckFailed + }; + + CertificateVerificationError(Type type = UnknownError) : type(type) {} + + Type getType() const { + return type; + } + + private: + Type type; + }; } diff --git a/Swiften/TLS/CertificateWithKey.h b/Swiften/TLS/CertificateWithKey.h index 1bdeb03..8414938 100644 --- a/Swiften/TLS/CertificateWithKey.h +++ b/Swiften/TLS/CertificateWithKey.h @@ -1,22 +1,23 @@ /* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class CertificateWithKey { - public: - typedef boost::shared_ptr<CertificateWithKey> ref; - CertificateWithKey() {} + class SWIFTEN_API CertificateWithKey { + public: + typedef std::shared_ptr<CertificateWithKey> ref; + CertificateWithKey() {} - virtual ~CertificateWithKey() {} + virtual ~CertificateWithKey() {} - virtual bool isNull() const = 0; + virtual bool isNull() const = 0; - }; + }; } diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp b/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp index d654787..66b650d 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/TLS/OpenSSL/OpenSSLCertificate.h> @@ -19,92 +19,100 @@ namespace Swift { -OpenSSLCertificate::OpenSSLCertificate(boost::shared_ptr<X509> cert) : cert(cert) { - parse(); +OpenSSLCertificate::OpenSSLCertificate(std::shared_ptr<X509> cert) : cert(cert) { + parse(); } OpenSSLCertificate::OpenSSLCertificate(const ByteArray& der) { #if OPENSSL_VERSION_NUMBER <= 0x009070cfL - unsigned char* p = const_cast<unsigned char*>(vecptr(der)); + unsigned char* p = const_cast<unsigned char*>(vecptr(der)); #else - const unsigned char* p = vecptr(der); + const unsigned char* p = vecptr(der); +#endif + cert = std::shared_ptr<X509>(d2i_X509(nullptr, &p, der.size()), X509_free); + if (!cert) { +// SWIFT_LOG(warning) << "Error creating certificate from DER data"; + } + parse(); +} + +void OpenSSLCertificate::incrementReferenceCount() const { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + X509_up_ref(cert.get()); +#else + CRYPTO_add(&(cert.get()->references), 1, CRYPTO_LOCK_EVP_PKEY); #endif - cert = boost::shared_ptr<X509>(d2i_X509(NULL, &p, der.size()), X509_free); - if (!cert) { - SWIFT_LOG(warning) << "Error creating certificate from DER data" << std::endl; - } - parse(); } ByteArray OpenSSLCertificate::toDER() const { - ByteArray result; - if (!cert) { - return result; - } - result.resize(i2d_X509(cert.get(), NULL)); - unsigned char* p = vecptr(result); - i2d_X509(cert.get(), &p); - return result; + ByteArray result; + if (!cert) { + return result; + } + result.resize(i2d_X509(cert.get(), nullptr)); + unsigned char* p = vecptr(result); + i2d_X509(cert.get(), &p); + return result; } void OpenSSLCertificate::parse() { - if (!cert) { - return; - } - // Subject name - X509_NAME* subjectName = X509_get_subject_name(cert.get()); - if (subjectName) { - // Subject name - ByteArray subjectNameData; - subjectNameData.resize(256); - X509_NAME_oneline(X509_get_subject_name(cert.get()), reinterpret_cast<char*>(vecptr(subjectNameData)), static_cast<unsigned int>(subjectNameData.size())); - this->subjectName = byteArrayToString(subjectNameData); + if (!cert) { + return; + } + // Subject name + X509_NAME* subjectName = X509_get_subject_name(cert.get()); + if (subjectName) { + // Subject name + ByteArray subjectNameData; + subjectNameData.resize(256); + X509_NAME_oneline(X509_get_subject_name(cert.get()), reinterpret_cast<char*>(vecptr(subjectNameData)), static_cast<unsigned int>(subjectNameData.size())); + this->subjectName = byteArrayToString(subjectNameData); - // Common name - int cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, -1); - while (cnLoc != -1) { - X509_NAME_ENTRY* cnEntry = X509_NAME_get_entry(subjectName, cnLoc); - ASN1_STRING* cnData = X509_NAME_ENTRY_get_data(cnEntry); - commonNames.push_back(byteArrayToString(createByteArray(reinterpret_cast<const char*>(cnData->data), cnData->length))); - cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, cnLoc); - } - } + // Common name + int cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, -1); + while (cnLoc != -1) { + X509_NAME_ENTRY* cnEntry = X509_NAME_get_entry(subjectName, cnLoc); + ASN1_STRING* cnData = X509_NAME_ENTRY_get_data(cnEntry); + commonNames.push_back(byteArrayToString(createByteArray(reinterpret_cast<const char*>(cnData->data), cnData->length))); + cnLoc = X509_NAME_get_index_by_NID(subjectName, NID_commonName, cnLoc); + } + } - // subjectAltNames - int subjectAltNameLoc = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); - if(subjectAltNameLoc != -1) { - X509_EXTENSION* extension = X509_get_ext(cert.get(), subjectAltNameLoc); - boost::shared_ptr<GENERAL_NAMES> generalNames(reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(extension)), GENERAL_NAMES_free); - boost::shared_ptr<ASN1_OBJECT> xmppAddrObject(OBJ_txt2obj(ID_ON_XMPPADDR_OID, 1), ASN1_OBJECT_free); - boost::shared_ptr<ASN1_OBJECT> dnsSRVObject(OBJ_txt2obj(ID_ON_DNSSRV_OID, 1), ASN1_OBJECT_free); - for (int i = 0; i < sk_GENERAL_NAME_num(generalNames.get()); ++i) { - GENERAL_NAME* generalName = sk_GENERAL_NAME_value(generalNames.get(), i); - if (generalName->type == GEN_OTHERNAME) { - OTHERNAME* otherName = generalName->d.otherName; - if (OBJ_cmp(otherName->type_id, xmppAddrObject.get()) == 0) { - // XmppAddr - if (otherName->value->type != V_ASN1_UTF8STRING) { - continue; - } - ASN1_UTF8STRING* xmppAddrValue = otherName->value->value.utf8string; - addXMPPAddress(byteArrayToString(createByteArray(reinterpret_cast<const char*>(ASN1_STRING_data(xmppAddrValue)), ASN1_STRING_length(xmppAddrValue)))); - } - else if (OBJ_cmp(otherName->type_id, dnsSRVObject.get()) == 0) { - // SRVName - if (otherName->value->type != V_ASN1_IA5STRING) { - continue; - } - ASN1_IA5STRING* srvNameValue = otherName->value->value.ia5string; - addSRVName(byteArrayToString(createByteArray(reinterpret_cast<const char*>(ASN1_STRING_data(srvNameValue)), ASN1_STRING_length(srvNameValue)))); - } - } - else if (generalName->type == GEN_DNS) { - // DNSName - addDNSName(byteArrayToString(createByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)))); - } - } - } + // subjectAltNames + int subjectAltNameLoc = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); + if(subjectAltNameLoc != -1) { + X509_EXTENSION* extension = X509_get_ext(cert.get(), subjectAltNameLoc); + std::shared_ptr<GENERAL_NAMES> generalNames(reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(extension)), GENERAL_NAMES_free); + std::shared_ptr<ASN1_OBJECT> xmppAddrObject(OBJ_txt2obj(ID_ON_XMPPADDR_OID, 1), ASN1_OBJECT_free); + std::shared_ptr<ASN1_OBJECT> dnsSRVObject(OBJ_txt2obj(ID_ON_DNSSRV_OID, 1), ASN1_OBJECT_free); + for (int i = 0; i < sk_GENERAL_NAME_num(generalNames.get()); ++i) { + GENERAL_NAME* generalName = sk_GENERAL_NAME_value(generalNames.get(), i); + if (generalName->type == GEN_OTHERNAME) { + OTHERNAME* otherName = generalName->d.otherName; + if (OBJ_cmp(otherName->type_id, xmppAddrObject.get()) == 0) { + // XmppAddr + if (otherName->value->type != V_ASN1_UTF8STRING) { + continue; + } + ASN1_UTF8STRING* xmppAddrValue = otherName->value->value.utf8string; + addXMPPAddress(byteArrayToString(createByteArray(reinterpret_cast<const char*>(ASN1_STRING_data(xmppAddrValue)), ASN1_STRING_length(xmppAddrValue)))); + } + else if (OBJ_cmp(otherName->type_id, dnsSRVObject.get()) == 0) { + // SRVName + if (otherName->value->type != V_ASN1_IA5STRING) { + continue; + } + ASN1_IA5STRING* srvNameValue = otherName->value->value.ia5string; + addSRVName(byteArrayToString(createByteArray(reinterpret_cast<const char*>(ASN1_STRING_data(srvNameValue)), ASN1_STRING_length(srvNameValue)))); + } + } + else if (generalName->type == GEN_DNS) { + // DNSName + addDNSName(byteArrayToString(createByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)))); + } + } + } } } diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificate.h b/Swiften/TLS/OpenSSL/OpenSSLCertificate.h index 897b432..64da82a 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLCertificate.h +++ b/Swiften/TLS/OpenSSL/OpenSSLCertificate.h @@ -1,70 +1,73 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + #include <openssl/ssl.h> -#include <string> #include <Swiften/TLS/Certificate.h> namespace Swift { - class OpenSSLCertificate : public Certificate { - public: - OpenSSLCertificate(boost::shared_ptr<X509>); - OpenSSLCertificate(const ByteArray& der); - - std::string getSubjectName() const { - return subjectName; - } - - std::vector<std::string> getCommonNames() const { - return commonNames; - } - - std::vector<std::string> getSRVNames() const { - return srvNames; - } - - std::vector<std::string> getDNSNames() const { - return dnsNames; - } - - std::vector<std::string> getXMPPAddresses() const { - return xmppAddresses; - } - - ByteArray toDER() const; - - boost::shared_ptr<X509> getInternalX509() const { - return cert; - } - - private: - void parse(); - - void addSRVName(const std::string& name) { - srvNames.push_back(name); - } - - void addDNSName(const std::string& name) { - dnsNames.push_back(name); - } - - void addXMPPAddress(const std::string& addr) { - xmppAddresses.push_back(addr); - } - - private: - boost::shared_ptr<X509> cert; - std::string subjectName; - std::vector<std::string> commonNames; - std::vector<std::string> dnsNames; - std::vector<std::string> xmppAddresses; - std::vector<std::string> srvNames; - }; + class OpenSSLCertificate : public Certificate { + public: + OpenSSLCertificate(std::shared_ptr<X509>); + OpenSSLCertificate(const ByteArray& der); + + std::string getSubjectName() const { + return subjectName; + } + + std::vector<std::string> getCommonNames() const { + return commonNames; + } + + std::vector<std::string> getSRVNames() const { + return srvNames; + } + + std::vector<std::string> getDNSNames() const { + return dnsNames; + } + + std::vector<std::string> getXMPPAddresses() const { + return xmppAddresses; + } + + ByteArray toDER() const; + + std::shared_ptr<X509> getInternalX509() const { + return cert; + } + + void incrementReferenceCount() const; + + private: + void parse(); + + void addSRVName(const std::string& name) { + srvNames.push_back(name); + } + + void addDNSName(const std::string& name) { + dnsNames.push_back(name); + } + + void addXMPPAddress(const std::string& addr) { + xmppAddresses.push_back(addr); + } + + private: + std::shared_ptr<X509> cert; + std::string subjectName; + std::vector<std::string> commonNames; + std::vector<std::string> dnsNames; + std::vector<std::string> xmppAddresses; + std::vector<std::string> srvNames; + }; } diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.cpp b/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.cpp new file mode 100644 index 0000000..73058a5 --- /dev/null +++ b/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h> + +#include <openssl/pem.h> +#include <openssl/err.h> + +namespace Swift { + +OpenSSLCertificateFactory::OpenSSLCertificateFactory() { +} + +OpenSSLCertificateFactory::~OpenSSLCertificateFactory() { +} + +Certificate* OpenSSLCertificateFactory::createCertificateFromDER(const ByteArray& der) { + return new OpenSSLCertificate(der); +} + +std::vector<std::shared_ptr<Certificate>> OpenSSLCertificateFactory::createCertificateChain(const ByteArray& data) { + std::vector<std::shared_ptr<Certificate>> certificateChain; + + if (data.size() > std::numeric_limits<int>::max()) { + return certificateChain; + } + + auto bio = std::shared_ptr<BIO>(BIO_new(BIO_s_mem()), BIO_free); + BIO_write(bio.get(), vecptr(data), int(data.size())); + + // Attempt parsing data as PEM + X509* openSSLCert = nullptr; + auto x509certFromPEM = PEM_read_bio_X509(bio.get(), &openSSLCert, nullptr, nullptr); + if (x509certFromPEM && openSSLCert) { + std::shared_ptr<X509> x509Cert(openSSLCert, X509_free); + certificateChain.emplace_back(std::make_shared<OpenSSLCertificate>(x509Cert)); + openSSLCert = nullptr; + while ((x509certFromPEM = PEM_read_bio_X509(bio.get(), &openSSLCert, nullptr, nullptr)) != nullptr) { + std::shared_ptr<X509> x509Cert(openSSLCert, X509_free); + certificateChain.emplace_back(std::make_shared<OpenSSLCertificate>(x509Cert)); + openSSLCert = nullptr; + } + } + + // Clear any (expected) errors which resulted from PEM parsing + // If we don't do this, any existing TLS context will detect these + // spurious errors and fail to work + ERR_clear_error(); + + return certificateChain; +} + +} diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h b/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h index 52f134c..a6974c8 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h +++ b/Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -10,10 +10,12 @@ #include <Swiften/TLS/OpenSSL/OpenSSLCertificate.h> namespace Swift { - class OpenSSLCertificateFactory : public CertificateFactory { - public: - virtual Certificate::ref createCertificateFromDER(const ByteArray& der) { - return Certificate::ref(new OpenSSLCertificate(der)); - } - }; + class OpenSSLCertificateFactory : public CertificateFactory { + public: + OpenSSLCertificateFactory(); + virtual ~OpenSSLCertificateFactory() override final; + + virtual Certificate* createCertificateFromDER(const ByteArray& der) override final; + virtual std::vector<std::shared_ptr<Certificate>> createCertificateChain(const ByteArray& data) override final; + }; } diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp index 77f780f..86b0504 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp @@ -1,8 +1,9 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ + #include <Swiften/Base/Platform.h> #ifdef SWIFTEN_PLATFORM_WINDOWS @@ -10,15 +11,21 @@ #include <wincrypt.h> #endif +#include <cassert> +#include <memory> #include <vector> + + +#include <openssl/bio.h> #include <openssl/err.h> #include <openssl/pkcs12.h> -#include <boost/smart_ptr/make_shared.hpp> #if defined(SWIFTEN_PLATFORM_MACOSX) #include <Security/Security.h> #endif +#include <Swiften/Base/Log.h> +#include <Swiften/Base/Algorithm.h> #include <Swiften/TLS/OpenSSL/OpenSSLContext.h> #include <Swiften/TLS/OpenSSL/OpenSSLCertificate.h> #include <Swiften/TLS/CertificateWithKey.h> @@ -35,300 +42,834 @@ namespace Swift { static const int MAX_FINISHED_SIZE = 4096; static const int SSL_READ_BUFFERSIZE = 8192; +#define SSL_DEFAULT_VERIFY_DEPTH 5 + +// Callback function declarations for certificate verification +extern "C" { + static int certVerifyCallback(X509_STORE_CTX *store_ctx, void*); + static int verifyCallback(int preverify_ok, X509_STORE_CTX *ctx); +} + static void freeX509Stack(STACK_OF(X509)* stack) { - sk_X509_free(stack); + sk_X509_free(stack); } -OpenSSLContext::OpenSSLContext() : state_(Start), context_(0), handle_(0), readBIO_(0), writeBIO_(0) { - ensureLibraryInitialized(); - context_ = SSL_CTX_new(TLSv1_client_method()); +namespace { + class OpenSSLInitializerFinalizer { + public: + OpenSSLInitializerFinalizer() { + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + + // Disable compression + /* + STACK_OF(SSL_COMP)* compressionMethods = SSL_COMP_get_compression_methods(); + sk_SSL_COMP_zero(compressionMethods);*/ + } + + ~OpenSSLInitializerFinalizer() { + EVP_cleanup(); + } + + OpenSSLInitializerFinalizer(const OpenSSLInitializerFinalizer &) = delete; + }; + + std::unique_ptr<SSL_CTX> createSSL_CTX(OpenSSLContext::Mode mode) { + std::unique_ptr<SSL_CTX> sslCtx; + switch (mode) { + case OpenSSLContext::Mode::Client: + sslCtx = std::unique_ptr<SSL_CTX>(SSL_CTX_new(SSLv23_client_method())); + break; + case OpenSSLContext::Mode::Server: + sslCtx = std::unique_ptr<SSL_CTX>(SSL_CTX_new(SSLv23_server_method())); + break; + } + return sslCtx; + } + + std::string openSSLInternalErrorToString() { + auto bio = std::shared_ptr<BIO>(BIO_new(BIO_s_mem()), BIO_free); + ERR_print_errors(bio.get()); + std::string errorString; + errorString.resize(BIO_pending(bio.get())); + BIO_read(bio.get(), (void*)errorString.data(), errorString.size()); + return errorString; + } + } + +OpenSSLContext::OpenSSLContext(const TLSOptions& options, Mode mode) : mode_(mode), state_(State::Start) { + ensureLibraryInitialized(); + context_ = createSSL_CTX(mode_); + SSL_CTX_set_options(context_.get(), SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + + if (mode_ == Mode::Server) { +#if OPENSSL_VERSION_NUMBER < 0x1010 + // Automatically select highest preference curve used for ECDH temporary keys used during + // key exchange if possible. + // Since version 1.1.0, this option is always enabled. + SSL_CTX_set_ecdh_auto(context_.get(), 1); +#endif + + SSL_CTX_set_tlsext_servername_arg(context_.get(), this); + SSL_CTX_set_tlsext_servername_callback(context_.get(), OpenSSLContext::handleServerNameCallback); + } + + // TODO: implement CRL checking + // TODO: download CRL (HTTP transport) + // TODO: cache CRL downloads for configurable time period - // TODO: implement CRL checking - // TODO: download CRL (HTTP transport) - // TODO: cache CRL downloads for configurable time period + // TODO: implement OCSP support + // TODO: handle OCSP stapling see https://www.rfc-editor.org/rfc/rfc4366.txt - // TODO: implement OCSP support - // TODO: handle OCSP stapling see https://www.rfc-editor.org/rfc/rfc4366.txt - // Load system certs + // Default for ignoreSystemTrustAnchors is false, i.e. load System TAs by default, + // to preserve previous behaviour + if (!options.ignoreSystemTrustAnchors) { + // Load system certs #if defined(SWIFTEN_PLATFORM_WINDOWS) - X509_STORE* store = SSL_CTX_get_cert_store(context_); - HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT"); - if (systemStore) { - PCCERT_CONTEXT certContext = NULL; - while (true) { - certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext); - if (!certContext) { - break; - } - OpenSSLCertificate cert(createByteArray(certContext->pbCertEncoded, certContext->cbCertEncoded)); - if (store && cert.getInternalX509()) { - X509_STORE_add_cert(store, cert.getInternalX509().get()); - } - } - } + X509_STORE* store = SSL_CTX_get_cert_store(context_.get()); + HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT"); + if (systemStore) { + PCCERT_CONTEXT certContext = nullptr; + while (true) { + certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, certContext); + if (!certContext) { + break; + } + OpenSSLCertificate cert(createByteArray(certContext->pbCertEncoded, certContext->cbCertEncoded)); + if (store && cert.getInternalX509()) { + X509_STORE_add_cert(store, cert.getInternalX509().get()); + } + } + } #elif !defined(SWIFTEN_PLATFORM_MACOSX) - SSL_CTX_load_verify_locations(context_, NULL, "/etc/ssl/certs"); -#elif defined(SWIFTEN_PLATFORM_MACOSX) - // On Mac OS X 10.5 (OpenSSL < 0.9.8), OpenSSL does not automatically look in the system store. - // On Mac OS X 10.6 (OpenSSL >= 0.9.8), OpenSSL *does* look in the system store to determine trust. - // However, if there is a certificate error, it will always emit the "Invalid CA" error if we didn't add - // the certificates first. See - // http://opensource.apple.com/source/OpenSSL098/OpenSSL098-27/src/crypto/x509/x509_vfy_apple.c - // to understand why. We therefore add all certs from the system store ourselves. - X509_STORE* store = SSL_CTX_get_cert_store(context_); - CFArrayRef anchorCertificates; - if (SecTrustCopyAnchorCertificates(&anchorCertificates) == 0) { - for (int i = 0; i < CFArrayGetCount(anchorCertificates); ++i) { - SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(anchorCertificates, i))); - CSSM_DATA certCSSMData; - if (SecCertificateGetData(cert, &certCSSMData) != 0 || certCSSMData.Length == 0) { - continue; - } - std::vector<unsigned char> certData; - certData.resize(certCSSMData.Length); - memcpy(&certData[0], certCSSMData.Data, certCSSMData.Length); - OpenSSLCertificate certificate(certData); - if (store && certificate.getInternalX509()) { - X509_STORE_add_cert(store, certificate.getInternalX509().get()); - } - } - CFRelease(anchorCertificates); - } + SSL_CTX_set_default_verify_paths(context_.get()); +#elif defined(SWIFTEN_PLATFORM_MACOSX) && !defined(SWIFTEN_PLATFORM_IPHONE) + // On Mac OS X 10.5 (OpenSSL < 0.9.8), OpenSSL does not automatically look in the system store. + // On Mac OS X 10.6 (OpenSSL >= 0.9.8), OpenSSL *does* look in the system store to determine trust. + // However, if there is a certificate error, it will always emit the "Invalid CA" error if we didn't add + // the certificates first. See + // http://opensource.apple.com/source/OpenSSL098/OpenSSL098-27/src/crypto/x509/x509_vfy_apple.c + // to understand why. We therefore add all certs from the system store ourselves. + X509_STORE* store = SSL_CTX_get_cert_store(context_.get()); + CFArrayRef anchorCertificates; + if (SecTrustCopyAnchorCertificates(&anchorCertificates) == 0) { + for (int i = 0; i < CFArrayGetCount(anchorCertificates); ++i) { + SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(anchorCertificates, i))); + CSSM_DATA certCSSMData; + if (SecCertificateGetData(cert, &certCSSMData) != 0 || certCSSMData.Length == 0) { + continue; + } + std::vector<unsigned char> certData; + certData.resize(certCSSMData.Length); + memcpy(&certData[0], certCSSMData.Data, certCSSMData.Length); + OpenSSLCertificate certificate(certData); + if (store && certificate.getInternalX509()) { + X509_STORE_add_cert(store, certificate.getInternalX509().get()); + } + } + CFRelease(anchorCertificates); + } #endif + } + configure(options); } OpenSSLContext::~OpenSSLContext() { - SSL_free(handle_); - SSL_CTX_free(context_); } void OpenSSLContext::ensureLibraryInitialized() { - static bool isLibraryInitialized = false; - if (!isLibraryInitialized) { - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); - - // Disable compression - /* - STACK_OF(SSL_COMP)* compressionMethods = SSL_COMP_get_compression_methods(); - sk_SSL_COMP_zero(compressionMethods);*/ - - isLibraryInitialized = true; - } + static OpenSSLInitializerFinalizer openSSLInit; +} + +void OpenSSLContext::initAndSetBIOs() { + // Ownership of BIOs is transferred + readBIO_ = BIO_new(BIO_s_mem()); + writeBIO_ = BIO_new(BIO_s_mem()); + SSL_set_bio(handle_.get(), readBIO_, writeBIO_); +} + +// This callback is called by OpenSSL when a client certificate needs to be verified. +// In turn, this calls the verification callback which the user +// of this OpenSSLContext has configured (if any). +static int certVerifyCallback(X509_STORE_CTX* store_ctx, void* arg) +{ + OpenSSLContext* context = static_cast<OpenSSLContext *>(arg); + + // Need to stash store_ctx pointer for use within verification + context->setX509StoreContext(store_ctx); + + int ret; + + // This callback shouldn't have been set up if the context doesn't + // have a verifyCertCallback set, but it doesn't hurt to double check + std::function<int (const TLSContext *)> cb = context->getVerifyCertCallback(); + if (cb != nullptr) { + ret = cb(static_cast<const OpenSSLContext*>(context)); + } else { + SWIFT_LOG(debug) << "certVerifyCallback called but context.verifyCertCallback is unset"; + ret = 0; + } + + context->setX509StoreContext(nullptr); + return ret; +} + +// Convenience function to generate a text representation +// of an X509 Name. This information is only used for logging. +static std::string X509_NAME_to_text(X509_NAME* name) +{ + std::string nameString; + + if (!name) { + return nameString; + } + + std::unique_ptr<BIO, decltype(&BIO_free)> io(BIO_new(BIO_s_mem()), &BIO_free); + int r = X509_NAME_print_ex(io.get(), name, 0, XN_FLAG_RFC2253); + BIO_write(io.get(), "\0", 1); + + if (r > 0) { + BUF_MEM* ptr = nullptr; + BIO_get_mem_ptr(io.get(), &ptr); + nameString = ptr->data; + } + + return nameString; +} + +// Check depth of certificate chain +static int verifyCallback(int preverifyOk, X509_STORE_CTX* ctx) +{ + // Retrieve the pointer to the SSL of the connection currently treated + // and the application specific data stored into the SSL object. + + int err = X509_STORE_CTX_get_error(ctx); + int depth = X509_STORE_CTX_get_error_depth(ctx); + + SSL* ssl = static_cast<SSL*>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); + SSL_CTX* sslctx = ssl ? SSL_get_SSL_CTX(ssl) : nullptr; + if (!sslctx) { + SWIFT_LOG(debug) << "verifyCallback: internal error"; + return preverifyOk; + } + + if (SSL_CTX_get_verify_mode(sslctx) == SSL_VERIFY_NONE) { + SWIFT_LOG(debug) << "verifyCallback: no verification required"; + // No verification requested + return 1; + } + + X509* errCert = X509_STORE_CTX_get_current_cert(ctx); + std::string subjectString; + if (errCert) { + X509_NAME* subjectName = X509_get_subject_name(errCert); + subjectString = X509_NAME_to_text(subjectName); + } + + // Catch a too long certificate chain. The depth limit set using + // SSL_CTX_set_verify_depth() is by purpose set to "limit+1" so + // that whenever the "depth>verify_depth" condition is met, we + // have violated the limit and want to log this error condition. + // We must do it here, because the CHAIN_TOO_LONG error would not + // be found explicitly; only errors introduced by cutting off the + // additional certificates would be logged. + if (depth >= SSL_CTX_get_verify_depth(sslctx)) { + preverifyOk = 0; + err = X509_V_ERR_CERT_CHAIN_TOO_LONG; + X509_STORE_CTX_set_error(ctx, err); + } + + if (!preverifyOk) { + std::string issuerString; + if (errCert) { + X509_NAME* issuerName = X509_get_issuer_name(errCert); + issuerString = X509_NAME_to_text(issuerName); + } + SWIFT_LOG(debug) << "verifyCallback: verification error " << + X509_verify_cert_error_string(err) << " depth: " << + depth << " issuer: " << ((issuerString.length() > 0) ? issuerString : "<unknown>"); + } else { + SWIFT_LOG(debug) << "verifyCallback: SSL depth: " << depth << " Subject: " << + ((subjectString.length() > 0) ? subjectString : "<>"); + } + // Always return "OK", as check on verification status + // will be performed once TLS handshake has completed, + // by calling OpenSSLContext::getVerificationErrorTypeForResult() to + // get the value set via X509_STORE_CTX_set_error() above. + return 1; +} + +bool OpenSSLContext::configure(const TLSOptions &options) +{ + if (options.cipherSuites) { + std::string cipherSuites = *(options.cipherSuites); + if (SSL_CTX_set_cipher_list(context_.get(), cipherSuites.c_str()) != 1 ) { + SWIFT_LOG(debug) << "Failed to set cipher-suites"; + return false; + } + } + + if (options.context) { + const auto& contextId = *options.context; + + if (SSL_CTX_set_session_id_context(context_.get(), + reinterpret_cast<const unsigned char *>(contextId.c_str()), + contextId.length()) != 1) { + SWIFT_LOG(debug) << "Failed to set context-id"; + return false; + } + } + + if (options.sessionCacheTimeout) { + int scto = *options.sessionCacheTimeout; + if (scto <= 0) { + SWIFT_LOG(debug) << "Invalid value for session-cache-timeout"; + return false; + } + (void)SSL_CTX_set_timeout(context_.get(), scto); + if (SSL_CTX_get_timeout(context_.get()) != scto) { + SWIFT_LOG(debug) << "Failed to set session-cache-timeout"; + return false; + } + } + + if (options.verifyCertificateCallback) { + verifyCertCallback = *options.verifyCertificateCallback; + } else { + verifyCertCallback = nullptr; + } + + if (options.verifyMode) { + TLSOptions::VerifyMode verify_mode = *options.verifyMode; + int mode; + switch (verify_mode) { + case TLSOptions::VerifyMode::None: + mode = SSL_VERIFY_NONE; + break; + case TLSOptions::VerifyMode::Required: + mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE; + break; + case TLSOptions::VerifyMode::Optional: + mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; + break; + } + + // Set up default certificate chain verification depth - may be overridden below + SSL_CTX_set_verify_depth(context_.get(), SSL_DEFAULT_VERIFY_DEPTH + 1); + + // Set callbacks up + SSL_CTX_set_verify(context_.get(), mode, verifyCallback); + + // Only set up certificate verification callback if a user callback has + // been configured via the TLSOptions + if (verifyCertCallback != nullptr) { + SSL_CTX_set_cert_verify_callback(context_.get(), certVerifyCallback, this); + } + } + + if (options.verifyDepth) { + int depth = *options.verifyDepth; + if (depth <= 0) { + SWIFT_LOG(debug) << "Invalid value for verify-depth"; + return false; + } + + // Increase depth limit by one, so that verifyCallback() will log it + SSL_CTX_set_verify_depth(context_.get(), depth + 1); + } + + auto updateOptionIfPresent = [this](boost::optional<bool> option, int flag) { + if (option) { + if (*option) { + SSL_CTX_set_options(context_.get(), flag); + } + else { + SSL_CTX_clear_options(context_.get(), flag); + } + } + }; + updateOptionIfPresent(options.workaroundMicrosoftSessID, SSL_OP_MICROSOFT_SESS_ID_BUG); + updateOptionIfPresent(options.workaroundNetscapeChallenge, SSL_OP_NETSCAPE_CHALLENGE_BUG); + updateOptionIfPresent(options.workaroundNetscapeReuseCipherChange, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG); + updateOptionIfPresent(options.workaroundSSLRef2ReuseCertType, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG); + updateOptionIfPresent(options.workaroundMicrosoftBigSSLv3Buffer, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER); + updateOptionIfPresent(options.workaroundSSLeay080ClientDH, SSL_OP_SSLEAY_080_CLIENT_DH_BUG); + updateOptionIfPresent(options.workaroundTLSD5, SSL_OP_TLS_D5_BUG); + updateOptionIfPresent(options.workaroundTLSBlockPadding, SSL_OP_TLS_BLOCK_PADDING_BUG); + updateOptionIfPresent(options.workaroundDontInsertEmptyFragments, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); + updateOptionIfPresent(options.workaroundAll, SSL_OP_ALL); + updateOptionIfPresent(options.suppressSSLv2, SSL_OP_NO_SSLv2); + updateOptionIfPresent(options.suppressSSLv3, SSL_OP_NO_SSLv3); + updateOptionIfPresent(options.suppressTLSv1, SSL_OP_NO_TLSv1); + updateOptionIfPresent(options.disableTLSRollBackBug, SSL_OP_TLS_ROLLBACK_BUG); + updateOptionIfPresent(options.singleDHUse, SSL_OP_SINGLE_DH_USE); + + if (options.trustAnchors) { + // Add any additional Trust Anchors which are present in the TLSOptions + X509_STORE* store = SSL_CTX_get_cert_store(context_.get()); + + if (store) { + for (auto& certificate : *options.trustAnchors) { + auto openSSLCert = dynamic_cast<OpenSSLCertificate*>(certificate.get()); + if (openSSLCert && openSSLCert->getInternalX509()) { + X509_STORE_add_cert(store, openSSLCert->getInternalX509().get()); + // Don't need to increment reference count as X509_STORE_add_cert does thiS + } + } + } + } + + return true; +} + + +void OpenSSLContext::accept() { + assert(mode_ == Mode::Server); + handle_ = std::unique_ptr<SSL>(SSL_new(context_.get())); + if (!handle_) { + state_ = State::Error; + onError(std::make_shared<TLSError>(TLSError::AcceptFailed, openSSLInternalErrorToString())); + return; + } + + initAndSetBIOs(); + + state_ = State::Accepting; + doAccept(); } void OpenSSLContext::connect() { - handle_ = SSL_new(context_); - // Ownership of BIOs is ransferred - readBIO_ = BIO_new(BIO_s_mem()); - writeBIO_ = BIO_new(BIO_s_mem()); - SSL_set_bio(handle_, readBIO_, writeBIO_); - - state_ = Connecting; - doConnect(); + connect(std::string()); +} + +void OpenSSLContext::connect(const std::string& requestedServerName) { + assert(mode_ == Mode::Client); + handle_ = std::unique_ptr<SSL>(SSL_new(context_.get())); + if (!handle_) { + state_ = State::Error; + onError(std::make_shared<TLSError>(TLSError::ConnectFailed, openSSLInternalErrorToString())); + return; + } + + if (!requestedServerName.empty()) { + if (SSL_set_tlsext_host_name(handle_.get(), const_cast<char*>(requestedServerName.c_str())) != 1) { + onError(std::make_shared<TLSError>(TLSError::ConnectFailed, "Failed to set Server Name Indication: " + openSSLInternalErrorToString()));\ + return; + } + } + + // Ownership of BIOs is transferred to the SSL_CTX instance in handle_. + initAndSetBIOs(); + + state_ = State::Connecting; + doConnect(); +} + +void OpenSSLContext::doAccept() { + auto acceptResult = SSL_accept(handle_.get()); + auto error = SSL_get_error(handle_.get(), acceptResult); + switch (error) { + case SSL_ERROR_NONE: { + state_ = State::Connected; + //std::cout << x->name << std::endl; + //const char* comp = SSL_get_current_compression(handle_.get()); + //std::cout << "Compression: " << SSL_COMP_get_name(comp) << std::endl; + onConnected(); + // The following call is important so the client knowns the handshake is finished. + sendPendingDataToNetwork(); + sendPendingDataToApplication(); + break; + } + case SSL_ERROR_WANT_READ: + sendPendingDataToNetwork(); + break; + case SSL_ERROR_WANT_WRITE: + sendPendingDataToNetwork(); + break; + default: + state_ = State::Error; + onError(std::make_shared<TLSError>(TLSError::AcceptFailed, openSSLInternalErrorToString())); + sendPendingDataToNetwork(); + } } void OpenSSLContext::doConnect() { - int connectResult = SSL_connect(handle_); - int error = SSL_get_error(handle_, connectResult); - switch (error) { - case SSL_ERROR_NONE: { - state_ = Connected; - //std::cout << x->name << std::endl; - //const char* comp = SSL_get_current_compression(handle_); - //std::cout << "Compression: " << SSL_COMP_get_name(comp) << std::endl; - onConnected(); - break; - } - case SSL_ERROR_WANT_READ: - sendPendingDataToNetwork(); - break; - default: - state_ = Error; - onError(boost::make_shared<TLSError>()); - } + int connectResult = SSL_connect(handle_.get()); + int error = SSL_get_error(handle_.get(), connectResult); + switch (error) { + case SSL_ERROR_NONE: { + state_ = State::Connected; + //std::cout << x->name << std::endl; + //const char* comp = SSL_get_current_compression(handle_.get()); + //std::cout << "Compression: " << SSL_COMP_get_name(comp) << std::endl; + onConnected(); + // The following is needed since OpenSSL 1.1.1 for the server to be able to calculate the + // TLS finish message. + sendPendingDataToNetwork(); + break; + } + case SSL_ERROR_WANT_READ: + sendPendingDataToNetwork(); + break; + default: + state_ = State::Error; + onError(std::make_shared<TLSError>()); + onError(std::make_shared<TLSError>(TLSError::ConnectFailed, openSSLInternalErrorToString())); + } +} + +int OpenSSLContext::handleServerNameCallback(SSL* ssl, int*, void* arg) { + if (ssl == nullptr) + return SSL_TLSEXT_ERR_NOACK; + + const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (servername) { + auto serverNameString = std::string(servername); + auto context = reinterpret_cast<OpenSSLContext*>(arg); + context->onServerNameRequested(serverNameString); + + if (context->abortTLSHandshake_) { + context->abortTLSHandshake_ = false; + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + } + return SSL_TLSEXT_ERR_OK; } void OpenSSLContext::sendPendingDataToNetwork() { - int size = BIO_pending(writeBIO_); - if (size > 0) { - SafeByteArray data; - data.resize(size); - BIO_read(writeBIO_, vecptr(data), size); - onDataForNetwork(data); - } + int size = BIO_pending(writeBIO_); + if (size > 0) { + SafeByteArray data; + data.resize(size); + BIO_read(writeBIO_, vecptr(data), size); + onDataForNetwork(data); + } } void OpenSSLContext::handleDataFromNetwork(const SafeByteArray& data) { - BIO_write(readBIO_, vecptr(data), data.size()); - switch (state_) { - case Connecting: - doConnect(); - break; - case Connected: - sendPendingDataToApplication(); - break; - case Start: assert(false); break; - case Error: /*assert(false);*/ break; - } + BIO_write(readBIO_, vecptr(data), data.size()); + switch (state_) { + case State::Accepting: + doAccept(); + break; + case State::Connecting: + doConnect(); + break; + case State::Connected: + sendPendingDataToApplication(); + break; + case State::Start: assert(false); break; + case State::Error: /*assert(false);*/ break; + } } void OpenSSLContext::handleDataFromApplication(const SafeByteArray& data) { - if (SSL_write(handle_, vecptr(data), data.size()) >= 0) { - sendPendingDataToNetwork(); - } - else { - state_ = Error; - onError(boost::make_shared<TLSError>()); - } + auto ret = SSL_write(handle_.get(), vecptr(data), data.size()); + if (ret > 0 || SSL_get_error(handle_.get(), ret) == SSL_ERROR_WANT_READ) { + sendPendingDataToNetwork(); + } + else { + state_ = State::Error; + onError(std::make_shared<TLSError>(TLSError::UnknownError, openSSLInternalErrorToString())); + } } void OpenSSLContext::sendPendingDataToApplication() { - SafeByteArray data; - data.resize(SSL_READ_BUFFERSIZE); - int ret = SSL_read(handle_, vecptr(data), data.size()); - while (ret > 0) { - data.resize(ret); - onDataForApplication(data); - data.resize(SSL_READ_BUFFERSIZE); - ret = SSL_read(handle_, vecptr(data), data.size()); - } - if (ret < 0 && SSL_get_error(handle_, ret) != SSL_ERROR_WANT_READ) { - state_ = Error; - onError(boost::make_shared<TLSError>()); - } + SafeByteArray data; + data.resize(SSL_READ_BUFFERSIZE); + int ret = SSL_read(handle_.get(), vecptr(data), data.size()); + while (ret > 0) { + data.resize(ret); + onDataForApplication(data); + data.resize(SSL_READ_BUFFERSIZE); + ret = SSL_read(handle_.get(), vecptr(data), data.size()); + } + if (ret < 0 && SSL_get_error(handle_.get(), ret) != SSL_ERROR_WANT_READ) { + state_ = State::Error; + onError(std::make_shared<TLSError>(TLSError::UnknownError, openSSLInternalErrorToString())); + } +} + +bool OpenSSLContext::setCertificateChain(const std::vector<std::shared_ptr<Certificate>>& certificateChain) { + if (certificateChain.size() == 0) { + SWIFT_LOG(debug) << "Trying to load empty certificate chain."; + return false; + } + + // load endpoint certificate + auto openSSLCert = dynamic_cast<OpenSSLCertificate*>(certificateChain[0].get()); + if (!openSSLCert) { + return false; + } + + // This increments the reference count on the X509 certificate automatically + if (SSL_CTX_use_certificate(context_.get(), openSSLCert->getInternalX509().get()) != 1) { + return false; + } + + if (certificateChain.size() > 1) { + for (auto certificate = certificateChain.begin() + 1; certificate != certificateChain.end(); ++certificate) { + auto openSSLCert = dynamic_cast<OpenSSLCertificate*>(certificate->get()); + if (!openSSLCert) { + return false; + } + + if (SSL_CTX_add_extra_chain_cert(context_.get(), openSSLCert->getInternalX509().get()) != 1) { + SWIFT_LOG(debug) << "Trying to load empty certificate chain."; + return false; + } + // Have to manually increment reference count as SSL_CTX_add_extra_chain_cert does not do so + openSSLCert->incrementReferenceCount(); + } + } + + if (handle_) { + // This workaround is needed as OpenSSL has a shortcut to not do anything + // if you set the SSL_CTX to the existing SSL_CTX and not reloading the + // certificates from the SSL_CTX. + auto dummyContext = createSSL_CTX(mode_); + SSL_set_SSL_CTX(handle_.get(), dummyContext.get()); + SSL_set_SSL_CTX(handle_.get(), context_.get()); + } + + return true; +} + +int empty_or_preset_password_cb(char* buf, int max_len, int flag, void* password); + +int empty_or_preset_password_cb(char* buf, int max_len, int /* flag */, void* password) { + char* charPassword = (char*)password; + if (charPassword == nullptr) { + return 0; + } + int len = strlen(charPassword); + if(len > max_len) { + return 0; + } + memcpy(buf, charPassword, len); + return len; +} + +bool OpenSSLContext::setPrivateKey(const PrivateKey::ref& privateKey) { + if (privateKey->getData().size() > std::numeric_limits<int>::max()) { + return false; + } + + auto bio = std::shared_ptr<BIO>(BIO_new(BIO_s_mem()), BIO_free); + BIO_write(bio.get(), vecptr(privateKey->getData()), int(privateKey->getData().size())); + + SafeByteArray safePassword; + void* password = nullptr; + if (privateKey->getPassword()) { + safePassword = privateKey->getPassword().get(); + safePassword.push_back(0); + password = safePassword.data(); + } + // Make sure resultKey is tidied up by wrapping it in a shared_ptr + auto resultKey = std::shared_ptr<EVP_PKEY>(PEM_read_bio_PrivateKey(bio.get(), nullptr, empty_or_preset_password_cb, password), EVP_PKEY_free); + if (resultKey) { + if (handle_) { + auto result = SSL_use_PrivateKey(handle_.get(), resultKey.get()); + if (result != 1) { + return false; + } + } + else { + auto result = SSL_CTX_use_PrivateKey(context_.get(), resultKey.get()); + if (result != 1) { + return false; + } + } + } + else { + return false; + } + return true; +} + +void OpenSSLContext::setAbortTLSHandshake(bool abort) { + abortTLSHandshake_ = abort; } bool OpenSSLContext::setClientCertificate(CertificateWithKey::ref certificate) { - boost::shared_ptr<PKCS12Certificate> pkcs12Certificate = boost::dynamic_pointer_cast<PKCS12Certificate>(certificate); - if (!pkcs12Certificate || pkcs12Certificate->isNull()) { - return false; - } - - // Create a PKCS12 structure - BIO* bio = BIO_new(BIO_s_mem()); - BIO_write(bio, vecptr(pkcs12Certificate->getData()), pkcs12Certificate->getData().size()); - boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free); - BIO_free(bio); - if (!pkcs12) { - return false; - } - - // Parse PKCS12 - X509 *certPtr = 0; - EVP_PKEY* privateKeyPtr = 0; - STACK_OF(X509)* caCertsPtr = 0; - int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(pkcs12Certificate->getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr); - if (result != 1) { - return false; - } - boost::shared_ptr<X509> cert(certPtr, X509_free); - boost::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free); - boost::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack); - - // Use the key & certificates - if (SSL_CTX_use_certificate(context_, cert.get()) != 1) { - return false; - } - if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) { - return false; - } - for (int i = 0; i < sk_X509_num(caCerts.get()); ++i) { - SSL_CTX_add_extra_chain_cert(context_, sk_X509_value(caCerts.get(), i)); - } - return true; + std::shared_ptr<PKCS12Certificate> pkcs12Certificate = std::dynamic_pointer_cast<PKCS12Certificate>(certificate); + if (!pkcs12Certificate || pkcs12Certificate->isNull()) { + return false; + } + + // Create a PKCS12 structure + BIO* bio = BIO_new(BIO_s_mem()); + BIO_write(bio, vecptr(pkcs12Certificate->getData()), pkcs12Certificate->getData().size()); + std::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, nullptr), PKCS12_free); + BIO_free(bio); + if (!pkcs12) { + return false; + } + + // Parse PKCS12 + X509 *certPtr = nullptr; + EVP_PKEY* privateKeyPtr = nullptr; + STACK_OF(X509)* caCertsPtr = nullptr; + SafeByteArray password(pkcs12Certificate->getPassword()); + password.push_back(0); + int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(password)), &privateKeyPtr, &certPtr, &caCertsPtr); + if (result != 1) { + return false; + } + std::shared_ptr<X509> cert(certPtr, X509_free); + std::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free); + std::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack); + + // Use the key & certificates + if (SSL_CTX_use_certificate(context_.get(), cert.get()) != 1) { + return false; + } + if (SSL_CTX_use_PrivateKey(context_.get(), privateKey.get()) != 1) { + return false; + } + for (int i = 0; i < sk_X509_num(caCerts.get()); ++i) { + SSL_CTX_add_extra_chain_cert(context_.get(), sk_X509_value(caCerts.get(), i)); + } + return true; +} + +bool OpenSSLContext::setDiffieHellmanParameters(const ByteArray& parametersInOpenSslDer) { + auto bio = std::unique_ptr<BIO, decltype(&BIO_free)>(BIO_new(BIO_s_mem()), BIO_free); + if (bio) { + BIO_write(bio.get(), vecptr(parametersInOpenSslDer), parametersInOpenSslDer.size()); + auto result = 0L; + if (auto dhparams = d2i_DHparams_bio(bio.get(), nullptr)) { + if (handle_) { + result = SSL_set_tmp_dh(handle_.get(), dhparams); + } + else { + result = SSL_CTX_set_tmp_dh(context_.get(), dhparams); + } + DH_free(dhparams); + } + return result == 1; + } + return false; } std::vector<Certificate::ref> OpenSSLContext::getPeerCertificateChain() const { - std::vector<Certificate::ref> result; - STACK_OF(X509)* chain = SSL_get_peer_cert_chain(handle_); - for (int i = 0; i < sk_X509_num(chain); ++i) { - boost::shared_ptr<X509> x509Cert(X509_dup(sk_X509_value(chain, i)), X509_free); - - Certificate::ref cert = boost::make_shared<OpenSSLCertificate>(x509Cert); - result.push_back(cert); - } - return result; + std::vector<Certificate::ref> result; + + // When this context is a server, the peer (client) certificate + // is obtained via SSL_get_peer_certificate, and any other + // certificates set by the peer are available via SSL_get_peer_cert_chain. + // When this context is a client, all of the server's certificates are + // obtained using SSL_get_peer_cert_chain + if (mode_ == Mode::Server) { + auto cert = SSL_get_peer_certificate(handle_.get()); + if (cert) { + // Do not need to copy the returned cert as SSL_get_peer_certificate + // increments the reference count on the certificate + std::shared_ptr<X509> x509Cert(cert, X509_free); + Certificate::ref cert = std::make_shared<OpenSSLCertificate>(x509Cert); + result.push_back(cert); + } + } + + STACK_OF(X509)* chain = SSL_get_peer_cert_chain(handle_.get()); + for (int i = 0; i < sk_X509_num(chain); ++i) { + // Here we do need to copy the returned cert, since SSL_get_peer_cert_chain + // does not increment the reference count on each certificate + std::shared_ptr<X509> x509Cert(X509_dup(sk_X509_value(chain, i)), X509_free); + + Certificate::ref cert = std::make_shared<OpenSSLCertificate>(x509Cert); + result.push_back(cert); + } + + return result; } -boost::shared_ptr<CertificateVerificationError> OpenSSLContext::getPeerCertificateVerificationError() const { - int verifyResult = SSL_get_verify_result(handle_); - if (verifyResult != X509_V_OK) { - return boost::make_shared<CertificateVerificationError>(getVerificationErrorTypeForResult(verifyResult)); - } - else { - return boost::shared_ptr<CertificateVerificationError>(); - } +std::shared_ptr<CertificateVerificationError> OpenSSLContext::getPeerCertificateVerificationError() const { + int verifyResult = SSL_get_verify_result(handle_.get()); + if (verifyResult != X509_V_OK) { + return std::make_shared<CertificateVerificationError>(getVerificationErrorTypeForResult(verifyResult)); + } + else { + return std::shared_ptr<CertificateVerificationError>(); + } } ByteArray OpenSSLContext::getFinishMessage() const { - ByteArray data; - data.resize(MAX_FINISHED_SIZE); - size_t size = SSL_get_finished(handle_, vecptr(data), data.size()); - data.resize(size); - return data; + ByteArray data; + data.resize(MAX_FINISHED_SIZE); + auto size = SSL_get_finished(handle_.get(), vecptr(data), data.size()); + data.resize(size); + return data; } +ByteArray OpenSSLContext::getPeerFinishMessage() const { + ByteArray data; + data.resize(MAX_FINISHED_SIZE); + auto size = SSL_get_peer_finished(handle_.get(), vecptr(data), data.size()); + data.resize(size); + return data; + } + CertificateVerificationError::Type OpenSSLContext::getVerificationErrorTypeForResult(int result) { - assert(result != 0); - switch (result) { - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - return CertificateVerificationError::NotYetValid; - - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - return CertificateVerificationError::Expired; - - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - return CertificateVerificationError::SelfSigned; - - case X509_V_ERR_CERT_UNTRUSTED: - return CertificateVerificationError::Untrusted; - - case X509_V_ERR_CERT_REJECTED: - return CertificateVerificationError::Rejected; - - case X509_V_ERR_INVALID_PURPOSE: - return CertificateVerificationError::InvalidPurpose; - - case X509_V_ERR_PATH_LENGTH_EXCEEDED: - return CertificateVerificationError::PathLengthExceeded; - - case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: - case X509_V_ERR_CERT_SIGNATURE_FAILURE: - case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - return CertificateVerificationError::InvalidSignature; - - case X509_V_ERR_INVALID_CA: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - return CertificateVerificationError::InvalidCA; - - case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: - case X509_V_ERR_AKID_SKID_MISMATCH: - case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: - case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: - return CertificateVerificationError::UnknownError; - - // Unused / should not happen - case X509_V_ERR_CERT_REVOKED: - case X509_V_ERR_OUT_OF_MEM: - case X509_V_ERR_UNABLE_TO_GET_CRL: - case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: - case X509_V_ERR_CRL_SIGNATURE_FAILURE: - case X509_V_ERR_CRL_NOT_YET_VALID: - case X509_V_ERR_CRL_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: - case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: - case X509_V_ERR_CERT_CHAIN_TOO_LONG: - case X509_V_ERR_APPLICATION_VERIFICATION: - default: - return CertificateVerificationError::UnknownError; - } + assert(result != 0); + switch (result) { + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + return CertificateVerificationError::NotYetValid; + + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + return CertificateVerificationError::Expired; + + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + return CertificateVerificationError::SelfSigned; + + case X509_V_ERR_CERT_UNTRUSTED: + return CertificateVerificationError::Untrusted; + + case X509_V_ERR_CERT_REJECTED: + return CertificateVerificationError::Rejected; + + case X509_V_ERR_INVALID_PURPOSE: + return CertificateVerificationError::InvalidPurpose; + + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + return CertificateVerificationError::PathLengthExceeded; + + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + return CertificateVerificationError::InvalidSignature; + + case X509_V_ERR_INVALID_CA: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + return CertificateVerificationError::InvalidCA; + + case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: + case X509_V_ERR_AKID_SKID_MISMATCH: + case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: + case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: + return CertificateVerificationError::UnknownError; + + // Unused / should not happen + case X509_V_ERR_CERT_REVOKED: + case X509_V_ERR_OUT_OF_MEM: + case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CRL_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + case X509_V_ERR_APPLICATION_VERIFICATION: + default: + return CertificateVerificationError::UnknownError; + } } } diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.h b/Swiften/TLS/OpenSSL/OpenSSLContext.h index d4327ca..8eb5758 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.h +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.h @@ -1,53 +1,92 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <openssl/ssl.h> -#include <Swiften/Base/boost_bsignals.h> +#include <memory> + #include <boost/noncopyable.hpp> +#include <boost/signals2.hpp> + +#include <openssl/ssl.h> -#include <Swiften/TLS/TLSContext.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/TLS/CertificateWithKey.h> +#include <Swiften/TLS/TLSContext.h> +#include <Swiften/TLS/TLSOptions.h> + +namespace std { + template<> + class default_delete<SSL_CTX> { + public: + void operator()(SSL_CTX *ptr) { + SSL_CTX_free(ptr); + } + }; + + template<> + class default_delete<SSL> { + public: + void operator()(SSL *ptr) { + SSL_free(ptr); + } + }; +} namespace Swift { + class OpenSSLContext : public TLSContext, boost::noncopyable { + public: + OpenSSLContext(const TLSOptions& options, Mode mode); + virtual ~OpenSSLContext() override final; - class OpenSSLContext : public TLSContext, boost::noncopyable { - public: - OpenSSLContext(); - ~OpenSSLContext(); + void accept() override final; + void connect() override final; + void connect(const std::string& requestHostname) override final; - void connect(); - bool setClientCertificate(CertificateWithKey::ref cert); + bool setCertificateChain(const std::vector<std::shared_ptr<Certificate>>& certificateChain) override final; + bool setPrivateKey(const PrivateKey::ref& privateKey) override final; + bool setClientCertificate(CertificateWithKey::ref cert) override final; + void setAbortTLSHandshake(bool abort) override final; + bool setDiffieHellmanParameters(const ByteArray& parametersInOpenSslDer) override final; - void handleDataFromNetwork(const SafeByteArray&); - void handleDataFromApplication(const SafeByteArray&); + void handleDataFromNetwork(const SafeByteArray&) override final; + void handleDataFromApplication(const SafeByteArray&) override final; - std::vector<Certificate::ref> getPeerCertificateChain() const; - boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; + std::vector<Certificate::ref> getPeerCertificateChain() const override final; + std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const override final; - virtual ByteArray getFinishMessage() const; + virtual ByteArray getFinishMessage() const override final; + virtual ByteArray getPeerFinishMessage() const override final; - private: - static void ensureLibraryInitialized(); + void setX509StoreContext(X509_STORE_CTX *ptr) { x509_store_ctx = ptr; } + std::function<int (const TLSContext *)> getVerifyCertCallback() { return verifyCertCallback; } - static CertificateVerificationError::Type getVerificationErrorTypeForResult(int); + private: + bool configure(const TLSOptions& options); + static void ensureLibraryInitialized(); + static int handleServerNameCallback(SSL *ssl, int *ad, void *arg); + static CertificateVerificationError::Type getVerificationErrorTypeForResult(int); - void doConnect(); - void sendPendingDataToNetwork(); - void sendPendingDataToApplication(); + void initAndSetBIOs(); + void doAccept(); + void doConnect(); + void sendPendingDataToNetwork(); + void sendPendingDataToApplication(); - private: - enum State { Start, Connecting, Connected, Error }; + private: + enum class State { Start, Accepting, Connecting, Connected, Error }; - State state_; - SSL_CTX* context_; - SSL* handle_; - BIO* readBIO_; - BIO* writeBIO_; - }; + const Mode mode_; + State state_; + std::unique_ptr<SSL_CTX> context_; + std::unique_ptr<SSL> handle_; + BIO* readBIO_ = nullptr; + BIO* writeBIO_ = nullptr; + bool abortTLSHandshake_ = false; + X509_STORE_CTX *x509_store_ctx = nullptr; + std::function<int (const TLSContext *)> verifyCertCallback = nullptr; + }; } diff --git a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp index 671cba7..e332ca8 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.cpp @@ -1,28 +1,61 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/TLS/OpenSSL/OpenSSLContextFactory.h> -#include <Swiften/TLS/OpenSSL/OpenSSLContext.h> + +#include <openssl/bio.h> +#include <openssl/dh.h> +#include <openssl/pem.h> + #include <Swiften/Base/Log.h> +#include <Swiften/TLS/OpenSSL/OpenSSLContext.h> + +#pragma clang diagnostic ignored "-Wshorten-64-to-32" namespace Swift { bool OpenSSLContextFactory::canCreate() const { - return true; + return true; } -TLSContext* OpenSSLContextFactory::createTLSContext() { - return new OpenSSLContext(); +std::unique_ptr<TLSContext> OpenSSLContextFactory::createTLSContext(const TLSOptions& options, TLSContext::Mode mode) { + return std::make_unique<OpenSSLContext>(options, mode); +} + +ByteArray OpenSSLContextFactory::convertDHParametersFromPEMToDER(const std::string& dhParametersInPEM) { + ByteArray dhParametersInDER; + + auto bio = std::unique_ptr<BIO, decltype(&BIO_free)>(BIO_new(BIO_s_mem()), BIO_free); + if (bio) { + BIO_write(bio.get(), dhParametersInPEM.data(), dhParametersInPEM.size()); + if (auto params = PEM_read_bio_DHparams(bio.get(), nullptr, nullptr, nullptr)) { + unsigned char* buffer = nullptr; + auto len = i2d_DHparams(params, &buffer); + if (len > 0) { + dhParametersInDER = createByteArray(buffer, static_cast<size_t>(len)); + free(buffer); + } + DH_free(params); + + } + } + return dhParametersInDER; } void OpenSSLContextFactory::setCheckCertificateRevocation(bool check) { - if (check) { - assert(false); - SWIFT_LOG(warning) << "CRL Checking not supported for OpenSSL" << std::endl; - } + if (check) { + SWIFT_LOG(warning) << "CRL Checking not supported for OpenSSL"; + assert(false); + } +} + +void OpenSSLContextFactory::setDisconnectOnCardRemoval(bool check) { + if (check) { + SWIFT_LOG(warning) << "Smart cards not supported for OpenSSL"; + } } diff --git a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h index 43ab960..834e479 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h +++ b/Swiften/TLS/OpenSSL/OpenSSLContextFactory.h @@ -1,22 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/TLS/TLSContextFactory.h> +#include <memory> -#include <cassert> +#include <Swiften/TLS/TLSContextFactory.h> namespace Swift { - class OpenSSLContextFactory : public TLSContextFactory { - public: - bool canCreate() const; - virtual TLSContext* createTLSContext(); + class OpenSSLContextFactory : public TLSContextFactory { + public: + bool canCreate() const override final; + virtual std::unique_ptr<TLSContext> createTLSContext(const TLSOptions& tlsOptions, TLSContext::Mode mode) override final; + + virtual ByteArray convertDHParametersFromPEMToDER(const std::string& dhParametersInPEM) override final; - // Not supported - virtual void setCheckCertificateRevocation(bool b); - }; + // Not supported + virtual void setCheckCertificateRevocation(bool b) override final; + virtual void setDisconnectOnCardRemoval(bool b) override final; + }; } diff --git a/Swiften/TLS/PKCS12Certificate.h b/Swiften/TLS/PKCS12Certificate.h index 2d4c2e5..4ed5040 100644 --- a/Swiften/TLS/PKCS12Certificate.h +++ b/Swiften/TLS/PKCS12Certificate.h @@ -1,60 +1,62 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <boost/filesystem/path.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> #include <Swiften/TLS/CertificateWithKey.h> -#include <boost/filesystem/path.hpp> namespace Swift { - class PKCS12Certificate : public Swift::CertificateWithKey { - public: - PKCS12Certificate() {} + class SWIFTEN_API PKCS12Certificate : public Swift::CertificateWithKey { + public: + PKCS12Certificate() {} - PKCS12Certificate(const boost::filesystem::path& filename, const SafeByteArray& password) : password_(password) { - readByteArrayFromFile(data_, filename); - } + PKCS12Certificate(const boost::filesystem::path& filename, const SafeByteArray& password) : password_(password) { + readByteArrayFromFile(data_, filename); + } - virtual ~PKCS12Certificate() {} + virtual ~PKCS12Certificate() {} - virtual bool isNull() const { - return data_.empty(); - } + virtual bool isNull() const { + return data_.empty(); + } - virtual bool isPrivateKeyExportable() const { + virtual bool isPrivateKeyExportable() const { /////Hopefully a PKCS12 is never missing a private key - return true; - } - - virtual const std::string& getCertStoreName() const { -///// assert(0); - throw std::exception(); - } - - virtual const std::string& getCertName() const { - /* We can return the original filename instead, if we care */ -///// assert(0); - throw std::exception(); - } - - virtual const ByteArray& getData() const { - return data_; - } - - void setData(const ByteArray& data) { - data_ = data; - } - - virtual const SafeByteArray& getPassword() const { - return password_; - } - - private: - ByteArray data_; - SafeByteArray password_; - }; + return true; + } + + virtual const std::string& getCertStoreName() const { +///// assert(0); + throw std::exception(); + } + + virtual const std::string& getCertName() const { + /* We can return the original filename instead, if we care */ +///// assert(0); + throw std::exception(); + } + + virtual const ByteArray& getData() const { + return data_; + } + + void setData(const ByteArray& data) { + data_ = data; + } + + virtual const SafeByteArray& getPassword() const { + return password_; + } + + private: + ByteArray data_; + SafeByteArray password_; + }; } diff --git a/Swiften/TLS/PlatformTLSFactories.cpp b/Swiften/TLS/PlatformTLSFactories.cpp index 64a5ab3..81f560b 100644 --- a/Swiften/TLS/PlatformTLSFactories.cpp +++ b/Swiften/TLS/PlatformTLSFactories.cpp @@ -1,48 +1,55 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/Platform.h> #include <Swiften/TLS/PlatformTLSFactories.h> -#include <cstring> -#include <cassert> - +#include <Swiften/Base/Platform.h> +#include <Swiften/TLS/CertificateFactory.h> +#include <Swiften/TLS/TLSContextFactory.h> #ifdef HAVE_OPENSSL - #include "Swiften/TLS/OpenSSL/OpenSSLContextFactory.h" - #include "Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h" + #include <Swiften/TLS/OpenSSL/OpenSSLContextFactory.h> + #include <Swiften/TLS/OpenSSL/OpenSSLCertificateFactory.h> #endif #ifdef HAVE_SCHANNEL - #include "Swiften/TLS/Schannel/SchannelContextFactory.h" - #include "Swiften/TLS/Schannel/SchannelCertificateFactory.h" + #include <Swiften/TLS/Schannel/SchannelContextFactory.h> + #include <Swiften/TLS/Schannel/SchannelCertificateFactory.h> +#endif +#ifdef HAVE_SECURETRANSPORT + #include <Swiften/TLS/SecureTransport/SecureTransportContextFactory.h> + #include <Swiften/TLS/SecureTransport/SecureTransportCertificateFactory.h> #endif namespace Swift { -PlatformTLSFactories::PlatformTLSFactories() : contextFactory(NULL), certificateFactory(NULL) { +PlatformTLSFactories::PlatformTLSFactories() : contextFactory(nullptr), certificateFactory(nullptr) { #ifdef HAVE_OPENSSL - contextFactory = new OpenSSLContextFactory(); - certificateFactory = new OpenSSLCertificateFactory(); + contextFactory = new OpenSSLContextFactory(); + certificateFactory = new OpenSSLCertificateFactory(); #endif #ifdef HAVE_SCHANNEL - contextFactory = new SchannelContextFactory(); - certificateFactory = new SchannelCertificateFactory(); + contextFactory = new SchannelContextFactory(); + certificateFactory = new SchannelCertificateFactory(); +#endif +#ifdef HAVE_SECURETRANSPORT + contextFactory = new SecureTransportContextFactory(); + certificateFactory = new SecureTransportCertificateFactory(); #endif } PlatformTLSFactories::~PlatformTLSFactories() { - delete contextFactory; - delete certificateFactory; + delete contextFactory; + delete certificateFactory; } TLSContextFactory* PlatformTLSFactories::getTLSContextFactory() const { - return contextFactory; + return contextFactory; } CertificateFactory* PlatformTLSFactories::getCertificateFactory() const { - return certificateFactory; + return certificateFactory; } } diff --git a/Swiften/TLS/PlatformTLSFactories.h b/Swiften/TLS/PlatformTLSFactories.h index 850d6f9..3821521 100644 --- a/Swiften/TLS/PlatformTLSFactories.h +++ b/Swiften/TLS/PlatformTLSFactories.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,19 +9,19 @@ #include <Swiften/Base/API.h> namespace Swift { - class TLSContextFactory; - class CertificateFactory; + class TLSContextFactory; + class CertificateFactory; - class SWIFTEN_API PlatformTLSFactories { - public: - PlatformTLSFactories(); - ~PlatformTLSFactories(); + class SWIFTEN_API PlatformTLSFactories { + public: + PlatformTLSFactories(); + ~PlatformTLSFactories(); - TLSContextFactory* getTLSContextFactory() const; - CertificateFactory* getCertificateFactory() const; + TLSContextFactory* getTLSContextFactory() const; + CertificateFactory* getCertificateFactory() const; - private: - TLSContextFactory* contextFactory; - CertificateFactory* certificateFactory; - }; + private: + TLSContextFactory* contextFactory; + CertificateFactory* certificateFactory; + }; } diff --git a/Swiften/TLS/PrivateKey.cpp b/Swiften/TLS/PrivateKey.cpp new file mode 100644 index 0000000..31cac1d --- /dev/null +++ b/Swiften/TLS/PrivateKey.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/TLS/PrivateKey.h> + +namespace Swift { + +PrivateKey::PrivateKey(const SafeByteArray& data, boost::optional<SafeByteArray> password) : data_(data), password_(password) { +} + +const SafeByteArray& PrivateKey::getData() const { + return data_; +} + +const boost::optional<SafeByteArray>& PrivateKey::getPassword() const { + return password_; +} + +} diff --git a/Swiften/TLS/PrivateKey.h b/Swiften/TLS/PrivateKey.h new file mode 100644 index 0000000..332fc48 --- /dev/null +++ b/Swiften/TLS/PrivateKey.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <boost/optional.hpp> + +#include <Swiften/Base/SafeByteArray.h> +#include <Swiften/TLS/PrivateKey.h> + +namespace Swift { + +class PrivateKey { +public: + using ref = std::shared_ptr<PrivateKey>; + +public: + PrivateKey(const SafeByteArray& data, boost::optional<SafeByteArray> password = boost::optional<SafeByteArray>()); + + const SafeByteArray& getData() const; + const boost::optional<SafeByteArray>& getPassword() const; + +private: + SafeByteArray data_; + boost::optional<SafeByteArray> password_; +}; + +} diff --git a/Swiften/TLS/SConscript b/Swiften/TLS/SConscript index fb327b9..a79e6a1 100644 --- a/Swiften/TLS/SConscript +++ b/Swiften/TLS/SConscript @@ -1,35 +1,45 @@ Import("swiften_env") objects = swiften_env.SwiftenObject([ - "Certificate.cpp", - "CertificateFactory.cpp", - "CertificateTrustChecker.cpp", - "ServerIdentityVerifier.cpp", - "TLSContext.cpp", - "TLSContextFactory.cpp", - ]) - + "Certificate.cpp", + "CertificateFactory.cpp", + "CertificateTrustChecker.cpp", + "PrivateKey.cpp", + "ServerIdentityVerifier.cpp", + "TLSContext.cpp", + "TLSContextFactory.cpp", + ]) + myenv = swiften_env.Clone() if myenv.get("HAVE_OPENSSL", 0) : - myenv.MergeFlags(myenv["OPENSSL_FLAGS"]) - objects += myenv.SwiftenObject([ - "OpenSSL/OpenSSLContext.cpp", - "OpenSSL/OpenSSLCertificate.cpp", - "OpenSSL/OpenSSLContextFactory.cpp", - ]) - myenv.Append(CPPDEFINES = "HAVE_OPENSSL") + myenv.MergeFlags(myenv["OPENSSL_FLAGS"]) + objects += myenv.SwiftenObject([ + "OpenSSL/OpenSSLContext.cpp", + "OpenSSL/OpenSSLCertificate.cpp", + "OpenSSL/OpenSSLContextFactory.cpp", + "OpenSSL/OpenSSLCertificateFactory.cpp", + ]) + myenv.Append(CPPDEFINES = "HAVE_OPENSSL") + if myenv["PLATFORM"] == "win32" : + myenv.Append(CPPDEFINES = "NOMINMAX") elif myenv.get("HAVE_SCHANNEL", 0) : - swiften_env.Append(LIBS = ["Winscard"]) - objects += myenv.StaticObject([ - "CAPICertificate.cpp", - "Schannel/SchannelContext.cpp", - "Schannel/SchannelCertificate.cpp", - "Schannel/SchannelContextFactory.cpp", - ]) - myenv.Append(CPPDEFINES = "HAVE_SCHANNEL") + swiften_env.Append(LIBS = ["Winscard"]) + objects += myenv.SwiftenObject([ + "CAPICertificate.cpp", + "Schannel/SchannelContext.cpp", + "Schannel/SchannelCertificate.cpp", + "Schannel/SchannelContextFactory.cpp", + ]) + myenv.Append(CPPDEFINES = "HAVE_SCHANNEL") +elif myenv.get("HAVE_SECURETRANSPORT", 0) : + #swiften_env.Append(LIBS = ["Winscard"]) + objects += myenv.SwiftenObject([ + "SecureTransport/SecureTransportContext.mm", + "SecureTransport/SecureTransportCertificate.mm", + "SecureTransport/SecureTransportContextFactory.cpp", + ]) + myenv.Append(CPPDEFINES = "HAVE_SECURETRANSPORT") objects += myenv.SwiftenObject(["PlatformTLSFactories.cpp"]) - - swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/TLS/Schannel/SchannelCertificate.cpp b/Swiften/TLS/Schannel/SchannelCertificate.cpp index 8aaec00..23c2479 100644 --- a/Swiften/TLS/Schannel/SchannelCertificate.cpp +++ b/Swiften/TLS/Schannel/SchannelCertificate.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include "Swiften/TLS/Schannel/SchannelCertificate.h" #include "Swiften/Base/ByteArray.h" @@ -20,176 +26,176 @@ namespace Swift { //------------------------------------------------------------------------ -SchannelCertificate::SchannelCertificate(const ScopedCertContext& certCtxt) -: m_cert(certCtxt) +SchannelCertificate::SchannelCertificate(const ScopedCertContext& certCtxt) +: m_cert(certCtxt) { - parse(); + parse(); } //------------------------------------------------------------------------ SchannelCertificate::SchannelCertificate(const ByteArray& der) { - if (!der.empty()) - { - // Convert the DER encoded certificate to a PCERT_CONTEXT - CERT_BLOB certBlob = {0}; - certBlob.cbData = der.size(); - certBlob.pbData = (BYTE*)&der[0]; - - if (!CryptQueryObject( - CERT_QUERY_OBJECT_BLOB, - &certBlob, - CERT_QUERY_CONTENT_FLAG_CERT, - CERT_QUERY_FORMAT_FLAG_ALL, - 0, - NULL, - NULL, - NULL, - NULL, - NULL, - (const void**)m_cert.Reset())) - { - // TODO: Because Swiften isn't exception safe, we have no way to indicate failure - } - } + if (!der.empty()) + { + // Convert the DER encoded certificate to a PCERT_CONTEXT + CERT_BLOB certBlob = {0}; + certBlob.cbData = der.size(); + certBlob.pbData = (BYTE*)&der[0]; + + if (!CryptQueryObject( + CERT_QUERY_OBJECT_BLOB, + &certBlob, + CERT_QUERY_CONTENT_FLAG_CERT, + CERT_QUERY_FORMAT_FLAG_ALL, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + (const void**)m_cert.Reset())) + { + // TODO: Because Swiften isn't exception safe, we have no way to indicate failure + } + } } //------------------------------------------------------------------------ -ByteArray SchannelCertificate::toDER() const +ByteArray SchannelCertificate::toDER() const { - ByteArray result; + ByteArray result; + + // Serialize the certificate. The CERT_CONTEXT is already DER encoded. + result.resize(m_cert->cbCertEncoded); + memcpy(&result[0], m_cert->pbCertEncoded, result.size()); - // Serialize the certificate. The CERT_CONTEXT is already DER encoded. - result.resize(m_cert->cbCertEncoded); - memcpy(&result[0], m_cert->pbCertEncoded, result.size()); - - return result; + return result; } //------------------------------------------------------------------------ std::string SchannelCertificate::wstrToStr(const std::wstring& wstr) { - if (wstr.empty()) - return ""; + if (wstr.empty()) + return ""; - // First request the size of the required UTF-8 buffer - int numRequiredBytes = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL); - if (!numRequiredBytes) - return ""; + // First request the size of the required UTF-8 buffer + int numRequiredBytes = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL); + if (!numRequiredBytes) + return ""; - // Allocate memory for the UTF-8 string - std::vector<char> utf8Str(numRequiredBytes); + // Allocate memory for the UTF-8 string + std::vector<char> utf8Str(numRequiredBytes); - int numConverted = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), &utf8Str[0], numRequiredBytes, NULL, NULL); - if (!numConverted) - return ""; + int numConverted = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), &utf8Str[0], numRequiredBytes, NULL, NULL); + if (!numConverted) + return ""; - std::string str(&utf8Str[0], numConverted); - return str; + std::string str(&utf8Str[0], numConverted); + return str; } //------------------------------------------------------------------------ -void SchannelCertificate::parse() +void SchannelCertificate::parse() { - // - // Subject name - // - DWORD requiredSize = CertNameToStr(X509_ASN_ENCODING, &m_cert->pCertInfo->Subject, CERT_OID_NAME_STR, NULL, 0); - if (requiredSize > 1) - { - vector<char> rawSubjectName(requiredSize); - CertNameToStr(X509_ASN_ENCODING, &m_cert->pCertInfo->Subject, CERT_OID_NAME_STR, &rawSubjectName[0], rawSubjectName.size()); - m_subjectName = std::string(&rawSubjectName[0]); - } - - // - // Common name - // - // Note: We only pull out one common name from the cert. - requiredSize = CertGetNameString(m_cert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, 0); - if (requiredSize > 1) - { - vector<char> rawCommonName(requiredSize); - requiredSize = CertGetNameString(m_cert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, &rawCommonName[0], rawCommonName.size()); - m_commonNames.push_back( std::string(&rawCommonName[0]) ); - } - - // - // Subject alternative names - // - PCERT_EXTENSION pExtensions = CertFindExtension(szOID_SUBJECT_ALT_NAME2, m_cert->pCertInfo->cExtension, m_cert->pCertInfo->rgExtension); - if (pExtensions) - { - CRYPT_DECODE_PARA decodePara = {0}; - decodePara.cbSize = sizeof(decodePara); - - CERT_ALT_NAME_INFO* pAltNameInfo = NULL; - DWORD altNameInfoSize = 0; - - BOOL status = CryptDecodeObjectEx( - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - szOID_SUBJECT_ALT_NAME2, - pExtensions->Value.pbData, - pExtensions->Value.cbData, - CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, - &decodePara, - &pAltNameInfo, - &altNameInfoSize); - - if (status && pAltNameInfo) - { - for (int i = 0; i < pAltNameInfo->cAltEntry; i++) - { - if (pAltNameInfo->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) - addDNSName( wstrToStr( pAltNameInfo->rgAltEntry[i].pwszDNSName ) ); - } - } - } - - // if (pExtensions) - // { - // vector<wchar_t> subjectAlt - // CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_SUBJECT_ALT_NAME, pExtensions->Value->pbData, pExtensions->Value->cbData, ) - // } - // - // // subjectAltNames - // int subjectAltNameLoc = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); - // if(subjectAltNameLoc != -1) { - // X509_EXTENSION* extension = X509_get_ext(cert.get(), subjectAltNameLoc); - // boost::shared_ptr<GENERAL_NAMES> generalNames(reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(extension)), GENERAL_NAMES_free); - // boost::shared_ptr<ASN1_OBJECT> xmppAddrObject(OBJ_txt2obj(ID_ON_XMPPADDR_OID, 1), ASN1_OBJECT_free); - // boost::shared_ptr<ASN1_OBJECT> dnsSRVObject(OBJ_txt2obj(ID_ON_DNSSRV_OID, 1), ASN1_OBJECT_free); - // for (int i = 0; i < sk_GENERAL_NAME_num(generalNames.get()); ++i) { - // GENERAL_NAME* generalName = sk_GENERAL_NAME_value(generalNames.get(), i); - // if (generalName->type == GEN_OTHERNAME) { - // OTHERNAME* otherName = generalName->d.otherName; - // if (OBJ_cmp(otherName->type_id, xmppAddrObject.get()) == 0) { - // // XmppAddr - // if (otherName->value->type != V_ASN1_UTF8STRING) { - // continue; - // } - // ASN1_UTF8STRING* xmppAddrValue = otherName->value->value.utf8string; - // addXMPPAddress(ByteArray(ASN1_STRING_data(xmppAddrValue), ASN1_STRING_length(xmppAddrValue)).toString()); - // } - // else if (OBJ_cmp(otherName->type_id, dnsSRVObject.get()) == 0) { - // // SRVName - // if (otherName->value->type != V_ASN1_IA5STRING) { - // continue; - // } - // ASN1_IA5STRING* srvNameValue = otherName->value->value.ia5string; - // addSRVName(ByteArray(ASN1_STRING_data(srvNameValue), ASN1_STRING_length(srvNameValue)).toString()); - // } - // } - // else if (generalName->type == GEN_DNS) { - // // DNSName - // addDNSName(ByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)).toString()); - // } - // } - // } + // + // Subject name + // + DWORD requiredSize = CertNameToStr(X509_ASN_ENCODING, &m_cert->pCertInfo->Subject, CERT_OID_NAME_STR, NULL, 0); + if (requiredSize > 1) + { + vector<char> rawSubjectName(requiredSize); + CertNameToStr(X509_ASN_ENCODING, &m_cert->pCertInfo->Subject, CERT_OID_NAME_STR, &rawSubjectName[0], rawSubjectName.size()); + m_subjectName = std::string(&rawSubjectName[0]); + } + + // + // Common name + // + // Note: We only pull out one common name from the cert. + requiredSize = CertGetNameString(m_cert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, 0); + if (requiredSize > 1) + { + vector<char> rawCommonName(requiredSize); + requiredSize = CertGetNameString(m_cert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, &rawCommonName[0], rawCommonName.size()); + m_commonNames.push_back( std::string(&rawCommonName[0]) ); + } + + // + // Subject alternative names + // + PCERT_EXTENSION pExtensions = CertFindExtension(szOID_SUBJECT_ALT_NAME2, m_cert->pCertInfo->cExtension, m_cert->pCertInfo->rgExtension); + if (pExtensions) + { + CRYPT_DECODE_PARA decodePara = {0}; + decodePara.cbSize = sizeof(decodePara); + + CERT_ALT_NAME_INFO* pAltNameInfo = NULL; + DWORD altNameInfoSize = 0; + + BOOL status = CryptDecodeObjectEx( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + szOID_SUBJECT_ALT_NAME2, + pExtensions->Value.pbData, + pExtensions->Value.cbData, + CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, + &decodePara, + &pAltNameInfo, + &altNameInfoSize); + + if (status && pAltNameInfo) + { + for (int i = 0; i < pAltNameInfo->cAltEntry; i++) + { + if (pAltNameInfo->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) + addDNSName( wstrToStr( pAltNameInfo->rgAltEntry[i].pwszDNSName ) ); + } + } + } + + // if (pExtensions) + // { + // vector<wchar_t> subjectAlt + // CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_SUBJECT_ALT_NAME, pExtensions->Value->pbData, pExtensions->Value->cbData, ) + // } + // + // // subjectAltNames + // int subjectAltNameLoc = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); + // if(subjectAltNameLoc != -1) { + // X509_EXTENSION* extension = X509_get_ext(cert.get(), subjectAltNameLoc); + // std::shared_ptr<GENERAL_NAMES> generalNames(reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(extension)), GENERAL_NAMES_free); + // std::shared_ptr<ASN1_OBJECT> xmppAddrObject(OBJ_txt2obj(ID_ON_XMPPADDR_OID, 1), ASN1_OBJECT_free); + // std::shared_ptr<ASN1_OBJECT> dnsSRVObject(OBJ_txt2obj(ID_ON_DNSSRV_OID, 1), ASN1_OBJECT_free); + // for (int i = 0; i < sk_GENERAL_NAME_num(generalNames.get()); ++i) { + // GENERAL_NAME* generalName = sk_GENERAL_NAME_value(generalNames.get(), i); + // if (generalName->type == GEN_OTHERNAME) { + // OTHERNAME* otherName = generalName->d.otherName; + // if (OBJ_cmp(otherName->type_id, xmppAddrObject.get()) == 0) { + // // XmppAddr + // if (otherName->value->type != V_ASN1_UTF8STRING) { + // continue; + // } + // ASN1_UTF8STRING* xmppAddrValue = otherName->value->value.utf8string; + // addXMPPAddress(ByteArray(ASN1_STRING_data(xmppAddrValue), ASN1_STRING_length(xmppAddrValue)).toString()); + // } + // else if (OBJ_cmp(otherName->type_id, dnsSRVObject.get()) == 0) { + // // SRVName + // if (otherName->value->type != V_ASN1_IA5STRING) { + // continue; + // } + // ASN1_IA5STRING* srvNameValue = otherName->value->value.ia5string; + // addSRVName(ByteArray(ASN1_STRING_data(srvNameValue), ASN1_STRING_length(srvNameValue)).toString()); + // } + // } + // else if (generalName->type == GEN_DNS) { + // // DNSName + // addDNSName(ByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)).toString()); + // } + // } + // } } //------------------------------------------------------------------------ diff --git a/Swiften/TLS/Schannel/SchannelCertificate.h b/Swiften/TLS/Schannel/SchannelCertificate.h index 395d3ec..d3bd66c 100644 --- a/Swiften/TLS/Schannel/SchannelCertificate.h +++ b/Swiften/TLS/Schannel/SchannelCertificate.h @@ -4,83 +4,89 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> -#include "Swiften/Base/String.h" -#include "Swiften/TLS/Certificate.h" -#include "Swiften/TLS/Schannel/SchannelUtil.h" +#include <Swiften/Base/String.h> +#include <Swiften/TLS/Certificate.h> +#include <Swiften/TLS/Schannel/SchannelUtil.h> -namespace Swift +namespace Swift { - class SchannelCertificate : public Certificate - { - public: - typedef boost::shared_ptr<SchannelCertificate> ref; - - public: - SchannelCertificate(const ScopedCertContext& certCtxt); - SchannelCertificate(const ByteArray& der); - - std::string getSubjectName() const - { - return m_subjectName; - } - - std::vector<std::string> getCommonNames() const - { - return m_commonNames; - } - - std::vector<std::string> getSRVNames() const - { - return m_srvNames; - } - - std::vector<std::string> getDNSNames() const - { - return m_dnsNames; - } - - std::vector<std::string> getXMPPAddresses() const - { - return m_xmppAddresses; - } - - ScopedCertContext getCertContext() const - { - return m_cert; - } - - ByteArray toDER() const; - - private: - void parse(); - std::string wstrToStr(const std::wstring& wstr); - - void addSRVName(const std::string& name) - { - m_srvNames.push_back(name); - } - - void addDNSName(const std::string& name) - { - m_dnsNames.push_back(name); - } - - void addXMPPAddress(const std::string& addr) - { - m_xmppAddresses.push_back(addr); - } - - private: - ScopedCertContext m_cert; - - std::string m_subjectName; - std::vector<std::string> m_commonNames; - std::vector<std::string> m_dnsNames; - std::vector<std::string> m_xmppAddresses; - std::vector<std::string> m_srvNames; - }; + class SchannelCertificate : public Certificate + { + public: + typedef std::shared_ptr<SchannelCertificate> ref; + + public: + SchannelCertificate(const ScopedCertContext& certCtxt); + SchannelCertificate(const ByteArray& der); + + std::string getSubjectName() const + { + return m_subjectName; + } + + std::vector<std::string> getCommonNames() const + { + return m_commonNames; + } + + std::vector<std::string> getSRVNames() const + { + return m_srvNames; + } + + std::vector<std::string> getDNSNames() const + { + return m_dnsNames; + } + + std::vector<std::string> getXMPPAddresses() const + { + return m_xmppAddresses; + } + + ScopedCertContext getCertContext() const + { + return m_cert; + } + + ByteArray toDER() const; + + private: + void parse(); + std::string wstrToStr(const std::wstring& wstr); + + void addSRVName(const std::string& name) + { + m_srvNames.push_back(name); + } + + void addDNSName(const std::string& name) + { + m_dnsNames.push_back(name); + } + + void addXMPPAddress(const std::string& addr) + { + m_xmppAddresses.push_back(addr); + } + + private: + ScopedCertContext m_cert; + + std::string m_subjectName; + std::vector<std::string> m_commonNames; + std::vector<std::string> m_dnsNames; + std::vector<std::string> m_xmppAddresses; + std::vector<std::string> m_srvNames; + }; } diff --git a/Swiften/TLS/Schannel/SchannelCertificateFactory.h b/Swiften/TLS/Schannel/SchannelCertificateFactory.h index d09bb54..be97c52 100644 --- a/Swiften/TLS/Schannel/SchannelCertificateFactory.h +++ b/Swiften/TLS/Schannel/SchannelCertificateFactory.h @@ -10,10 +10,10 @@ #include <Swiften/TLS/Schannel/SchannelCertificate.h> namespace Swift { - class SchannelCertificateFactory : public CertificateFactory { - public: - virtual Certificate::ref createCertificateFromDER(const ByteArray& der) { - return Certificate::ref(new SchannelCertificate(der)); - } - }; + class SchannelCertificateFactory : public CertificateFactory { + public: + virtual Certificate* createCertificateFromDER(const ByteArray& der) { + return new SchannelCertificate(der); + } + }; } diff --git a/Swiften/TLS/Schannel/SchannelContext.cpp b/Swiften/TLS/Schannel/SchannelContext.cpp index b4b2843..722fb4a 100644 --- a/Swiften/TLS/Schannel/SchannelContext.cpp +++ b/Swiften/TLS/Schannel/SchannelContext.cpp @@ -5,674 +5,703 @@ */ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <Swiften/TLS/Schannel/SchannelContext.h> + #include <boost/bind.hpp> -#include <Swiften/TLS/Schannel/SchannelContext.h> -#include <Swiften/TLS/Schannel/SchannelCertificate.h> -#include <Swiften/TLS/CAPICertificate.h> #include <WinHTTP.h> /* For SECURITY_FLAG_IGNORE_CERT_CN_INVALID */ +#include <Swiften/Base/Log.h> +#include <Swiften/TLS/CAPICertificate.h> +#include <Swiften/TLS/Schannel/SchannelCertificate.h> + namespace Swift { //------------------------------------------------------------------------ -SchannelContext::SchannelContext() : m_state(Start), m_secContext(0), m_my_cert_store(NULL), m_cert_store_name("MY"), m_cert_name(), m_smartcard_reader(), checkCertificateRevocation(true) { - m_ctxtFlags = ISC_REQ_ALLOCATE_MEMORY | - ISC_REQ_CONFIDENTIALITY | - ISC_REQ_EXTENDED_ERROR | - ISC_REQ_INTEGRITY | - ISC_REQ_REPLAY_DETECT | - ISC_REQ_SEQUENCE_DETECT | - ISC_REQ_USE_SUPPLIED_CREDS | - ISC_REQ_STREAM; - - ZeroMemory(&m_streamSizes, sizeof(m_streamSizes)); +SchannelContext::SchannelContext(bool tls1_0Workaround) : state_(Start), secContext_(0), myCertStore_(NULL), certStoreName_("MY"), certName_(), smartCardReader_(), checkCertificateRevocation_(true), tls1_0Workaround_(tls1_0Workaround), disconnectOnCardRemoval_(true) { + contextFlags_ = ISC_REQ_ALLOCATE_MEMORY | + ISC_REQ_CONFIDENTIALITY | + ISC_REQ_EXTENDED_ERROR | + ISC_REQ_INTEGRITY | + ISC_REQ_REPLAY_DETECT | + ISC_REQ_SEQUENCE_DETECT | + ISC_REQ_USE_SUPPLIED_CREDS | + ISC_REQ_STREAM; + + ZeroMemory(&streamSizes_, sizeof(streamSizes_)); } //------------------------------------------------------------------------ SchannelContext::~SchannelContext() { - if (m_my_cert_store) CertCloseStore(m_my_cert_store, 0); + SWIFT_LOG(debug) << "Destroying SchannelContext"; + if (myCertStore_) { + if (CertCloseStore(myCertStore_, 0) == FALSE) { + SWIFT_LOG(debug) << "Failed to close the certificate store"; + } + } } //------------------------------------------------------------------------ void SchannelContext::determineStreamSizes() { - QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_STREAM_SIZES, &m_streamSizes); + if (QueryContextAttributes(contextHandle_, SECPKG_ATTR_STREAM_SIZES, &streamSizes_) != SEC_E_OK) { + SWIFT_LOG(debug) << "QueryContextAttributes failed to determinate the stream size"; + } } //------------------------------------------------------------------------ void SchannelContext::connect() { - ScopedCertContext pCertContext; - - m_state = Connecting; - - // If a user name is specified, then attempt to find a client - // certificate. Otherwise, just create a NULL credential. - if (!m_cert_name.empty()) { - if (m_my_cert_store == NULL) { - m_my_cert_store = CertOpenSystemStore(0, m_cert_store_name.c_str()); - if (!m_my_cert_store) { - indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); - return; - } - } - - pCertContext = findCertificateInStore( m_my_cert_store, m_cert_name ); - if (pCertContext == NULL) { - indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); - return; - } - } - - // We use an empty list for client certificates - PCCERT_CONTEXT clientCerts[1] = {0}; - - SCHANNEL_CRED sc = {0}; - sc.dwVersion = SCHANNEL_CRED_VERSION; - -/////SSL3? - sc.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; - sc.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION; - - if (pCertContext) { - sc.cCreds = 1; - sc.paCred = pCertContext.GetPointer(); - sc.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; - } - else { - sc.cCreds = 0; - sc.paCred = clientCerts; - sc.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; - } - - // Swiften performs the server name check for us - sc.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; - - SECURITY_STATUS status = AcquireCredentialsHandle( - NULL, - UNISP_NAME, - SECPKG_CRED_OUTBOUND, - NULL, - &sc, - NULL, - NULL, - m_credHandle.Reset(), - NULL); - - if (status != SEC_E_OK) { - // We failed to obtain the credentials handle - indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); - return; - } - - SecBuffer outBuffers[2]; - - // We let Schannel allocate the output buffer for us - outBuffers[0].pvBuffer = NULL; - outBuffers[0].cbBuffer = 0; - outBuffers[0].BufferType = SECBUFFER_TOKEN; - - // Contains alert data if an alert is generated - outBuffers[1].pvBuffer = NULL; - outBuffers[1].cbBuffer = 0; - outBuffers[1].BufferType = SECBUFFER_ALERT; - - // Make sure the output buffers are freed - ScopedSecBuffer scopedOutputData(&outBuffers[0]); - ScopedSecBuffer scopedOutputAlertData(&outBuffers[1]); - - SecBufferDesc outBufferDesc = {0}; - outBufferDesc.cBuffers = 2; - outBufferDesc.pBuffers = outBuffers; - outBufferDesc.ulVersion = SECBUFFER_VERSION; - - // Create the initial security context - status = InitializeSecurityContext( - m_credHandle, - NULL, - NULL, - m_ctxtFlags, - 0, - 0, - NULL, - 0, - m_ctxtHandle.Reset(), - &outBufferDesc, - &m_secContext, - NULL); - - if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { - // We failed to initialize the security context - handleCertError(status); - indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); - return; - } - - // Start the handshake - sendDataOnNetwork(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer); - - if (status == SEC_E_OK) { - status = validateServerCertificate(); - if (status != SEC_E_OK) { - handleCertError(status); - } - - m_state = Connected; - determineStreamSizes(); - - onConnected(); - } + ScopedCertContext pCertContext; + + state_ = Connecting; + + // If a user name is specified, then attempt to find a client + // certificate. Otherwise, just create a NULL credential. + if (!certName_.empty()) { + if (myCertStore_ == NULL) { + myCertStore_ = CertOpenSystemStore(0, certStoreName_.c_str()); + if (!myCertStore_) { + indicateError(std::make_shared<TLSError>(TLSError::UnknownError)); + return; + } + } + + pCertContext = findCertificateInStore( myCertStore_, certName_ ); + if (pCertContext == NULL) { + indicateError(std::make_shared<TLSError>(TLSError::UnknownError)); + return; + } + } + + // We use an empty list for client certificates + PCCERT_CONTEXT clientCerts[1] = {0}; + + SCHANNEL_CRED sc = {0}; + sc.dwVersion = SCHANNEL_CRED_VERSION; + + if (tls1_0Workaround_) { + sc.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT; + } + else { + sc.grbitEnabledProtocols = /*SP_PROT_SSL3_CLIENT | */SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; + } + + sc.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION; + + if (pCertContext) { + sc.cCreds = 1; + sc.paCred = pCertContext.GetPointer(); + sc.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; + } + else { + sc.cCreds = 0; + sc.paCred = clientCerts; + sc.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; + } + + // Swiften performs the server name check for us + sc.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; + + SECURITY_STATUS status = AcquireCredentialsHandle( + NULL, + UNISP_NAME, + SECPKG_CRED_OUTBOUND, + NULL, + &sc, + NULL, + NULL, + credHandle_.Reset(), + NULL); + + if (status != SEC_E_OK) { + // We failed to obtain the credentials handle + indicateError(std::make_shared<TLSError>(TLSError::UnknownError)); + return; + } + + SecBuffer outBuffers[2]; + + // We let Schannel allocate the output buffer for us + outBuffers[0].pvBuffer = NULL; + outBuffers[0].cbBuffer = 0; + outBuffers[0].BufferType = SECBUFFER_TOKEN; + + // Contains alert data if an alert is generated + outBuffers[1].pvBuffer = NULL; + outBuffers[1].cbBuffer = 0; + outBuffers[1].BufferType = SECBUFFER_ALERT; + + // Make sure the output buffers are freed + ScopedSecBuffer scopedOutputData(&outBuffers[0]); + ScopedSecBuffer scopedOutputAlertData(&outBuffers[1]); + + SecBufferDesc outBufferDesc = {0}; + outBufferDesc.cBuffers = 2; + outBufferDesc.pBuffers = outBuffers; + outBufferDesc.ulVersion = SECBUFFER_VERSION; + + // Create the initial security context + status = InitializeSecurityContext( + credHandle_, + NULL, + NULL, + contextFlags_, + 0, + 0, + NULL, + 0, + contextHandle_.Reset(), + &outBufferDesc, + &secContext_, + NULL); + + if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + // We failed to initialize the security context + handleCertError(status); + indicateError(std::make_shared<TLSError>(TLSError::UnknownError)); + return; + } + + // Start the handshake + sendDataOnNetwork(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer); + + if (status == SEC_E_OK) { + status = validateServerCertificate(); + if (status != SEC_E_OK) { + handleCertError(status); + } + + state_ = Connected; + determineStreamSizes(); + + onConnected(); + } } //------------------------------------------------------------------------ SECURITY_STATUS SchannelContext::validateServerCertificate() { - SchannelCertificate::ref pServerCert = boost::dynamic_pointer_cast<SchannelCertificate>( getPeerCertificate() ); - if (!pServerCert) { - return SEC_E_WRONG_PRINCIPAL; - } - - const LPSTR usage[] = - { - szOID_PKIX_KP_SERVER_AUTH, - szOID_SERVER_GATED_CRYPTO, - szOID_SGC_NETSCAPE - }; - - CERT_CHAIN_PARA chainParams = {0}; - chainParams.cbSize = sizeof(chainParams); - chainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; - chainParams.RequestedUsage.Usage.cUsageIdentifier = ARRAYSIZE(usage); - chainParams.RequestedUsage.Usage.rgpszUsageIdentifier = const_cast<LPSTR*>(usage); - - DWORD chainFlags = CERT_CHAIN_CACHE_END_CERT; - if (checkCertificateRevocation) { - chainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; - } - - ScopedCertChainContext pChainContext; - - BOOL success = CertGetCertificateChain( - NULL, // Use the chain engine for the current user (assumes a user is logged in) - pServerCert->getCertContext(), - NULL, - pServerCert->getCertContext()->hCertStore, - &chainParams, - chainFlags, - NULL, - pChainContext.Reset()); - - if (!success) { - return GetLastError(); - } - - SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslChainPolicy = {0}; - sslChainPolicy.cbSize = sizeof(sslChainPolicy); - sslChainPolicy.dwAuthType = AUTHTYPE_SERVER; - sslChainPolicy.fdwChecks = SECURITY_FLAG_IGNORE_CERT_CN_INVALID; // Swiften checks the server name for us. Is this the correct way to disable server name checking? - sslChainPolicy.pwszServerName = NULL; - - CERT_CHAIN_POLICY_PARA certChainPolicy = {0}; - certChainPolicy.cbSize = sizeof(certChainPolicy); - certChainPolicy.dwFlags = CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG; // Swiften checks the server name for us. Is this the correct way to disable server name checking? - certChainPolicy.pvExtraPolicyPara = &sslChainPolicy; - - CERT_CHAIN_POLICY_STATUS certChainPolicyStatus = {0}; - certChainPolicyStatus.cbSize = sizeof(certChainPolicyStatus); - - // Verify the chain - if (!CertVerifyCertificateChainPolicy( - CERT_CHAIN_POLICY_SSL, - pChainContext, - &certChainPolicy, - &certChainPolicyStatus)) { - return GetLastError(); - } - - if (certChainPolicyStatus.dwError != S_OK) { - return certChainPolicyStatus.dwError; - } - - return S_OK; + SchannelCertificate::ref pServerCert = std::dynamic_pointer_cast<SchannelCertificate>( getPeerCertificate() ); + if (!pServerCert) { + return SEC_E_WRONG_PRINCIPAL; + } + + const LPSTR usage[] = + { + szOID_PKIX_KP_SERVER_AUTH, + szOID_SERVER_GATED_CRYPTO, + szOID_SGC_NETSCAPE + }; + + CERT_CHAIN_PARA chainParams = {0}; + chainParams.cbSize = sizeof(chainParams); + chainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; + chainParams.RequestedUsage.Usage.cUsageIdentifier = ARRAYSIZE(usage); + chainParams.RequestedUsage.Usage.rgpszUsageIdentifier = const_cast<LPSTR*>(usage); + + DWORD chainFlags = CERT_CHAIN_CACHE_END_CERT; + if (checkCertificateRevocation_) { + chainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; + } + + ScopedCertChainContext pChainContext; + + BOOL success = CertGetCertificateChain( + NULL, // Use the chain engine for the current user (assumes a user is logged in) + pServerCert->getCertContext(), + NULL, + pServerCert->getCertContext()->hCertStore, + &chainParams, + chainFlags, + NULL, + pChainContext.Reset()); + + if (!success) { + return GetLastError(); + } + + SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslChainPolicy = {0}; + sslChainPolicy.cbSize = sizeof(sslChainPolicy); + sslChainPolicy.dwAuthType = AUTHTYPE_SERVER; + sslChainPolicy.fdwChecks = SECURITY_FLAG_IGNORE_CERT_CN_INVALID; // Swiften checks the server name for us. Is this the correct way to disable server name checking? + sslChainPolicy.pwszServerName = NULL; + + CERT_CHAIN_POLICY_PARA certChainPolicy = {0}; + certChainPolicy.cbSize = sizeof(certChainPolicy); + certChainPolicy.dwFlags = CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG; // Swiften checks the server name for us. Is this the correct way to disable server name checking? + certChainPolicy.pvExtraPolicyPara = &sslChainPolicy; + + CERT_CHAIN_POLICY_STATUS certChainPolicyStatus = {0}; + certChainPolicyStatus.cbSize = sizeof(certChainPolicyStatus); + + // Verify the chain + if (!CertVerifyCertificateChainPolicy( + CERT_CHAIN_POLICY_SSL, + pChainContext, + &certChainPolicy, + &certChainPolicyStatus)) { + return GetLastError(); + } + + if (certChainPolicyStatus.dwError != S_OK) { + return certChainPolicyStatus.dwError; + } + + return S_OK; } //------------------------------------------------------------------------ void SchannelContext::appendNewData(const SafeByteArray& data) { - size_t originalSize = m_receivedData.size(); - m_receivedData.resize(originalSize + data.size()); - memcpy(&m_receivedData[0] + originalSize, &data[0], data.size()); + size_t originalSize = receivedData_.size(); + receivedData_.resize(originalSize + data.size()); + memcpy(&receivedData_[0] + originalSize, &data[0], data.size()); } //------------------------------------------------------------------------ void SchannelContext::continueHandshake(const SafeByteArray& data) { - appendNewData(data); - - while (!m_receivedData.empty()) { - SecBuffer inBuffers[2]; - - // Provide Schannel with the remote host's handshake data - inBuffers[0].pvBuffer = (char*)(&m_receivedData[0]); - inBuffers[0].cbBuffer = (unsigned long)m_receivedData.size(); - inBuffers[0].BufferType = SECBUFFER_TOKEN; - - inBuffers[1].pvBuffer = NULL; - inBuffers[1].cbBuffer = 0; - inBuffers[1].BufferType = SECBUFFER_EMPTY; - - SecBufferDesc inBufferDesc = {0}; - inBufferDesc.cBuffers = 2; - inBufferDesc.pBuffers = inBuffers; - inBufferDesc.ulVersion = SECBUFFER_VERSION; - - SecBuffer outBuffers[2]; - - // We let Schannel allocate the output buffer for us - outBuffers[0].pvBuffer = NULL; - outBuffers[0].cbBuffer = 0; - outBuffers[0].BufferType = SECBUFFER_TOKEN; - - // Contains alert data if an alert is generated - outBuffers[1].pvBuffer = NULL; - outBuffers[1].cbBuffer = 0; - outBuffers[1].BufferType = SECBUFFER_ALERT; - - // Make sure the output buffers are freed - ScopedSecBuffer scopedOutputData(&outBuffers[0]); - ScopedSecBuffer scopedOutputAlertData(&outBuffers[1]); - - SecBufferDesc outBufferDesc = {0}; - outBufferDesc.cBuffers = 2; - outBufferDesc.pBuffers = outBuffers; - outBufferDesc.ulVersion = SECBUFFER_VERSION; - - SECURITY_STATUS status = InitializeSecurityContext( - m_credHandle, - m_ctxtHandle, - NULL, - m_ctxtFlags, - 0, - 0, - &inBufferDesc, - 0, - NULL, - &outBufferDesc, - &m_secContext, - NULL); - - if (status == SEC_E_INCOMPLETE_MESSAGE) { - // Wait for more data to arrive - break; - } - else if (status == SEC_I_CONTINUE_NEEDED) { - SecBuffer* pDataBuffer = &outBuffers[0]; - SecBuffer* pExtraBuffer = &inBuffers[1]; - - if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL) { - sendDataOnNetwork(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer); - } - - if (pExtraBuffer->BufferType == SECBUFFER_EXTRA) { - m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer); - } - else { - m_receivedData.clear(); - } - - break; - } - else if (status == SEC_E_OK) { - status = validateServerCertificate(); - if (status != SEC_E_OK) { - handleCertError(status); - } - - SecBuffer* pExtraBuffer = &inBuffers[1]; - - if (pExtraBuffer && pExtraBuffer->cbBuffer > 0) { - m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer); - } - else { - m_receivedData.clear(); - } - - m_state = Connected; - determineStreamSizes(); - - onConnected(); - } - else { - // We failed to initialize the security context - handleCertError(status); - indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); - return; - } - } + appendNewData(data); + + while (!receivedData_.empty()) { + SecBuffer inBuffers[2]; + + // Provide Schannel with the remote host's handshake data + inBuffers[0].pvBuffer = static_cast<char*>(&receivedData_[0]); + inBuffers[0].cbBuffer = static_cast<unsigned long>(receivedData_.size()); + inBuffers[0].BufferType = SECBUFFER_TOKEN; + + inBuffers[1].pvBuffer = NULL; + inBuffers[1].cbBuffer = 0; + inBuffers[1].BufferType = SECBUFFER_EMPTY; + + SecBufferDesc inBufferDesc = {0}; + inBufferDesc.cBuffers = 2; + inBufferDesc.pBuffers = inBuffers; + inBufferDesc.ulVersion = SECBUFFER_VERSION; + + SecBuffer outBuffers[2]; + + // We let Schannel allocate the output buffer for us + outBuffers[0].pvBuffer = NULL; + outBuffers[0].cbBuffer = 0; + outBuffers[0].BufferType = SECBUFFER_TOKEN; + + // Contains alert data if an alert is generated + outBuffers[1].pvBuffer = NULL; + outBuffers[1].cbBuffer = 0; + outBuffers[1].BufferType = SECBUFFER_ALERT; + + // Make sure the output buffers are freed + ScopedSecBuffer scopedOutputData(&outBuffers[0]); + ScopedSecBuffer scopedOutputAlertData(&outBuffers[1]); + + SecBufferDesc outBufferDesc = {0}; + outBufferDesc.cBuffers = 2; + outBufferDesc.pBuffers = outBuffers; + outBufferDesc.ulVersion = SECBUFFER_VERSION; + + SECURITY_STATUS status = InitializeSecurityContext( + credHandle_, + contextHandle_, + NULL, + contextFlags_, + 0, + 0, + &inBufferDesc, + 0, + NULL, + &outBufferDesc, + &secContext_, + NULL); + + if (status == SEC_E_INCOMPLETE_MESSAGE) { + // Wait for more data to arrive + break; + } + else if (status == SEC_I_CONTINUE_NEEDED) { + SecBuffer* pDataBuffer = &outBuffers[0]; + SecBuffer* pExtraBuffer = &inBuffers[1]; + + if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL) { + sendDataOnNetwork(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer); + } + + if (pExtraBuffer->BufferType == SECBUFFER_EXTRA) { + receivedData_.erase(receivedData_.begin(), receivedData_.end() - pExtraBuffer->cbBuffer); + } + else { + receivedData_.clear(); + } + + break; + } + else if (status == SEC_E_OK) { + status = validateServerCertificate(); + if (status != SEC_E_OK) { + handleCertError(status); + } + + SecBuffer* pExtraBuffer = &inBuffers[1]; + + if (pExtraBuffer && pExtraBuffer->cbBuffer > 0) { + receivedData_.erase(receivedData_.begin(), receivedData_.end() - pExtraBuffer->cbBuffer); + } + else { + receivedData_.clear(); + } + + state_ = Connected; + determineStreamSizes(); + + onConnected(); + } + else { + // We failed to initialize the security context + handleCertError(status); + indicateError(std::make_shared<TLSError>(TLSError::UnknownError)); + return; + } + } } //------------------------------------------------------------------------ -void SchannelContext::handleCertError(SECURITY_STATUS status) +void SchannelContext::handleCertError(SECURITY_STATUS status) { - if (status == SEC_E_UNTRUSTED_ROOT || - status == CERT_E_UNTRUSTEDROOT || - status == CRYPT_E_ISSUER_SERIALNUMBER || - status == CRYPT_E_SIGNER_NOT_FOUND || - status == CRYPT_E_NO_TRUSTED_SIGNER) { - m_verificationError = CertificateVerificationError::Untrusted; - } - else if (status == SEC_E_CERT_EXPIRED || - status == CERT_E_EXPIRED) { - m_verificationError = CertificateVerificationError::Expired; - } - else if (status == CRYPT_E_SELF_SIGNED) { - m_verificationError = CertificateVerificationError::SelfSigned; - } - else if (status == CRYPT_E_HASH_VALUE || - status == TRUST_E_CERT_SIGNATURE) { - m_verificationError = CertificateVerificationError::InvalidSignature; - } - else if (status == CRYPT_E_REVOKED) { - m_verificationError = CertificateVerificationError::Revoked; - } - else if (status == CRYPT_E_NO_REVOCATION_CHECK || - status == CRYPT_E_REVOCATION_OFFLINE) { - m_verificationError = CertificateVerificationError::RevocationCheckFailed; - } - else { - m_verificationError = CertificateVerificationError::UnknownError; - } + if (status == SEC_E_UNTRUSTED_ROOT || + status == CERT_E_UNTRUSTEDROOT || + status == CRYPT_E_ISSUER_SERIALNUMBER || + status == CRYPT_E_SIGNER_NOT_FOUND || + status == CRYPT_E_NO_TRUSTED_SIGNER) { + verificationError_ = CertificateVerificationError::Untrusted; + } + else if (status == SEC_E_CERT_EXPIRED || + status == CERT_E_EXPIRED) { + verificationError_ = CertificateVerificationError::Expired; + } + else if (status == CRYPT_E_SELF_SIGNED) { + verificationError_ = CertificateVerificationError::SelfSigned; + } + else if (status == CRYPT_E_HASH_VALUE || + status == TRUST_E_CERT_SIGNATURE) { + verificationError_ = CertificateVerificationError::InvalidSignature; + } + else if (status == CRYPT_E_REVOKED) { + verificationError_ = CertificateVerificationError::Revoked; + } + else if (status == CRYPT_E_NO_REVOCATION_CHECK || + status == CRYPT_E_REVOCATION_OFFLINE) { + verificationError_ = CertificateVerificationError::RevocationCheckFailed; + } + else if (status == CERT_E_WRONG_USAGE) { + verificationError_ = CertificateVerificationError::InvalidPurpose; + } + else { + verificationError_ = CertificateVerificationError::UnknownError; + } } //------------------------------------------------------------------------ void SchannelContext::sendDataOnNetwork(const void* pData, size_t dataSize) { - if (dataSize > 0 && pData) { - SafeByteArray byteArray(dataSize); - memcpy(&byteArray[0], pData, dataSize); + if (dataSize > 0 && pData) { + SafeByteArray byteArray(dataSize); + memcpy(&byteArray[0], pData, dataSize); - onDataForNetwork(byteArray); - } + onDataForNetwork(byteArray); + } } //------------------------------------------------------------------------ void SchannelContext::forwardDataToApplication(const void* pData, size_t dataSize) { - SafeByteArray byteArray(dataSize); - memcpy(&byteArray[0], pData, dataSize); + SafeByteArray byteArray(dataSize); + memcpy(&byteArray[0], pData, dataSize); - onDataForApplication(byteArray); + onDataForApplication(byteArray); } //------------------------------------------------------------------------ void SchannelContext::handleDataFromApplication(const SafeByteArray& data) { - // Don't attempt to send data until we're fully connected - if (m_state == Connecting) { - return; - } + // Don't attempt to send data until we're fully connected + if (state_ == Connecting) { + return; + } - // Encrypt the data - encryptAndSendData(data); + // Encrypt the data + encryptAndSendData(data); } //------------------------------------------------------------------------ void SchannelContext::handleDataFromNetwork(const SafeByteArray& data) { - switch (m_state) { - case Connecting: - { - // We're still establishing the connection, so continue the handshake - continueHandshake(data); - } - break; - - case Connected: - { - // Decrypt the data - decryptAndProcessData(data); - } - break; - - default: - return; - } + switch (state_) { + case Connecting: + { + // We're still establishing the connection, so continue the handshake + continueHandshake(data); + } + break; + + case Connected: + { + // Decrypt the data + decryptAndProcessData(data); + } + break; + + default: + return; + } } //------------------------------------------------------------------------ -void SchannelContext::indicateError(boost::shared_ptr<TLSError> error) { - m_state = Error; - m_receivedData.clear(); - onError(error); +void SchannelContext::indicateError(std::shared_ptr<TLSError> error) { + state_ = Error; + receivedData_.clear(); + onError(error); } //------------------------------------------------------------------------ void SchannelContext::decryptAndProcessData(const SafeByteArray& data) { - SecBuffer inBuffers[4] = {0}; - - appendNewData(data); - - while (!m_receivedData.empty()) { - // - // MSDN: - // When using the Schannel SSP with contexts that are not connection oriented, on input, - // the structure must contain four SecBuffer structures. Exactly one buffer must be of type - // SECBUFFER_DATA and contain an encrypted message, which is decrypted in place. The remaining - // buffers are used for output and must be of type SECBUFFER_EMPTY. For connection-oriented - // contexts, a SECBUFFER_DATA type buffer must be supplied, as noted for nonconnection-oriented - // contexts. Additionally, a second SECBUFFER_TOKEN type buffer that contains a security token - // must also be supplied. - // - inBuffers[0].pvBuffer = (char*)(&m_receivedData[0]); - inBuffers[0].cbBuffer = (unsigned long)m_receivedData.size(); - inBuffers[0].BufferType = SECBUFFER_DATA; - - inBuffers[1].BufferType = SECBUFFER_EMPTY; - inBuffers[2].BufferType = SECBUFFER_EMPTY; - inBuffers[3].BufferType = SECBUFFER_EMPTY; - - SecBufferDesc inBufferDesc = {0}; - inBufferDesc.cBuffers = 4; - inBufferDesc.pBuffers = inBuffers; - inBufferDesc.ulVersion = SECBUFFER_VERSION; - - size_t inData = m_receivedData.size(); - SECURITY_STATUS status = DecryptMessage(m_ctxtHandle, &inBufferDesc, 0, NULL); - - if (status == SEC_E_INCOMPLETE_MESSAGE) { - // Wait for more data to arrive - break; - } - else if (status == SEC_I_RENEGOTIATE) { - // TODO: Handle renegotiation scenarios - indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); - break; - } - else if (status == SEC_I_CONTEXT_EXPIRED) { - indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); - break; - } - else if (status != SEC_E_OK) { - indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); - break; - } - - SecBuffer* pDataBuffer = NULL; - SecBuffer* pExtraBuffer = NULL; - for (int i = 0; i < 4; ++i) { - if (inBuffers[i].BufferType == SECBUFFER_DATA) { - pDataBuffer = &inBuffers[i]; - } - else if (inBuffers[i].BufferType == SECBUFFER_EXTRA) { - pExtraBuffer = &inBuffers[i]; - } - } - - if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL) { - forwardDataToApplication(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer); - } - - // If there is extra data left over from the decryption operation, we call DecryptMessage() again - if (pExtraBuffer) { - m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer); - } - else { - // We're done - m_receivedData.erase(m_receivedData.begin(), m_receivedData.begin() + inData); - } - } + SecBuffer inBuffers[4] = {0}; + + appendNewData(data); + + while (!receivedData_.empty()) { + // + // MSDN: + // When using the Schannel SSP with contexts that are not connection oriented, on input, + // the structure must contain four SecBuffer structures. Exactly one buffer must be of type + // SECBUFFER_DATA and contain an encrypted message, which is decrypted in place. The remaining + // buffers are used for output and must be of type SECBUFFER_EMPTY. For connection-oriented + // contexts, a SECBUFFER_DATA type buffer must be supplied, as noted for nonconnection-oriented + // contexts. Additionally, a second SECBUFFER_TOKEN type buffer that contains a security token + // must also be supplied. + // + inBuffers[0].pvBuffer = static_cast<char*>(&receivedData_[0]); + inBuffers[0].cbBuffer = static_cast<unsigned long>(receivedData_.size()); + inBuffers[0].BufferType = SECBUFFER_DATA; + + inBuffers[1].BufferType = SECBUFFER_EMPTY; + inBuffers[2].BufferType = SECBUFFER_EMPTY; + inBuffers[3].BufferType = SECBUFFER_EMPTY; + + SecBufferDesc inBufferDesc = {0}; + inBufferDesc.cBuffers = 4; + inBufferDesc.pBuffers = inBuffers; + inBufferDesc.ulVersion = SECBUFFER_VERSION; + + size_t inData = receivedData_.size(); + SECURITY_STATUS status = DecryptMessage(contextHandle_, &inBufferDesc, 0, NULL); + + if (status == SEC_E_INCOMPLETE_MESSAGE) { + // Wait for more data to arrive + break; + } + else if (status == SEC_I_RENEGOTIATE) { + // TODO: Handle renegotiation scenarios + indicateError(std::make_shared<TLSError>(TLSError::UnknownError)); + break; + } + else if (status == SEC_I_CONTEXT_EXPIRED) { + indicateError(std::make_shared<TLSError>(TLSError::UnknownError)); + break; + } + else if (status != SEC_E_OK) { + indicateError(std::make_shared<TLSError>(TLSError::UnknownError)); + break; + } + + SecBuffer* pDataBuffer = NULL; + SecBuffer* pExtraBuffer = NULL; + for (int i = 0; i < 4; ++i) { + if (inBuffers[i].BufferType == SECBUFFER_DATA) { + pDataBuffer = &inBuffers[i]; + } + else if (inBuffers[i].BufferType == SECBUFFER_EXTRA) { + pExtraBuffer = &inBuffers[i]; + } + } + + if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL) { + forwardDataToApplication(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer); + } + + // If there is extra data left over from the decryption operation, we call DecryptMessage() again + if (pExtraBuffer) { + receivedData_.erase(receivedData_.begin(), receivedData_.end() - pExtraBuffer->cbBuffer); + } + else { + // We're done + receivedData_.erase(receivedData_.begin(), receivedData_.begin() + inData); + } + } } //------------------------------------------------------------------------ void SchannelContext::encryptAndSendData(const SafeByteArray& data) { - if (m_streamSizes.cbMaximumMessage == 0) { - return; - } - - SecBuffer outBuffers[4] = {0}; - - // Calculate the largest required size of the send buffer - size_t messageBufferSize = (data.size() > m_streamSizes.cbMaximumMessage) - ? m_streamSizes.cbMaximumMessage - : data.size(); - - // Allocate a packet for the encrypted data - SafeByteArray sendBuffer; - sendBuffer.resize(m_streamSizes.cbHeader + messageBufferSize + m_streamSizes.cbTrailer); - - size_t bytesSent = 0; - do { - size_t bytesLeftToSend = data.size() - bytesSent; - - // Calculate how much of the send buffer we'll be using for this chunk - size_t bytesToSend = (bytesLeftToSend > m_streamSizes.cbMaximumMessage) - ? m_streamSizes.cbMaximumMessage - : bytesLeftToSend; - - // Copy the plain text data into the send buffer - memcpy(&sendBuffer[0] + m_streamSizes.cbHeader, &data[0] + bytesSent, bytesToSend); - - outBuffers[0].pvBuffer = &sendBuffer[0]; - outBuffers[0].cbBuffer = m_streamSizes.cbHeader; - outBuffers[0].BufferType = SECBUFFER_STREAM_HEADER; - - outBuffers[1].pvBuffer = &sendBuffer[0] + m_streamSizes.cbHeader; - outBuffers[1].cbBuffer = (unsigned long)bytesToSend; - outBuffers[1].BufferType = SECBUFFER_DATA; - - outBuffers[2].pvBuffer = &sendBuffer[0] + m_streamSizes.cbHeader + bytesToSend; - outBuffers[2].cbBuffer = m_streamSizes.cbTrailer; - outBuffers[2].BufferType = SECBUFFER_STREAM_TRAILER; - - outBuffers[3].pvBuffer = 0; - outBuffers[3].cbBuffer = 0; - outBuffers[3].BufferType = SECBUFFER_EMPTY; - - SecBufferDesc outBufferDesc = {0}; - outBufferDesc.cBuffers = 4; - outBufferDesc.pBuffers = outBuffers; - outBufferDesc.ulVersion = SECBUFFER_VERSION; - - SECURITY_STATUS status = EncryptMessage(m_ctxtHandle, 0, &outBufferDesc, 0); - if (status != SEC_E_OK) { - indicateError(boost::make_shared<TLSError>(TLSError::UnknownError)); - return; - } - - sendDataOnNetwork(&sendBuffer[0], outBuffers[0].cbBuffer + outBuffers[1].cbBuffer + outBuffers[2].cbBuffer); - bytesSent += bytesToSend; - - } while (bytesSent < data.size()); + if (streamSizes_.cbMaximumMessage == 0) { + return; + } + + SecBuffer outBuffers[4] = {0}; + + // Calculate the largest required size of the send buffer + size_t messageBufferSize = (data.size() > streamSizes_.cbMaximumMessage) + ? streamSizes_.cbMaximumMessage + : data.size(); + + // Allocate a packet for the encrypted data + SafeByteArray sendBuffer; + sendBuffer.resize(streamSizes_.cbHeader + messageBufferSize + streamSizes_.cbTrailer); + + size_t bytesSent = 0; + do { + size_t bytesLeftToSend = data.size() - bytesSent; + + // Calculate how much of the send buffer we'll be using for this chunk + size_t bytesToSend = (bytesLeftToSend > streamSizes_.cbMaximumMessage) + ? streamSizes_.cbMaximumMessage + : bytesLeftToSend; + + // Copy the plain text data into the send buffer + memcpy(&sendBuffer[0] + streamSizes_.cbHeader, &data[0] + bytesSent, bytesToSend); + + outBuffers[0].pvBuffer = &sendBuffer[0]; + outBuffers[0].cbBuffer = streamSizes_.cbHeader; + outBuffers[0].BufferType = SECBUFFER_STREAM_HEADER; + + outBuffers[1].pvBuffer = &sendBuffer[0] + streamSizes_.cbHeader; + outBuffers[1].cbBuffer = static_cast<unsigned long>(bytesToSend); + outBuffers[1].BufferType = SECBUFFER_DATA; + + outBuffers[2].pvBuffer = &sendBuffer[0] + streamSizes_.cbHeader + bytesToSend; + outBuffers[2].cbBuffer = streamSizes_.cbTrailer; + outBuffers[2].BufferType = SECBUFFER_STREAM_TRAILER; + + outBuffers[3].pvBuffer = 0; + outBuffers[3].cbBuffer = 0; + outBuffers[3].BufferType = SECBUFFER_EMPTY; + + SecBufferDesc outBufferDesc = {0}; + outBufferDesc.cBuffers = 4; + outBufferDesc.pBuffers = outBuffers; + outBufferDesc.ulVersion = SECBUFFER_VERSION; + + SECURITY_STATUS status = EncryptMessage(contextHandle_, 0, &outBufferDesc, 0); + if (status != SEC_E_OK) { + indicateError(std::make_shared<TLSError>(TLSError::UnknownError)); + return; + } + + sendDataOnNetwork(&sendBuffer[0], outBuffers[0].cbBuffer + outBuffers[1].cbBuffer + outBuffers[2].cbBuffer); + bytesSent += bytesToSend; + + } while (bytesSent < data.size()); } //------------------------------------------------------------------------ bool SchannelContext::setClientCertificate(CertificateWithKey::ref certificate) { - boost::shared_ptr<CAPICertificate> capiCertificate = boost::dynamic_pointer_cast<CAPICertificate>(certificate); - if (!capiCertificate || capiCertificate->isNull()) { - return false; - } + std::shared_ptr<CAPICertificate> capiCertificate = std::dynamic_pointer_cast<CAPICertificate>(certificate); + if (!capiCertificate || capiCertificate->isNull()) { + return false; + } - userCertificate = capiCertificate; + userCertificate_ = capiCertificate; - // We assume that the Certificate Store Name/Certificate Name - // are valid at this point - m_cert_store_name = capiCertificate->getCertStoreName(); - m_cert_name = capiCertificate->getCertName(); + // We assume that the Certificate Store Name/Certificate Name + // are valid at this point + certStoreName_ = capiCertificate->getCertStoreName(); + certName_ = capiCertificate->getCertName(); ////At the moment this is only useful for logging: - m_smartcard_reader = capiCertificate->getSmartCardReaderName(); + smartCardReader_ = capiCertificate->getSmartCardReaderName(); - capiCertificate->onCertificateCardRemoved.connect(boost::bind(&SchannelContext::handleCertificateCardRemoved, this)); + capiCertificate->onCertificateCardRemoved.connect(boost::bind(&SchannelContext::handleCertificateCardRemoved, this)); - return true; + return true; } //------------------------------------------------------------------------ void SchannelContext::handleCertificateCardRemoved() { - indicateError(boost::make_shared<TLSError>(TLSError::CertificateCardRemoved)); + if (disconnectOnCardRemoval_) { + indicateError(std::make_shared<TLSError>(TLSError::CertificateCardRemoved)); + } } //------------------------------------------------------------------------ std::vector<Certificate::ref> SchannelContext::getPeerCertificateChain() const { - std::vector<Certificate::ref> certificateChain; - ScopedCertContext pServerCert; - ScopedCertContext pIssuerCert; - ScopedCertContext pCurrentCert; - SECURITY_STATUS status = QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset()); - - if (status != SEC_E_OK) { - return certificateChain; - } - certificateChain.push_back(boost::make_shared<SchannelCertificate>(pServerCert)); - - pCurrentCert = pServerCert; - while(pCurrentCert.GetPointer()) { - DWORD dwVerificationFlags = 0; - pIssuerCert = CertGetIssuerCertificateFromStore(pServerCert->hCertStore, pCurrentCert, NULL, &dwVerificationFlags ); - if (!(*pIssuerCert.GetPointer())) { - break; - } - certificateChain.push_back(boost::make_shared<SchannelCertificate>(pIssuerCert)); - - pCurrentCert = pIssuerCert; - pIssuerCert = NULL; - } - return certificateChain; + std::vector<Certificate::ref> certificateChain; + ScopedCertContext pServerCert; + ScopedCertContext pIssuerCert; + ScopedCertContext pCurrentCert; + SECURITY_STATUS status = QueryContextAttributes(contextHandle_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset()); + + if (status != SEC_E_OK) { + SWIFT_LOG(debug) << "Error while Querying the Certificate Chain"; + return certificateChain; + } + certificateChain.push_back(std::make_shared<SchannelCertificate>(pServerCert)); + + pCurrentCert = pServerCert; + while(pCurrentCert.GetPointer()) { + DWORD dwVerificationFlags = 0; + pIssuerCert = CertGetIssuerCertificateFromStore(pServerCert->hCertStore, pCurrentCert, NULL, &dwVerificationFlags ); + if (!(*pIssuerCert.GetPointer())) { + break; + } + certificateChain.push_back(std::make_shared<SchannelCertificate>(pIssuerCert)); + + pCurrentCert = pIssuerCert; + pIssuerCert = NULL; + } + return certificateChain; } //------------------------------------------------------------------------ CertificateVerificationError::ref SchannelContext::getPeerCertificateVerificationError() const { - return m_verificationError ? boost::make_shared<CertificateVerificationError>(*m_verificationError) : CertificateVerificationError::ref(); + return verificationError_ ? std::make_shared<CertificateVerificationError>(*verificationError_) : CertificateVerificationError::ref(); } //------------------------------------------------------------------------ ByteArray SchannelContext::getFinishMessage() const { - SecPkgContext_Bindings bindings; - int ret = QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_UNIQUE_BINDINGS, &bindings); - if (ret == SEC_E_OK) { - return createByteArray(((unsigned char*) bindings.Bindings) + bindings.Bindings->dwApplicationDataOffset + 11 /* tls-unique:*/, bindings.Bindings->cbApplicationDataLength - 11); - } - return ByteArray(); + SecPkgContext_Bindings bindings; + int ret = QueryContextAttributes(contextHandle_, SECPKG_ATTR_UNIQUE_BINDINGS, &bindings); + if (ret == SEC_E_OK) { + return createByteArray(((unsigned char*) bindings.Bindings) + bindings.Bindings->dwApplicationDataOffset + 11 /* tls-unique:*/, bindings.Bindings->cbApplicationDataLength - 11); + } + else { + SWIFT_LOG(debug) << "Error while retrieving Finish Message"; + } + + return ByteArray(); } //------------------------------------------------------------------------ void SchannelContext::setCheckCertificateRevocation(bool b) { - checkCertificateRevocation = b; + checkCertificateRevocation_ = b; +} + +void SchannelContext::setDisconnectOnCardRemoval(bool b) { + disconnectOnCardRemoval_ = b; } diff --git a/Swiften/TLS/Schannel/SchannelContext.h b/Swiften/TLS/Schannel/SchannelContext.h index 8603498..a3748fe 100644 --- a/Swiften/TLS/Schannel/SchannelContext.h +++ b/Swiften/TLS/Schannel/SchannelContext.h @@ -5,14 +5,14 @@ */ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> #include <Swiften/TLS/TLSContext.h> #include <Swiften/TLS/Schannel/SchannelUtil.h> @@ -28,81 +28,85 @@ #include <boost/noncopyable.hpp> -namespace Swift -{ - class CAPICertificate; - class SchannelContext : public TLSContext, boost::noncopyable - { - public: - typedef boost::shared_ptr<SchannelContext> sp_t; +namespace Swift +{ + class CAPICertificate; + class SchannelContext : public TLSContext, boost::noncopyable + { + public: + typedef std::shared_ptr<SchannelContext> sp_t; - public: - SchannelContext(); + public: + SchannelContext(bool tls1_0Workaround); - ~SchannelContext(); + virtual ~SchannelContext(); - // - // TLSContext - // - virtual void connect(); - virtual bool setClientCertificate(CertificateWithKey::ref cert); + // + // TLSContext + // + virtual void connect(); + virtual bool setClientCertificate(CertificateWithKey::ref cert); - virtual void handleDataFromNetwork(const SafeByteArray& data); - virtual void handleDataFromApplication(const SafeByteArray& data); + virtual void handleDataFromNetwork(const SafeByteArray& data); + virtual void handleDataFromApplication(const SafeByteArray& data); - virtual std::vector<Certificate::ref> getPeerCertificateChain() const; - virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const; + virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const; - virtual ByteArray getFinishMessage() const; + virtual ByteArray getFinishMessage() const; - virtual void setCheckCertificateRevocation(bool b); + virtual void setCheckCertificateRevocation(bool b); - private: - void determineStreamSizes(); - void continueHandshake(const SafeByteArray& data); - void indicateError(boost::shared_ptr<TLSError> error); - //FIXME: Remove - void indicateError() {indicateError(boost::make_shared<TLSError>());} - void handleCertError(SECURITY_STATUS status) ; + virtual void setDisconnectOnCardRemoval(bool b); - void sendDataOnNetwork(const void* pData, size_t dataSize); - void forwardDataToApplication(const void* pData, size_t dataSize); + private: + void determineStreamSizes(); + void continueHandshake(const SafeByteArray& data); + void indicateError(std::shared_ptr<TLSError> error); + //FIXME: Remove + void indicateError() {indicateError(std::make_shared<TLSError>());} + void handleCertError(SECURITY_STATUS status) ; - void decryptAndProcessData(const SafeByteArray& data); - void encryptAndSendData(const SafeByteArray& data); + void sendDataOnNetwork(const void* pData, size_t dataSize); + void forwardDataToApplication(const void* pData, size_t dataSize); - void appendNewData(const SafeByteArray& data); - SECURITY_STATUS validateServerCertificate(); + void decryptAndProcessData(const SafeByteArray& data); + void encryptAndSendData(const SafeByteArray& data); - void handleCertificateCardRemoved(); + void appendNewData(const SafeByteArray& data); + SECURITY_STATUS validateServerCertificate(); - private: - enum SchannelState - { - Start, - Connecting, - Connected, - Error + void handleCertificateCardRemoved(); - }; + private: + enum SchannelState + { + Start, + Connecting, + Connected, + Error - SchannelState m_state; - boost::optional<CertificateVerificationError> m_verificationError; + }; - ULONG m_secContext; - ScopedCredHandle m_credHandle; - ScopedCtxtHandle m_ctxtHandle; - DWORD m_ctxtFlags; - SecPkgContext_StreamSizes m_streamSizes; + SchannelState state_; + boost::optional<CertificateVerificationError> verificationError_; - std::vector<char> m_receivedData; + ULONG secContext_; + ScopedCredHandle credHandle_; + ScopedCtxtHandle contextHandle_; + DWORD contextFlags_; + SecPkgContext_StreamSizes streamSizes_; - HCERTSTORE m_my_cert_store; - std::string m_cert_store_name; - std::string m_cert_name; + std::vector<char> receivedData_; + + HCERTSTORE myCertStore_; + std::string certStoreName_; + std::string certName_; ////Not needed, most likely - std::string m_smartcard_reader; //Can be empty string for non SmartCard certificates - boost::shared_ptr<CAPICertificate> userCertificate; - bool checkCertificateRevocation; - }; + std::string smartCardReader_; //Can be empty string for non SmartCard certificates + std::shared_ptr<CAPICertificate> userCertificate_; + bool checkCertificateRevocation_; + bool tls1_0Workaround_; + bool disconnectOnCardRemoval_; + }; } diff --git a/Swiften/TLS/Schannel/SchannelContextFactory.cpp b/Swiften/TLS/Schannel/SchannelContextFactory.cpp index 8b0044c..d029730 100644 --- a/Swiften/TLS/Schannel/SchannelContextFactory.cpp +++ b/Swiften/TLS/Schannel/SchannelContextFactory.cpp @@ -4,27 +4,40 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "Swiften/TLS/Schannel/SchannelContextFactory.h" -#include "Swiften/TLS/Schannel/SchannelContext.h" +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/TLS/Schannel/SchannelContextFactory.h> + +#include <Swiften/TLS/Schannel/SchannelContext.h> namespace Swift { -SchannelContextFactory::SchannelContextFactory() : checkCertificateRevocation(true) { +SchannelContextFactory::SchannelContextFactory() : checkCertificateRevocation(true), disconnectOnCardRemoval(true) { } bool SchannelContextFactory::canCreate() const { - return true; + return true; } -TLSContext* SchannelContextFactory::createTLSContext() { - SchannelContext* context = new SchannelContext(); - context->setCheckCertificateRevocation(checkCertificateRevocation); - return context; +std::unique_ptr<TLSContext> SchannelContextFactory::createTLSContext(const TLSOptions& tlsOptions, TLSContext::Mode mode) { + // TLS server mode is not supported for the SecureTransport backend yet. + assert(mode == TLSContext::Mode::Client); + SchannelContext* context = new SchannelContext(tlsOptions.schannelTLS1_0Workaround); + context->setCheckCertificateRevocation(checkCertificateRevocation); + context->setDisconnectOnCardRemoval(disconnectOnCardRemoval); + return std::unique_ptr<TLSContext>(context); } void SchannelContextFactory::setCheckCertificateRevocation(bool b) { - checkCertificateRevocation = b; + checkCertificateRevocation = b; } +void SchannelContextFactory::setDisconnectOnCardRemoval(bool b) { + disconnectOnCardRemoval = b; +} } diff --git a/Swiften/TLS/Schannel/SchannelContextFactory.h b/Swiften/TLS/Schannel/SchannelContextFactory.h index 9dc835c..76ff365 100644 --- a/Swiften/TLS/Schannel/SchannelContextFactory.h +++ b/Swiften/TLS/Schannel/SchannelContextFactory.h @@ -4,21 +4,31 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include "Swiften/TLS/TLSContextFactory.h" +#include <memory> + +#include <Swiften/TLS/TLSContextFactory.h> namespace Swift { - class SchannelContextFactory : public TLSContextFactory { - public: - SchannelContextFactory(); + class SchannelContextFactory : public TLSContextFactory { + public: + SchannelContextFactory(); - bool canCreate() const; - virtual TLSContext* createTLSContext(); + bool canCreate() const; + virtual std::unique_ptr<TLSContext> createTLSContext(const TLSOptions& tlsOptions, TLSContext::Mode mode = TLSContext::Mode::Client); + virtual void setCheckCertificateRevocation(bool b); - virtual void setCheckCertificateRevocation(bool b); + virtual void setDisconnectOnCardRemoval(bool b); - public: - bool checkCertificateRevocation; - }; + public: + bool checkCertificateRevocation; + bool disconnectOnCardRemoval; + }; } diff --git a/Swiften/TLS/Schannel/SchannelUtil.h b/Swiften/TLS/Schannel/SchannelUtil.h index 4f73aac..ec71d9d 100644 --- a/Swiften/TLS/Schannel/SchannelUtil.h +++ b/Swiften/TLS/Schannel/SchannelUtil.h @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #define SECURITY_WIN32 @@ -14,412 +20,412 @@ #include <boost/noncopyable.hpp> -namespace Swift +namespace Swift { - // - // Convenience wrapper around the Schannel CredHandle struct. - // - class ScopedCredHandle - { - private: - struct HandleContext - { - HandleContext() - { - ZeroMemory(&m_h, sizeof(m_h)); - } - - HandleContext(const CredHandle& h) - { - memcpy(&m_h, &h, sizeof(m_h)); - } - - ~HandleContext() - { - ::FreeCredentialsHandle(&m_h); - } - - CredHandle m_h; - }; - - public: - ScopedCredHandle() - : m_pHandle( new HandleContext ) - { - } - - explicit ScopedCredHandle(const CredHandle& h) - : m_pHandle( new HandleContext(h) ) - { - } - - // Copy constructor - explicit ScopedCredHandle(const ScopedCredHandle& rhs) - { - m_pHandle = rhs.m_pHandle; - } - - ~ScopedCredHandle() - { - m_pHandle.reset(); - } - - PCredHandle Reset() - { - CloseHandle(); - return &m_pHandle->m_h; - } - - operator PCredHandle() const - { - return &m_pHandle->m_h; - } - - ScopedCredHandle& operator=(const ScopedCredHandle& sh) - { - // Only update the internal handle if it's different - if (&m_pHandle->m_h != &sh.m_pHandle->m_h) - { - m_pHandle = sh.m_pHandle; - } - - return *this; - } - - void CloseHandle() - { - m_pHandle.reset( new HandleContext ); - } - - private: - boost::shared_ptr<HandleContext> m_pHandle; - }; - - //------------------------------------------------------------------------ - - // - // Convenience wrapper around the Schannel CtxtHandle struct. - // - class ScopedCtxtHandle - { - private: - struct HandleContext - { - HandleContext() - { - ZeroMemory(&m_h, sizeof(m_h)); - } - - ~HandleContext() - { - ::DeleteSecurityContext(&m_h); - } - - CtxtHandle m_h; - }; - - public: - ScopedCtxtHandle() - : m_pHandle( new HandleContext ) - { - } - - explicit ScopedCtxtHandle(CredHandle h) - : m_pHandle( new HandleContext ) - { - } - - // Copy constructor - explicit ScopedCtxtHandle(const ScopedCtxtHandle& rhs) - { - m_pHandle = rhs.m_pHandle; - } - - ~ScopedCtxtHandle() - { - m_pHandle.reset(); - } - - PCredHandle Reset() - { - CloseHandle(); - return &m_pHandle->m_h; - } - - operator PCredHandle() const - { - return &m_pHandle->m_h; - } - - ScopedCtxtHandle& operator=(const ScopedCtxtHandle& sh) - { - // Only update the internal handle if it's different - if (&m_pHandle->m_h != &sh.m_pHandle->m_h) - { - m_pHandle = sh.m_pHandle; - } - - return *this; - } - - void CloseHandle() - { - m_pHandle.reset( new HandleContext ); - } - - private: - boost::shared_ptr<HandleContext> m_pHandle; - }; - - //------------------------------------------------------------------------ - - // - // Convenience wrapper around the Schannel ScopedSecBuffer struct. - // - class ScopedSecBuffer : boost::noncopyable - { - public: - ScopedSecBuffer(PSecBuffer pSecBuffer) - : m_pSecBuffer(pSecBuffer) - { - } - - ~ScopedSecBuffer() - { - // Loop through all the output buffers and make sure we free them - if (m_pSecBuffer->pvBuffer) - FreeContextBuffer(m_pSecBuffer->pvBuffer); - } - - PSecBuffer AsPtr() - { - return m_pSecBuffer; - } - - PSecBuffer operator->() - { - return m_pSecBuffer; - } - - private: - PSecBuffer m_pSecBuffer; - }; - - //------------------------------------------------------------------------ - - // - // Convenience wrapper around the Schannel PCCERT_CONTEXT. - // - class ScopedCertContext - { - private: - struct HandleContext - { - HandleContext() - : m_pCertCtxt(NULL) - { - } - - HandleContext(PCCERT_CONTEXT pCert) - : m_pCertCtxt(pCert) - { - } - - ~HandleContext() - { - if (m_pCertCtxt) - CertFreeCertificateContext(m_pCertCtxt); - } - - PCCERT_CONTEXT m_pCertCtxt; - }; - - public: - ScopedCertContext() - : m_pHandle( new HandleContext ) - { - } - - explicit ScopedCertContext(PCCERT_CONTEXT pCert) - : m_pHandle( new HandleContext(pCert) ) - { - } - - // Copy constructor - ScopedCertContext(const ScopedCertContext& rhs) - { - m_pHandle = rhs.m_pHandle; - } - - ~ScopedCertContext() - { - m_pHandle.reset(); - } - - PCCERT_CONTEXT* Reset() - { - FreeContext(); - return &m_pHandle->m_pCertCtxt; - } - - operator PCCERT_CONTEXT() const - { - return m_pHandle->m_pCertCtxt; - } - - PCCERT_CONTEXT* GetPointer() const - { - return &m_pHandle->m_pCertCtxt; - } - - PCCERT_CONTEXT operator->() const - { - return m_pHandle->m_pCertCtxt; - } - - ScopedCertContext& operator=(const ScopedCertContext& sh) - { - // Only update the internal handle if it's different - if (&m_pHandle->m_pCertCtxt != &sh.m_pHandle->m_pCertCtxt) - { - m_pHandle = sh.m_pHandle; - } - - return *this; - } - - ScopedCertContext& operator=(PCCERT_CONTEXT pCertCtxt) - { - // Only update the internal handle if it's different - if (m_pHandle && m_pHandle->m_pCertCtxt != pCertCtxt) - m_pHandle.reset( new HandleContext(pCertCtxt) ); - - return *this; - } - - void FreeContext() - { - m_pHandle.reset( new HandleContext ); - } - - private: - boost::shared_ptr<HandleContext> m_pHandle; - }; - - //------------------------------------------------------------------------ - - // - // Convenience wrapper around the Schannel HCERTSTORE. - // - class ScopedCertStore : boost::noncopyable - { - public: - ScopedCertStore(HCERTSTORE hCertStore) - : m_hCertStore(hCertStore) - { - } - - ~ScopedCertStore() - { - // Forcefully free all memory related to the store, i.e. we assume all CertContext's that have been opened via this - // cert store have been closed at this point. - if (m_hCertStore) - CertCloseStore(m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG); - } - - operator HCERTSTORE() const - { - return m_hCertStore; - } - - private: - HCERTSTORE m_hCertStore; - }; - - //------------------------------------------------------------------------ - - // - // Convenience wrapper around the Schannel CERT_CHAIN_CONTEXT. - // - class ScopedCertChainContext - { - private: - struct HandleContext - { - HandleContext() - : m_pCertChainCtxt(NULL) - { - } - - HandleContext(PCCERT_CHAIN_CONTEXT pCert) - : m_pCertChainCtxt(pCert) - { - } - - ~HandleContext() - { - if (m_pCertChainCtxt) - CertFreeCertificateChain(m_pCertChainCtxt); - } - - PCCERT_CHAIN_CONTEXT m_pCertChainCtxt; - }; - - public: - ScopedCertChainContext() - : m_pHandle( new HandleContext ) - { - } - - explicit ScopedCertChainContext(PCCERT_CHAIN_CONTEXT pCert) - : m_pHandle( new HandleContext(pCert) ) - { - } - - // Copy constructor - ScopedCertChainContext(const ScopedCertChainContext& rhs) - { - m_pHandle = rhs.m_pHandle; - } - - ~ScopedCertChainContext() - { - m_pHandle.reset(); - } - - PCCERT_CHAIN_CONTEXT* Reset() - { - FreeContext(); - return &m_pHandle->m_pCertChainCtxt; - } - - operator PCCERT_CHAIN_CONTEXT() const - { - return m_pHandle->m_pCertChainCtxt; - } - - PCCERT_CHAIN_CONTEXT operator->() const - { - return m_pHandle->m_pCertChainCtxt; - } - - ScopedCertChainContext& operator=(const ScopedCertChainContext& sh) - { - // Only update the internal handle if it's different - if (&m_pHandle->m_pCertChainCtxt != &sh.m_pHandle->m_pCertChainCtxt) - { - m_pHandle = sh.m_pHandle; - } - - return *this; - } - - void FreeContext() - { - m_pHandle.reset( new HandleContext ); - } - - private: - boost::shared_ptr<HandleContext> m_pHandle; - }; + // + // Convenience wrapper around the Schannel CredHandle struct. + // + class ScopedCredHandle + { + private: + struct HandleContext + { + HandleContext() + { + ZeroMemory(&m_h, sizeof(m_h)); + } + + HandleContext(const CredHandle& h) + { + memcpy(&m_h, &h, sizeof(m_h)); + } + + ~HandleContext() + { + ::FreeCredentialsHandle(&m_h); + } + + CredHandle m_h; + }; + + public: + ScopedCredHandle() + : m_pHandle( new HandleContext ) + { + } + + explicit ScopedCredHandle(const CredHandle& h) + : m_pHandle( new HandleContext(h) ) + { + } + + // Copy constructor + explicit ScopedCredHandle(const ScopedCredHandle& rhs) + { + m_pHandle = rhs.m_pHandle; + } + + ~ScopedCredHandle() + { + m_pHandle.reset(); + } + + PCredHandle Reset() + { + CloseHandle(); + return &m_pHandle->m_h; + } + + operator PCredHandle() const + { + return &m_pHandle->m_h; + } + + ScopedCredHandle& operator=(const ScopedCredHandle& sh) + { + // Only update the internal handle if it's different + if (&m_pHandle->m_h != &sh.m_pHandle->m_h) + { + m_pHandle = sh.m_pHandle; + } + + return *this; + } + + void CloseHandle() + { + m_pHandle.reset( new HandleContext ); + } + + private: + std::shared_ptr<HandleContext> m_pHandle; + }; + + //------------------------------------------------------------------------ + + // + // Convenience wrapper around the Schannel CtxtHandle struct. + // + class ScopedCtxtHandle + { + private: + struct HandleContext + { + HandleContext() + { + ZeroMemory(&m_h, sizeof(m_h)); + } + + ~HandleContext() + { + ::DeleteSecurityContext(&m_h); + } + + CtxtHandle m_h; + }; + + public: + ScopedCtxtHandle() + : m_pHandle( new HandleContext ) + { + } + + explicit ScopedCtxtHandle(CredHandle h) + : m_pHandle( new HandleContext ) + { + } + + // Copy constructor + explicit ScopedCtxtHandle(const ScopedCtxtHandle& rhs) + { + m_pHandle = rhs.m_pHandle; + } + + ~ScopedCtxtHandle() + { + m_pHandle.reset(); + } + + PCredHandle Reset() + { + CloseHandle(); + return &m_pHandle->m_h; + } + + operator PCredHandle() const + { + return &m_pHandle->m_h; + } + + ScopedCtxtHandle& operator=(const ScopedCtxtHandle& sh) + { + // Only update the internal handle if it's different + if (&m_pHandle->m_h != &sh.m_pHandle->m_h) + { + m_pHandle = sh.m_pHandle; + } + + return *this; + } + + void CloseHandle() + { + m_pHandle.reset( new HandleContext ); + } + + private: + std::shared_ptr<HandleContext> m_pHandle; + }; + + //------------------------------------------------------------------------ + + // + // Convenience wrapper around the Schannel ScopedSecBuffer struct. + // + class ScopedSecBuffer : boost::noncopyable + { + public: + ScopedSecBuffer(PSecBuffer pSecBuffer) + : m_pSecBuffer(pSecBuffer) + { + } + + ~ScopedSecBuffer() + { + // Loop through all the output buffers and make sure we free them + if (m_pSecBuffer->pvBuffer) + FreeContextBuffer(m_pSecBuffer->pvBuffer); + } + + PSecBuffer AsPtr() + { + return m_pSecBuffer; + } + + PSecBuffer operator->() + { + return m_pSecBuffer; + } + + private: + PSecBuffer m_pSecBuffer; + }; + + //------------------------------------------------------------------------ + + // + // Convenience wrapper around the Schannel PCCERT_CONTEXT. + // + class ScopedCertContext + { + private: + struct HandleContext + { + HandleContext() + : m_pCertCtxt(NULL) + { + } + + HandleContext(PCCERT_CONTEXT pCert) + : m_pCertCtxt(pCert) + { + } + + ~HandleContext() + { + if (m_pCertCtxt) + CertFreeCertificateContext(m_pCertCtxt); + } + + PCCERT_CONTEXT m_pCertCtxt; + }; + + public: + ScopedCertContext() + : m_pHandle( new HandleContext ) + { + } + + explicit ScopedCertContext(PCCERT_CONTEXT pCert) + : m_pHandle( new HandleContext(pCert) ) + { + } + + // Copy constructor + ScopedCertContext(const ScopedCertContext& rhs) + { + m_pHandle = rhs.m_pHandle; + } + + ~ScopedCertContext() + { + m_pHandle.reset(); + } + + PCCERT_CONTEXT* Reset() + { + FreeContext(); + return &m_pHandle->m_pCertCtxt; + } + + operator PCCERT_CONTEXT() const + { + return m_pHandle->m_pCertCtxt; + } + + PCCERT_CONTEXT* GetPointer() const + { + return &m_pHandle->m_pCertCtxt; + } + + PCCERT_CONTEXT operator->() const + { + return m_pHandle->m_pCertCtxt; + } + + ScopedCertContext& operator=(const ScopedCertContext& sh) + { + // Only update the internal handle if it's different + if (&m_pHandle->m_pCertCtxt != &sh.m_pHandle->m_pCertCtxt) + { + m_pHandle = sh.m_pHandle; + } + + return *this; + } + + ScopedCertContext& operator=(PCCERT_CONTEXT pCertCtxt) + { + // Only update the internal handle if it's different + if (m_pHandle && m_pHandle->m_pCertCtxt != pCertCtxt) + m_pHandle.reset( new HandleContext(pCertCtxt) ); + + return *this; + } + + void FreeContext() + { + m_pHandle.reset( new HandleContext ); + } + + private: + std::shared_ptr<HandleContext> m_pHandle; + }; + + //------------------------------------------------------------------------ + + // + // Convenience wrapper around the Schannel HCERTSTORE. + // + class ScopedCertStore : boost::noncopyable + { + public: + ScopedCertStore(HCERTSTORE hCertStore) + : m_hCertStore(hCertStore) + { + } + + ~ScopedCertStore() + { + // Forcefully free all memory related to the store, i.e. we assume all CertContext's that have been opened via this + // cert store have been closed at this point. + if (m_hCertStore) + CertCloseStore(m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG); + } + + operator HCERTSTORE() const + { + return m_hCertStore; + } + + private: + HCERTSTORE m_hCertStore; + }; + + //------------------------------------------------------------------------ + + // + // Convenience wrapper around the Schannel CERT_CHAIN_CONTEXT. + // + class ScopedCertChainContext + { + private: + struct HandleContext + { + HandleContext() + : m_pCertChainCtxt(NULL) + { + } + + HandleContext(PCCERT_CHAIN_CONTEXT pCert) + : m_pCertChainCtxt(pCert) + { + } + + ~HandleContext() + { + if (m_pCertChainCtxt) + CertFreeCertificateChain(m_pCertChainCtxt); + } + + PCCERT_CHAIN_CONTEXT m_pCertChainCtxt; + }; + + public: + ScopedCertChainContext() + : m_pHandle( new HandleContext ) + { + } + + explicit ScopedCertChainContext(PCCERT_CHAIN_CONTEXT pCert) + : m_pHandle( new HandleContext(pCert) ) + { + } + + // Copy constructor + ScopedCertChainContext(const ScopedCertChainContext& rhs) + { + m_pHandle = rhs.m_pHandle; + } + + ~ScopedCertChainContext() + { + m_pHandle.reset(); + } + + PCCERT_CHAIN_CONTEXT* Reset() + { + FreeContext(); + return &m_pHandle->m_pCertChainCtxt; + } + + operator PCCERT_CHAIN_CONTEXT() const + { + return m_pHandle->m_pCertChainCtxt; + } + + PCCERT_CHAIN_CONTEXT operator->() const + { + return m_pHandle->m_pCertChainCtxt; + } + + ScopedCertChainContext& operator=(const ScopedCertChainContext& sh) + { + // Only update the internal handle if it's different + if (&m_pHandle->m_pCertChainCtxt != &sh.m_pHandle->m_pCertChainCtxt) + { + m_pHandle = sh.m_pHandle; + } + + return *this; + } + + void FreeContext() + { + m_pHandle.reset( new HandleContext ); + } + + private: + std::shared_ptr<HandleContext> m_pHandle; + }; } diff --git a/Swiften/TLS/SecureTransport/SecureTransportCertificate.h b/Swiften/TLS/SecureTransport/SecureTransportCertificate.h new file mode 100644 index 0000000..7faf3be --- /dev/null +++ b/Swiften/TLS/SecureTransport/SecureTransportCertificate.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <boost/type_traits.hpp> + +#include <Security/SecCertificate.h> + +#include <Swiften/TLS/Certificate.h> + +namespace Swift { + +class SecureTransportCertificate : public Certificate { +public: + SecureTransportCertificate(SecCertificateRef certificate); + SecureTransportCertificate(const ByteArray& der); + virtual ~SecureTransportCertificate(); + + virtual std::string getSubjectName() const; + virtual std::vector<std::string> getCommonNames() const; + virtual std::vector<std::string> getSRVNames() const; + virtual std::vector<std::string> getDNSNames() const; + virtual std::vector<std::string> getXMPPAddresses() const; + + virtual ByteArray toDER() const; + +private: + void parse(); + typedef boost::remove_pointer<SecCertificateRef>::type SecCertificate; + +private: + std::shared_ptr<SecCertificate> certificateHandle_; + std::string subjectName_; + std::vector<std::string> commonNames_; + std::vector<std::string> srvNames_; + std::vector<std::string> dnsNames_; + std::vector<std::string> xmppAddresses_; +}; + +} diff --git a/Swiften/TLS/SecureTransport/SecureTransportCertificate.mm b/Swiften/TLS/SecureTransport/SecureTransportCertificate.mm new file mode 100644 index 0000000..fffb3ed --- /dev/null +++ b/Swiften/TLS/SecureTransport/SecureTransportCertificate.mm @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/TLS/SecureTransport/SecureTransportCertificate.h> + +#include <boost/numeric/conversion/cast.hpp> + +#include <Cocoa/Cocoa.h> +#include <Security/Security.h> + +#include <Swiften/Base/Log.h> + +namespace { + +template <typename T, typename S> +T bridge_cast(S source) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" + return (__bridge T)(source); +#pragma clang diagnostic pop +} + +} + +namespace { + +inline std::string ns2StdString(NSString* _Nullable nsString); +inline std::string ns2StdString(NSString* _Nullable nsString) { + std::string stdString; + if (nsString != nil) { + stdString = std::string([nsString cStringUsingEncoding:NSUTF8StringEncoding]); + } + return stdString; +} + +} + +namespace Swift { + +SecureTransportCertificate::SecureTransportCertificate(SecCertificateRef certificate) { + assert(certificate); + CFRetain(certificate); + certificateHandle_ = std::shared_ptr<SecCertificate>(certificate, CFRelease); + parse(); +} + + +SecureTransportCertificate::SecureTransportCertificate(const ByteArray& der) { + CFDataRef derData = CFDataCreateWithBytesNoCopy(nullptr, der.data(), static_cast<CFIndex>(der.size()), nullptr); + // certificate will take ownership of derData and free it on its release. + SecCertificateRef certificate = SecCertificateCreateWithData(nullptr, derData); + if (certificate) { + certificateHandle_ = std::shared_ptr<SecCertificate>(certificate, CFRelease); + parse(); + } +} + +SecureTransportCertificate::~SecureTransportCertificate() { + +} + +void SecureTransportCertificate::parse() { + assert(certificateHandle_); + CFErrorRef error = nullptr; + + // The SecCertificateCopyValues function is not part of the iOS Secure Transport API. + CFDictionaryRef valueDict = SecCertificateCopyValues(certificateHandle_.get(), nullptr, &error); + if (valueDict) { + // Handle subject. + CFStringRef subject = SecCertificateCopySubjectSummary(certificateHandle_.get()); + if (subject) { + NSString* subjectStr = bridge_cast<NSString*>(subject); + subjectName_ = ns2StdString(subjectStr); + CFRelease(subject); + } + + // Handle a single Common Name. + CFStringRef commonName = nullptr; + OSStatus error = SecCertificateCopyCommonName(certificateHandle_.get(), &commonName); + if (!error && commonName) { + NSString* commonNameStr = bridge_cast<NSString*>(commonName); + commonNames_.push_back(ns2StdString(commonNameStr)); + } + if (commonName) { + CFRelease(commonName); + } + + // Handle Subject Alternative Names + NSDictionary* certDict = bridge_cast<NSDictionary*>(valueDict); + NSDictionary* subjectAltNamesDict = certDict[@"2.5.29.17"][@"value"]; + + for (NSDictionary* entry in subjectAltNamesDict) { + NSString* label = entry[@"label"]; + if ([label isEqualToString:static_cast<NSString * _Nonnull>([NSString stringWithUTF8String:ID_ON_XMPPADDR_OID])]) { + xmppAddresses_.push_back(ns2StdString(entry[@"value"])); + } + else if ([label isEqualToString:static_cast<NSString * _Nonnull>([NSString stringWithUTF8String:ID_ON_DNSSRV_OID])]) { + srvNames_.push_back(ns2StdString(entry[@"value"])); + } + else if ([label isEqualToString:@"DNS Name"]) { + dnsNames_.push_back(ns2StdString(entry[@"value"])); + } + } + CFRelease(valueDict); + } + + if (error) { + CFRelease(error); + } +} + +std::string SecureTransportCertificate::getSubjectName() const { + return subjectName_; +} + +std::vector<std::string> SecureTransportCertificate::getCommonNames() const { + return commonNames_; +} + +std::vector<std::string> SecureTransportCertificate::getSRVNames() const { + return srvNames_; +} + +std::vector<std::string> SecureTransportCertificate::getDNSNames() const { + return dnsNames_; +} + +std::vector<std::string> SecureTransportCertificate::getXMPPAddresses() const { + return xmppAddresses_; +} + +ByteArray SecureTransportCertificate::toDER() const { + ByteArray der; + if (certificateHandle_) { + CFDataRef derData = SecCertificateCopyData(certificateHandle_.get()); + if (derData) { + try { + size_t dataSize = boost::numeric_cast<size_t>(CFDataGetLength(derData)); + der.resize(dataSize); + CFDataGetBytes(derData, CFRangeMake(0,CFDataGetLength(derData)), der.data()); + } catch (...) { + } + CFRelease(derData); + } + } + return der; +} + +} diff --git a/Swiften/TLS/SecureTransport/SecureTransportCertificateFactory.h b/Swiften/TLS/SecureTransport/SecureTransportCertificateFactory.h new file mode 100644 index 0000000..3ea469d --- /dev/null +++ b/Swiften/TLS/SecureTransport/SecureTransportCertificateFactory.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/TLS/CertificateFactory.h> +#include <Swiften/TLS/SecureTransport/SecureTransportCertificate.h> + +namespace Swift { + +class SecureTransportCertificateFactory : public CertificateFactory { + public: + virtual Certificate* createCertificateFromDER(const ByteArray& der) { + return new SecureTransportCertificate(der); + } + }; +} diff --git a/Swiften/TLS/SecureTransport/SecureTransportContext.h b/Swiften/TLS/SecureTransport/SecureTransportContext.h new file mode 100644 index 0000000..3942904 --- /dev/null +++ b/Swiften/TLS/SecureTransport/SecureTransportContext.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Security/SecureTransport.h> + +#include <Swiften/TLS/TLSContext.h> + +namespace Swift { + +class SecureTransportContext : public TLSContext { + public: + SecureTransportContext(bool checkCertificateRevocation); + virtual ~SecureTransportContext(); + + virtual void connect(); + + virtual bool setClientCertificate(CertificateWithKey::ref cert); + + virtual void handleDataFromNetwork(const SafeByteArray&); + virtual void handleDataFromApplication(const SafeByteArray&); + + virtual std::vector<Certificate::ref> getPeerCertificateChain() const; + virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const; + + virtual ByteArray getFinishMessage() const; + + private: + static OSStatus SSLSocketReadCallback(SSLConnectionRef connection, void *data, size_t *dataLength); + static OSStatus SSLSocketWriteCallback(SSLConnectionRef connection, const void *data, size_t *dataLength); + + private: + enum State { None, Handshake, HandshakeDone, Error}; + static std::string stateToString(State state); + void setState(State newState); + + static std::shared_ptr<TLSError> nativeToTLSError(OSStatus error); + std::shared_ptr<CertificateVerificationError> CSSMErrorToVerificationError(OSStatus resultCode); + + void processHandshake(); + void verifyServerCertificate(); + + void fatalError(std::shared_ptr<TLSError> error, std::shared_ptr<CertificateVerificationError> certificateError); + + private: + std::shared_ptr<SSLContext> sslContext_; + SafeByteArray readingBuffer_; + State state_; + CertificateVerificationError::ref verificationError_; + CertificateWithKey::ref clientCertificate_; + bool checkCertificateRevocation_; +}; + +} diff --git a/Swiften/TLS/SecureTransport/SecureTransportContext.mm b/Swiften/TLS/SecureTransport/SecureTransportContext.mm new file mode 100644 index 0000000..b4f7842 --- /dev/null +++ b/Swiften/TLS/SecureTransport/SecureTransportContext.mm @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/TLS/SecureTransport/SecureTransportContext.h> + +#include <boost/type_traits.hpp> +#include <boost/numeric/conversion/cast.hpp> + +#include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/Log.h> +#include <Swiften/TLS/SecureTransport/SecureTransportCertificate.h> +#include <Swiften/TLS/PKCS12Certificate.h> +#include <Swiften/TLS/CertificateWithKey.h> + +#include <Cocoa/Cocoa.h> + +#import <Security/SecCertificate.h> +#import <Security/SecImportExport.h> + +namespace { + typedef boost::remove_pointer<CFArrayRef>::type CFArray; + typedef boost::remove_pointer<SecTrustRef>::type SecTrust; +} + +template <typename T, typename S> +T bridge_cast(S source) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" + return (__bridge T)(source); +#pragma clang diagnostic pop +} + +namespace Swift { + +namespace { + + +CFArrayRef CreateClientCertificateChainAsCFArrayRef(CertificateWithKey::ref key) { + std::shared_ptr<PKCS12Certificate> pkcs12 = std::dynamic_pointer_cast<PKCS12Certificate>(key); + if (!key) { + return nullptr; + } + + SafeByteArray safePassword = pkcs12->getPassword(); + CFIndex passwordSize = 0; + try { + passwordSize = boost::numeric_cast<CFIndex>(safePassword.size()); + } catch (...) { + return nullptr; + } + + CFMutableArrayRef certChain = CFArrayCreateMutable(nullptr, 0, nullptr); + + OSStatus securityError = errSecSuccess; + CFStringRef password = CFStringCreateWithBytes(kCFAllocatorDefault, safePassword.data(), passwordSize, kCFStringEncodingUTF8, false); + const void* keys[] = { kSecImportExportPassphrase }; + const void* values[] = { password }; + + CFDictionaryRef options = CFDictionaryCreate(nullptr, keys, values, 1, nullptr, nullptr); + + CFArrayRef items = nullptr; + CFDataRef pkcs12Data = bridge_cast<CFDataRef>([NSData dataWithBytes: static_cast<const void *>(pkcs12->getData().data()) length:pkcs12->getData().size()]); + securityError = SecPKCS12Import(pkcs12Data, options, &items); + CFRelease(options); + NSArray* nsItems = bridge_cast<NSArray*>(items); + + switch(securityError) { + case errSecSuccess: + break; + case errSecAuthFailed: + // Password did not work for decoding the certificate. + SWIFT_LOG(warning) << "Invalid password."; + break; + case errSecDecode: + // Other decoding error. + SWIFT_LOG(warning) << "PKCS12 decoding error."; + break; + default: + SWIFT_LOG(warning) << "Unknown error."; + } + + if (securityError != errSecSuccess) { + if (items) { + CFRelease(items); + items = nullptr; + } + CFRelease(certChain); + certChain = nullptr; + } + + if (certChain) { + CFArrayAppendValue(certChain, nsItems[0][@"identity"]); + + for (CFIndex index = 0; index < CFArrayGetCount(bridge_cast<CFArrayRef>(nsItems[0][@"chain"])); index++) { + CFArrayAppendValue(certChain, CFArrayGetValueAtIndex(bridge_cast<CFArrayRef>(nsItems[0][@"chain"]), index)); + } + } + return certChain; +} + +} + +SecureTransportContext::SecureTransportContext(bool checkCertificateRevocation) : state_(None), checkCertificateRevocation_(checkCertificateRevocation) { + sslContext_ = std::shared_ptr<SSLContext>(SSLCreateContext(nullptr, kSSLClientSide, kSSLStreamType), CFRelease); + + OSStatus error = noErr; + // set IO callbacks + error = SSLSetIOFuncs(sslContext_.get(), &SecureTransportContext::SSLSocketReadCallback, &SecureTransportContext::SSLSocketWriteCallback); + if (error != noErr) { + SWIFT_LOG(error) << "Unable to set IO functions to SSL context."; + sslContext_.reset(); + } + + error = SSLSetConnection(sslContext_.get(), this); + if (error != noErr) { + SWIFT_LOG(error) << "Unable to set connection to SSL context."; + sslContext_.reset(); + } + + + error = SSLSetSessionOption(sslContext_.get(), kSSLSessionOptionBreakOnServerAuth, true); + if (error != noErr) { + SWIFT_LOG(error) << "Unable to set kSSLSessionOptionBreakOnServerAuth on session."; + sslContext_.reset(); + } +} + +SecureTransportContext::~SecureTransportContext() { + if (sslContext_) { + SSLClose(sslContext_.get()); + } +} + +std::string SecureTransportContext::stateToString(State state) { + std::string returnValue; + switch(state) { + case Handshake: + returnValue = "Handshake"; + break; + case HandshakeDone: + returnValue = "HandshakeDone"; + break; + case None: + returnValue = "None"; + break; + case Error: + returnValue = "Error"; + break; + } + return returnValue; +} + +void SecureTransportContext::setState(State newState) { + SWIFT_LOG(debug) << "Switch state from " << stateToString(state_) << " to " << stateToString(newState) << "."; + state_ = newState; +} + +void SecureTransportContext::connect() { + SWIFT_LOG_ASSERT(state_ == None, error) << "current state '" << stateToString(state_) << " invalid."; + if (clientCertificate_) { + CFArrayRef certs = CreateClientCertificateChainAsCFArrayRef(clientCertificate_); + if (certs) { + std::shared_ptr<CFArray> certRefs(certs, CFRelease); + OSStatus result = SSLSetCertificate(sslContext_.get(), certRefs.get()); + if (result != noErr) { + SWIFT_LOG(error) << "SSLSetCertificate failed with error " << result << "."; + } + } + } + processHandshake(); +} + +void SecureTransportContext::processHandshake() { + SWIFT_LOG_ASSERT(state_ == None || state_ == Handshake, error) << "current state '" << stateToString(state_) << " invalid."; + OSStatus error = SSLHandshake(sslContext_.get()); + if (error == errSSLWouldBlock) { + setState(Handshake); + } + else if (error == noErr) { + SWIFT_LOG(debug) << "TLS handshake successful."; + setState(HandshakeDone); + onConnected(); + } + else if (error == errSSLPeerAuthCompleted) { + SWIFT_LOG(debug) << "Received server certificate. Start verification."; + setState(Handshake); + verifyServerCertificate(); + } + else { + SWIFT_LOG(debug) << "Error returned from SSLHandshake call is " << error << "."; + fatalError(nativeToTLSError(error), std::make_shared<CertificateVerificationError>()); + } +} + + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +void SecureTransportContext::verifyServerCertificate() { + SecTrustRef trust = nullptr; + OSStatus error = SSLCopyPeerTrust(sslContext_.get(), &trust); + if (error != noErr) { + fatalError(std::make_shared<TLSError>(), std::make_shared<CertificateVerificationError>()); + return; + } + std::shared_ptr<SecTrust> trustRef = std::shared_ptr<SecTrust>(trust, CFRelease); + + if (checkCertificateRevocation_) { + error = SecTrustSetOptions(trust, kSecTrustOptionRequireRevPerCert | kSecTrustOptionFetchIssuerFromNet); + if (error != noErr) { + fatalError(std::make_shared<TLSError>(), std::make_shared<CertificateVerificationError>()); + return; + } + } + + SecTrustResultType trustResult; + error = SecTrustEvaluate(trust, &trustResult); + if (error != errSecSuccess) { + fatalError(std::make_shared<TLSError>(), std::make_shared<CertificateVerificationError>()); + return; + } + + OSStatus cssmResult = 0; + switch(trustResult) { + case kSecTrustResultUnspecified: + SWIFT_LOG(warning) << "Successful implicit validation. Result unspecified."; + break; + case kSecTrustResultProceed: + SWIFT_LOG(warning) << "Validation resulted in explicitly trusted."; + break; + case kSecTrustResultRecoverableTrustFailure: + SWIFT_LOG(warning) << "recoverable trust failure"; + error = SecTrustGetCssmResultCode(trust, &cssmResult); + if (error == errSecSuccess) { + verificationError_ = CSSMErrorToVerificationError(cssmResult); + if (cssmResult == CSSMERR_TP_VERIFY_ACTION_FAILED || cssmResult == CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK ) { + // Find out the reason why the verification failed. + CFArrayRef certChain; + CSSM_TP_APPLE_EVIDENCE_INFO* statusChain; + error = SecTrustGetResult(trustRef.get(), &trustResult, &certChain, &statusChain); + if (error == errSecSuccess) { + std::shared_ptr<CFArray> certChainRef = std::shared_ptr<CFArray>(certChain, CFRelease); + for (CFIndex index = 0; index < CFArrayGetCount(certChainRef.get()); index++) { + for (CFIndex n = 0; n < statusChain[index].NumStatusCodes; n++) { + // Even though Secure Transport reported CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK on the whole certificate + // chain, the actual cause can be that a revocation check for a specific cert returned CSSMERR_TP_CERT_REVOKED. + if (!verificationError_ || verificationError_->getType() == CertificateVerificationError::RevocationCheckFailed) { + verificationError_ = CSSMErrorToVerificationError(statusChain[index].StatusCodes[n]); + } + } + } + } + else { + + } + } + } + else { + verificationError_ = std::make_shared<CertificateVerificationError>(CertificateVerificationError::UnknownError); + } + break; + case kSecTrustResultInvalid: + verificationError_ = std::make_shared<CertificateVerificationError>(CertificateVerificationError::UnknownError); + break; + case kSecTrustResultConfirm: + // TODO: Confirmation from the user is required before proceeding. + verificationError_ = std::make_shared<CertificateVerificationError>(CertificateVerificationError::UnknownError); + break; + case kSecTrustResultDeny: + // The user specified that the certificate should not be trusted. + verificationError_ = std::make_shared<CertificateVerificationError>(CertificateVerificationError::Untrusted); + break; + case kSecTrustResultFatalTrustFailure: + // Trust denied; no simple fix is available. + verificationError_ = std::make_shared<CertificateVerificationError>(CertificateVerificationError::UnknownError); + break; + case kSecTrustResultOtherError: + verificationError_ = std::make_shared<CertificateVerificationError>(CertificateVerificationError::UnknownError); + break; + } + + // We proceed with the TLS handshake here to give the application an opportunity + // to apply custom validation and trust management. The application is responsible + // to call \ref getPeerCertificateVerificationError directly after the \ref onConnected + // signal is called and before any application data is send to the context. + processHandshake(); +} + +#pragma clang diagnostic pop + +bool SecureTransportContext::setClientCertificate(CertificateWithKey::ref cert) { + CFArrayRef nativeClientChain = CreateClientCertificateChainAsCFArrayRef(cert); + if (nativeClientChain) { + clientCertificate_ = cert; + CFRelease(nativeClientChain); + return true; + } + else { + return false; + } +} + +void SecureTransportContext::handleDataFromNetwork(const SafeByteArray& data) { + SWIFT_LOG(debug); + SWIFT_LOG_ASSERT(state_ == HandshakeDone || state_ == Handshake, error) << "current state '" << stateToString(state_) << " invalid."; + + append(readingBuffer_, data); + + size_t bytesRead = 0; + OSStatus error = noErr; + SafeByteArray applicationData; + + switch(state_) { + case None: + assert(false && "Invalid state 'None'."); + break; + case Handshake: + processHandshake(); + break; + case HandshakeDone: + while (error == noErr) { + applicationData.resize(readingBuffer_.size()); + error = SSLRead(sslContext_.get(), applicationData.data(), applicationData.size(), &bytesRead); + if (error == noErr) { + // Read successful. + } + else if (error == errSSLWouldBlock) { + // Secure Transport does not want more data. + break; + } + else { + SWIFT_LOG(error) << "SSLRead failed with error " << error << ", read bytes: " << bytesRead << "."; + fatalError(std::make_shared<TLSError>(), std::make_shared<CertificateVerificationError>()); + return; + } + + if (bytesRead > 0) { + applicationData.resize(bytesRead); + onDataForApplication(applicationData); + } + else { + break; + } + } + break; + case Error: + SWIFT_LOG(debug) << "Igoring received data in error state."; + break; + } +} + + +void SecureTransportContext::handleDataFromApplication(const SafeByteArray& data) { + size_t processedBytes = 0; + OSStatus error = SSLWrite(sslContext_.get(), data.data(), data.size(), &processedBytes); + switch(error) { + case errSSLWouldBlock: + SWIFT_LOG(warning) << "Unexpected because the write callback does not block."; + return; + case errSSLClosedGraceful: + case noErr: + return; + default: + SWIFT_LOG(warning) << "SSLWrite returned error code: " << error << ", processed bytes: " << processedBytes; + fatalError(std::make_shared<TLSError>(), std::shared_ptr<CertificateVerificationError>()); + } +} + +std::vector<Certificate::ref> SecureTransportContext::getPeerCertificateChain() const { + std::vector<Certificate::ref> peerCertificateChain; + + if (sslContext_) { + typedef boost::remove_pointer<SecTrustRef>::type SecTrust; + std::shared_ptr<SecTrust> securityTrust; + + SecTrustRef secTrust = nullptr; + OSStatus error = SSLCopyPeerTrust(sslContext_.get(), &secTrust); + if (error == noErr) { + securityTrust = std::shared_ptr<SecTrust>(secTrust, CFRelease); + + CFIndex chainSize = SecTrustGetCertificateCount(securityTrust.get()); + for (CFIndex n = 0; n < chainSize; n++) { + SecCertificateRef certificate = SecTrustGetCertificateAtIndex(securityTrust.get(), n); + if (certificate) { + peerCertificateChain.push_back(std::make_shared<SecureTransportCertificate>(certificate)); + } + } + } + else { + SWIFT_LOG(warning) << "Failed to obtain peer trust structure; error = " << error << "."; + } + } + + return peerCertificateChain; +} + +CertificateVerificationError::ref SecureTransportContext::getPeerCertificateVerificationError() const { + return verificationError_; +} + +ByteArray SecureTransportContext::getFinishMessage() const { + SWIFT_LOG(warning) << "Access to TLS handshake finish message is not part of OS X Secure Transport APIs."; + return ByteArray(); +} + +/** + * This I/O callback simulates an asynchronous read to the read buffer of the context. If it is empty, it returns errSSLWouldBlock; else + * the data within the buffer is returned. + */ +OSStatus SecureTransportContext::SSLSocketReadCallback(SSLConnectionRef connection, void *data, size_t *dataLength) { + SecureTransportContext* context = const_cast<SecureTransportContext*>(static_cast<const SecureTransportContext*>(connection)); + OSStatus retValue = noErr; + + if (context->readingBuffer_.size() < *dataLength) { + // Would block because Secure Transport is trying to read more data than there currently is available in the buffer. + *dataLength = 0; + retValue = errSSLWouldBlock; + } + else { + size_t bufferLen = *dataLength; + size_t copyToBuffer = bufferLen < context->readingBuffer_.size() ? bufferLen : context->readingBuffer_.size(); + + memcpy(data, context->readingBuffer_.data(), copyToBuffer); + + context->readingBuffer_ = SafeByteArray(context->readingBuffer_.data() + copyToBuffer, context->readingBuffer_.data() + context->readingBuffer_.size()); + *dataLength = copyToBuffer; + } + return retValue; +} + +OSStatus SecureTransportContext::SSLSocketWriteCallback(SSLConnectionRef connection, const void *data, size_t *dataLength) { + SecureTransportContext* context = const_cast<SecureTransportContext*>(static_cast<const SecureTransportContext*>(connection)); + OSStatus retValue = noErr; + + SafeByteArray safeData; + safeData.resize(*dataLength); + memcpy(safeData.data(), data, safeData.size()); + + context->onDataForNetwork(safeData); + return retValue; +} + +std::shared_ptr<TLSError> SecureTransportContext::nativeToTLSError(OSStatus /* error */) { + std::shared_ptr<TLSError> swiftenError; + swiftenError = std::make_shared<TLSError>(); + return swiftenError; +} + +std::shared_ptr<CertificateVerificationError> SecureTransportContext::CSSMErrorToVerificationError(OSStatus resultCode) { + std::shared_ptr<CertificateVerificationError> error; + switch(resultCode) { + case CSSMERR_TP_NOT_TRUSTED: + SWIFT_LOG(debug) << "CSSM result code: CSSMERR_TP_NOT_TRUSTED"; + error = std::make_shared<CertificateVerificationError>(CertificateVerificationError::Untrusted); + break; + case CSSMERR_TP_CERT_NOT_VALID_YET: + SWIFT_LOG(debug) << "CSSM result code: CSSMERR_TP_CERT_NOT_VALID_YET"; + error = std::make_shared<CertificateVerificationError>(CertificateVerificationError::NotYetValid); + break; + case CSSMERR_TP_CERT_EXPIRED: + SWIFT_LOG(debug) << "CSSM result code: CSSMERR_TP_CERT_EXPIRED"; + error = std::make_shared<CertificateVerificationError>(CertificateVerificationError::Expired); + break; + case CSSMERR_TP_CERT_REVOKED: + SWIFT_LOG(debug) << "CSSM result code: CSSMERR_TP_CERT_REVOKED"; + error = std::make_shared<CertificateVerificationError>(CertificateVerificationError::Revoked); + break; + case CSSMERR_TP_VERIFY_ACTION_FAILED: + SWIFT_LOG(debug) << "CSSM result code: CSSMERR_TP_VERIFY_ACTION_FAILED"; + break; + case CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK: + SWIFT_LOG(debug) << "CSSM result code: CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK"; + if (checkCertificateRevocation_) { + error = std::make_shared<CertificateVerificationError>(CertificateVerificationError::RevocationCheckFailed); + } + break; + case CSSMERR_APPLETP_OCSP_UNAVAILABLE: + SWIFT_LOG(debug) << "CSSM result code: CSSMERR_APPLETP_OCSP_UNAVAILABLE"; + if (checkCertificateRevocation_) { + error = std::make_shared<CertificateVerificationError>(CertificateVerificationError::RevocationCheckFailed); + } + break; + case CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE: + SWIFT_LOG(debug) << "CSSM result code: CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE"; + error = std::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidPurpose); + break; + default: + SWIFT_LOG(warning) << "unhandled CSSM error: " << resultCode << ", CSSM_TP_BASE_TP_ERROR: " << CSSM_TP_BASE_TP_ERROR; + error = std::make_shared<CertificateVerificationError>(CertificateVerificationError::UnknownError); + break; + } + return error; +} + +void SecureTransportContext::fatalError(std::shared_ptr<TLSError> error, std::shared_ptr<CertificateVerificationError> certificateError) { + setState(Error); + if (sslContext_) { + SSLClose(sslContext_.get()); + } + verificationError_ = certificateError; + onError(error); +} + +} diff --git a/Swiften/TLS/SecureTransport/SecureTransportContextFactory.cpp b/Swiften/TLS/SecureTransport/SecureTransportContextFactory.cpp new file mode 100644 index 0000000..ac399e1 --- /dev/null +++ b/Swiften/TLS/SecureTransport/SecureTransportContextFactory.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/TLS/SecureTransport/SecureTransportContextFactory.h> + +#include <Swiften/Base/Log.h> +#include <Swiften/TLS/SecureTransport/SecureTransportContext.h> + +namespace Swift { + +// Default to disabled revocation checking as SecureTransport API is missing +// methods for detailed revocation checking configuration which are needed for +// good UX. +SecureTransportContextFactory::SecureTransportContextFactory() : checkCertificateRevocation_(false), disconnectOnCardRemoval_(true) { + +} + +SecureTransportContextFactory::~SecureTransportContextFactory() { + +} + +bool SecureTransportContextFactory::canCreate() const { + return true; +} + +std::unique_ptr<TLSContext> SecureTransportContextFactory::createTLSContext(const TLSOptions& /* tlsOptions */, TLSContext::Mode mode) { + // TLS server mode is not supported for the SecureTransport backend yet. + assert(mode == TLSContext::Mode::Client); + return std::unique_ptr<TLSContext>(new SecureTransportContext(checkCertificateRevocation_)); +} + +void SecureTransportContextFactory::setCheckCertificateRevocation(bool b) { + checkCertificateRevocation_ = b; +} + +void SecureTransportContextFactory::setDisconnectOnCardRemoval(bool b) { + disconnectOnCardRemoval_ = b; + if (disconnectOnCardRemoval_) { + SWIFT_LOG(warning) << "Smart cards have not been tested yet"; + } +} + +} diff --git a/Swiften/TLS/SecureTransport/SecureTransportContextFactory.h b/Swiften/TLS/SecureTransport/SecureTransportContextFactory.h new file mode 100644 index 0000000..b86639a --- /dev/null +++ b/Swiften/TLS/SecureTransport/SecureTransportContextFactory.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <Swiften/TLS/TLSContextFactory.h> + +namespace Swift { + +class SecureTransportContextFactory : public TLSContextFactory { + public: + SecureTransportContextFactory(); + virtual ~SecureTransportContextFactory(); + + virtual bool canCreate() const; + + virtual std::unique_ptr<TLSContext> createTLSContext(const TLSOptions& tlsOptions, TLSContext::Mode mode = TLSContext::Mode::Client); + virtual void setCheckCertificateRevocation(bool b); + virtual void setDisconnectOnCardRemoval(bool b); + + private: + bool checkCertificateRevocation_; + bool disconnectOnCardRemoval_; +}; + +} diff --git a/Swiften/TLS/ServerIdentityVerifier.cpp b/Swiften/TLS/ServerIdentityVerifier.cpp index 02459b9..18ea2aa 100644 --- a/Swiften/TLS/ServerIdentityVerifier.cpp +++ b/Swiften/TLS/ServerIdentityVerifier.cpp @@ -1,88 +1,96 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/TLS/ServerIdentityVerifier.h> #include <boost/algorithm/string.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/IDN/IDNConverter.h> namespace Swift { -ServerIdentityVerifier::ServerIdentityVerifier(const JID& jid, IDNConverter* idnConverter) { - domain = jid.getDomain(); - encodedDomain = idnConverter->getIDNAEncoded(domain); +ServerIdentityVerifier::ServerIdentityVerifier(const JID& jid, IDNConverter* idnConverter, bool checkServer) : domainValid(false), checkServer_(checkServer) { + domain = jid.getDomain(); + boost::optional<std::string> domainResult = idnConverter->getIDNAEncoded(domain); + if (!!domainResult) { + encodedDomain = *domainResult; + domainValid = true; + } } bool ServerIdentityVerifier::certificateVerifies(Certificate::ref certificate) { - bool hasSAN = false; + bool hasSAN = false; - if (certificate == NULL) { - return false; - } - // DNS names - std::vector<std::string> dnsNames = certificate->getDNSNames(); - foreach (const std::string& dnsName, dnsNames) { - if (matchesDomain(dnsName)) { - return true; - } - } - hasSAN |= !dnsNames.empty(); + if (certificate == nullptr) { + return false; + } + // DNS names + std::vector<std::string> dnsNames = certificate->getDNSNames(); + for (const auto& dnsName : dnsNames) { + if (matchesDomain(dnsName)) { + return true; + } + } + hasSAN |= !dnsNames.empty(); - // SRV names - std::vector<std::string> srvNames = certificate->getSRVNames(); - foreach (const std::string& srvName, srvNames) { - // Only match SRV names that begin with the service; this isn't required per - // spec, but we're being purist about this. - if (boost::starts_with(srvName, "_xmpp-client.") && matchesDomain(srvName.substr(std::string("_xmpp-client.").size(), srvName.npos))) { - return true; - } - } - hasSAN |= !srvNames.empty(); + std::string prefix = (checkServer_) ? "_xmpp-server." : "_xmpp-client."; - // XmppAddr - std::vector<std::string> xmppAddresses = certificate->getXMPPAddresses(); - foreach (const std::string& xmppAddress, xmppAddresses) { - if (matchesAddress(xmppAddress)) { - return true; - } - } - hasSAN |= !xmppAddresses.empty(); + // SRV names + std::vector<std::string> srvNames = certificate->getSRVNames(); + for (const auto& srvName : srvNames) { + // Only match SRV names that begin with the service; this isn't required per + // spec, but we're being purist about this. + if (boost::starts_with(srvName, prefix) && matchesDomain(srvName.substr(prefix.size(), srvName.npos))) { + return true; + } + } + hasSAN |= !srvNames.empty(); - // CommonNames. Only check this if there was no SAN (according to spec). - if (!hasSAN) { - std::vector<std::string> commonNames = certificate->getCommonNames(); - foreach (const std::string& commonName, commonNames) { - if (matchesDomain(commonName)) { - return true; - } - } - } + // XmppAddr + std::vector<std::string> xmppAddresses = certificate->getXMPPAddresses(); + for (const auto& xmppAddress : xmppAddresses) { + if (matchesAddress(xmppAddress)) { + return true; + } + } + hasSAN |= !xmppAddresses.empty(); - return false; + // CommonNames. Only check this if there was no SAN (according to spec). + if (!hasSAN) { + std::vector<std::string> commonNames = certificate->getCommonNames(); + for (const auto& commonName : commonNames) { + if (matchesDomain(commonName)) { + return true; + } + } + } + + return false; } bool ServerIdentityVerifier::matchesDomain(const std::string& s) const { - if (boost::starts_with(s, "*.")) { - std::string matchString(s.substr(2, s.npos)); - std::string matchDomain = encodedDomain; - size_t dotIndex = matchDomain.find('.'); - if (dotIndex != matchDomain.npos) { - matchDomain = matchDomain.substr(dotIndex + 1, matchDomain.npos); - } - return matchString == matchDomain; - } - else { - return s == encodedDomain; - } + if (!domainValid) { + return false; + } + if (boost::starts_with(s, "*.")) { + std::string matchString(s.substr(2, s.npos)); + std::string matchDomain = encodedDomain; + size_t dotIndex = matchDomain.find('.'); + if (dotIndex != matchDomain.npos) { + matchDomain = matchDomain.substr(dotIndex + 1, matchDomain.npos); + } + return boost::iequals(matchString, matchDomain); + } + else { + return boost::iequals(s, encodedDomain); + } } bool ServerIdentityVerifier::matchesAddress(const std::string& s) const { - return s == domain; + return boost::iequals(s, domain); } } diff --git a/Swiften/TLS/ServerIdentityVerifier.h b/Swiften/TLS/ServerIdentityVerifier.h index 4167ce8..f2cf46f 100644 --- a/Swiften/TLS/ServerIdentityVerifier.h +++ b/Swiften/TLS/ServerIdentityVerifier.h @@ -1,33 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> - +#include <memory> #include <string> + #include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> #include <Swiften/TLS/Certificate.h> namespace Swift { - class IDNConverter; + class IDNConverter; - class SWIFTEN_API ServerIdentityVerifier { - public: - ServerIdentityVerifier(const JID& jid, IDNConverter* idnConverter); + class SWIFTEN_API ServerIdentityVerifier { + public: + ServerIdentityVerifier(const JID& jid, IDNConverter* idnConverter, bool checkServer=false); - bool certificateVerifies(Certificate::ref); + bool certificateVerifies(Certificate::ref); - private: - bool matchesDomain(const std::string&) const ; - bool matchesAddress(const std::string&) const; + private: + bool matchesDomain(const std::string&) const ; + bool matchesAddress(const std::string&) const; - private: - std::string domain; - std::string encodedDomain; - }; + private: + std::string domain; + std::string encodedDomain; + bool domainValid; + bool checkServer_; + }; } diff --git a/Swiften/TLS/SimpleCertificate.h b/Swiften/TLS/SimpleCertificate.h index 4cf0cc2..08cf1e3 100644 --- a/Swiften/TLS/SimpleCertificate.h +++ b/Swiften/TLS/SimpleCertificate.h @@ -1,76 +1,78 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + +#include <Swiften/Base/API.h> #include <Swiften/TLS/Certificate.h> namespace Swift { - class SimpleCertificate : public Certificate { - public: - typedef boost::shared_ptr<SimpleCertificate> ref; - - void setSubjectName(const std::string& name) { - subjectName = name; - } - - std::string getSubjectName() const { - return subjectName; - } - - std::vector<std::string> getCommonNames() const { - return commonNames; - } - - void addCommonName(const std::string& name) { - commonNames.push_back(name); - } - - void addSRVName(const std::string& name) { - srvNames.push_back(name); - } - - void addDNSName(const std::string& name) { - dnsNames.push_back(name); - } - - void addXMPPAddress(const std::string& addr) { - xmppAddresses.push_back(addr); - } - - std::vector<std::string> getSRVNames() const { - return srvNames; - } - - std::vector<std::string> getDNSNames() const { - return dnsNames; - } - - std::vector<std::string> getXMPPAddresses() const { - return xmppAddresses; - } - - ByteArray toDER() const { - return der; - } - - void setDER(const ByteArray& der) { - this->der = der; - } - - private: - void parse(); - - private: - std::string subjectName; - ByteArray der; - std::vector<std::string> commonNames; - std::vector<std::string> dnsNames; - std::vector<std::string> xmppAddresses; - std::vector<std::string> srvNames; - }; + class SWIFTEN_API SimpleCertificate : public Certificate { + public: + typedef std::shared_ptr<SimpleCertificate> ref; + + void setSubjectName(const std::string& name) { + subjectName = name; + } + + std::string getSubjectName() const { + return subjectName; + } + + std::vector<std::string> getCommonNames() const { + return commonNames; + } + + void addCommonName(const std::string& name) { + commonNames.push_back(name); + } + + void addSRVName(const std::string& name) { + srvNames.push_back(name); + } + + void addDNSName(const std::string& name) { + dnsNames.push_back(name); + } + + void addXMPPAddress(const std::string& addr) { + xmppAddresses.push_back(addr); + } + + std::vector<std::string> getSRVNames() const { + return srvNames; + } + + std::vector<std::string> getDNSNames() const { + return dnsNames; + } + + std::vector<std::string> getXMPPAddresses() const { + return xmppAddresses; + } + + ByteArray toDER() const { + return der; + } + + void setDER(const ByteArray& der) { + this->der = der; + } + + private: + void parse(); + + private: + std::string subjectName; + ByteArray der; + std::vector<std::string> commonNames; + std::vector<std::string> dnsNames; + std::vector<std::string> xmppAddresses; + std::vector<std::string> srvNames; + }; } diff --git a/Swiften/TLS/TLSContext.cpp b/Swiften/TLS/TLSContext.cpp index d461d91..fd31c2d 100644 --- a/Swiften/TLS/TLSContext.cpp +++ b/Swiften/TLS/TLSContext.cpp @@ -1,19 +1,53 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/TLS/TLSContext.h> +#include <cassert> + namespace Swift { TLSContext::~TLSContext() { } +void TLSContext::accept() { + assert(false); +} + +void TLSContext::connect(const std::string& /* serverName */) { + assert(false); +} + +bool TLSContext::setCertificateChain(const std::vector<std::shared_ptr<Certificate>>& /* certificateChain */) { + assert(false); + return false; +} + +bool TLSContext::setPrivateKey(const PrivateKey::ref& /* privateKey */) { + assert(false); + return false; +} + +bool TLSContext::setDiffieHellmanParameters(const ByteArray& /*parametersInOpenSslDer*/) { + assert(false); + return false; +} + +void TLSContext::setAbortTLSHandshake(bool /* abort */) { + assert(false); +} + Certificate::ref TLSContext::getPeerCertificate() const { - std::vector<Certificate::ref> chain = getPeerCertificateChain(); - return chain.empty() ? Certificate::ref() : chain[0]; + std::vector<Certificate::ref> chain = getPeerCertificateChain(); + return chain.empty() ? Certificate::ref() : chain[0]; +} + +ByteArray TLSContext::getPeerFinishMessage() const { + assert(false); + return ByteArray(); } } diff --git a/Swiften/TLS/TLSContext.h b/Swiften/TLS/TLSContext.h index 5fee021..f2dbdce 100644 --- a/Swiften/TLS/TLSContext.h +++ b/Swiften/TLS/TLSContext.h @@ -1,43 +1,66 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> +#include <memory> +#include <boost/signals2.hpp> + +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> #include <Swiften/TLS/Certificate.h> -#include <Swiften/TLS/CertificateWithKey.h> #include <Swiften/TLS/CertificateVerificationError.h> +#include <Swiften/TLS/CertificateWithKey.h> +#include <Swiften/TLS/PrivateKey.h> #include <Swiften/TLS/TLSError.h> namespace Swift { - class TLSContext { - public: - virtual ~TLSContext(); + class SWIFTEN_API TLSContext { + public: + virtual ~TLSContext(); + + virtual void accept(); + virtual void connect() = 0; + virtual void connect(const std::string& serverName); + + virtual bool setCertificateChain(const std::vector<std::shared_ptr<Certificate>>& /* certificateChain */); + virtual bool setPrivateKey(const PrivateKey::ref& /* privateKey */); + + virtual bool setClientCertificate(CertificateWithKey::ref cert) = 0; + virtual bool setDiffieHellmanParameters(const ByteArray& parametersInOpenSslDer); - virtual void connect() = 0; + /** + * This method can be used during the \ref onServerNameRequested signal, + * to report an error about an unknown host back to the requesting client. + */ + virtual void setAbortTLSHandshake(bool /* abort */); - virtual bool setClientCertificate(CertificateWithKey::ref cert) = 0; + virtual void handleDataFromNetwork(const SafeByteArray&) = 0; + virtual void handleDataFromApplication(const SafeByteArray&) = 0; - virtual void handleDataFromNetwork(const SafeByteArray&) = 0; - virtual void handleDataFromApplication(const SafeByteArray&) = 0; + Certificate::ref getPeerCertificate() const; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; + virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const = 0; - Certificate::ref getPeerCertificate() const; - virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; - virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const = 0; + virtual ByteArray getFinishMessage() const = 0; + virtual ByteArray getPeerFinishMessage() const; - virtual ByteArray getFinishMessage() const = 0; + public: + enum class Mode { + Client, + Server + }; - public: - boost::signal<void (const SafeByteArray&)> onDataForNetwork; - boost::signal<void (const SafeByteArray&)> onDataForApplication; - boost::signal<void (boost::shared_ptr<TLSError>)> onError; - boost::signal<void ()> onConnected; - }; + public: + boost::signals2::signal<void (const SafeByteArray&)> onDataForNetwork; + boost::signals2::signal<void (const SafeByteArray&)> onDataForApplication; + boost::signals2::signal<void (std::shared_ptr<TLSError>)> onError; + boost::signals2::signal<void ()> onConnected; + boost::signals2::signal<void (const std::string&)> onServerNameRequested; + }; } diff --git a/Swiften/TLS/TLSContextFactory.cpp b/Swiften/TLS/TLSContextFactory.cpp index eb02f0c..91e60d6 100644 --- a/Swiften/TLS/TLSContextFactory.cpp +++ b/Swiften/TLS/TLSContextFactory.cpp @@ -1,14 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/TLS/TLSContextFactory.h> +#include <cassert> + namespace Swift { TLSContextFactory::~TLSContextFactory() { } +ByteArray TLSContextFactory::convertDHParametersFromPEMToDER(const std::string& /* pem */) { + assert(false); + return ByteArray(); +} + } diff --git a/Swiften/TLS/TLSContextFactory.h b/Swiften/TLS/TLSContextFactory.h index 5f08925..5f70541 100644 --- a/Swiften/TLS/TLSContextFactory.h +++ b/Swiften/TLS/TLSContextFactory.h @@ -1,21 +1,29 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> + +#include <Swiften/Base/API.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/TLS/TLSContext.h> +#include <Swiften/TLS/TLSOptions.h> + namespace Swift { - class TLSContext; + class SWIFTEN_API TLSContextFactory { + public: + virtual ~TLSContextFactory(); - class TLSContextFactory { - public: - virtual ~TLSContextFactory(); + virtual bool canCreate() const = 0; - virtual bool canCreate() const = 0; + virtual std::unique_ptr<TLSContext> createTLSContext(const TLSOptions& tlsOptions, TLSContext::Mode = TLSContext::Mode::Client) = 0; + virtual void setCheckCertificateRevocation(bool b) = 0; + virtual void setDisconnectOnCardRemoval(bool b) = 0; - virtual TLSContext* createTLSContext() = 0; - virtual void setCheckCertificateRevocation(bool b) = 0; - }; + virtual ByteArray convertDHParametersFromPEMToDER(const std::string& pem); + }; } diff --git a/Swiften/TLS/TLSError.h b/Swiften/TLS/TLSError.h index f9ed8f7..9e4af2f 100644 --- a/Swiften/TLS/TLSError.h +++ b/Swiften/TLS/TLSError.h @@ -1,31 +1,41 @@ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + +#include <Swiften/Base/API.h> #include <Swiften/Base/Error.h> namespace Swift { - class TLSError : public Error { - public: - typedef boost::shared_ptr<TLSError> ref; + class SWIFTEN_API TLSError : public Error { + public: + typedef std::shared_ptr<TLSError> ref; + + enum Type { + UnknownError, + CertificateCardRemoved, + AcceptFailed, + ConnectFailed + }; - enum Type { - UnknownError, - CertificateCardRemoved - }; + TLSError(Type type = UnknownError, std::string message = "") : type_(type), message_(std::move(message)) {} - TLSError(Type type = UnknownError) : type(type) {} + Type getType() const { + return type_; + } - Type getType() const { - return type; - } + const std::string& getMessage() const { + return message_; + } - private: - Type type; - }; + private: + Type type_; + std::string message_; + }; } diff --git a/Swiften/TLS/TLSOptions.h b/Swiften/TLS/TLSOptions.h new file mode 100644 index 0000000..e3faaf9 --- /dev/null +++ b/Swiften/TLS/TLSOptions.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +namespace Swift { + class TLSContext; + class Certificate; + + class TLSOptions { + public: + TLSOptions() : schannelTLS1_0Workaround(false) { + + } + + /** + * A bug in the Windows SChannel TLS stack, combined with + * overly-restrictive server stacks means it's sometimes necessary to + * not use TLS>1.0. This option has no effect unless compiled on + * Windows against SChannel (OpenSSL users are unaffected). + */ + bool schannelTLS1_0Workaround; + + /** + * OpenSSL configuration flags + */ + boost::optional<bool> workaroundMicrosoftSessID; + boost::optional<bool> workaroundNetscapeChallenge; + boost::optional<bool> workaroundNetscapeReuseCipherChange; + boost::optional<bool> workaroundSSLRef2ReuseCertType; + boost::optional<bool> workaroundMicrosoftBigSSLv3Buffer; + boost::optional<bool> workaroundSSLeay080ClientDH; + boost::optional<bool> workaroundTLSD5; + boost::optional<bool> workaroundTLSBlockPadding; + boost::optional<bool> workaroundDontInsertEmptyFragments; + boost::optional<bool> workaroundAll; + boost::optional<bool> suppressSSLv2; + boost::optional<bool> suppressSSLv3; + boost::optional<bool> suppressTLSv1; + boost::optional<bool> disableTLSRollBackBug; + boost::optional<bool> singleDHUse; + + /** + * Other OpenSSL configuration items + */ + boost::optional<std::string> cipherSuites; + boost::optional<std::string> context; + boost::optional<int> sessionCacheTimeout; + boost::optional<int> verifyDepth; + + enum class VerifyMode { + None, + Required, + Optional + }; + boost::optional<VerifyMode> verifyMode; + + /** + * Callback for certificate verification + */ + + boost::optional<std::function<int(const TLSContext *)>> verifyCertificateCallback; + + /** + * Allows specification of application-specific Trust Anchors + */ + boost::optional<std::vector<std::shared_ptr<Certificate>>> trustAnchors; + + /** + * Turns off automatic loading of system Trust Anchors + */ + bool ignoreSystemTrustAnchors = false; + }; +} diff --git a/Swiften/TLS/UnitTest/CertificateTest.cpp b/Swiften/TLS/UnitTest/CertificateTest.cpp index 3352118..d5bf210 100644 --- a/Swiften/TLS/UnitTest/CertificateTest.cpp +++ b/Swiften/TLS/UnitTest/CertificateTest.cpp @@ -1,34 +1,143 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> +#include <memory> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/TLS/Certificate.h> -#include <Swiften/TLS/SimpleCertificate.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Platform.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/TLS/Certificate.h> +#include <Swiften/TLS/CertificateFactory.h> +#include <Swiften/TLS/PlatformTLSFactories.h> +#include <Swiften/TLS/SimpleCertificate.h> using namespace Swift; class CertificateTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(CertificateTest); - CPPUNIT_TEST(testGetSHA1Fingerprint); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(CertificateTest); + CPPUNIT_TEST(testGetSHA1Fingerprint); +#ifdef HAVE_OPENSSL + CPPUNIT_TEST(testParsingPEMCertificate); +#endif + CPPUNIT_TEST(testParsingPEMPrivateKey); + CPPUNIT_TEST_SUITE_END(); + + public: + void testGetSHA1Fingerprint() { + SimpleCertificate::ref testling = std::make_shared<SimpleCertificate>(); + testling->setDER(createByteArray("abcdefg")); + + CPPUNIT_ASSERT_EQUAL(std::string("2f:b5:e1:34:19:fc:89:24:68:65:e7:a3:24:f4:76:ec:62:4e:87:40"), Certificate::getSHA1Fingerprint(testling, std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()).get())); + } + + void testParsingPEMCertificate() { + PlatformTLSFactories tlsFactories; + + auto PEMCertificate = R"(-----BEGIN CERTIFICATE----- +MIIEsjCCApoCCQCbkjlQfUqPtTANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBBt +b250YWd1ZS5leGFtcGxlMB4XDTE4MDExODE2NTMxMloXDTQ1MDYwNDE2NTMxMlow +GzEZMBcGA1UEAwwQbW9udGFndWUuZXhhbXBsZTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBALAx5xuEYOjDJ9QHMvwRuDzxbHl1zR97SJFPAkmD8xH0sC61 +DNRyUvRq6UXb4znhqeqrNuZ9PV47GyK2Dpy/c/MY5NE3m/c+Z1tUnrcqyCkxITIn +jdSI/elc9yhtMXX6lRi68BdPJnj/9+6trW0cWHlKEgnaSTAgCVB+4Dg9mjTIroCa +HLoAKhr2zS7Ihs28aWb0cSvZ+qFgQhr7FGP2kfssTTQYyRPn9uHhtyWH6RqSv5x9 +BBGZWN5GtjkJvupcYWLt8ftuQyFpwEeEz5cgtiyKgsfz9CYvS9/OcwdLQr4z5Zq6 +eKxsog9GdwIi1Us4KR0X6tKu9ze42iEWF+foEWFP9/bjrVK/tt5lTSKnenk0nA8I +amkG0btNAGihDti3lv60bGpd3B2/uh4gzzT2buXdf0EaybCt52MIr8xkwMU0Tkri +RAYchdS8U8sekWG5Lg9m3L2BDa8/TKS/WflJhGcZeInGQslgIx7fCgO1M7Zr50pO +wSURPXpvqUkXNEBy639UQEUsnBhntEQwZWx/6x6Ma/U5a5dL6qbtEJjlwIvS+nl9 +3w26g3DvWydNMCtZIVhgdrl+dZs+Uw5eA3QkHkDTSfYvQk7X5SYL0J5ZxwBvU9r1 +ED054+TAEuX2euiRA37xLhxonj8BaKkPQGlAHCLZaZPmNJWkNxElJhMoCfqBAgMB +AAEwDQYJKoZIhvcNAQELBQADggIBAF+FNyW3nVeQeugBMksIhj7EMJl1AEKi0+78 +ZPsYX3CDbc/8GRZoTg/EWSiwPCBYc9VsxuKtODEYABCZgk7LnSBYoEauJDKWqkgM +UOKPJI2hu7mIK7FJpjvEZe2MnRRA63oI/NVDJm8T2clrv/vPkY+ppsVl0toC0SpH +/3dF5c65vYI19rTJraRU6kIrrgxFBzxzpn07LGh2rrOCQfy2umTSRMwz3ORAFfmi ++Kek1Dt7c+JVJ0ivCwhhc8MKza3JS2MuDfVWGnXtDLb81Ai0t4tQfLKvZEcgW+lh +Drz9gv22buwncWL/IxtuhzyILtDSDKAYFbhfG6IAQut9BjMgpMnKrBCDlOLJl08K +tgj2h7vUKyNSt3ndcSAtXjr6FD7+xPExJuyn/MgLONGGAZoZHFB4QO90wQaXxMPh +7rnjUtzfLR8qkDmX8ZB4f4VOWpDWo4hBpgjTk0gYfzEkrh+zTqE9reh7CZ1WzwXO +KnIBU2dZOE+XsJe49lW106DLqGzKRuQMUAwFMb7C7Nlg9GKTnvi41o+g6YE+MgxR +uPKu891pCBtnDxZiWPT+7Fa/9UXxdIOTVIHW6utSWiWYbeNwXSmIm2ShfmNfWj9m +x1JgJrFB6daWGR9aDBeDVRhgL6Z35lH7xI62pLJ4o2d2Y/9dUWAJfz5O8opeCyrF +zqCzpwGL +-----END CERTIFICATE----- +)"; + + auto certificateChain = tlsFactories.getCertificateFactory()->createCertificateChain(createByteArray(PEMCertificate)); + CPPUNIT_ASSERT_EQUAL(size_t(1), certificateChain.size()); + + auto certificate = certificateChain[0].get(); + CPPUNIT_ASSERT_EQUAL(std::string("/CN=montague.example"), certificate->getSubjectName()); + } + + void testParsingPEMPrivateKey() { + PlatformTLSFactories tlsFactories; + + auto PEMPrivateKey = R"(-----BEGIN PRIVATE KEY----- +MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCwMecbhGDowyfU +BzL8Ebg88Wx5dc0fe0iRTwJJg/MR9LAutQzUclL0aulF2+M54anqqzbmfT1eOxsi +tg6cv3PzGOTRN5v3PmdbVJ63KsgpMSEyJ43UiP3pXPcobTF1+pUYuvAXTyZ4//fu +ra1tHFh5ShIJ2kkwIAlQfuA4PZo0yK6Amhy6ACoa9s0uyIbNvGlm9HEr2fqhYEIa ++xRj9pH7LE00GMkT5/bh4bclh+kakr+cfQQRmVjeRrY5Cb7qXGFi7fH7bkMhacBH +hM+XILYsioLH8/QmL0vfznMHS0K+M+WaunisbKIPRncCItVLOCkdF+rSrvc3uNoh +Fhfn6BFhT/f2461Sv7beZU0ip3p5NJwPCGppBtG7TQBooQ7Yt5b+tGxqXdwdv7oe +IM809m7l3X9BGsmwredjCK/MZMDFNE5K4kQGHIXUvFPLHpFhuS4PZty9gQ2vP0yk +v1n5SYRnGXiJxkLJYCMe3woDtTO2a+dKTsElET16b6lJFzRAcut/VEBFLJwYZ7RE +MGVsf+sejGv1OWuXS+qm7RCY5cCL0vp5fd8NuoNw71snTTArWSFYYHa5fnWbPlMO +XgN0JB5A00n2L0JO1+UmC9CeWccAb1Pa9RA9OePkwBLl9nrokQN+8S4caJ4/AWip +D0BpQBwi2WmT5jSVpDcRJSYTKAn6gQIDAQABAoICABqc/wZ2AVlHGP36tGXEm2qB +INxbwcbujTB9mZ/XEWD176KucCiquAL5HxERPIointK2V82Kvzk7fkbI7v4YIQBo +Ey/S0XkP8Panmm2aRa+LHzN/K/odUxTrmN1/WMg0OE8K9Xbf2rTOHPntO9POQ0LW +wFDCqulc/WsuLtnv3Bn68fi0zn/9xF5cRvO5EDuFKPqHE40HGMdFTdbbc+IBfV1N +/L9QuxaJpA3MVSiTFc+QuOZ/L50k53pzfdSxtyeZGpCh1jofFn62hXeIBP8TztB9 +f3GKVKdr328HtPI2GPe3yQeNAOsyYWwjPZiSAFujOPqPAUYfbXH6NuBmgOfjcrRb +AhOv9F1VNi+G56NJ6jo/NPygD+LYQdIKs5rv3E4ehyQzbu+SoGyVCnF3qm0cvz+v +tB5/gNiWiyRhNF94DZHlceDMQSdyB/pfTZsKZ44Yv44Bzl54YbzR8yr/ZKzAj6gt +5lwAqCIcdRj4i5DmIa7psj3iYWe9hYV7f+zwdosPKibRvO9FpvDCbb7biIPkMozw +cYH6QlSsZ+XsK/Z3WPFPq0wHOgoWW9Tr8LYyQxGjLO+xD8ziQ7Rp0KApEunuO29s +CPXj+l1HqNmAK2LkdNI3c/yStlaAcOzYD6pauciHWlTnIGZG8aHV6elIjK0C/h7B +3GndVc0TbewbP0bL56QBAoIBAQDU/yl4nlELhpoI1WW8v/FcDnc3V5dBilJ3LQtp +a3SKBcNWXE850TviOAklMrYmS1wuWdBTjEay9Ka6dImqMFGupmJjLmUw0KXrtPin +xIz5DZ42nmTKnYevuBQoQrrq7toxf5hYow2ZjeH2vSX+igY1gxDZbLW4Wb9GPYMo +Au5+z8XpA8R0key52nvnKastm5YxNstAlBOodAPKlbIr2bzmrHSjXAGjUzb+z6NZ +5Lx+zvQCy9kaIYvfOJm3eLSbMXzeP2S59qbwL+dC4ZJ5m3hjRmMaactV6LSchVNt +eLEYJpm92IdjQhG6oqM0IaU3aSjWMSrOAytylmqoEt4wA+WhAoIBAQDTxJ9VLb+J +OD0x/9cm17KpK1nGQBQ0T0oZQUH5M/tXTPCCoIpoL9UhKQ34vlPaZXkBQrXPw+PN +Y0J26uR6w4CowWAMn8LR6cYsWcOKuURcDYs/SPflD3rraevJwugQhkXtub2nV7dP +88Z/jGvhXthJmjUmNoKq3OC2MuSfHSkm8ipvaAblwb+lt5zBJGQ6iGXbi5TI6b+D +lnAidQpG/V464Zc9gb788P0K2vUeoZRLI7CurYqpDV0mBtPhFv5L1M0S8+psG7Pa +NIEKcW/b76vU9odTrtGBT0gCVYU7f8QnTN4g6c7dEhcZa2Zvg0YSmb4XuU9RQGC5 +As47nEUnPCjhAoIBAQDTXKnAogn2kAmGvoyIs0hFe61d47ObPDH9RVvPruwkkvd2 +WX/c9f6gy853dU0/zwSYklOitM7rgs94s3BwzCYiU8XKeh28RTCBKEKf6PGjq5nW +xXNrhMtC2j5WfXGS9JbdC6sYOiWivSMAgE6Vuk3TCE7OE4x4dcbTYvMl31Lf0Dqq +sixfKPdqrp7Jk5XkWkK+b4teeBLR1N52R/pYfWdw2K2d9g1CD6/BSDbnW46Zn7CQ +nczAm417Y2VWpZdDceZhfTLtPxAFxOOOgN2jg14B1bU+XsGCbLvdnohdV6kVOCjU +NWyUWNnTBNVDRCf5RodZlczORmL1AMKyKpcFurhBAoIBABSxbfBg3AqImFI+ccO1 +6BtnxQn+UPsblF4LZmr3jWPmfMoG7f9oTSdEX70ivAbnS3+4CRQYTDZRsLj2EwV7 +/SKAYuZY5iyk71x+GQGBQRDNsgGpG7AiZxyB6Sx6Azs6I7MrJ0Em7R6+73KfQhtv +rSrkCrWFNheEJeEn7/csXk0T9NmWDLZ+zD9hRcwJxlGB6pIdfZh0XuZ42NRFI4/0 +SjTuvlygRQ1qbw+UfcdUeq0s+6LWCmqih6ujlyizmn3GeZOUih+uRVDZOJLQquGO +9feFb4vZ1VcRbDPuL2q0/XHprPsCXdh0YBV3zTawWTSQGWcwEHQcGld50rU4e/lt +g4ECggEBAKwoqsqIHheL+uS2CHXmwFIr+rvOlLYlfB8XrwV/da3p7QChaDLbNIVM +uOAozCMkJY+dufPGI+3cKsR3kLAGejmfbH5OTzTbwCLOJFCWaoMuvOTY2Govte61 +gU1BWnjUgVJgVA/YTwn2yo02d0nG5/rSZ9xIt3hfO6ac5FhHBTA1DAZ1wDiLeow+ +qngZ2sA4ePtwhGFtvLVwTcGAfkWvQFi2YPBpesFIAmQ/ACGC7Ye75Ja4k36/8YwE +NiXR2Yy1hxwwi7CTWWzI0X+mvE/Oqpd8PUqPJCJcpz892Gq4EGCxM7Bz7NxCcvvw +5IMXuORWuoq0gXiCdEyko+saXsyWlqw= +-----END PRIVATE KEY----- +)"; - public: - void testGetSHA1Fingerprint() { - SimpleCertificate::ref testling = boost::make_shared<SimpleCertificate>(); - testling->setDER(createByteArray("abcdefg")); + auto privateKey = tlsFactories.getCertificateFactory()->createPrivateKey(createSafeByteArray(PEMPrivateKey)); - CPPUNIT_ASSERT_EQUAL(std::string("2f:b5:e1:34:19:fc:89:24:68:65:e7:a3:24:f4:76:ec:62:4e:87:40"), Certificate::getSHA1Fingerprint(testling, boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()).get())); - } + CPPUNIT_ASSERT(privateKey != nullptr); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(CertificateTest); diff --git a/Swiften/TLS/UnitTest/ClientServerTest.cpp b/Swiften/TLS/UnitTest/ClientServerTest.cpp new file mode 100644 index 0000000..a356dcf --- /dev/null +++ b/Swiften/TLS/UnitTest/ClientServerTest.cpp @@ -0,0 +1,883 @@ +/* + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <map> +#include <memory> +#include <utility> +#include <vector> + +#include <boost/variant.hpp> + +#include <gtest/gtest.h> + +#include <Swiften/Base/Log.h> +#include <Swiften/TLS/CertificateFactory.h> +#include <Swiften/TLS/PlatformTLSFactories.h> +#include <Swiften/TLS/TLSContext.h> +#include <Swiften/TLS/TLSContextFactory.h> +#include <Swiften/TLS/TLSOptions.h> + +using namespace Swift; +namespace { + + +std::map<std::string, std::string> certificatePEM = { + {"montague.example", +R"(-----BEGIN CERTIFICATE----- +MIIEsjCCApoCCQCbkjlQfUqPtTANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBBt +b250YWd1ZS5leGFtcGxlMB4XDTE4MDExODE2NTMxMloXDTQ1MDYwNDE2NTMxMlow +GzEZMBcGA1UEAwwQbW9udGFndWUuZXhhbXBsZTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBALAx5xuEYOjDJ9QHMvwRuDzxbHl1zR97SJFPAkmD8xH0sC61 +DNRyUvRq6UXb4znhqeqrNuZ9PV47GyK2Dpy/c/MY5NE3m/c+Z1tUnrcqyCkxITIn +jdSI/elc9yhtMXX6lRi68BdPJnj/9+6trW0cWHlKEgnaSTAgCVB+4Dg9mjTIroCa +HLoAKhr2zS7Ihs28aWb0cSvZ+qFgQhr7FGP2kfssTTQYyRPn9uHhtyWH6RqSv5x9 +BBGZWN5GtjkJvupcYWLt8ftuQyFpwEeEz5cgtiyKgsfz9CYvS9/OcwdLQr4z5Zq6 +eKxsog9GdwIi1Us4KR0X6tKu9ze42iEWF+foEWFP9/bjrVK/tt5lTSKnenk0nA8I +amkG0btNAGihDti3lv60bGpd3B2/uh4gzzT2buXdf0EaybCt52MIr8xkwMU0Tkri +RAYchdS8U8sekWG5Lg9m3L2BDa8/TKS/WflJhGcZeInGQslgIx7fCgO1M7Zr50pO +wSURPXpvqUkXNEBy639UQEUsnBhntEQwZWx/6x6Ma/U5a5dL6qbtEJjlwIvS+nl9 +3w26g3DvWydNMCtZIVhgdrl+dZs+Uw5eA3QkHkDTSfYvQk7X5SYL0J5ZxwBvU9r1 +ED054+TAEuX2euiRA37xLhxonj8BaKkPQGlAHCLZaZPmNJWkNxElJhMoCfqBAgMB +AAEwDQYJKoZIhvcNAQELBQADggIBAF+FNyW3nVeQeugBMksIhj7EMJl1AEKi0+78 +ZPsYX3CDbc/8GRZoTg/EWSiwPCBYc9VsxuKtODEYABCZgk7LnSBYoEauJDKWqkgM +UOKPJI2hu7mIK7FJpjvEZe2MnRRA63oI/NVDJm8T2clrv/vPkY+ppsVl0toC0SpH +/3dF5c65vYI19rTJraRU6kIrrgxFBzxzpn07LGh2rrOCQfy2umTSRMwz3ORAFfmi ++Kek1Dt7c+JVJ0ivCwhhc8MKza3JS2MuDfVWGnXtDLb81Ai0t4tQfLKvZEcgW+lh +Drz9gv22buwncWL/IxtuhzyILtDSDKAYFbhfG6IAQut9BjMgpMnKrBCDlOLJl08K +tgj2h7vUKyNSt3ndcSAtXjr6FD7+xPExJuyn/MgLONGGAZoZHFB4QO90wQaXxMPh +7rnjUtzfLR8qkDmX8ZB4f4VOWpDWo4hBpgjTk0gYfzEkrh+zTqE9reh7CZ1WzwXO +KnIBU2dZOE+XsJe49lW106DLqGzKRuQMUAwFMb7C7Nlg9GKTnvi41o+g6YE+MgxR +uPKu891pCBtnDxZiWPT+7Fa/9UXxdIOTVIHW6utSWiWYbeNwXSmIm2ShfmNfWj9m +x1JgJrFB6daWGR9aDBeDVRhgL6Z35lH7xI62pLJ4o2d2Y/9dUWAJfz5O8opeCyrF +zqCzpwGL +-----END CERTIFICATE----- +)"}, + {"capulet.example", +R"(-----BEGIN CERTIFICATE----- +MIIEsDCCApgCCQDUGdmqHfGngTANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9j +YXB1bGV0LmV4YW1wbGUwHhcNMTgwMTE4MTY1NjEyWhcNNDUwNjA0MTY1NjEyWjAa +MRgwFgYDVQQDDA9jYXB1bGV0LmV4YW1wbGUwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCgA/CpV7UGqUdjhEVoMjFIZ6Ca/C7utrVPAqBvE14eiurIhQrQ +AmYeC9zA4/uXCdqkGq/a/RbF3OOCKLRUejCcynb0EnxiHxHa48ZsvLbKCK6guoXE +pWnaZsmRpvJrBB2z6ohmxRuaDuc5CJT+Oq8AFPp3StTAFDo3Cju3fsGZPkNpCGbj +ELwk4ok9INtEuTrMEmHZTD+VfjpXauUfN4ygKaPXJanCuxuifyin403BWgd8igkD +oSCWxoDFMy3HGbh/NU+nJPJ23FxVC39RdDG3elvjNFpSZnALbiMnyor7YjF5TN93 +1ZWwn3VTnl7DnFquEbKbYyVFUzRII8Cd1TzKOL48rVLrCAqMXwm6YFtST6qPb9TZ +0SX8qZGCwBfHV5OeS0ZgiBMMlmUPYcw9MlyvZnYyDPCOoPWmhEqd2gQzn//7hzb5 +mriCEyfcMzAqohylBNHXUVZTx5KcazJz6oOYdWEs1jfSXNKefgSWlgeoG2fgTXPN +1OkQVS+FOiI0VCAIwR+vxhG3hVTz3kzXWvEt7M51faaHWWlnSzOrbSuj3f0ibS5J +cj6ClyzOQRQDwzofyZ7oPWh6No/XkepVIn3HTTlnj1/8e6VsH+EBKSzoX2XvWPkO +GAZEGHKiKh944u6d6mW37BPD2oKyusP3uPL5j2Fdm+m0HkP3/7yw+5EFVQIDAQAB +MA0GCSqGSIb3DQEBCwUAA4ICAQCfCGK4iDo8H0i12wBC0+6GB9NBmgn8P09AUN0l +tQjZPaqZCtLtBBqOrAaZQBQMfI0QAm5/h/VkhMvz5HQjqmQhI2drSDOmarYzOGgY +yVItkEwtLEVhiGoeJ+L3Smosoqq6QFjcDzH7UzPTrJNspnY+09+m53pJggh41zzt +1TOU+QasaB5oGopFaFUUlwjHAc7FpZgEd+tV6j0cpdT3GabVkkoLg01Z+0mqkpLD +OjRBKJX8XvZ38VESsy3gWpcXnDq03n+8OgZo4R9SEcyyxjWbyb+qg2dzbQvRB2Va +QNoXp5EzemXvFSulhR+TfDk2K1h45BurikRQxDi8LpBTUsCMwiqXdem68HOlTwLi +/kMWbnVBcdurYcWVSwlJU4EJcTEdk51JStO1V0nAA0nCwn/iEhY8I6BitnrcCJ5e +4CGVWr+zAm8DBjaFMTzy46Q5NcT0hwnHGN6T6l4aMcRggIK9anRbXCn6dSzma1pd +R5N/Do00FTpyZGcUlVPnSlIfZVl7y/9XEO1n6xDJURrefL1JrM7UMyB17jA8HMq3 +S05kF7XRpludRB4QkAJt5BNNv6BPP7HPIKyR/rq94ONvzVPAo7uASyFE2sMBsfwP +pXAI1LVolPCoUC13jEkKdmc8kMSxU+XtsvFryNhkfQtZfSg+nBRFYptFE7GrZ9WY +GMSL4g== +-----END CERTIFICATE----- +)"}, + {"casigned.example.com", +R"(-----BEGIN CERTIFICATE----- +MIIDYTCCAkmgAwIBAgIJAPEpYlUWlJW8MA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV +BAYTAkdCMRAwDgYDVQQIDAdFbmdsYW5kMQ4wDAYDVQQKDAVJc29kZTEPMA0GA1UE +AwwGVGVzdENBMB4XDTE4MDExODAwMDAwMFoXDTQ5MDExODAwMDAwMFowTjELMAkG +A1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxDjAMBgNVBAoMBUlzb2RlMR0wGwYD +VQQDDBRjYXNpZ25lZC5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKw4iCscGIDCc55mwxgJsn/v2GEorpE9zHYsMfl6px2aRLGgB8ki +xYyNiEPA/b/ilShRp7pp22LPb5O3aOVVWzAs5FTvPdFY2vS8YIxR6XSKXO3u4Q8/ +w8CR0AbKpeCtL0TwSl1u76nq6ORMep6QGsTjDLQ7wUwdShL4qV4nIGxJWon/5GI0 +nl4Xr/wzmysbMjAMSiWOR90DNZMvqQBBhQcJdqdirc+whR8gOhIMvJBn5jlMuFEB +zL/bR+kG/zFuD0EMsMTy6TETefYuxeWmhuzQENyAV5+1v48G/1a9zzN9Y0xQ6T0N +ppbLzq+/zhxT1eBN8/O0bAGUzzk1VSFvouECAwEAAaNQME4wHQYDVR0OBBYEFCnR +umlxjdaUvcpf77zahrDmPnt1MB8GA1UdIwQYMBaAFAbbhPAKtD5YzxQqGH2Um4/f +OmdFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEPrTTKS+7A4dJJh +gSAS44ZYyR8/kt9Y3V4qxJM2xrOrW6rM8N15n2i/osSy0AYHiPuvgDG+D7hLt5Ct +7jZKrp3JRsBaU8//9k6+euwVyWS+EKo/eb7qtSNibZOk7GwrXekJMbRXz1cHTKnW +0R8UG+EMkOqKQh5dhWuEBXff9SYLTALf0/i+/Ixl3b9rQ6zpY/7UwBdlWLaliM1i +odIgVu1XRE6Su+bGMa1L5ArniN0LMFq9Mxag2H0V7Kru7vIvbBkL7U6tbi7u26hv +q4kUFROW2U2C02FTmJeSEBvWoDyMoVjKkmaTL0+vDSQRPGtCsvCgaCXgOwU2Po9s +8jjHQxg= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIJAPEpYlUWlJW7MA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV +BAYTAkdCMRAwDgYDVQQIDAdFbmdsYW5kMQ4wDAYDVQQKDAVJc29kZTEPMA0GA1UE +AwwGVGVzdENBMB4XDTE4MDExODAwMDAwMFoXDTQ5MDExODAwMDAwMFowQDELMAkG +A1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxDjAMBgNVBAoMBUlzb2RlMQ8wDQYD +VQQDDAZUZXN0Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCiCA+9 +bdSHFNPOgbsnhrKbLJP+1lxWTe06+ExwJA3QgCKsR13MsAK8rhmuNB0k8ZIFJL+c +yUOUgw0370eP940QAtK+HinJpvaGEZKEwaB8VUCjzFTb7zUBio1Y7B45aawEV3qT +Lzcnil3f7vPIxnAoaptzPriySdggIsimj+y6AWum5FUPyfZzF7EnYfF/VH8V/ZNX +fku7PPbaeDHvu4EF/0s8P+/l6jddz8dqbDMjH3GDM8sjryWPQPNDjKZ1x80BIdyq +s9m/kXqIIySNwdIa/X+nYTMchUa5y46n2N4n0RA4F+rf+Ni1Cxk9Ejmmz5hinV+t +Yzh6jsbB7yZiqEnzAgMBAAGjUDBOMB0GA1UdDgQWBBQG24TwCrQ+WM8UKhh9lJuP +3zpnRTAfBgNVHSMEGDAWgBQG24TwCrQ+WM8UKhh9lJuP3zpnRTAMBgNVHRMEBTAD +AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBMHQ3WMEhkEc0VoOEw3mbsngt1eyJz+nFM +FeGdRb7JSwpJfe/yBxyGodGyHsQJPVole6sUdq8S1QGT547PkgDHc6Btoq96Mahq +brgfx1JL9a1F8qaqcENebHc7ltW8kps4xtdlithfo4nKaciYZ5mKbug+AFv569mb +LU3F282dyW1dLa7+L8dGbb8Ntpnp0BB0Cotm4GX3Xi6Y+fikouqcmXj7vX+uMhG4 +pQpXqb2ML1Gev4w6XUsnls+OJok97x99NsOcqtwqsLJS/sg0cpwrgZ9+50hQKlHO +8H6hhNjGBkvpIiNsWb9UOc+Id86J+drs9Ed93Eyyvwnq2XcqPGF3 +-----END CERTIFICATE-----)"}}; +std::map<std::string, std::string> privateKeyPEM = { + {"montague.example", +R"(-----BEGIN PRIVATE KEY----- +MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCwMecbhGDowyfU +BzL8Ebg88Wx5dc0fe0iRTwJJg/MR9LAutQzUclL0aulF2+M54anqqzbmfT1eOxsi +tg6cv3PzGOTRN5v3PmdbVJ63KsgpMSEyJ43UiP3pXPcobTF1+pUYuvAXTyZ4//fu +ra1tHFh5ShIJ2kkwIAlQfuA4PZo0yK6Amhy6ACoa9s0uyIbNvGlm9HEr2fqhYEIa ++xRj9pH7LE00GMkT5/bh4bclh+kakr+cfQQRmVjeRrY5Cb7qXGFi7fH7bkMhacBH +hM+XILYsioLH8/QmL0vfznMHS0K+M+WaunisbKIPRncCItVLOCkdF+rSrvc3uNoh +Fhfn6BFhT/f2461Sv7beZU0ip3p5NJwPCGppBtG7TQBooQ7Yt5b+tGxqXdwdv7oe +IM809m7l3X9BGsmwredjCK/MZMDFNE5K4kQGHIXUvFPLHpFhuS4PZty9gQ2vP0yk +v1n5SYRnGXiJxkLJYCMe3woDtTO2a+dKTsElET16b6lJFzRAcut/VEBFLJwYZ7RE +MGVsf+sejGv1OWuXS+qm7RCY5cCL0vp5fd8NuoNw71snTTArWSFYYHa5fnWbPlMO +XgN0JB5A00n2L0JO1+UmC9CeWccAb1Pa9RA9OePkwBLl9nrokQN+8S4caJ4/AWip +D0BpQBwi2WmT5jSVpDcRJSYTKAn6gQIDAQABAoICABqc/wZ2AVlHGP36tGXEm2qB +INxbwcbujTB9mZ/XEWD176KucCiquAL5HxERPIointK2V82Kvzk7fkbI7v4YIQBo +Ey/S0XkP8Panmm2aRa+LHzN/K/odUxTrmN1/WMg0OE8K9Xbf2rTOHPntO9POQ0LW +wFDCqulc/WsuLtnv3Bn68fi0zn/9xF5cRvO5EDuFKPqHE40HGMdFTdbbc+IBfV1N +/L9QuxaJpA3MVSiTFc+QuOZ/L50k53pzfdSxtyeZGpCh1jofFn62hXeIBP8TztB9 +f3GKVKdr328HtPI2GPe3yQeNAOsyYWwjPZiSAFujOPqPAUYfbXH6NuBmgOfjcrRb +AhOv9F1VNi+G56NJ6jo/NPygD+LYQdIKs5rv3E4ehyQzbu+SoGyVCnF3qm0cvz+v +tB5/gNiWiyRhNF94DZHlceDMQSdyB/pfTZsKZ44Yv44Bzl54YbzR8yr/ZKzAj6gt +5lwAqCIcdRj4i5DmIa7psj3iYWe9hYV7f+zwdosPKibRvO9FpvDCbb7biIPkMozw +cYH6QlSsZ+XsK/Z3WPFPq0wHOgoWW9Tr8LYyQxGjLO+xD8ziQ7Rp0KApEunuO29s +CPXj+l1HqNmAK2LkdNI3c/yStlaAcOzYD6pauciHWlTnIGZG8aHV6elIjK0C/h7B +3GndVc0TbewbP0bL56QBAoIBAQDU/yl4nlELhpoI1WW8v/FcDnc3V5dBilJ3LQtp +a3SKBcNWXE850TviOAklMrYmS1wuWdBTjEay9Ka6dImqMFGupmJjLmUw0KXrtPin +xIz5DZ42nmTKnYevuBQoQrrq7toxf5hYow2ZjeH2vSX+igY1gxDZbLW4Wb9GPYMo +Au5+z8XpA8R0key52nvnKastm5YxNstAlBOodAPKlbIr2bzmrHSjXAGjUzb+z6NZ +5Lx+zvQCy9kaIYvfOJm3eLSbMXzeP2S59qbwL+dC4ZJ5m3hjRmMaactV6LSchVNt +eLEYJpm92IdjQhG6oqM0IaU3aSjWMSrOAytylmqoEt4wA+WhAoIBAQDTxJ9VLb+J +OD0x/9cm17KpK1nGQBQ0T0oZQUH5M/tXTPCCoIpoL9UhKQ34vlPaZXkBQrXPw+PN +Y0J26uR6w4CowWAMn8LR6cYsWcOKuURcDYs/SPflD3rraevJwugQhkXtub2nV7dP +88Z/jGvhXthJmjUmNoKq3OC2MuSfHSkm8ipvaAblwb+lt5zBJGQ6iGXbi5TI6b+D +lnAidQpG/V464Zc9gb788P0K2vUeoZRLI7CurYqpDV0mBtPhFv5L1M0S8+psG7Pa +NIEKcW/b76vU9odTrtGBT0gCVYU7f8QnTN4g6c7dEhcZa2Zvg0YSmb4XuU9RQGC5 +As47nEUnPCjhAoIBAQDTXKnAogn2kAmGvoyIs0hFe61d47ObPDH9RVvPruwkkvd2 +WX/c9f6gy853dU0/zwSYklOitM7rgs94s3BwzCYiU8XKeh28RTCBKEKf6PGjq5nW +xXNrhMtC2j5WfXGS9JbdC6sYOiWivSMAgE6Vuk3TCE7OE4x4dcbTYvMl31Lf0Dqq +sixfKPdqrp7Jk5XkWkK+b4teeBLR1N52R/pYfWdw2K2d9g1CD6/BSDbnW46Zn7CQ +nczAm417Y2VWpZdDceZhfTLtPxAFxOOOgN2jg14B1bU+XsGCbLvdnohdV6kVOCjU +NWyUWNnTBNVDRCf5RodZlczORmL1AMKyKpcFurhBAoIBABSxbfBg3AqImFI+ccO1 +6BtnxQn+UPsblF4LZmr3jWPmfMoG7f9oTSdEX70ivAbnS3+4CRQYTDZRsLj2EwV7 +/SKAYuZY5iyk71x+GQGBQRDNsgGpG7AiZxyB6Sx6Azs6I7MrJ0Em7R6+73KfQhtv +rSrkCrWFNheEJeEn7/csXk0T9NmWDLZ+zD9hRcwJxlGB6pIdfZh0XuZ42NRFI4/0 +SjTuvlygRQ1qbw+UfcdUeq0s+6LWCmqih6ujlyizmn3GeZOUih+uRVDZOJLQquGO +9feFb4vZ1VcRbDPuL2q0/XHprPsCXdh0YBV3zTawWTSQGWcwEHQcGld50rU4e/lt +g4ECggEBAKwoqsqIHheL+uS2CHXmwFIr+rvOlLYlfB8XrwV/da3p7QChaDLbNIVM +uOAozCMkJY+dufPGI+3cKsR3kLAGejmfbH5OTzTbwCLOJFCWaoMuvOTY2Govte61 +gU1BWnjUgVJgVA/YTwn2yo02d0nG5/rSZ9xIt3hfO6ac5FhHBTA1DAZ1wDiLeow+ +qngZ2sA4ePtwhGFtvLVwTcGAfkWvQFi2YPBpesFIAmQ/ACGC7Ye75Ja4k36/8YwE +NiXR2Yy1hxwwi7CTWWzI0X+mvE/Oqpd8PUqPJCJcpz892Gq4EGCxM7Bz7NxCcvvw +5IMXuORWuoq0gXiCdEyko+saXsyWlqw= +-----END PRIVATE KEY----- +)"},{"capulet.example", +R"(-----BEGIN PRIVATE KEY----- +MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCgA/CpV7UGqUdj +hEVoMjFIZ6Ca/C7utrVPAqBvE14eiurIhQrQAmYeC9zA4/uXCdqkGq/a/RbF3OOC +KLRUejCcynb0EnxiHxHa48ZsvLbKCK6guoXEpWnaZsmRpvJrBB2z6ohmxRuaDuc5 +CJT+Oq8AFPp3StTAFDo3Cju3fsGZPkNpCGbjELwk4ok9INtEuTrMEmHZTD+VfjpX +auUfN4ygKaPXJanCuxuifyin403BWgd8igkDoSCWxoDFMy3HGbh/NU+nJPJ23FxV +C39RdDG3elvjNFpSZnALbiMnyor7YjF5TN931ZWwn3VTnl7DnFquEbKbYyVFUzRI +I8Cd1TzKOL48rVLrCAqMXwm6YFtST6qPb9TZ0SX8qZGCwBfHV5OeS0ZgiBMMlmUP +Ycw9MlyvZnYyDPCOoPWmhEqd2gQzn//7hzb5mriCEyfcMzAqohylBNHXUVZTx5Kc +azJz6oOYdWEs1jfSXNKefgSWlgeoG2fgTXPN1OkQVS+FOiI0VCAIwR+vxhG3hVTz +3kzXWvEt7M51faaHWWlnSzOrbSuj3f0ibS5Jcj6ClyzOQRQDwzofyZ7oPWh6No/X +kepVIn3HTTlnj1/8e6VsH+EBKSzoX2XvWPkOGAZEGHKiKh944u6d6mW37BPD2oKy +usP3uPL5j2Fdm+m0HkP3/7yw+5EFVQIDAQABAoICAQCBom+IYdvwp5eEUhaA0ZkH +lZyRsxi6oB7HAdPD6SbpC5YmGVKnLipY0TdotcqPlJYjONObUErwxYEzY5KkldFo +VMaF+av3OkCW2s1YLpLPnrUK1dGlfHUDUR6f92aRuGXv6mPTDoDMEKLWm9NJG3XH +VTeNCXzOmBSJnqq+f9yML9sg7oOcFWS3ZSfV9BZv2Lh/t6y6BIHGtNrDE4DIB5LP +9qwbkxGzBy7eOLJRQV8u86b5CENBQ3pJbEvKdynxES9dL212dgJQtTnAVG4zKTVV +9bUXnsRF2WOQfwvQItDx051NLjAkv05kJutAcR9IzhTQzNmr9Wiufzft8bkMpUJ3 +Mf8cJk5VNm9mgKvWnqKrPSyfNcicykcVHXr0yDICLgttWy5d9bj9/DcfrIOzEwhd +MOhTixYtR1dv/7p9kqw2mRgMV3GtB6f+AoQ29NrCt9bD6T2Rth9lXSo90sLW47J9 +QIan8jb/T4N7nuga37wLlpL5KhA7nyzlaF37PyvhbErzOxRfq287iQKCyF+nh3n5 +9HzWDWz+8zYcjsxlYc1x7XHWWAYKS1h+ZWPjWCLH8hlh3ZRdPm4CUfwuZmA2EjNT +8dRblRQ8QB9cvsKoLjKt8vB8mIoH6Sjk5I3vqNVXl6Su0JrvLg5A/3tfyPfxsm5c +rTunLQllzpgo2/q6ssz9yQKCAQEAzgDf0ozoyH9+k4ND7LCy5G1vGr8LqMhyjgSC +4AhBIM/Hz56YSrU0hIFpgu/VGWLkGN/0AiwhHBKpt+6KkvLBjxnv71dmI2hBIbb4 +Hzy4EXtPTtFqn4gffYjOen6co8RUl1vTOmRDUdfS6su0v9TD3335TIIfF+5DAGvR +V6OIHkQWWrHazUZx0tbwRyty3Q4NtYgXLFrcWFYfMFd26GhFrM7uHFrbOg5U3gpZ +/YdaaJzfdaJKHNPNQJUPD40n36n8RyjlWSWkUfEV3ITm0IMiCJ19WDjyddLUXuzC +KSoeiTCISXzZ8lhmvnBB4pW9V1O1o8cDJFRT1ouUfOKqK86lxwKCAQEAxtnMzmEp +Z+W3Jlz9istkJHerNATtQzj3KSNHbrM8gB+O0igq0BWbj+lvNtbuZVprLrOpbDk8 +Ksk+PdbgSbsQjALcs1FpoIsPWt6sKTwrZQuMCocHzGfrp0MA613YCRw9sNBM08C6 +TNbjSTiVlBb3xyjsI3hLZ9sj8N9rV6yomlwM6MnpdIDUxfiv5tlqZcqCYdibJ9zu +tWi44O2tim3uCVrajop/NsHXbROjd7MeV4gaj3SsJ4cLyvfcBkfwrhUse5D6qy6y +08ZsbrMUqY50ZG0WUcKzJxJcF/mOANZ+Dgqe9jwKlxV8E1Lj7PaQWWzQ5bWVgnLe +TuKoZurGEaJMAwKCAQEAgWHJMYswlOSGUg2KdrjP0mns8wZ0QzCJyiqJLD3i8cGu +Q/bevWUrs+E3rHYHCCe1DO5zaX3f2arbD1txizOOX9sxd8gTrT9IUO2CztOq48fn +mqAqcEHlTUnELOkiZjTj0CBq/OyF33xGyxLf1e/CibasAeJjtvr89+G/nGRoFGI9 +C/9SZcTNrlcyl/Bw9udhstbjfwceBxkoA4ubcgIzaIKayBJESCVCJiaoOHRvUu7b +5hzkoVBhRCOaTvEfzvkLKoJD8YaTuqdJTLPn56PEl1aap/M0TM36dhgLJiF/BjkG +D+mrVOsytH760l2ripJXraJLleCku0X1H66YpGTodwKCAQA34vCntDEB7VLrKklr +37v2b9ejGBtiwDjey/aAi0lerP/j2rwlnV0KNk42eHOp8p6bEo10SCW71LF0idah +gjylTQygLSpln4+iN2Dlee6sSHGEZ+zuKurVKISyob5c2R4ReomNHeZ+QArDAm8v +nsDmrX6ofV+cAb/5K6Gsk28TavmJ122Qe8DRHxK467P2hdLdExaQPoysWZFUThhv +BnRXFrzEQPJ9/j7Afjt8IdBOQ4dLeDwGI/NRiRXCgieHlZXZ6KY6xDYoROUmu5f8 +C3h03R/fvLvDKGrPpiid3aqx4ZRJmhhT3AryF2LNr4JkT6vqU32Amy4Vt6givKsM +O7PnAoIBAAggpMq7PMugGP4B9PgNb00oGmWfXSa+M83O0GGN7jSirxqkaK+/eDOY +kSnVFWmORNBlSz+bLoA3Bw2mFXI8HfSbHM9E/Qt0scf0hV+SwpTuO3pDWF5ev20G +mL1QEBUNDmvOn2SYERKI1iRevjBBXSzwTpAXnfaWvvTn1XSKzSJK3TjMhFTZHtbj +mgPPV65cznhofUsg2QenT8zKisvYPYN3p3p9Jo6IqHyT/CCymwIB4OMZITiwXxQs +PMAxlZGkX3Uri5A8Ln3QQ46elanI2TlC+ZDa84gu/Gw691JWCfsaSaQDTJKnGqos +dwiNVl130YWaJLjiA9Poc2llKtypfQ8= +-----END PRIVATE KEY----- +)"}, + {"casigned.example.com", +R"(-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCsOIgrHBiAwnOe +ZsMYCbJ/79hhKK6RPcx2LDH5eqcdmkSxoAfJIsWMjYhDwP2/4pUoUae6adtiz2+T +t2jlVVswLORU7z3RWNr0vGCMUel0ilzt7uEPP8PAkdAGyqXgrS9E8Epdbu+p6ujk +THqekBrE4wy0O8FMHUoS+KleJyBsSVqJ/+RiNJ5eF6/8M5srGzIwDEoljkfdAzWT +L6kAQYUHCXanYq3PsIUfIDoSDLyQZ+Y5TLhRAcy/20fpBv8xbg9BDLDE8ukxE3n2 +LsXlpobs0BDcgFeftb+PBv9Wvc8zfWNMUOk9DaaWy86vv84cU9XgTfPztGwBlM85 +NVUhb6LhAgMBAAECggEAP5KesUstwFoHU/GbEsSBn7hpp3Pc/MBTOUwXJoCgL81C +jk8EkLrFMZ0NL/WNtcduR/PcdnOdCFyKU3zgu8dGYgIwRyoJJ74lFTJ0cVfLVbm9 +lBcZ/QcMu4kXwWoM0WMcj9YjnVnWHmMYlS2mFeIb/5HQnrdwIyisr1QbMSZAUbgn +HOLSjkd0KUcXxwP9HfE/8zUFbUsv/wPHE9T5eWqZz7lKZRvgUyk3jYElpewxqPvR +HPOq9BN87ft7rPzmmZ4JCU2tM5MEQONo3jT5pljTU/iz4pfs1HArHS+/zZbGcoiu +AhODErhLucodwZ07MZsE9KAdGPGUeob4SgMwmkIiAQKBgQDYZ33DHOgYd5Fa7Tqv +TC77Nbpjmnk5lyoInNf+7pxBTgqIuKbpS6Ctq76nHI0qerNfd44LqojQEJ9S5rbL +3s+HR+pypx3DyysE92uLaVsF4rfwZeEpJyQ1Q9NGbsKVb2nNrdGs3LZhG5PL+JQT +8lS9h/sMIbh5Gd/Dkt8a2HlTawKBgQDLu3YdXWeWUOcq63YrLFDO+RUGsCe1cf+2 +3wTmMRgxfzpAPDZKymUPwrJNd1ddCQiRVKg91pLhlDl8B89Q4iWdOpYnE6vrnw3w +6iEdEyA6IauvEvD3JPXHGtVHKBS/wz06wQVGzsgMvVun1w32SDzTGZ/somvkN1UE +BTMRVqXB4wKBgCgkgnq4GQG45FjGmtU7v5dP7yRc2lHpjZ2NYq/imU+v51pXTncG +VWcB7drX/AO+QRnbdpkJaFmYS8W4EH6e9UY1+/KKt4XDYVaJgwSYZY8g8FgCvhLB +NQFAdKejEitgQHMr5DI5uwcmc3MpyGYu1LNXzyT/+FVWjGCeFQ7IyzDDAoGAXK9I ++ez/bkQaFs2OMe/0R2TL6wIC3qohMpndSbf2ELaX0pdR/856EaR6p4FujlXIvw0r +iQ5wPg3H5SRMbbikchYwL1DkusnedsadD/QeijO9PmW4mEcJRW5wrvGOFvuEhJFB +jEgQfLM82muc33lXqpYSyn3N5cJCfBS9edrYiA8CgYEA0Tsa4KvwzmBXzy2jexUT +PPYtV9S7hS0D7Owf5SBI1wtWczOu3Y6DsCG4mbDi/tvo1dxC9d5Ns8RXHH9mtdyn +8VUuSu24lk7VZ0OP5/byiAGqC2urDFGe0iBqePdb+3uS1g132LzAJm4RqBYw4Xjd +P6n9b0V3iodcFLMTy1ShJ+I= +-----END PRIVATE KEY----- +)"}}; + +auto montagueEncryptedPEM = R"(-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,6B0A69362920334824667C1B6207279B + +vlDCCnUf9aDbCD4+PUuo5LGvzTFlT03ZRMnHDcBzE2mp1OMBjxeEu4j4cqUJE2qV +NXCRbsedMsydoHlg76LssYM7J/AI9dp5cek0HgYMqdeB+hoNn22AmjRb7WhY4VeW +RqKAzkXT1lsxEF8hykQcalbsrbdmKkPosiNJF4Pb9EEefl01e+Ny3nb7GRs22tzX +lJNBk+lrM0Jlg1Y6c3F5/5CkKHTXP4924Pzjzf6Bw5hG80izrYeBUC5lZJtqDM7B +lmFXAng4RIDKk1TsqeJ11Fa1nMqFkvRvlU8RdrcZ5rtngWxIAvTXAjbDk5mvS6Iw +WdjmH46TrVMQLXC2Qh++grldyx4GDm7rShLm23J9lUAdPLjIvurYT+LfbCRqfgIw +hkPtm6BWkkf95KfpMKZ0giOhikqnF2YsozgqI5SphDFIAGN7bXa7Z8g/xFI9Uqie +2+rWqVvBOQ8PBepTd2H2uahV+pP1wHmgqN/bp/paXt6+Qf7ptH6MNTwgnTanDfnk +wzyhVlw5tTsG8okjD1cT2R7RbuDQRkArpzbnATPEU9Itrx0Sh/ZPKPDDVS+aSBHA +3JytZX5yzd/yilNjE3NfN1G923lcWXRX3KsdZUQjbcPugML7xbC+orqwxeYLipMN +jfNEGK0IrTNmRN5HqFU6JBNbas67BlFU4Zt4Tt73sUHrMpSSRINd8itRZaKtqZuM +8upj7ZUD/j6j/JmSxN2w+TcmHXfNWZirTFWUvtF/l1WCHilsuO49VW/CqGFW2Bad +32YzPkENljj/xuijGOHr1qVFozfG4/noXdVtJm0oflt1ImdjvOO91LneaAhVE8lO +K5SwOnsrlr6UM0tb/HnunT5Se49YQSGnXOiXO68bPO9S0JZ33MeAP5kSbMSZ6VXr +luw7dga0jfJLqnWU2arxOqruc9bSwkfU0RUoWXZqrKwUiXdyl/vVeU1Y67yuYqXH +7eUrdL+BdSDbeOC/5xmWAkeheC4OBBYCcwbVv1Aw67sUaQIcyWMkx8Kq9tn8vpRa +ETcagVjUXqAjrYtRpmCXU6KdmeGKoQZq14EVREytk0KnTUQTFtv8LJhsau16v4pS +in7Yt658hdf9CSA5snfUcvLeETNeQHQWvmN+0uD/UB9vRPbHp3kPSvitoS799QB1 +ydrD8zXdUSpcW+V2P75c7u0XkcUTbyGIBuwLAtr5fweyyiKs/v//rPaBlzEG1WUr +OFSH9KZ+m9UwqmauXesySXoVsmjCQKUVVj4/QI/aWftmMY58CDNJw+q77dAzSYrj +yFbhUt5ZKqAvb+rt3dJswkZ1sxAbmTw290NAV4NPP8cjXUjLwmU+KNZ2VFkxt77p +1LxG+Ia+TV1JystBvFeiJ6sWEC3lQ7+0b8oDfE5aovQpGk+Cb7hyt0EvDh0/AkvT +B/KCQc8wUjyn+yejBicfMzHVaOphwlajrt+vSNF4G7J+Wo5luTEXpWQrKq22xnah +sal7IusjSgPdFpLCuyAy6atb/4aQoeXlE/r8tXbmrl48SnadwAndoZVt3gzIv1/Z +oDc5koTBQk6aIoWHb6qslRt9tmrnF22aP+/a10oahgIliWAL3jUwLqZYzdbMKkMv +NEbobf7kO5LTzv+w09K0A8miF+8js351FBw05gsaUHgufF3OCGAdQfXDN7d6Lxho +HbhiuzxlHOnth3TWNfqhvNkwFP3gfAIaqlU1Z28AP6pZtUw93QYNABUez8QFZj5c +sdUpopUO8krnwUPNup6yTB/m72Vx2aSqXgu4upxUNVJlgDFmnCBhOe0KKjzduIvy +bRHxL93UZxDnpn8DBB1bgmdSzgInc2gfq91j1AyL+nbZv+kob/jG3OxMWNjenVDj ++TeyP3OypAUK/8jP98ExS75mE661mN28kKrUfTRxZGt8CJY4AFL4lAzIf2p4JMch +aPE30/DmXmKng+VP+3ik5FEomMLIc6QkrEzzcMYQkDsNdjd202CAXRSAqnT+VFtR +MlopkSVvEpn83HdCqcANl8rNo+ANnFMyyPL7sFd470KhSVTcQVSb+wR8DOiZr8Vt +uR0G3+KgdEDAvZStkWTCr5eMYhm95QVclnHhsLq0AaLrOm32PqBi2C4mGyW04Mud +m7lUuRkf/mLKWZZfKleefp12waahMqSXAo3shqyTNVPKOFSVA/UF0mFGon1Npo/x +6z4hd5sbG1kiPlrt9EeTgtwFhQ0lxM755QTvAB6GXcLxkGkdNdqhJzFtTRAE9P01 +CiI1JYEvTHBdGcsBbw9zJikOEXCA19fAMkHqSfo5aU/qbuvDsY2QLZkgfiMnpoOx +ghQzeJ95jiYE3V5WNtB/7CRthfC54moWW7w6ZgdIuCEN6JvK0zmsahv2o16kkzWA +YTw1lqaNMHIhlidRwy2Q+ke0mmNTIHHtNqLGVfOE4TwSN3VIIhXNZ5E65LuBw7tQ +SyFK07dfMQXixqaeo+ytXBNTFEq1MEza/PxwUojn7njbCKhO5qGavkiyNs5nk3ZE +htkhtreIUj6kHzWAvylxLbRy9+4AJA3/UCnudMRtX/McjtN2jNwZKPaXWCQF85ff +koOclVf4j/eYQnWT03zXjAx1DKazIk0laEfB4soXfQfgXdFyj3YKXKKD8WzCW/ag +cloY4yZVa+SWnj0P23oPdptL9vOM1NK1lXAp2tvvZHPp0UmLtXVU4eNaabC79dXC +3KU9bVruCdpQki4kGk3MvsoB9OyNEZE1jxLZ+7FI0D1XKJ4qHZcwOyGqD07+Xect +w2xs4stXxvogUZdQ3G6GBANFXEjDzEu5vZn9z668mCe0cQG/iNWOR5ZGmdjlmW5O +6O9ibFmk7pc975V9SVHH9rS/GZGz/PW6CJ8O0GALw5y9fczXxjvCz7dPHK5MO40m +fDWCwIqK1D2LOEewMFqOOleBhHMpVfQX+Uu34UlWHGFnOm1fK+dIdT7tss5o8Gkz +gCBFpmjyi8H+VtXOy5JTTIi/80pnLO8nsv27FNPVU3UZJCZjfR9LCeqZwgF1MFIe +X137HnkpmtJGF+bcMRwY5u9fSQQZtBNLCadRsvHnz6J+1uodFDnre0+Q4dokmFfv +0UveWc1CDRa3qXpzW5U6NpFjYWQmiS3KA5VY5/KHE7UJxnEI1R1gEaQ6/Ogp2cmI +-----END RSA PRIVATE KEY----- +)"; + +auto dhParamsOpenSslDer1024 = R"(-----BEGIN DH PARAMETERS----- +MIGHAoGBANjw4f5+gu8b8X8O6ALyJA1tH9TQTWZEI3YjUKQ1m0dVBMJ6XDC7FLJn +gqE4hIGcm1FAWwIiuo0uMufqyVwFT2c+G8j4JHWK5z1tEP+GaqiO34N0cUo86qHp +THSkJN7LuHbYRqI9fHWDZocW/5yAsDq5RPUCjFZAoh1BWdfDFfrjAgEC +-----END DH PARAMETERS----- +)"; +auto dhParamsOpenSslDer2048 = R"(-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA0Q6vD5qtrh3XEkVkbN29ord/k3sgo2Q3PiFmyFt89qqVbebEzYmt +t8DwaFGMcGlyKs4Lb1s7vocm9y3M9C0FZm85Muvv8WCbLZVZ+wfEtMibOjgRoDqt +p7Qqe7/iPgMVrSjWegVkg3V8K8dnPpohPClM0yOe4NpBjSVNgBVJRpEtH8gFiCor +H7hw63HpN/MgFdkjZNeCN+erv8p673xH8LrN98gQpkdQ9vCqYt1dHxF2XZcxBp8x +XganwPeGgQosofkA6nVB70hyjwjEyxnHJZIMlx6DPXWC7X6ed0SazgH0sQNdACvG +uU1zHCVIv6/f0adKrJg0s1jrM3qWZ6HmUwIBAg== +-----END DH PARAMETERS----- +)"; + +auto createTLSContext = [](TLSContext::Mode mode) { + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + auto tlsContextFactory = tlsFactories->getTLSContextFactory(); + + auto tlsContext = std::unique_ptr<TLSContext>(tlsContextFactory->createTLSContext({}, mode)); + return tlsContext; +}; + +// This connects a TLSContext to another TLSContext +class ClientServerConnector { + public: + ClientServerConnector(TLSContext* client, TLSContext* server) : clientContext_(client), serverContext_(server) { + connections_.push_back(clientContext_->onDataForNetwork.connect([&](const SafeByteArray& data) { + serverContext_->handleDataFromNetwork(data); + })); + connections_.push_back(serverContext_->onDataForNetwork.connect([&](const SafeByteArray& data) { + clientContext_->handleDataFromNetwork(data); + })); + } + + private: + TLSContext* clientContext_; + TLSContext* serverContext_; + std::vector<boost::signals2::connection> connections_; +}; + +struct TLSDataForNetwork { + SafeByteArray data; +}; + +struct TLSDataForApplication { + SafeByteArray data; +}; + +struct TLSFault { + std::shared_ptr<Swift::TLSError> error; +}; + +struct TLSConnected { + std::vector<Certificate::ref> chain; +}; + +struct TLSServerNameRequested { + std::string name; +}; + +using TLSEvent = boost::variant<TLSDataForNetwork, TLSDataForApplication, TLSFault, TLSConnected, TLSServerNameRequested>; + +class TLSEventToSafeByteArrayVisitor : public boost::static_visitor<SafeByteArray> { + public: + SafeByteArray operator()(const TLSDataForNetwork& tlsData) const { + return tlsData.data; + } + + SafeByteArray operator()(const TLSDataForApplication& tlsData) const { + return tlsData.data; + } + + SafeByteArray operator()(const TLSFault&) const { + return createSafeByteArray(""); + } + + SafeByteArray operator()(const TLSConnected&) const { + return createSafeByteArray(""); + } + + SafeByteArray operator()(const TLSServerNameRequested&) const { + return createSafeByteArray(""); + } +}; + +class TLSEventToStringVisitor : public boost::static_visitor<std::string> { + public: + std::string operator()(const TLSDataForNetwork& event) const { + return std::string("TLSDataForNetwork(") + "size: " + std::to_string(event.data.size()) + ")"; + } + + std::string operator()(const TLSDataForApplication& event) const { + return std::string("TLSDataForApplication(") + "size: " + std::to_string(event.data.size()) + ")"; + } + + std::string operator()(const TLSFault&) const { + return "TLSFault()"; + } + + std::string operator()(const TLSConnected& event) const { + std::string certificates; + for (auto cert : event.chain) { + certificates += "\t" + cert->getSubjectName() + "\n"; + } + return std::string("TLSConnected()") + "\n" + certificates; + } + + std::string operator()(const TLSServerNameRequested& event) const { + return std::string("TLSServerNameRequested(") + "name: " + event.name + ")"; + } +}; + +class TLSClientServerEventHistory { + public: + TLSClientServerEventHistory(TLSContext* client, TLSContext* server) { + connectContext(std::string("client"), client); + connectContext(std::string("server"), server); + } + + __attribute__((unused)) + void print() { + auto count = 0; + std::cout << "\n"; + for (auto event : events) { + if (event.first == "server") { + std::cout << std::string(80, ' '); + } + std::cout << count << ". "; + std::cout << event.first << " : " << boost::apply_visitor(TLSEventToStringVisitor(), event.second) << std::endl; + count++; + } + } + + template<class TLSEventType> + boost::optional<TLSEventType> getEvent(const std::string& peer, size_t number = 0) { + for (const auto& pair : events) { + if (pair.first == peer) { + if (pair.second.type() == typeid(TLSEventType)) { + if (number == 0) { + return boost::optional<TLSEventType>(boost::get<TLSEventType>(pair.second)); + } + else { + number--; + } + } + } + } + return {}; + } + + private: + void connectContext(const std::string& name, TLSContext* context) { + connections_.push_back(context->onDataForNetwork.connect([=](const SafeByteArray& data) { + events.push_back(std::pair<std::string, TLSEvent>(name, TLSDataForNetwork{data})); + })); + connections_.push_back(context->onDataForApplication.connect([=](const SafeByteArray& data) { + events.push_back(std::pair<std::string, TLSEvent>(name, TLSDataForApplication{data})); + })); + connections_.push_back(context->onError.connect([=](std::shared_ptr<Swift::TLSError> error) { + events.push_back(std::pair<std::string, TLSEvent>(name, TLSFault{error})); + })); + connections_.push_back(context->onConnected.connect([=](){ + events.push_back(std::pair<std::string, TLSEvent>(name, TLSConnected{context->getPeerCertificateChain()})); + })); + } + + public: + std::vector<std::pair<std::string, TLSEvent>> events; + + private: + std::vector<boost::signals2::connection> connections_; +}; + +} + +TEST(ClientServerTest, testInitAndFreeContext) { + auto tlsClientContext = createTLSContext(TLSContext::Mode::Client); + auto tlsServerContext = createTLSContext(TLSContext::Mode::Server); +} + +TEST(ClientServerTest, testServerSetPrivateKey) { + auto tlsServerContext = createTLSContext(TLSContext::Mode::Server); +} + +TEST(ClientServerTest, testServerSetCertificateChain) { + auto tlsServerContext = createTLSContext(TLSContext::Mode::Server); +} + +TEST(ClientServerTest, testClientServerBasicCommunicationWithCertificateMissing) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["capulet.example"])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + + serverContext->accept(); + clientContext->connect(); + + ASSERT_EQ("server", events.events[1].first); + ASSERT_EQ("TLSFault()", boost::apply_visitor(TLSEventToStringVisitor(), events.events[1].second)); +} + +TEST(ClientServerTest, testClientServerBasicCommunicationWithPrivateKeyMissing) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + + serverContext->accept(); + clientContext->connect(); + + ASSERT_EQ("server", events.events[1].first); + ASSERT_EQ("TLSFault()", boost::apply_visitor(TLSEventToStringVisitor(), events.events[1].second)); +} + +TEST(ClientServerTest, testWrongPrivateKeyAfterCertificate) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["montague.example"])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(false, serverContext->setPrivateKey(privateKey)); + + serverContext->accept(); + clientContext->connect(); +} + +TEST(ClientServerTest, testWrongCertificateAfterPrivateKey) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["montague.example"])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + + serverContext->accept(); + clientContext->connect(); + + ASSERT_EQ("server", events.events[1].first); + ASSERT_EQ("TLSFault()", boost::apply_visitor(TLSEventToStringVisitor(), events.events[1].second)); +} + +TEST(ClientServerTest, testClientServerBasicCommunication) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["capulet.example"])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + + serverContext->accept(); + clientContext->connect(); + + clientContext->handleDataFromApplication(createSafeByteArray("This is a test message from the client.")); + serverContext->handleDataFromApplication(createSafeByteArray("This is a test message from the server.")); + + auto firstMessageFromClient = events.getEvent<TLSDataForApplication>("server"); + ASSERT_EQ(true, firstMessageFromClient.is_initialized()); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the client.")), safeByteArrayToString(firstMessageFromClient->data)); + auto firstMessageFromServer = events.getEvent<TLSDataForApplication>("client"); + ASSERT_EQ(true, firstMessageFromServer.is_initialized()); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the server.")), safeByteArrayToString(firstMessageFromServer->data)); +} + +TEST(ClientServerTest, testClientServerBasicCommunicationEncryptedPrivateKeyRightPassword) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["montague.example"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(montagueEncryptedPEM), createSafeByteArray("test")); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + + serverContext->accept(); + clientContext->connect(); + + clientContext->handleDataFromApplication(createSafeByteArray("This is a test message from the client.")); + serverContext->handleDataFromApplication(createSafeByteArray("This is a test message from the server.")); + + auto firstMessageFromClient = events.getEvent<TLSDataForApplication>("server"); + ASSERT_EQ(true, firstMessageFromClient.is_initialized()); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the client.")), safeByteArrayToString(firstMessageFromClient->data)); + auto firstMessageFromServer = events.getEvent<TLSDataForApplication>("client"); + ASSERT_EQ(true, firstMessageFromServer.is_initialized()); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the server.")), safeByteArrayToString(firstMessageFromServer->data)); +} + +TEST(ClientServerTest, testClientServerBasicCommunicationWithChainedCert) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + ASSERT_TRUE(serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["casigned.example.com"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["casigned.example.com"])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_TRUE(serverContext->setPrivateKey(privateKey)); + + serverContext->accept(); + clientContext->connect(); + + clientContext->handleDataFromApplication(createSafeByteArray("This is a test message from the client.")); + serverContext->handleDataFromApplication(createSafeByteArray("This is a test message from the server.")); + + auto serverEvent = std::find_if(events.events.begin(), events.events.end(), [](std::pair<std::string, TLSEvent>& event){ + return event.first == "server" && (event.second.type() == typeid(TLSDataForApplication)); + }); + ASSERT_NE(events.events.end(), serverEvent); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the client.")), safeByteArrayToString(boost::apply_visitor(TLSEventToSafeByteArrayVisitor(), serverEvent->second))); + auto clientEvent = std::find_if(events.events.begin(), events.events.end(), [](std::pair<std::string, TLSEvent>& event){ + return event.first == "client" && (event.second.type() == typeid(TLSDataForApplication)); + }); + ASSERT_NE(events.events.end(), clientEvent); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the server.")), safeByteArrayToString(boost::apply_visitor(TLSEventToSafeByteArrayVisitor(), clientEvent->second))); +} + +TEST(ClientServerTest, testSettingPrivateKeyWithWrongPassword) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["montague.example"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(montagueEncryptedPEM), createSafeByteArray("foo")); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(false, serverContext->setPrivateKey(privateKey)); +} + +TEST(ClientServerTest, testSettingPrivateKeyWithoutRequiredPassword) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["montague.example"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(montagueEncryptedPEM)); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(false, serverContext->setPrivateKey(privateKey)); +} + +TEST(ClientServerTest, testClientServerSNIRequestedHostAvailable) { + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + serverContext->onServerNameRequested.connect([&](const std::string& requestedName) { + if (certificatePEM.find(requestedName) != certificatePEM.end() && privateKeyPEM.find(requestedName) != privateKeyPEM.end()) { + auto certChain = tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM[requestedName])); + ASSERT_EQ(true, serverContext->setCertificateChain(std::move(certChain))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM[requestedName])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + } + }); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["capulet.example"])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + + serverContext->accept(); + clientContext->connect("montague.example"); + + clientContext->handleDataFromApplication(createSafeByteArray("This is a test message from the client.")); + serverContext->handleDataFromApplication(createSafeByteArray("This is a test message from the server.")); + + auto firstMessageFromClient = events.getEvent<TLSDataForApplication>("server"); + ASSERT_EQ(true, firstMessageFromClient.is_initialized()); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the client.")), safeByteArrayToString(firstMessageFromClient->data)); + auto firstMessageFromServer = events.getEvent<TLSDataForApplication>("client"); + ASSERT_EQ(true, firstMessageFromServer.is_initialized()); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the server.")), safeByteArrayToString(firstMessageFromServer->data)); + + ASSERT_EQ("/CN=montague.example", events.getEvent<TLSConnected>("client")->chain[0]->getSubjectName()); +} + +TEST(ClientServerTest, testClientServerSNIRequestedHostUnavailable) { + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + serverContext->onServerNameRequested.connect([&](const std::string&) { + serverContext->setAbortTLSHandshake(true); + }); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["capulet.example"])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + + serverContext->accept(); + clientContext->connect("montague.example"); + + ASSERT_EQ("server", events.events[1].first); + ASSERT_EQ("TLSFault()", boost::apply_visitor(TLSEventToStringVisitor(), events.events[1].second)); + + ASSERT_EQ("client", events.events[3].first); + ASSERT_EQ("TLSFault()", boost::apply_visitor(TLSEventToStringVisitor(), events.events[3].second)); +} + +TEST(ClientServerTest, testClientServerEqualFinishedMessage) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["capulet.example"])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + + serverContext->accept(); + clientContext->connect(); + + ASSERT_EQ(serverContext->getPeerFinishMessage(), clientContext->getFinishMessage()); + ASSERT_EQ(clientContext->getPeerFinishMessage(), serverContext->getFinishMessage()); +} + +TEST(ClientServerTest, testClientServerBasicCommunicationWith2048BitDHParams) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["capulet.example"])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + + ASSERT_EQ(true, serverContext->setDiffieHellmanParameters(tlsFactories->getTLSContextFactory()->convertDHParametersFromPEMToDER(dhParamsOpenSslDer2048))); + + serverContext->accept(); + clientContext->connect(); + + clientContext->handleDataFromApplication(createSafeByteArray("This is a test message from the client.")); + serverContext->handleDataFromApplication(createSafeByteArray("This is a test message from the server.")); + + auto firstMessageFromClient = events.getEvent<TLSDataForApplication>("server"); + ASSERT_EQ(true, firstMessageFromClient.is_initialized()); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the client.")), safeByteArrayToString(firstMessageFromClient->data)); + auto firstMessageFromServer = events.getEvent<TLSDataForApplication>("client"); + ASSERT_EQ(true, firstMessageFromServer.is_initialized()); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the server.")), safeByteArrayToString(firstMessageFromServer->data)); +} + +TEST(ClientServerTest, testClientServerBasicCommunicationWith1024BitDHParams) { + auto clientContext = createTLSContext(TLSContext::Mode::Client); + auto serverContext = createTLSContext(TLSContext::Mode::Server); + + TLSClientServerEventHistory events(clientContext.get(), serverContext.get()); + + ClientServerConnector connector(clientContext.get(), serverContext.get()); + + auto tlsFactories = std::make_shared<PlatformTLSFactories>(); + + ASSERT_EQ(true, serverContext->setCertificateChain(tlsFactories->getCertificateFactory()->createCertificateChain(createByteArray(certificatePEM["capulet.example"])))); + + auto privateKey = tlsFactories->getCertificateFactory()->createPrivateKey(createSafeByteArray(privateKeyPEM["capulet.example"])); + ASSERT_NE(nullptr, privateKey.get()); + ASSERT_EQ(true, serverContext->setPrivateKey(privateKey)); + + ASSERT_EQ(true, serverContext->setDiffieHellmanParameters(tlsFactories->getTLSContextFactory()->convertDHParametersFromPEMToDER(dhParamsOpenSslDer1024))); + + serverContext->accept(); + clientContext->connect(); + + clientContext->handleDataFromApplication(createSafeByteArray("This is a test message from the client.")); + serverContext->handleDataFromApplication(createSafeByteArray("This is a test message from the server.")); + + auto firstMessageFromClient = events.getEvent<TLSDataForApplication>("server"); + ASSERT_EQ(true, firstMessageFromClient.is_initialized()); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the client.")), safeByteArrayToString(firstMessageFromClient->data)); + auto firstMessageFromServer = events.getEvent<TLSDataForApplication>("client"); + ASSERT_EQ(true, firstMessageFromServer.is_initialized()); + ASSERT_EQ(safeByteArrayToString(createSafeByteArray("This is a test message from the server.")), safeByteArrayToString(firstMessageFromServer->data)); +} diff --git a/Swiften/TLS/UnitTest/ServerIdentityVerifierTest.cpp b/Swiften/TLS/UnitTest/ServerIdentityVerifierTest.cpp index e974eb7..47f3db2 100644 --- a/Swiften/TLS/UnitTest/ServerIdentityVerifierTest.cpp +++ b/Swiften/TLS/UnitTest/ServerIdentityVerifierTest.cpp @@ -1,178 +1,230 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> +#include <vector> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <vector> -#include <Swiften/TLS/ServerIdentityVerifier.h> -#include <Swiften/TLS/SimpleCertificate.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/IDN/IDNConverter.h> #include <Swiften/IDN/PlatformIDNConverter.h> +#include <Swiften/TLS/ServerIdentityVerifier.h> +#include <Swiften/TLS/SimpleCertificate.h> using namespace Swift; class ServerIdentityVerifierTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ServerIdentityVerifierTest); - CPPUNIT_TEST(testCertificateVerifies_WithoutMatchingDNSName); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingDNSName); - CPPUNIT_TEST(testCertificateVerifies_WithSecondMatchingDNSName); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingInternationalDNSName); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingDNSNameWithWildcard); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingDNSNameWithWildcardMatchingNoComponents); - CPPUNIT_TEST(testCertificateVerifies_WithDNSNameWithWildcardMatchingTwoComponents); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingSRVNameWithoutService); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingSRVNameWithService); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingSRVNameWithServiceAndWildcard); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingSRVNameWithDifferentService); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingXmppAddr); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingXmppAddrWithWildcard); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingInternationalXmppAddr); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingCNWithoutSAN); - CPPUNIT_TEST(testCertificateVerifies_WithMatchingCNWithSAN); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); - } - - void testCertificateVerifies_WithoutMatchingDNSName() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addDNSName("foo.com"); - - CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithMatchingDNSName() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addDNSName("bar.com"); - - CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithSecondMatchingDNSName() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addDNSName("foo.com"); - certificate->addDNSName("bar.com"); - - CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithMatchingInternationalDNSName() { - ServerIdentityVerifier testling(JID("foo@tron\xc3\xa7on.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addDNSName("xn--tronon-zua.com"); - - CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithMatchingDNSNameWithWildcard() { - ServerIdentityVerifier testling(JID("foo@im.bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addDNSName("*.bar.com"); - - CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithMatchingDNSNameWithWildcardMatchingNoComponents() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addDNSName("*.bar.com"); - - CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithDNSNameWithWildcardMatchingTwoComponents() { - ServerIdentityVerifier testling(JID("foo@xmpp.im.bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addDNSName("*.bar.com"); - - CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithMatchingSRVNameWithoutService() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addSRVName("bar.com"); - - CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithMatchingSRVNameWithService() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addSRVName("_xmpp-client.bar.com"); - - CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithMatchingSRVNameWithServiceAndWildcard() { - ServerIdentityVerifier testling(JID("foo@im.bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addSRVName("_xmpp-client.*.bar.com"); - - CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithMatchingSRVNameWithDifferentService() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addSRVName("_xmpp-server.bar.com"); - - CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); - } - - void testCertificateVerifies_WithMatchingXmppAddr() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addXMPPAddress("bar.com"); + CPPUNIT_TEST_SUITE(ServerIdentityVerifierTest); + CPPUNIT_TEST(testCertificateVerifies_WithoutMatchingDNSName); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingDNSName); + CPPUNIT_TEST(testCertificateVerifies_WithSecondMatchingDNSName); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingInternationalDNSName); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingDNSNameWithWildcard); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingDNSNameWithWildcardMatchingNoComponents); + CPPUNIT_TEST(testCertificateVerifies_WithDNSNameWithWildcardMatchingTwoComponents); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingSRVNameWithoutService); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingSRVNameWithService); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingSRVNameWithServiceAndWildcard); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingSRVNameWithDifferentService); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingXmppAddr); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingXmppAddrWithWildcard); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingInternationalXmppAddr); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingCNWithoutSAN); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingCNWithSAN); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingSRVNameWithServerExpected); + CPPUNIT_TEST(testCertificateVerifies_WithMatchingSRVNameWithClientUnexpected); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + idnConverter = std::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); + } + + void testCertificateVerifies_WithoutMatchingDNSName() { + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addDNSName("foo.com"); + + CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingDNSName() { + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addDNSName("bar.com"); + + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingDNSNameMixedCase() { + ServerIdentityVerifier testling(JID("foo@baR.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addDNSName("Bar.com"); + + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithSecondMatchingDNSName() { + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addDNSName("foo.com"); + certificate->addDNSName("bar.com"); + + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingInternationalDNSName() { + ServerIdentityVerifier testling(JID("foo@tron\xc3\xa7on.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addDNSName("xn--tronon-zua.com"); + + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingDNSNameWithWildcard() { + ServerIdentityVerifier testling(JID("foo@im.bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addDNSName("*.bar.com"); + + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingDNSNameWithWildcardMatchingNoComponents() { + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addDNSName("*.bar.com"); + + CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithDNSNameWithWildcardMatchingTwoComponents() { + ServerIdentityVerifier testling(JID("foo@xmpp.im.bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addDNSName("*.bar.com"); + + CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingSRVNameWithoutService() { + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addSRVName("bar.com"); + + CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingSRVNameWithService() { + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addSRVName("_xmpp-client.bar.com"); + + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingSRVNameWithServiceAndWildcard() { + ServerIdentityVerifier testling(JID("foo@im.bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addSRVName("_xmpp-client.*.bar.com"); + + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingSRVNameWithDifferentService() { + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addSRVName("_xmpp-server.bar.com"); + + CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingSRVNameWithServerExpected() { + // Server-mode test which gets cert with "xmpp-server" SRV name + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get(), true); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addSRVName("_xmpp-server.bar.com"); + + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingSRVNameWithClientUnexpected() { + // Server-mode test which gets cert with "xmpp-client" SRV name + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get(), true); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addSRVName("_xmpp-client.bar.com"); + + CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingXmppAddr() { + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addXMPPAddress("bar.com"); + + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingXmppAddrMixedCase() { + ServerIdentityVerifier testling(JID("foo@baR.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addXMPPAddress("bAr.com"); + + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingXmppAddrWithWildcard() { + ServerIdentityVerifier testling(JID("foo@im.bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addXMPPAddress("*.bar.com"); + + CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); + } + + void testCertificateVerifies_WithMatchingXmppAddrWithWildcardMixedCase() { + ServerIdentityVerifier testling(JID("foo@im.bAr.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addXMPPAddress("*.baR.com"); - CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); - } + CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); + } - void testCertificateVerifies_WithMatchingXmppAddrWithWildcard() { - ServerIdentityVerifier testling(JID("foo@im.bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addXMPPAddress("*.bar.com"); + void testCertificateVerifies_WithMatchingInternationalXmppAddr() { + ServerIdentityVerifier testling(JID("foo@tron\xc3\xa7.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addXMPPAddress("tron\xc3\xa7.com"); - CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); - } + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } - void testCertificateVerifies_WithMatchingInternationalXmppAddr() { - ServerIdentityVerifier testling(JID("foo@tron\xc3\xa7.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addXMPPAddress("tron\xc3\xa7.com"); + void testCertificateVerifies_WithMatchingInternationalXmppAddrMixedCase() { + ServerIdentityVerifier testling(JID("foo@tRon\xc3\xa7.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addXMPPAddress("trOn\xc3\xa7.com"); - CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); - } + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } - void testCertificateVerifies_WithMatchingCNWithoutSAN() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addCommonName("bar.com"); + void testCertificateVerifies_WithMatchingCNWithoutSAN() { + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addCommonName("bar.com"); - CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); - } + CPPUNIT_ASSERT(testling.certificateVerifies(certificate)); + } - void testCertificateVerifies_WithMatchingCNWithSAN() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); - SimpleCertificate::ref certificate(new SimpleCertificate()); - certificate->addSRVName("foo.com"); - certificate->addCommonName("bar.com"); + void testCertificateVerifies_WithMatchingCNWithSAN() { + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); + SimpleCertificate::ref certificate(new SimpleCertificate()); + certificate->addSRVName("foo.com"); + certificate->addCommonName("bar.com"); - CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); - } + CPPUNIT_ASSERT(!testling.certificateVerifies(certificate)); + } - boost::shared_ptr<IDNConverter> idnConverter; + std::shared_ptr<IDNConverter> idnConverter; }; CPPUNIT_TEST_SUITE_REGISTRATION(ServerIdentityVerifierTest); diff --git a/Swiften/VCards/GetVCardRequest.h b/Swiften/VCards/GetVCardRequest.h index dc65773..1b575c0 100644 --- a/Swiften/VCards/GetVCardRequest.h +++ b/Swiften/VCards/GetVCardRequest.h @@ -1,26 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/VCard.h> - +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class GetVCardRequest : public GenericRequest<VCard> { - public: - typedef boost::shared_ptr<GetVCardRequest> ref; + class SWIFTEN_API GetVCardRequest : public GenericRequest<VCard> { + public: + typedef std::shared_ptr<GetVCardRequest> ref; - static ref create(const JID& jid, IQRouter* router) { - return ref(new GetVCardRequest(jid, router)); - } + static ref create(const JID& jid, IQRouter* router) { + return ref(new GetVCardRequest(jid, router)); + } - private: - GetVCardRequest(const JID& jid, IQRouter* router) : GenericRequest<VCard>(IQ::Get, jid, boost::shared_ptr<Payload>(new VCard()), router) { - } - }; + private: + GetVCardRequest(const JID& jid, IQRouter* router) : GenericRequest<VCard>(IQ::Get, jid, std::make_shared<VCard>(), router) { + } + }; } diff --git a/Swiften/VCards/SConscript b/Swiften/VCards/SConscript index c20c17d..d8189cb 100644 --- a/Swiften/VCards/SConscript +++ b/Swiften/VCards/SConscript @@ -1,7 +1,7 @@ Import("swiften_env") objects = swiften_env.SwiftenObject([ - "VCardManager.cpp", - "VCardStorage.cpp", - ]) + "VCardManager.cpp", + "VCardStorage.cpp", + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/VCards/SetVCardRequest.h b/Swiften/VCards/SetVCardRequest.h index 8dfda5d..15cc78b 100644 --- a/Swiften/VCards/SetVCardRequest.h +++ b/Swiften/VCards/SetVCardRequest.h @@ -1,26 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/VCard.h> - +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class SetVCardRequest : public GenericRequest<VCard> { - public: - typedef boost::shared_ptr<SetVCardRequest> ref; + class SWIFTEN_API SetVCardRequest : public GenericRequest<VCard> { + public: + typedef std::shared_ptr<SetVCardRequest> ref; - static ref create(VCard::ref vcard, IQRouter* router) { - return ref(new SetVCardRequest(vcard, router)); - } + static ref create(VCard::ref vcard, IQRouter* router) { + return ref(new SetVCardRequest(vcard, router)); + } - private: - SetVCardRequest(VCard::ref vcard, IQRouter* router) : GenericRequest<VCard>(IQ::Set, JID(), vcard, router) { - } - }; + private: + SetVCardRequest(VCard::ref vcard, IQRouter* router) : GenericRequest<VCard>(IQ::Set, JID(), vcard, router) { + } + }; } diff --git a/Swiften/VCards/UnitTest/VCardManagerTest.cpp b/Swiften/VCards/UnitTest/VCardManagerTest.cpp index 9f1c8bb..669c3ff 100644 --- a/Swiften/VCards/UnitTest/VCardManagerTest.cpp +++ b/Swiften/VCards/UnitTest/VCardManagerTest.cpp @@ -1,210 +1,312 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> +#include <memory> +#include <vector> + +#include <boost/bind.hpp> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <vector> -#include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/VCards/VCardManager.h> -#include <Swiften/VCards/VCardMemoryStorage.h> -#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/VCards/VCardManager.h> +#include <Swiften/VCards/VCardMemoryStorage.h> using namespace Swift; class VCardManagerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(VCardManagerTest); - CPPUNIT_TEST(testGet_NewVCardRequestsVCard); - CPPUNIT_TEST(testGet_ExistingVCard); - CPPUNIT_TEST(testRequest_RequestsVCard); - CPPUNIT_TEST(testRequest_ReceiveEmitsNotification); - CPPUNIT_TEST(testRequest_Error); - CPPUNIT_TEST(testRequest_VCardAlreadyRequested); - CPPUNIT_TEST(testRequest_AfterPreviousRequest); - CPPUNIT_TEST(testRequestOwnVCard); - CPPUNIT_TEST(testCreateSetVCardRequest); - CPPUNIT_TEST(testCreateSetVCardRequest_Error); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - ownJID = JID("baz@fum.com/dum"); - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - vcardStorage = new VCardMemoryStorage(crypto.get()); - } - - void tearDown() { - delete vcardStorage; - delete iqRouter; - delete stanzaChannel; - } - - void testGet_NewVCardRequestsVCard() { - boost::shared_ptr<VCardManager> testling = createManager(); - VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz")); - - CPPUNIT_ASSERT(!result); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get)); - } - - void testGet_ExistingVCard() { - boost::shared_ptr<VCardManager> testling = createManager(); - VCard::ref vcard(new VCard()); - vcard->setFullName("Foo Bar"); - vcardStorage->setVCard(JID("foo@bar.com/baz"), vcard); - - VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz")); - - CPPUNIT_ASSERT_EQUAL(std::string("Foo Bar"), result->getFullName()); - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testRequest_RequestsVCard() { - boost::shared_ptr<VCardManager> testling = createManager(); - testling->requestVCard(JID("foo@bar.com/baz")); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get)); - } - - void testRequest_ReceiveEmitsNotification() { - boost::shared_ptr<VCardManager> testling = createManager(); - testling->requestVCard(JID("foo@bar.com/baz")); - stanzaChannel->onIQReceived(createVCardResult()); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), changes[0].first); - CPPUNIT_ASSERT_EQUAL(std::string("Foo Bar"), changes[0].second->getFullName()); - CPPUNIT_ASSERT_EQUAL(std::string("Foo Bar"), vcardStorage->getVCard(JID("foo@bar.com/baz"))->getFullName()); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(ownChanges.size())); - } - - void testRequest_Error() { - boost::shared_ptr<VCardManager> testling = createManager(); - testling->requestVCard(JID("foo@bar.com/baz")); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), changes[0].first); - CPPUNIT_ASSERT_EQUAL(std::string(""), changes[0].second->getFullName()); - CPPUNIT_ASSERT_EQUAL(std::string(""), vcardStorage->getVCard(JID("foo@bar.com/baz"))->getFullName()); - } - - void testRequest_VCardAlreadyRequested() { - boost::shared_ptr<VCardManager> testling = createManager(); - testling->requestVCard(JID("foo@bar.com/baz")); - VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz")); - - CPPUNIT_ASSERT(!result); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testRequest_AfterPreviousRequest() { - boost::shared_ptr<VCardManager> testling = createManager(); - testling->requestVCard(JID("foo@bar.com/baz")); - stanzaChannel->onIQReceived(createVCardResult()); - testling->requestVCard(JID("foo@bar.com/baz")); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(1, JID("foo@bar.com/baz"), IQ::Get)); - } - - void testRequestOwnVCard() { - boost::shared_ptr<VCardManager> testling = createManager(); - testling->requestVCard(ownJID); - stanzaChannel->onIQReceived(createOwnVCardResult()); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID(), IQ::Get)); - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(ownJID.toBare(), changes[0].first); - CPPUNIT_ASSERT_EQUAL(std::string("Myself"), changes[0].second->getFullName()); - CPPUNIT_ASSERT_EQUAL(std::string("Myself"), vcardStorage->getVCard(ownJID.toBare())->getFullName()); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(ownChanges.size())); - CPPUNIT_ASSERT_EQUAL(std::string("Myself"), ownChanges[0]->getFullName()); - } - - void testCreateSetVCardRequest() { - boost::shared_ptr<VCardManager> testling = createManager(); - VCard::ref vcard = boost::make_shared<VCard>(); - vcard->setFullName("New Name"); - SetVCardRequest::ref request = testling->createSetVCardRequest(vcard); - request->send(); - - stanzaChannel->onIQReceived(createSetVCardResult()); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(ownJID.toBare(), changes[0].first); - CPPUNIT_ASSERT_EQUAL(std::string("New Name"), changes[0].second->getFullName()); - } - - void testCreateSetVCardRequest_Error() { - boost::shared_ptr<VCardManager> testling = createManager(); - VCard::ref vcard = boost::make_shared<VCard>(); - vcard->setFullName("New Name"); - SetVCardRequest::ref request = testling->createSetVCardRequest(vcard); - request->send(); - - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); - } - - private: - boost::shared_ptr<VCardManager> createManager() { - boost::shared_ptr<VCardManager> manager(new VCardManager(ownJID, iqRouter, vcardStorage)); - manager->onVCardChanged.connect(boost::bind(&VCardManagerTest::handleVCardChanged, this, _1, _2)); - manager->onOwnVCardChanged.connect(boost::bind(&VCardManagerTest::handleOwnVCardChanged, this, _1)); - return manager; - } - - void handleVCardChanged(const JID& jid, VCard::ref vcard) { - changes.push_back(std::pair<JID, VCard::ref>(jid, vcard)); - } - - void handleOwnVCardChanged(VCard::ref vcard) { - ownChanges.push_back(vcard); - } - - IQ::ref createVCardResult() { - VCard::ref vcard(new VCard()); - vcard->setFullName("Foo Bar"); - return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard); - } - - IQ::ref createOwnVCardResult() { - VCard::ref vcard(new VCard()); - vcard->setFullName("Myself"); - return IQ::createResult(JID(), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard); - } - - IQ::ref createSetVCardResult() { - return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), VCard::ref()); - } - - - private: - JID ownJID; - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - VCardMemoryStorage* vcardStorage; - std::vector< std::pair<JID, VCard::ref> > changes; - std::vector<VCard::ref> ownChanges; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(VCardManagerTest); + CPPUNIT_TEST(testGet_NewVCardRequestsVCard); + CPPUNIT_TEST(testGet_ExistingVCard); + CPPUNIT_TEST(testRequest_RequestsVCard); + CPPUNIT_TEST(testRequest_ReceiveEmitsNotification); + CPPUNIT_TEST(testRequest_Error); + CPPUNIT_TEST(testRequest_VCardAlreadyRequested); + CPPUNIT_TEST(testRequest_AfterPreviousRequest); + + CPPUNIT_TEST(testRequestVCard_ReturnFullVCard); + CPPUNIT_TEST(testRequestVCard_ReturnEmptyVCard); + CPPUNIT_TEST(testRequestVCard_ReturnItemNotFoundError); + CPPUNIT_TEST(testRequestVCard_ReturnFeatureNotImplementedError); + + CPPUNIT_TEST(testRequestOwnVCard_ReturnFullVCard); + CPPUNIT_TEST(testRequestOwnVCard_ReturnEmptyVCard); + CPPUNIT_TEST(testRequestOwnVCard_ReturnItemNotFoundError); + CPPUNIT_TEST(testRequestOwnVCard_ReturnFeatureNotImplementedError); + + CPPUNIT_TEST(testCreateSetVCardRequest); + CPPUNIT_TEST(testCreateSetVCardRequest_Error); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + changes.clear(); + ownChanges.clear(); + ownJID = JID("baz@fum.com/dum"); + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + vcardStorage = new VCardMemoryStorage(crypto.get()); + } + + void tearDown() { + delete vcardStorage; + delete iqRouter; + delete stanzaChannel; + } + + void testGet_NewVCardRequestsVCard() { + auto testling = createManager(); + VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz")); + + CPPUNIT_ASSERT(!result); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get)); + } + + void testGet_ExistingVCard() { + auto testling = createManager(); + VCard::ref vcard(new VCard()); + vcard->setFullName("Foo Bar"); + vcardStorage->setVCard(JID("foo@bar.com/baz"), vcard); + + VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz")); + + CPPUNIT_ASSERT_EQUAL(std::string("Foo Bar"), result->getFullName()); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testRequest_RequestsVCard() { + auto testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get)); + } + + void testRequest_ReceiveEmitsNotification() { + auto testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + stanzaChannel->onIQReceived(createVCardResult()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), changes[0].first); + CPPUNIT_ASSERT_EQUAL(std::string("Foo Bar"), changes[0].second->getFullName()); + CPPUNIT_ASSERT_EQUAL(std::string("Foo Bar"), vcardStorage->getVCard(JID("foo@bar.com/baz"))->getFullName()); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(ownChanges.size())); + } + + void testRequest_Error() { + auto testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + + // On error, cached vCards should not be changed. + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testRequest_VCardAlreadyRequested() { + auto testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz")); + + CPPUNIT_ASSERT(!result); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testRequest_AfterPreviousRequest() { + auto testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + stanzaChannel->onIQReceived(createVCardResult()); + testling->requestVCard(JID("foo@bar.com/baz")); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(1, JID("foo@bar.com/baz"), IQ::Get)); + } + + void testRequestVCard_ReturnFullVCard() { + auto testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + stanzaChannel->onIQReceived(createVCardResult()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get)); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), changes[0].first); + CPPUNIT_ASSERT_EQUAL(std::string("Foo Bar"), changes[0].second->getFullName()); + CPPUNIT_ASSERT_EQUAL(false, changes[0].second->isEmpty()); + } + + void testRequestVCard_ReturnEmptyVCard() { + auto testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + stanzaChannel->onIQReceived([&](){ + auto vcard = std::make_shared<VCard>(); + return IQ::createResult(JID("foo@bar.com/baz"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard); + }()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get)); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(true, changes[0].second->isEmpty()); + } + + void testRequestVCard_ReturnItemNotFoundError() { + auto testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + stanzaChannel->onIQReceived([&](){ + return IQ::createError(JID("foo@bar.com/baz"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), ErrorPayload::ItemNotFound); + }()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get)); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(true, changes[0].second->isEmpty()); + } + + void testRequestVCard_ReturnFeatureNotImplementedError() { + auto testling = createManager(); + testling->requestVCard(JID("foo@bar.com/baz")); + stanzaChannel->onIQReceived([&](){ + return IQ::createError(JID("foo@bar.com/baz"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), ErrorPayload::FeatureNotImplemented); + }()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get)); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testRequestOwnVCard_ReturnFullVCard() { + auto testling = createManager(); + testling->requestVCard(ownJID); + stanzaChannel->onIQReceived(createOwnVCardResult()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID(), IQ::Get)); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(ownJID.toBare(), changes[0].first); + CPPUNIT_ASSERT_EQUAL(std::string("Myself"), changes[0].second->getFullName()); + CPPUNIT_ASSERT_EQUAL(std::string("Myself"), vcardStorage->getVCard(ownJID.toBare())->getFullName()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(ownChanges.size())); + CPPUNIT_ASSERT_EQUAL(std::string("Myself"), ownChanges[0]->getFullName()); + } + + void testRequestOwnVCard_ReturnEmptyVCard() { + auto testling = createManager(); + testling->requestVCard(ownJID); + stanzaChannel->onIQReceived([&](){ + auto vcard = std::make_shared<VCard>(); + return IQ::createResult(JID(), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard); + }()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID(), IQ::Get)); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(true, changes[0].second->isEmpty()); + } + + void testRequestOwnVCard_ReturnItemNotFoundError() { + auto testling = createManager(); + testling->requestVCard(ownJID); + stanzaChannel->onIQReceived([&](){ + return IQ::createError(JID(), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), ErrorPayload::ItemNotFound); + }()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID(), IQ::Get)); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(true, changes[0].second->isEmpty()); + } + + void testRequestOwnVCard_ReturnFeatureNotImplementedError() { + auto testling = createManager(); + testling->requestVCard(ownJID); + stanzaChannel->onIQReceived([&](){ + return IQ::createError(JID(), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), ErrorPayload::FeatureNotImplemented); + }()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID(), IQ::Get)); + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testCreateSetVCardRequest() { + auto testling = createManager(); + VCard::ref vcard = std::make_shared<VCard>(); + vcard->setFullName("New Name"); + SetVCardRequest::ref request = testling->createSetVCardRequest(vcard); + request->send(); + + stanzaChannel->onIQReceived(createSetVCardResult()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(ownJID.toBare(), changes[0].first); + CPPUNIT_ASSERT_EQUAL(std::string("New Name"), changes[0].second->getFullName()); + } + + void testCreateSetVCardRequest_Error() { + auto testling = createManager(); + VCard::ref vcard = std::make_shared<VCard>(); + vcard->setFullName("New Name"); + SetVCardRequest::ref request = testling->createSetVCardRequest(vcard); + request->send(); + + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + private: + std::shared_ptr<VCardManager> createManager() { + std::shared_ptr<VCardManager> manager(new VCardManager(ownJID, iqRouter, vcardStorage)); + manager->onVCardChanged.connect(boost::bind(&VCardManagerTest::handleVCardChanged, this, _1, _2)); + manager->onOwnVCardChanged.connect(boost::bind(&VCardManagerTest::handleOwnVCardChanged, this, _1)); + return manager; + } + + void handleVCardChanged(const JID& jid, VCard::ref vcard) { + changes.push_back(std::pair<JID, VCard::ref>(jid, vcard)); + } + + void handleOwnVCardChanged(VCard::ref vcard) { + ownChanges.push_back(vcard); + } + + IQ::ref createVCardResult() { + VCard::ref vcard(new VCard()); + vcard->setFullName("Foo Bar"); + return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard); + } + + IQ::ref createOwnVCardResult() { + VCard::ref vcard(new VCard()); + vcard->setFullName("Myself"); + return IQ::createResult(JID(), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard); + } + + IQ::ref createSetVCardResult() { + return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), VCard::ref()); + } + + + private: + JID ownJID; + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + VCardMemoryStorage* vcardStorage; + std::vector< std::pair<JID, VCard::ref> > changes; + std::vector<VCard::ref> ownChanges; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardManagerTest); diff --git a/Swiften/VCards/VCardManager.cpp b/Swiften/VCards/VCardManager.cpp index 52447a1..9423702 100644 --- a/Swiften/VCards/VCardManager.cpp +++ b/Swiften/VCards/VCardManager.cpp @@ -1,17 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/VCards/VCardManager.h> #include <boost/bind.hpp> +#include <Swiften/Base/Log.h> #include <Swiften/JID/JID.h> -#include <Swiften/VCards/VCardStorage.h> #include <Swiften/VCards/GetVCardRequest.h> - +#include <Swiften/VCards/VCardStorage.h> namespace Swift { @@ -22,64 +22,70 @@ VCardManager::~VCardManager() { } VCard::ref VCardManager::getVCard(const JID& jid) const { - return storage->getVCard(jid); + return storage->getVCard(jid); } -VCard::ref VCardManager::getVCardAndRequestWhenNeeded(const JID& jid) { - VCard::ref vcard = storage->getVCard(jid); - if (!vcard) { - requestVCard(jid); - } - return vcard; +VCard::ref VCardManager::getVCardAndRequestWhenNeeded(const JID& jid, const boost::posix_time::time_duration& allowedAge) { + VCard::ref vcard = storage->getVCard(jid); + boost::posix_time::ptime vcardFetchedTime = storage->getVCardWriteTime(jid); + bool vcardTooOld = vcard && (vcardFetchedTime.is_special() || ((boost::posix_time::second_clock::universal_time() - vcardFetchedTime) > allowedAge)); + if (!vcard || vcardTooOld) { + requestVCard(jid); + } + return vcard; } void VCardManager::requestVCard(const JID& requestedJID) { - JID jid = requestedJID.equals(ownJID, JID::WithoutResource) ? JID() : requestedJID; - if (requestedVCards.find(jid) != requestedVCards.end()) { - return; - } - GetVCardRequest::ref request = GetVCardRequest::create(jid, iqRouter); - request->onResponse.connect(boost::bind(&VCardManager::handleVCardReceived, this, jid, _1, _2)); - request->send(); - requestedVCards.insert(jid); + JID jid = requestedJID.equals(ownJID, JID::WithoutResource) ? JID() : requestedJID; + if (requestedVCards.find(jid) != requestedVCards.end()) { + return; + } + GetVCardRequest::ref request = GetVCardRequest::create(jid, iqRouter); + request->onResponse.connect(boost::bind(&VCardManager::handleVCardReceived, this, jid, _1, _2)); + request->send(); + requestedVCards.insert(jid); } void VCardManager::requestOwnVCard() { - requestVCard(JID()); + requestVCard(JID()); } - void VCardManager::handleVCardReceived(const JID& actualJID, VCard::ref vcard, ErrorPayload::ref error) { - if (error || !vcard) { - vcard = VCard::ref(new VCard()); - } - requestedVCards.erase(actualJID); - JID jid = actualJID.isValid() ? actualJID : ownJID.toBare(); - setVCard(jid, vcard); + requestedVCards.erase(actualJID); + if (!error || (error && error->getCondition() == ErrorPayload::ItemNotFound)) { + if (!vcard) { + vcard = VCard::ref(new VCard()); + } + JID jid = actualJID.isValid() ? actualJID : ownJID.toBare(); + setVCard(jid, vcard); + } + else { + onVCardRetrievalError(actualJID, error); + } } SetVCardRequest::ref VCardManager::createSetVCardRequest(VCard::ref vcard) { - SetVCardRequest::ref request = SetVCardRequest::create(vcard, iqRouter); - request->onResponse.connect(boost::bind(&VCardManager::handleSetVCardResponse, this, vcard, _2)); - return request; + SetVCardRequest::ref request = SetVCardRequest::create(vcard, iqRouter); + request->onResponse.connect(boost::bind(&VCardManager::handleSetVCardResponse, this, vcard, _2)); + return request; } void VCardManager::handleSetVCardResponse(VCard::ref vcard, ErrorPayload::ref error) { - if (!error) { - setVCard(ownJID.toBare(), vcard); - } + if (!error) { + setVCard(ownJID.toBare(), vcard); + } } void VCardManager::setVCard(const JID& jid, VCard::ref vcard) { - storage->setVCard(jid, vcard); - onVCardChanged(jid, vcard); - if (jid.compare(ownJID, JID::WithoutResource) == 0) { - onOwnVCardChanged(vcard); - } + storage->setVCard(jid, vcard); + onVCardChanged(jid, vcard); + if (jid.compare(ownJID, JID::WithoutResource) == 0) { + onOwnVCardChanged(vcard); + } } std::string VCardManager::getPhotoHash(const JID& jid) const { - return storage->getPhotoHash(jid); + return storage->getPhotoHash(jid); } } diff --git a/Swiften/VCards/VCardManager.h b/Swiften/VCards/VCardManager.h index b7e3c32..e28e8e6 100644 --- a/Swiften/VCards/VCardManager.h +++ b/Swiften/VCards/VCardManager.h @@ -1,62 +1,68 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <set> +#include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/VCard.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/VCard.h> +#include <Swiften/JID/JID.h> #include <Swiften/VCards/SetVCardRequest.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class JID; - class VCardStorage; - class IQRouter; - - class SWIFTEN_API VCardManager : public boost::bsignals::trackable { - public: - VCardManager(const JID& ownJID, IQRouter* iqRouter, VCardStorage* vcardStorage); - ~VCardManager(); - - VCard::ref getVCard(const JID& jid) const; - VCard::ref getVCardAndRequestWhenNeeded(const JID& jid); - void requestVCard(const JID& jid); - void requestOwnVCard(); - - std::string getPhotoHash(const JID& jid) const; - - - SetVCardRequest::ref createSetVCardRequest(VCard::ref); - - public: - /** - * The JID will always be bare. - */ - boost::signal<void (const JID&, VCard::ref)> onVCardChanged; - - /** - * Emitted when our own vcard changes. - * - * onVCardChanged will also be emitted. - */ - boost::signal<void (VCard::ref)> onOwnVCardChanged; - - private: - void handleVCardReceived(const JID& from, VCard::ref, ErrorPayload::ref); - void handleSetVCardResponse(VCard::ref, ErrorPayload::ref); - void setVCard(const JID& jid, VCard::ref vcard); - - private: - JID ownJID; - IQRouter* iqRouter; - VCardStorage* storage; - std::set<JID> requestedVCards; - }; + class IQRouter; + class VCardStorage; + + class SWIFTEN_API VCardManager : public boost::signals2::trackable { + public: + VCardManager(const JID& ownJID, IQRouter* iqRouter, VCardStorage* vcardStorage); + ~VCardManager(); + + VCard::ref getVCard(const JID& jid) const; + VCard::ref getVCardAndRequestWhenNeeded(const JID& jid, const boost::posix_time::time_duration& allowedAge = boost::posix_time::time_duration(boost::date_time::pos_infin)); + void requestVCard(const JID& jid); + void requestOwnVCard(); + + std::string getPhotoHash(const JID& jid) const; + + + SetVCardRequest::ref createSetVCardRequest(VCard::ref); + + public: + /** + * The JID will always be bare. + */ + boost::signals2::signal<void (const JID&, VCard::ref)> onVCardChanged; + + /** + * Emitted when we received an error on looking up a vCard. + */ + boost::signals2::signal<void (const JID&, ErrorPayload::ref)> onVCardRetrievalError; + + /** + * Emitted when our own vcard changes. + * + * onVCardChanged will also be emitted. + */ + boost::signals2::signal<void (VCard::ref)> onOwnVCardChanged; + + private: + void handleVCardReceived(const JID& from, VCard::ref, ErrorPayload::ref); + void handleSetVCardResponse(VCard::ref, ErrorPayload::ref); + void setVCard(const JID& jid, VCard::ref vcard); + + private: + JID ownJID; + IQRouter* iqRouter; + VCardStorage* storage; + std::set<JID> requestedVCards; + }; } diff --git a/Swiften/VCards/VCardMemoryStorage.h b/Swiften/VCards/VCardMemoryStorage.h index 86ae1b2..9a79edc 100644 --- a/Swiften/VCards/VCardMemoryStorage.h +++ b/Swiften/VCards/VCardMemoryStorage.h @@ -1,38 +1,51 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> #include <map> +#include <memory> +#include <Swiften/Base/API.h> #include <Swiften/JID/JID.h> #include <Swiften/VCards/VCardStorage.h> namespace Swift { - class VCardMemoryStorage : public VCardStorage { - public: - VCardMemoryStorage(CryptoProvider* crypto) : VCardStorage(crypto) {} - - virtual VCard::ref getVCard(const JID& jid) const { - VCardMap::const_iterator i = vcards.find(jid); - if (i != vcards.end()) { - return i->second; - } - else { - return VCard::ref(); - } - } - - virtual void setVCard(const JID& jid, VCard::ref v) { - vcards[jid] = v; - } - - private: - typedef std::map<JID, VCard::ref> VCardMap; - VCardMap vcards; - }; + class SWIFTEN_API VCardMemoryStorage : public VCardStorage { + public: + VCardMemoryStorage(CryptoProvider* crypto) : VCardStorage(crypto) {} + + virtual VCard::ref getVCard(const JID& jid) const { + VCardMap::const_iterator i = vcards.find(jid); + if (i != vcards.end()) { + return i->second; + } + else { + return VCard::ref(); + } + } + + virtual boost::posix_time::ptime getVCardWriteTime(const JID& jid) const { + if (vcardWriteTimes.find(jid) == vcardWriteTimes.end()) { + return boost::posix_time::ptime(); + } + else { + return vcardWriteTimes.at(jid); + } + } + + virtual void setVCard(const JID& jid, VCard::ref v) { + vcards[jid] = v; + vcardWriteTimes[jid] = boost::posix_time::second_clock::universal_time(); + } + + private: + typedef std::map<JID, VCard::ref> VCardMap; + typedef std::map<JID, boost::posix_time::ptime> VCardWriteTimeMap; + VCardMap vcards; + VCardWriteTimeMap vcardWriteTimes; + }; } diff --git a/Swiften/VCards/VCardStorage.cpp b/Swiften/VCards/VCardStorage.cpp index fefea83..2a4f04c 100644 --- a/Swiften/VCards/VCardStorage.cpp +++ b/Swiften/VCards/VCardStorage.cpp @@ -1,13 +1,13 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/VCards/VCardStorage.h> -#include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/StringCodecs/Hexify.h> namespace Swift { @@ -18,13 +18,13 @@ VCardStorage::~VCardStorage() { } std::string VCardStorage::getPhotoHash(const JID& jid) const { - VCard::ref vCard = getVCard(jid); - if (vCard && !vCard->getPhoto().empty()) { - return Hexify::hexify(crypto->getSHA1Hash(vCard->getPhoto())); - } - else { - return ""; - } + VCard::ref vCard = getVCard(jid); + if (vCard && !vCard->getPhoto().empty()) { + return Hexify::hexify(crypto->getSHA1Hash(vCard->getPhoto())); + } + else { + return ""; + } } } diff --git a/Swiften/VCards/VCardStorage.h b/Swiften/VCards/VCardStorage.h index 924204c..632e9e3 100644 --- a/Swiften/VCards/VCardStorage.h +++ b/Swiften/VCards/VCardStorage.h @@ -1,32 +1,35 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <string> -#include <boost/shared_ptr.hpp> + +#include <boost/date_time/posix_time/posix_time.hpp> #include <Swiften/Base/API.h> #include <Swiften/Elements/VCard.h> namespace Swift { - class JID; - class CryptoProvider; + class JID; + class CryptoProvider; - class SWIFTEN_API VCardStorage { - public: - VCardStorage(CryptoProvider*); - virtual ~VCardStorage(); + class SWIFTEN_API VCardStorage { + public: + VCardStorage(CryptoProvider*); + virtual ~VCardStorage(); - virtual VCard::ref getVCard(const JID& jid) const = 0; - virtual void setVCard(const JID&, VCard::ref) = 0; + virtual VCard::ref getVCard(const JID& jid) const = 0; + virtual boost::posix_time::ptime getVCardWriteTime(const JID& jid) const = 0; + virtual void setVCard(const JID&, VCard::ref) = 0; - virtual std::string getPhotoHash(const JID&) const; + virtual std::string getPhotoHash(const JID&) const; - private: - CryptoProvider* crypto; - }; + private: + CryptoProvider* crypto; + }; } diff --git a/Swiften/Whiteboard/IncomingWhiteboardSession.cpp b/Swiften/Whiteboard/IncomingWhiteboardSession.cpp index d64a0d2..462bf21 100644 --- a/Swiften/Whiteboard/IncomingWhiteboardSession.cpp +++ b/Swiften/Whiteboard/IncomingWhiteboardSession.cpp @@ -4,55 +4,62 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Whiteboard/IncomingWhiteboardSession.h> -#include <Swiften/Elements/WhiteboardPayload.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> +#include <memory> + #include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> +#include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h> +#include <Swiften/Elements/WhiteboardPayload.h> namespace Swift { - IncomingWhiteboardSession::IncomingWhiteboardSession(const JID& jid, IQRouter* router) : WhiteboardSession(jid, router) { - } - - IncomingWhiteboardSession::~IncomingWhiteboardSession() { - } - - void IncomingWhiteboardSession::accept() { - boost::shared_ptr<WhiteboardPayload> payload = boost::make_shared<WhiteboardPayload>(WhiteboardPayload::SessionAccept); - boost::shared_ptr<GenericRequest<WhiteboardPayload> > request = boost::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); - request->send(); - onRequestAccepted(toJID_); - } - - void IncomingWhiteboardSession::handleIncomingOperation(WhiteboardOperation::ref operation) { - WhiteboardClient::Result pairResult = client.handleServerOperationReceived(operation); - if (pairResult.client) { - if (pairResult.client->getPos() != -1) { - onOperationReceived(pairResult.client); - } - lastOpID = pairResult.client->getID(); - } - - if (pairResult.server) { - WhiteboardPayload::ref payload = boost::make_shared<WhiteboardPayload>(); - payload->setOperation(pairResult.server); - sendPayload(payload); - } - } - - void IncomingWhiteboardSession::sendOperation(WhiteboardOperation::ref operation) { - operation->setID(idGenerator.generateID()); - operation->setParentID(lastOpID); - lastOpID = operation->getID(); - - WhiteboardOperation::ref result = client.handleLocalOperationReceived(operation); - - if (result) { - WhiteboardPayload::ref payload = boost::make_shared<WhiteboardPayload>(); - payload->setOperation(result); - sendPayload(payload); - } - } + IncomingWhiteboardSession::IncomingWhiteboardSession(const JID& jid, IQRouter* router) : WhiteboardSession(jid, router) { + } + + IncomingWhiteboardSession::~IncomingWhiteboardSession() { + } + + void IncomingWhiteboardSession::accept() { + std::shared_ptr<WhiteboardPayload> payload = std::make_shared<WhiteboardPayload>(WhiteboardPayload::SessionAccept); + std::shared_ptr<GenericRequest<WhiteboardPayload> > request = std::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); + request->send(); + onRequestAccepted(toJID_); + } + + void IncomingWhiteboardSession::handleIncomingOperation(WhiteboardOperation::ref operation) { + WhiteboardClient::Result pairResult = client.handleServerOperationReceived(operation); + if (pairResult.client) { + if (pairResult.client->getPos() != -1) { + onOperationReceived(pairResult.client); + } + lastOpID = pairResult.client->getID(); + } + + if (pairResult.server) { + WhiteboardPayload::ref payload = std::make_shared<WhiteboardPayload>(); + payload->setOperation(pairResult.server); + sendPayload(payload); + } + } + + void IncomingWhiteboardSession::sendOperation(WhiteboardOperation::ref operation) { + operation->setID(idGenerator.generateID()); + operation->setParentID(lastOpID); + lastOpID = operation->getID(); + + WhiteboardOperation::ref result = client.handleLocalOperationReceived(operation); + + if (result) { + WhiteboardPayload::ref payload = std::make_shared<WhiteboardPayload>(); + payload->setOperation(result); + sendPayload(payload); + } + } } diff --git a/Swiften/Whiteboard/IncomingWhiteboardSession.h b/Swiften/Whiteboard/IncomingWhiteboardSession.h index 54b5fb6..0f43cea 100644 --- a/Swiften/Whiteboard/IncomingWhiteboardSession.h +++ b/Swiften/Whiteboard/IncomingWhiteboardSession.h @@ -4,28 +4,35 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <memory> + #include <Swiften/Base/API.h> -#include <Swiften/Whiteboard/WhiteboardSession.h> #include <Swiften/Whiteboard/WhiteboardClient.h> -#include <boost/shared_ptr.hpp> +#include <Swiften/Whiteboard/WhiteboardSession.h> namespace Swift { - class SWIFTEN_API IncomingWhiteboardSession : public WhiteboardSession { - public: - typedef boost::shared_ptr<IncomingWhiteboardSession> ref; + class SWIFTEN_API IncomingWhiteboardSession : public WhiteboardSession { + public: + typedef std::shared_ptr<IncomingWhiteboardSession> ref; - public: - IncomingWhiteboardSession(const JID& jid, IQRouter* router); - ~IncomingWhiteboardSession(); + public: + IncomingWhiteboardSession(const JID& jid, IQRouter* router); + ~IncomingWhiteboardSession(); - void accept(); + void accept(); - private: - void handleIncomingOperation(WhiteboardOperation::ref operation); - void sendOperation(WhiteboardOperation::ref operation); + private: + void handleIncomingOperation(WhiteboardOperation::ref operation); + void sendOperation(WhiteboardOperation::ref operation); - WhiteboardClient client; - }; + WhiteboardClient client; + }; } diff --git a/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp b/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp index ad81daa..49f48aa 100644 --- a/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp +++ b/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp @@ -4,56 +4,63 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Whiteboard/OutgoingWhiteboardSession.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/bind.hpp> -#include <Swiften/Elements/WhiteboardPayload.h> +#include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h> -#include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> +#include <Swiften/Elements/WhiteboardPayload.h> namespace Swift { - OutgoingWhiteboardSession::OutgoingWhiteboardSession(const JID& jid, IQRouter* router) : WhiteboardSession(jid, router) { - } - - OutgoingWhiteboardSession::~OutgoingWhiteboardSession() { - } - - void OutgoingWhiteboardSession::startSession() { - boost::shared_ptr<WhiteboardPayload> payload = boost::make_shared<WhiteboardPayload>(WhiteboardPayload::SessionRequest); - boost::shared_ptr<GenericRequest<WhiteboardPayload> > request = boost::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); - request->onResponse.connect(boost::bind(&OutgoingWhiteboardSession::handleRequestResponse, this, _1, _2)); - request->send(); - } - - void OutgoingWhiteboardSession::handleRequestResponse(boost::shared_ptr<WhiteboardPayload> /*payload*/, ErrorPayload::ref error) { - if (error) { - onRequestRejected(toJID_); - } - } - - void OutgoingWhiteboardSession::handleIncomingOperation(WhiteboardOperation::ref operation) { - WhiteboardOperation::ref op = server.handleClientOperationReceived(operation); - if (op->getPos() != -1) { - onOperationReceived(op); - } - lastOpID = op->getID(); - - WhiteboardPayload::ref payload = boost::make_shared<WhiteboardPayload>(); - payload->setOperation(op); - sendPayload(payload); - } - - void OutgoingWhiteboardSession::sendOperation(WhiteboardOperation::ref operation) { - operation->setID(idGenerator.generateID()); - operation->setParentID(lastOpID); - lastOpID = operation->getID(); - - server.handleLocalOperationReceived(operation); - WhiteboardPayload::ref payload = boost::make_shared<WhiteboardPayload>(); - payload->setOperation(operation); - sendPayload(payload); - } + OutgoingWhiteboardSession::OutgoingWhiteboardSession(const JID& jid, IQRouter* router) : WhiteboardSession(jid, router) { + } + + OutgoingWhiteboardSession::~OutgoingWhiteboardSession() { + } + + void OutgoingWhiteboardSession::startSession() { + std::shared_ptr<WhiteboardPayload> payload = std::make_shared<WhiteboardPayload>(WhiteboardPayload::SessionRequest); + std::shared_ptr<GenericRequest<WhiteboardPayload> > request = std::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); + request->onResponse.connect(boost::bind(&OutgoingWhiteboardSession::handleRequestResponse, this, _1, _2)); + request->send(); + } + + void OutgoingWhiteboardSession::handleRequestResponse(std::shared_ptr<WhiteboardPayload> /*payload*/, ErrorPayload::ref error) { + if (error) { + onRequestRejected(toJID_); + } + } + + void OutgoingWhiteboardSession::handleIncomingOperation(WhiteboardOperation::ref operation) { + WhiteboardOperation::ref op = server.handleClientOperationReceived(operation); + if (op->getPos() != -1) { + onOperationReceived(op); + } + lastOpID = op->getID(); + + WhiteboardPayload::ref payload = std::make_shared<WhiteboardPayload>(); + payload->setOperation(op); + sendPayload(payload); + } + + void OutgoingWhiteboardSession::sendOperation(WhiteboardOperation::ref operation) { + operation->setID(idGenerator.generateID()); + operation->setParentID(lastOpID); + lastOpID = operation->getID(); + + server.handleLocalOperationReceived(operation); + WhiteboardPayload::ref payload = std::make_shared<WhiteboardPayload>(); + payload->setOperation(operation); + sendPayload(payload); + } } diff --git a/Swiften/Whiteboard/OutgoingWhiteboardSession.h b/Swiften/Whiteboard/OutgoingWhiteboardSession.h index 5db9c97..52fb1db 100644 --- a/Swiften/Whiteboard/OutgoingWhiteboardSession.h +++ b/Swiften/Whiteboard/OutgoingWhiteboardSession.h @@ -4,29 +4,36 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Whiteboard/WhiteboardSession.h> -#include <Swiften/Whiteboard/WhiteboardServer.h> -#include <boost/shared_ptr.hpp> -#include <Swiften/Queries/GenericRequest.h> +#include <memory> + #include <Swiften/Base/API.h> +#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Whiteboard/WhiteboardServer.h> +#include <Swiften/Whiteboard/WhiteboardSession.h> namespace Swift { - class SWIFTEN_API OutgoingWhiteboardSession : public WhiteboardSession { - public: - typedef boost::shared_ptr<OutgoingWhiteboardSession> ref; - - public: - OutgoingWhiteboardSession(const JID& jid, IQRouter* router); - virtual ~OutgoingWhiteboardSession(); - void startSession(); - - private: - void handleRequestResponse(boost::shared_ptr<WhiteboardPayload> /*payload*/, ErrorPayload::ref error); - void handleIncomingOperation(WhiteboardOperation::ref operation); - void sendOperation(WhiteboardOperation::ref operation); - - WhiteboardServer server; - }; + class SWIFTEN_API OutgoingWhiteboardSession : public WhiteboardSession { + public: + typedef std::shared_ptr<OutgoingWhiteboardSession> ref; + + public: + OutgoingWhiteboardSession(const JID& jid, IQRouter* router); + virtual ~OutgoingWhiteboardSession(); + void startSession(); + + private: + void handleRequestResponse(std::shared_ptr<WhiteboardPayload> /*payload*/, ErrorPayload::ref error); + void handleIncomingOperation(WhiteboardOperation::ref operation); + void sendOperation(WhiteboardOperation::ref operation); + + WhiteboardServer server; + }; } diff --git a/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp b/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp index 09c25bb..fd26825 100644 --- a/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp +++ b/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp @@ -4,673 +4,680 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + + +#include <memory> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Whiteboard/WhiteboardClient.h> -#include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> -#include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> +#include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h> +#include <Swiften/Whiteboard/WhiteboardClient.h> using namespace Swift; class WhiteboardClientTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(WhiteboardClientTest); - CPPUNIT_TEST(testSynchronize_simplestSync); - CPPUNIT_TEST(testSynchronize_withoutTranslation); - CPPUNIT_TEST(testSynchronize_nonInterrupted); - CPPUNIT_TEST(testSynchronize_clientInterruption); - CPPUNIT_TEST(testSynchronize_serverInterruption); - CPPUNIT_TEST(testSynchronize_nonInterruptedMixOperations); - CPPUNIT_TEST(testSynchronize_nonInterruptedMixOperations2); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(WhiteboardClientTest); + CPPUNIT_TEST(testSynchronize_simplestSync); + CPPUNIT_TEST(testSynchronize_withoutTranslation); + CPPUNIT_TEST(testSynchronize_nonInterrupted); + CPPUNIT_TEST(testSynchronize_clientInterruption); + CPPUNIT_TEST(testSynchronize_serverInterruption); + CPPUNIT_TEST(testSynchronize_nonInterruptedMixOperations); + CPPUNIT_TEST(testSynchronize_nonInterruptedMixOperations2); + CPPUNIT_TEST_SUITE_END(); public: - /*! - * /\ - * \/ - * \ - */ - void testSynchronize_simplestSync() { - WhiteboardClient client; - WhiteboardInsertOperation::ref serverOp; - serverOp = createInsertOperation("0", "", 0); - WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives first local operation, because it's parented off "0" which exists - //in server history and client doesn't wait for any operation ack from server, - //so this operation could be send - WhiteboardInsertOperation::ref clientOp; - clientOp = createInsertOperation("a", "0", 1); - WhiteboardEllipseElement::ref aElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(aElement); - WhiteboardInsertOperation::ref result; - checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); - - //Client receives server operation parented off "0", which isn't last client operation - //so it have to be transformed against local operations and then transformed value can - //be returned to draw - serverOp = createInsertOperation("b", "0", 1); - WhiteboardEllipseElement::ref bElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverOp->setElement(bElement); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.client, "b", "a", 2, bElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives confirmation from the server about processed "a" operation, it had to - //be transformed against "b" on the server side to receive operation parented off "b". - //There aren't any waiting operations to send to server, this operation should return - //nothing - serverOp = createInsertOperation("a", "b", 1); - pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives local operation, it doesn't have to be transformed against anything - //but operation returned to send to the server should be parented off last server - //operation, which is "b" - clientOp = createInsertOperation("c", "b", 3); - WhiteboardEllipseElement::ref cElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(cElement); - checkOperation(client.handleLocalOperationReceived(clientOp), "c", "a", 3, cElement); - - //Client receives confirmation from the server about processed "a" operation, it - //should be the same operation as it was sent because server didn't have to - //transform it - clientOp = createInsertOperation("c", "a", 3); - clientOp->setElement(cElement); - pairResult = client.handleServerOperationReceived(clientOp); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Results: - //Client operations: - //ID pos - //0 0 - //a 1 - //b 2 - //c 3 - // - //Server operations: - //ID pos - //0 0 - //b 1 - //a 1 - //c 3 - // - //what gives 0abc on both sides - } - - /*! - * / - * / - * \ - */ - void testSynchronize_withoutTranslation() { - WhiteboardClient client; - WhiteboardInsertOperation::ref serverOp; - serverOp = createInsertOperation("0", "", 0); - WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives first local operation, because it's parented off "0" which exists - //in server history and client doesn't wait for any operation ack from server, - //so this operation could be send - WhiteboardInsertOperation::ref clientOp = createInsertOperation("c", "0", 1); - WhiteboardEllipseElement::ref cElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(cElement); - checkOperation(client.handleLocalOperationReceived(clientOp), "c", "0", 1, cElement); - - //Client receives second local operation, client didn't receive ack about previous - //operation from the server so it can't be send. - clientOp = createInsertOperation("d", "c", 2); - WhiteboardEllipseElement::ref dElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(dElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); - - //Client receives confirmation about processing "c" operation, it should be the - //same as sent operation because it wasn't transformed, client could send now - //operation "d" - clientOp = createInsertOperation("c", "0", 1); - clientOp->setElement(cElement); - pairResult = client.handleServerOperationReceived(clientOp); - checkOperation(pairResult.server, "d", "c", 2, dElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - - //Client receives confirmation about processing "d", it should be the same as - //sent operation. There aren't any operations in queue to send. - clientOp = createInsertOperation("d", "c", 2); - clientOp->setElement(dElement); - pairResult = client.handleServerOperationReceived(clientOp); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives new operation from server, it's parented off "d" which is at - //the end of local history so it doesn't have to be transformed, so operation - //to pass to window should be the same - serverOp = createInsertOperation("e", "d", 3); - WhiteboardEllipseElement::ref eElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverOp->setElement(eElement); - pairResult = client.handleServerOperationReceived(serverOp); - WhiteboardInsertOperation::ref result = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client); - CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - - //Client operations: - //ID pos - //0 0 - //c 1 - //d 2 - //e 3 - // - //Server operations: - //ID pos - //0 0 - //c 1 - //d 2 - //e 3 - } - - /*! - * /\ - * / \ - * \ / - * \/ - */ - void testSynchronize_nonInterrupted() { - WhiteboardClient client; - WhiteboardInsertOperation::ref serverOp; - serverOp = createInsertOperation("0", "", 0); - WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives first local operation, because it's parented off "0" which exists - //in server history and client doesn't wait for any operation ack from server, - //so this operation could be send - WhiteboardInsertOperation::ref clientOp; - clientOp = createInsertOperation("a", "0", 1); - WhiteboardEllipseElement::ref aElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(aElement); - checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); - - //Client receives second local operation, client didn't receive ack about previous - //operation from the server so it can't be send. - clientOp = createInsertOperation("b", "a", 2); - WhiteboardEllipseElement::ref bElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(bElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); - - //Client receives new operation from server, it should be transformed against - //"a" and "b" before adding to local operations history because it's parented off "0". - //Because client is waiting for ack of "a", there is no operation to send to server - serverOp = createInsertOperation("c", "0", 1); - WhiteboardEllipseElement::ref cElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverOp->setElement(cElement); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.client, "c", "b", 3, cElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives new operation from server, it should be transformed against - //results of previous transformations, returned operation should be parented off - //"c" existing in local history. - //Because client is waiting for ack of "a", there is no operation to send to server - serverOp = createInsertOperation("d", "c", 2); - WhiteboardEllipseElement::ref dElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverOp->setElement(dElement); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.client, "d", "c", 4, dElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives confirmation about processing "a", it should send next operation - //to server which is "b", but it should be version parented of transformed "a" - serverOp = createInsertOperation("a", "d", 1); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.server, "b", "a", 2, bElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - - - //Client receives confirmation about processing "b", there aren't any operations - //waiting so it should return nothing. - serverOp = createInsertOperation("b", "a", 2); - pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client operations: - //ID pos - //0 0 - //a 1 - //b 2 - //c 3 - //d 4 - // - //Server operations: - //ID pos - //0 0 - //c 1 - //d 2 - //a 1 - //b 2 - // - //what gives 0abcd on both sides. - } - - /*! - * /\ - * / \ - * \ / - * / / - * \/ - */ - void testSynchronize_clientInterruption() { - WhiteboardClient client; - WhiteboardInsertOperation::ref serverOp; - serverOp = createInsertOperation("0", "", 0); - WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives first local operation, because it's parented off "0" which exists - //in server history and client doesn't wait for any operation ack from server, - //so this operation could be send - WhiteboardInsertOperation::ref clientOp; - clientOp = createInsertOperation("a", "0", 1); - WhiteboardEllipseElement::ref aElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(aElement); - checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); - - //Client receives second local operation, client didn't receive ack about previous - //operation from the server so it can't be send. - clientOp = createInsertOperation("b", "a", 2); - WhiteboardEllipseElement::ref bElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(bElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); - - //Client receives new operation from server, it should be transformed against - //"a" and "b" before adding to local operations history because it's parented off "0". - //Because client is waiting for ack of "a", there is no operation to send to server - serverOp = createInsertOperation("c", "0", 1); - WhiteboardEllipseElement::ref cElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverOp->setElement(cElement); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.client, "c", "b", 3, cElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives new local operation, client is still waiting for ack so, it - //should return nothing - clientOp = createInsertOperation("e", "a", 4); - WhiteboardEllipseElement::ref eElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(eElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); - - //Client receives new server operation, to add it to local history it should be transformed - //against result of previous transformations and operation "e", returned operation should - //be parented off "e", which was last local operation - serverOp = createInsertOperation("d", "c", 2); - WhiteboardEllipseElement::ref dElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverOp->setElement(dElement); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.client, "d", "e", 5, dElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives confirmation about processing "a", it had to be transformed against - //"c" and "d" and it is now parented off "d", returned value should be next operation - //which have to be send to server("b" parented off server version of "a"). - serverOp = createInsertOperation("a", "d", 1); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.server, "b", "a", 2, bElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - - //Client receives confirmation about processing "b", it is the same operation as sent because - //it didn't have to be transformed, returned value should be next operation - //which have to be send to server("e" parented off server version of "b"). - serverOp = createInsertOperation("b", "a", 2); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.server, "e", "b", 4, eElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - - //Client receives confirmation about processing "b", it is the same operation as sent because - //it didn't have to be transformed, there aren't any operations to send so this function returns - //nothing - serverOp = createInsertOperation("e", "b", 4); - pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Result: - //Client operations: - //ID pos - //0 0 - //a 1 - //b 2 - //c 3 - //e 4 - //d 5 - // - //Server operations: - //0 0 - //c 1 - //d 2 - //a 1 - //b 2 - //e 4 - //what gives 0abced on both sides - } - - /*! - * /\ - * / / - * \ \ - * \/ - */ - void testSynchronize_serverInterruption() { - WhiteboardClient client; - WhiteboardInsertOperation::ref serverOp; - serverOp = createInsertOperation("0", "", 0); - WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives first local operation, because it's parented off "0" which exists - //in server history and client doesn't wait for any operation ack from server, - //so this operation could be send - WhiteboardInsertOperation::ref clientOp; - clientOp = createInsertOperation("a", "0", 1); - WhiteboardEllipseElement::ref aElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(aElement); - checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); - - //Client receives second local operation, client didn't receive ack about previous - //operation from the server so it can't be send. - clientOp = createInsertOperation("b", "a", 2); - WhiteboardEllipseElement::ref bElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(bElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); - - //Client receives new operation from server, it should be transformed against - //"a" and "b" before adding to local operations history because it's parented off "0". - //Because client is waiting for ack of "a", there is no operation to send to server - serverOp = createInsertOperation("c", "0", 1); - WhiteboardEllipseElement::ref cElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverOp->setElement(cElement); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.client, "c", "b", 3, cElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives confirmation about processing "a", it had to be transformed against - //"c" and it is now parented off "c", returned value should be next operation - //which have to be send to server("b" parented off server version of "a"). - serverOp = createInsertOperation("a", "c", 1); - serverOp->setElement(aElement); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.server, "b", "a", 2, bElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - - //Client receives new server operation, to add it to local history it should be transformed - //against result of previous transformation(but only with transformation of "b"), returned - //operation should be parented off "c", which was last local operation - serverOp = createInsertOperation("d", "a", 3); - WhiteboardEllipseElement::ref dElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverOp->setElement(dElement); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.client, "d", "c", 4, dElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives confirmation about processing "b", it had to be transformed against - //"d" because both operations was parented off server version of "a". - //there aren't any operations to send so this function returns nothing. - serverOp = createInsertOperation("b", "d", 2); - serverOp->setElement(bElement); - pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client operations: - //ID pos - //0 0 - //a 1 - //b 2 - //c 3 - //d 4 - // - //Server operations: - //ID pos - //0 0 - //c 1 - //a 1 - //d 3 - //b 2 - // - //what gives 0abcd on both sides - - } - - /*! - * /\ - * / \ - * \ / - * \/ - */ - void testSynchronize_nonInterruptedMixOperations() { - WhiteboardClient client; - WhiteboardInsertOperation::ref serverOp; - serverOp = createInsertOperation("0", "", 0); - WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives first local operation, because it's parented off "0" which exists - //in server history and client doesn't wait for any operation ack from server, - //so this operation could be send - WhiteboardInsertOperation::ref clientOp; - clientOp = createInsertOperation("a", "0", 1); - WhiteboardEllipseElement::ref aElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setElement(aElement); - checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); - - //Client receives second local operation, client didn't receive ack about previous - //operation from the server so it can't be send. - WhiteboardUpdateOperation::ref clientUpdateOp = createUpdateOperation("b", "a", 0); - WhiteboardEllipseElement::ref bElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientUpdateOp->setElement(bElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientUpdateOp)); - - //Client receives new operation from server, it should be transformed against - //"a" and "b" before adding to local operations history because it's parented off "0". - //Because client is waiting for ack of "a", there is no operation to send to server - WhiteboardUpdateOperation::ref serverUpdateOp = createUpdateOperation("c", "0", 0); - WhiteboardEllipseElement::ref cElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverUpdateOp->setElement(cElement); - pairResult = client.handleServerOperationReceived(serverUpdateOp); - checkOperation(pairResult.client, "c", "b", 0, cElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives new operation from server, it should be transformed against - //results of previous transformations, returned operation should be parented off - //"c" existing in local history. - //Because client is waiting for ack of "a", there is no operation to send to server - serverOp = createInsertOperation("d", "c", 1); - WhiteboardEllipseElement::ref dElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverOp->setElement(dElement); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.client, "d", "c", 2, dElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives confirmation about processing "a", it should send next operation - //to server which is "b", but it should be version parented of transformed "a" - serverOp = createInsertOperation("a", "d", 1); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.server, "b", "a", 0, cElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - - - //Client receives confirmation about processing "b", there aren't any operations - //waiting so it should return nothing. - serverUpdateOp = createUpdateOperation("b", "a", 0); - pairResult = client.handleServerOperationReceived(serverUpdateOp); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client operations: - //ID pos - //0 0 - //a 1 - //b 2 - //c 3 - //d 4 - // - //Server operations: - //ID pos - //0 0 - //c 1 - //d 2 - //a 1 - //b 2 - // - //what gives 0abcd on both sides. - } - - /*! - * /\ - * / \ - * \ / - * \/ - */ - void testSynchronize_nonInterruptedMixOperations2() { - WhiteboardClient client; - WhiteboardInsertOperation::ref serverOp; - serverOp = createInsertOperation("0", "", 0); - WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - serverOp = createInsertOperation("1", "0", 1); - pairResult = client.handleServerOperationReceived(serverOp); - CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - //Client receives first local operation, because it's parented off "0" which exists - //in server history and client doesn't wait for any operation ack from server, - //so this operation could be send - WhiteboardInsertOperation::ref clientOp; - WhiteboardUpdateOperation::ref clientUpdateOp; - WhiteboardDeleteOperation::ref clientDeleteOp; - clientUpdateOp = createUpdateOperation("a", "1", 0); - WhiteboardEllipseElement::ref aElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientUpdateOp->setElement(aElement); - checkOperation(client.handleLocalOperationReceived(clientUpdateOp), "a", "1", 0, aElement); - - //Client receives second local operation, client didn't receive ack about previous - //operation from the server so it can't be send. - clientDeleteOp = createDeleteOperation("b", "a", 1); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientDeleteOp)); - - //Client receives new operation from server, it should be transformed against - //"a" and "b" before adding to local operations history because it's parented off "0". - //Because client is waiting for ack of "a", there is no operation to send to server - serverOp = createInsertOperation("c", "1", 2); - WhiteboardEllipseElement::ref cElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverOp->setElement(cElement); - pairResult = client.handleServerOperationReceived(serverOp); - checkOperation(pairResult.client, "c", "b", 1, cElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives new operation from server, it should be transformed against - //results of previous transformations, returned operation should be parented off - //"c" existing in local history. - //Because client is waiting for ack of "a", there is no operation to send to server - WhiteboardUpdateOperation::ref serverUpdateOp = createUpdateOperation("d", "c", 0); - WhiteboardEllipseElement::ref dElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - serverUpdateOp->setElement(dElement); - pairResult = client.handleServerOperationReceived(serverUpdateOp); - checkOperation(pairResult.client, "d", "c", 0, dElement); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client receives confirmation about processing "a", it should send next operation - //to server which is "b", but it should be version parented of transformed "a" - serverUpdateOp = createUpdateOperation("a", "d", 0); - pairResult = client.handleServerOperationReceived(serverUpdateOp); - checkOperation(pairResult.server, "b", "a", 1); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - - - //Client receives confirmation about processing "b", there aren't any operations - //waiting so it should return nothing. - WhiteboardDeleteOperation::ref serverDeleteOp = createDeleteOperation("b", "a", 0); - pairResult = client.handleServerOperationReceived(serverDeleteOp); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); - CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); - - //Client operations: - //ID pos - //0 0 - //a 1 - //b 2 - //c 3 - //d 4 - // - //Server operations: - //ID pos - //0 0 - //c 1 - //d 2 - //a 1 - //b 2 - // - //what gives 0abcd on both sides. - } - - - WhiteboardInsertOperation::ref createInsertOperation(std::string id, std::string parent, int pos) { - WhiteboardInsertOperation::ref operation = boost::make_shared<WhiteboardInsertOperation>(); - operation->setParentID(parent); - operation->setID(id); - operation->setPos(pos); - return operation; - } - - WhiteboardUpdateOperation::ref createUpdateOperation(std::string id, std::string parent, int pos) { - WhiteboardUpdateOperation::ref operation = boost::make_shared<WhiteboardUpdateOperation>(); - operation->setParentID(parent); - operation->setID(id); - operation->setPos(pos); - return operation; - } - - WhiteboardDeleteOperation::ref createDeleteOperation(std::string id, std::string parent, int pos) { - WhiteboardDeleteOperation::ref operation = boost::make_shared<WhiteboardDeleteOperation>(); - operation->setParentID(parent); - operation->setID(id); - operation->setPos(pos); - return operation; - } - - void checkOperation(WhiteboardOperation::ref operation, std::string id, std::string parent, int pos = -1, WhiteboardElement::ref element = WhiteboardElement::ref()) { - CPPUNIT_ASSERT_EQUAL(id, operation->getID()); - CPPUNIT_ASSERT_EQUAL(parent, operation->getParentID()); - if (pos != -1) { - CPPUNIT_ASSERT_EQUAL(pos, operation->getPos()); - } - - if (element) { - WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(operation); - if (insertOp) { - CPPUNIT_ASSERT_EQUAL(element, insertOp->getElement()); - } - - WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast<WhiteboardUpdateOperation>(operation); - if (updateOp) { - CPPUNIT_ASSERT_EQUAL(element, updateOp->getElement()); - } - } - } + /*! + * /\ + * \/ + * \ + */ + void testSynchronize_simplestSync() { + WhiteboardClient client; + WhiteboardInsertOperation::ref serverOp; + serverOp = createInsertOperation("0", "", 0); + WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(serverOp, std::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives first local operation, because it's parented off "0" which exists + //in server history and client doesn't wait for any operation ack from server, + //so this operation could be send + WhiteboardInsertOperation::ref clientOp; + clientOp = createInsertOperation("a", "0", 1); + WhiteboardEllipseElement::ref aElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(aElement); + WhiteboardInsertOperation::ref result; + checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); + + //Client receives server operation parented off "0", which isn't last client operation + //so it have to be transformed against local operations and then transformed value can + //be returned to draw + serverOp = createInsertOperation("b", "0", 1); + WhiteboardEllipseElement::ref bElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverOp->setElement(bElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.client, "b", "a", 2, bElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives confirmation from the server about processed "a" operation, it had to + //be transformed against "b" on the server side to receive operation parented off "b". + //There aren't any waiting operations to send to server, this operation should return + //nothing + serverOp = createInsertOperation("a", "b", 1); + pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives local operation, it doesn't have to be transformed against anything + //but operation returned to send to the server should be parented off last server + //operation, which is "b" + clientOp = createInsertOperation("c", "b", 3); + WhiteboardEllipseElement::ref cElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(cElement); + checkOperation(client.handleLocalOperationReceived(clientOp), "c", "a", 3, cElement); + + //Client receives confirmation from the server about processed "a" operation, it + //should be the same operation as it was sent because server didn't have to + //transform it + clientOp = createInsertOperation("c", "a", 3); + clientOp->setElement(cElement); + pairResult = client.handleServerOperationReceived(clientOp); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Results: + //Client operations: + //ID pos + //0 0 + //a 1 + //b 2 + //c 3 + // + //Server operations: + //ID pos + //0 0 + //b 1 + //a 1 + //c 3 + // + //what gives 0abc on both sides + } + + /*! + * / + * / + * \ + */ + void testSynchronize_withoutTranslation() { + WhiteboardClient client; + WhiteboardInsertOperation::ref serverOp; + serverOp = createInsertOperation("0", "", 0); + WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(serverOp, std::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives first local operation, because it's parented off "0" which exists + //in server history and client doesn't wait for any operation ack from server, + //so this operation could be send + WhiteboardInsertOperation::ref clientOp = createInsertOperation("c", "0", 1); + WhiteboardEllipseElement::ref cElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(cElement); + checkOperation(client.handleLocalOperationReceived(clientOp), "c", "0", 1, cElement); + + //Client receives second local operation, client didn't receive ack about previous + //operation from the server so it can't be send. + clientOp = createInsertOperation("d", "c", 2); + WhiteboardEllipseElement::ref dElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(dElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); + + //Client receives confirmation about processing "c" operation, it should be the + //same as sent operation because it wasn't transformed, client could send now + //operation "d" + clientOp = createInsertOperation("c", "0", 1); + clientOp->setElement(cElement); + pairResult = client.handleServerOperationReceived(clientOp); + checkOperation(pairResult.server, "d", "c", 2, dElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + + //Client receives confirmation about processing "d", it should be the same as + //sent operation. There aren't any operations in queue to send. + clientOp = createInsertOperation("d", "c", 2); + clientOp->setElement(dElement); + pairResult = client.handleServerOperationReceived(clientOp); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives new operation from server, it's parented off "d" which is at + //the end of local history so it doesn't have to be transformed, so operation + //to pass to window should be the same + serverOp = createInsertOperation("e", "d", 3); + WhiteboardEllipseElement::ref eElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverOp->setElement(eElement); + pairResult = client.handleServerOperationReceived(serverOp); + WhiteboardInsertOperation::ref result = std::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client); + CPPUNIT_ASSERT_EQUAL(serverOp, std::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + + //Client operations: + //ID pos + //0 0 + //c 1 + //d 2 + //e 3 + // + //Server operations: + //ID pos + //0 0 + //c 1 + //d 2 + //e 3 + } + + /*! + * /\ + * / \ + * \ / + * \/ + */ + void testSynchronize_nonInterrupted() { + WhiteboardClient client; + WhiteboardInsertOperation::ref serverOp; + serverOp = createInsertOperation("0", "", 0); + WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(serverOp, std::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives first local operation, because it's parented off "0" which exists + //in server history and client doesn't wait for any operation ack from server, + //so this operation could be send + WhiteboardInsertOperation::ref clientOp; + clientOp = createInsertOperation("a", "0", 1); + WhiteboardEllipseElement::ref aElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(aElement); + checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); + + //Client receives second local operation, client didn't receive ack about previous + //operation from the server so it can't be send. + clientOp = createInsertOperation("b", "a", 2); + WhiteboardEllipseElement::ref bElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(bElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); + + //Client receives new operation from server, it should be transformed against + //"a" and "b" before adding to local operations history because it's parented off "0". + //Because client is waiting for ack of "a", there is no operation to send to server + serverOp = createInsertOperation("c", "0", 1); + WhiteboardEllipseElement::ref cElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverOp->setElement(cElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.client, "c", "b", 3, cElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives new operation from server, it should be transformed against + //results of previous transformations, returned operation should be parented off + //"c" existing in local history. + //Because client is waiting for ack of "a", there is no operation to send to server + serverOp = createInsertOperation("d", "c", 2); + WhiteboardEllipseElement::ref dElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverOp->setElement(dElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.client, "d", "c", 4, dElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives confirmation about processing "a", it should send next operation + //to server which is "b", but it should be version parented of transformed "a" + serverOp = createInsertOperation("a", "d", 1); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.server, "b", "a", 2, bElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + + + //Client receives confirmation about processing "b", there aren't any operations + //waiting so it should return nothing. + serverOp = createInsertOperation("b", "a", 2); + pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client operations: + //ID pos + //0 0 + //a 1 + //b 2 + //c 3 + //d 4 + // + //Server operations: + //ID pos + //0 0 + //c 1 + //d 2 + //a 1 + //b 2 + // + //what gives 0abcd on both sides. + } + + /*! + * /\ + * / \ + * \ / + * / / + * \/ + */ + void testSynchronize_clientInterruption() { + WhiteboardClient client; + WhiteboardInsertOperation::ref serverOp; + serverOp = createInsertOperation("0", "", 0); + WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(serverOp, std::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives first local operation, because it's parented off "0" which exists + //in server history and client doesn't wait for any operation ack from server, + //so this operation could be send + WhiteboardInsertOperation::ref clientOp; + clientOp = createInsertOperation("a", "0", 1); + WhiteboardEllipseElement::ref aElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(aElement); + checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); + + //Client receives second local operation, client didn't receive ack about previous + //operation from the server so it can't be send. + clientOp = createInsertOperation("b", "a", 2); + WhiteboardEllipseElement::ref bElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(bElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); + + //Client receives new operation from server, it should be transformed against + //"a" and "b" before adding to local operations history because it's parented off "0". + //Because client is waiting for ack of "a", there is no operation to send to server + serverOp = createInsertOperation("c", "0", 1); + WhiteboardEllipseElement::ref cElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverOp->setElement(cElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.client, "c", "b", 3, cElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives new local operation, client is still waiting for ack so, it + //should return nothing + clientOp = createInsertOperation("e", "a", 4); + WhiteboardEllipseElement::ref eElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(eElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); + + //Client receives new server operation, to add it to local history it should be transformed + //against result of previous transformations and operation "e", returned operation should + //be parented off "e", which was last local operation + serverOp = createInsertOperation("d", "c", 2); + WhiteboardEllipseElement::ref dElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverOp->setElement(dElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.client, "d", "e", 5, dElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives confirmation about processing "a", it had to be transformed against + //"c" and "d" and it is now parented off "d", returned value should be next operation + //which have to be send to server("b" parented off server version of "a"). + serverOp = createInsertOperation("a", "d", 1); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.server, "b", "a", 2, bElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + + //Client receives confirmation about processing "b", it is the same operation as sent because + //it didn't have to be transformed, returned value should be next operation + //which have to be send to server("e" parented off server version of "b"). + serverOp = createInsertOperation("b", "a", 2); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.server, "e", "b", 4, eElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + + //Client receives confirmation about processing "b", it is the same operation as sent because + //it didn't have to be transformed, there aren't any operations to send so this function returns + //nothing + serverOp = createInsertOperation("e", "b", 4); + pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Result: + //Client operations: + //ID pos + //0 0 + //a 1 + //b 2 + //c 3 + //e 4 + //d 5 + // + //Server operations: + //0 0 + //c 1 + //d 2 + //a 1 + //b 2 + //e 4 + //what gives 0abced on both sides + } + + /*! + * /\ + * / / + * \ \ + * \/ + */ + void testSynchronize_serverInterruption() { + WhiteboardClient client; + WhiteboardInsertOperation::ref serverOp; + serverOp = createInsertOperation("0", "", 0); + WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(serverOp, std::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives first local operation, because it's parented off "0" which exists + //in server history and client doesn't wait for any operation ack from server, + //so this operation could be send + WhiteboardInsertOperation::ref clientOp; + clientOp = createInsertOperation("a", "0", 1); + WhiteboardEllipseElement::ref aElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(aElement); + checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); + + //Client receives second local operation, client didn't receive ack about previous + //operation from the server so it can't be send. + clientOp = createInsertOperation("b", "a", 2); + WhiteboardEllipseElement::ref bElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(bElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); + + //Client receives new operation from server, it should be transformed against + //"a" and "b" before adding to local operations history because it's parented off "0". + //Because client is waiting for ack of "a", there is no operation to send to server + serverOp = createInsertOperation("c", "0", 1); + WhiteboardEllipseElement::ref cElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverOp->setElement(cElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.client, "c", "b", 3, cElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives confirmation about processing "a", it had to be transformed against + //"c" and it is now parented off "c", returned value should be next operation + //which have to be send to server("b" parented off server version of "a"). + serverOp = createInsertOperation("a", "c", 1); + serverOp->setElement(aElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.server, "b", "a", 2, bElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + + //Client receives new server operation, to add it to local history it should be transformed + //against result of previous transformation(but only with transformation of "b"), returned + //operation should be parented off "c", which was last local operation + serverOp = createInsertOperation("d", "a", 3); + WhiteboardEllipseElement::ref dElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverOp->setElement(dElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.client, "d", "c", 4, dElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives confirmation about processing "b", it had to be transformed against + //"d" because both operations was parented off server version of "a". + //there aren't any operations to send so this function returns nothing. + serverOp = createInsertOperation("b", "d", 2); + serverOp->setElement(bElement); + pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client operations: + //ID pos + //0 0 + //a 1 + //b 2 + //c 3 + //d 4 + // + //Server operations: + //ID pos + //0 0 + //c 1 + //a 1 + //d 3 + //b 2 + // + //what gives 0abcd on both sides + + } + + /*! + * /\ + * / \ + * \ / + * \/ + */ + void testSynchronize_nonInterruptedMixOperations() { + WhiteboardClient client; + WhiteboardInsertOperation::ref serverOp; + serverOp = createInsertOperation("0", "", 0); + WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(serverOp, std::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives first local operation, because it's parented off "0" which exists + //in server history and client doesn't wait for any operation ack from server, + //so this operation could be send + WhiteboardInsertOperation::ref clientOp; + clientOp = createInsertOperation("a", "0", 1); + WhiteboardEllipseElement::ref aElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setElement(aElement); + checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); + + //Client receives second local operation, client didn't receive ack about previous + //operation from the server so it can't be send. + WhiteboardUpdateOperation::ref clientUpdateOp = createUpdateOperation("b", "a", 0); + WhiteboardEllipseElement::ref bElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientUpdateOp->setElement(bElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientUpdateOp)); + + //Client receives new operation from server, it should be transformed against + //"a" and "b" before adding to local operations history because it's parented off "0". + //Because client is waiting for ack of "a", there is no operation to send to server + WhiteboardUpdateOperation::ref serverUpdateOp = createUpdateOperation("c", "0", 0); + WhiteboardEllipseElement::ref cElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverUpdateOp->setElement(cElement); + pairResult = client.handleServerOperationReceived(serverUpdateOp); + checkOperation(pairResult.client, "c", "b", 0, cElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives new operation from server, it should be transformed against + //results of previous transformations, returned operation should be parented off + //"c" existing in local history. + //Because client is waiting for ack of "a", there is no operation to send to server + serverOp = createInsertOperation("d", "c", 1); + WhiteboardEllipseElement::ref dElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverOp->setElement(dElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.client, "d", "c", 2, dElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives confirmation about processing "a", it should send next operation + //to server which is "b", but it should be version parented of transformed "a" + serverOp = createInsertOperation("a", "d", 1); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.server, "b", "a", 0, cElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + + + //Client receives confirmation about processing "b", there aren't any operations + //waiting so it should return nothing. + serverUpdateOp = createUpdateOperation("b", "a", 0); + pairResult = client.handleServerOperationReceived(serverUpdateOp); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client operations: + //ID pos + //0 0 + //a 1 + //b 2 + //c 3 + //d 4 + // + //Server operations: + //ID pos + //0 0 + //c 1 + //d 2 + //a 1 + //b 2 + // + //what gives 0abcd on both sides. + } + + /*! + * /\ + * / \ + * \ / + * \/ + */ + void testSynchronize_nonInterruptedMixOperations2() { + WhiteboardClient client; + WhiteboardInsertOperation::ref serverOp; + serverOp = createInsertOperation("0", "", 0); + WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(serverOp, std::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + serverOp = createInsertOperation("1", "0", 1); + pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(serverOp, std::dynamic_pointer_cast<WhiteboardInsertOperation>(pairResult.client)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + //Client receives first local operation, because it's parented off "0" which exists + //in server history and client doesn't wait for any operation ack from server, + //so this operation could be send + WhiteboardInsertOperation::ref clientOp; + WhiteboardUpdateOperation::ref clientUpdateOp; + WhiteboardDeleteOperation::ref clientDeleteOp; + clientUpdateOp = createUpdateOperation("a", "1", 0); + WhiteboardEllipseElement::ref aElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientUpdateOp->setElement(aElement); + checkOperation(client.handleLocalOperationReceived(clientUpdateOp), "a", "1", 0, aElement); + + //Client receives second local operation, client didn't receive ack about previous + //operation from the server so it can't be send. + clientDeleteOp = createDeleteOperation("b", "a", 1); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientDeleteOp)); + + //Client receives new operation from server, it should be transformed against + //"a" and "b" before adding to local operations history because it's parented off "0". + //Because client is waiting for ack of "a", there is no operation to send to server + serverOp = createInsertOperation("c", "1", 2); + WhiteboardEllipseElement::ref cElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverOp->setElement(cElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.client, "c", "b", 1, cElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives new operation from server, it should be transformed against + //results of previous transformations, returned operation should be parented off + //"c" existing in local history. + //Because client is waiting for ack of "a", there is no operation to send to server + WhiteboardUpdateOperation::ref serverUpdateOp = createUpdateOperation("d", "c", 0); + WhiteboardEllipseElement::ref dElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + serverUpdateOp->setElement(dElement); + pairResult = client.handleServerOperationReceived(serverUpdateOp); + checkOperation(pairResult.client, "d", "c", 0, dElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives confirmation about processing "a", it should send next operation + //to server which is "b", but it should be version parented of transformed "a" + serverUpdateOp = createUpdateOperation("a", "d", 0); + pairResult = client.handleServerOperationReceived(serverUpdateOp); + checkOperation(pairResult.server, "b", "a", 1); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + + + //Client receives confirmation about processing "b", there aren't any operations + //waiting so it should return nothing. + WhiteboardDeleteOperation::ref serverDeleteOp = createDeleteOperation("b", "a", 0); + pairResult = client.handleServerOperationReceived(serverDeleteOp); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client operations: + //ID pos + //0 0 + //a 1 + //b 2 + //c 3 + //d 4 + // + //Server operations: + //ID pos + //0 0 + //c 1 + //d 2 + //a 1 + //b 2 + // + //what gives 0abcd on both sides. + } + + + WhiteboardInsertOperation::ref createInsertOperation(std::string id, std::string parent, int pos) { + WhiteboardInsertOperation::ref operation = std::make_shared<WhiteboardInsertOperation>(); + operation->setParentID(parent); + operation->setID(id); + operation->setPos(pos); + return operation; + } + + WhiteboardUpdateOperation::ref createUpdateOperation(std::string id, std::string parent, int pos) { + WhiteboardUpdateOperation::ref operation = std::make_shared<WhiteboardUpdateOperation>(); + operation->setParentID(parent); + operation->setID(id); + operation->setPos(pos); + return operation; + } + + WhiteboardDeleteOperation::ref createDeleteOperation(std::string id, std::string parent, int pos) { + WhiteboardDeleteOperation::ref operation = std::make_shared<WhiteboardDeleteOperation>(); + operation->setParentID(parent); + operation->setID(id); + operation->setPos(pos); + return operation; + } + + void checkOperation(WhiteboardOperation::ref operation, std::string id, std::string parent, int pos = -1, WhiteboardElement::ref element = WhiteboardElement::ref()) { + CPPUNIT_ASSERT_EQUAL(id, operation->getID()); + CPPUNIT_ASSERT_EQUAL(parent, operation->getParentID()); + if (pos != -1) { + CPPUNIT_ASSERT_EQUAL(pos, operation->getPos()); + } + + if (element) { + WhiteboardInsertOperation::ref insertOp = std::dynamic_pointer_cast<WhiteboardInsertOperation>(operation); + if (insertOp) { + CPPUNIT_ASSERT_EQUAL(element, insertOp->getElement()); + } + + WhiteboardUpdateOperation::ref updateOp = std::dynamic_pointer_cast<WhiteboardUpdateOperation>(operation); + if (updateOp) { + CPPUNIT_ASSERT_EQUAL(element, updateOp->getElement()); + } + } + } }; CPPUNIT_TEST_SUITE_REGISTRATION(WhiteboardClientTest); diff --git a/Swiften/Whiteboard/UnitTest/WhiteboardServerTest.cpp b/Swiften/Whiteboard/UnitTest/WhiteboardServerTest.cpp index a7b9acc..e868968 100644 --- a/Swiften/Whiteboard/UnitTest/WhiteboardServerTest.cpp +++ b/Swiften/Whiteboard/UnitTest/WhiteboardServerTest.cpp @@ -4,125 +4,132 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + + +#include <memory> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Whiteboard/WhiteboardServer.h> -#include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> -#include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> +#include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h> +#include <Swiften/Whiteboard/WhiteboardServer.h> using namespace Swift; class WhiteboardServerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(WhiteboardServerTest); - CPPUNIT_TEST(testSimpleOp); - CPPUNIT_TEST(testSimpleOp1); - CPPUNIT_TEST(testSimpleOp2); - CPPUNIT_TEST(testFewSimpleOps); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(WhiteboardServerTest); + CPPUNIT_TEST(testSimpleOp); + CPPUNIT_TEST(testSimpleOp1); + CPPUNIT_TEST(testSimpleOp2); + CPPUNIT_TEST(testFewSimpleOps); + CPPUNIT_TEST_SUITE_END(); public: - void testSimpleOp() { - WhiteboardServer server; - WhiteboardInsertOperation::ref firstOp = boost::make_shared<WhiteboardInsertOperation>(); - firstOp->setID("0"); - server.handleLocalOperationReceived(firstOp); - WhiteboardInsertOperation::ref serverOp = boost::make_shared<WhiteboardInsertOperation>(); - serverOp->setID("b"); - serverOp->setParentID("0"); - serverOp->setPos(1); - server.handleLocalOperationReceived(serverOp); - WhiteboardInsertOperation::ref clientOp = boost::make_shared<WhiteboardInsertOperation>(); - WhiteboardEllipseElement::ref clientElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setID("a"); - clientOp->setParentID("0"); - clientOp->setPos(1); - clientOp->setElement(clientElement); - WhiteboardInsertOperation::ref op = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(server.handleClientOperationReceived(clientOp)); - CPPUNIT_ASSERT_EQUAL(std::string("b"), op->getParentID()); - CPPUNIT_ASSERT_EQUAL(std::string("a"), op->getID()); - CPPUNIT_ASSERT_EQUAL(1, op->getPos()); - CPPUNIT_ASSERT_EQUAL(clientElement, boost::dynamic_pointer_cast<WhiteboardEllipseElement>(op->getElement())); - } + void testSimpleOp() { + WhiteboardServer server; + WhiteboardInsertOperation::ref firstOp = std::make_shared<WhiteboardInsertOperation>(); + firstOp->setID("0"); + server.handleLocalOperationReceived(firstOp); + WhiteboardInsertOperation::ref serverOp = std::make_shared<WhiteboardInsertOperation>(); + serverOp->setID("b"); + serverOp->setParentID("0"); + serverOp->setPos(1); + server.handleLocalOperationReceived(serverOp); + WhiteboardInsertOperation::ref clientOp = std::make_shared<WhiteboardInsertOperation>(); + WhiteboardEllipseElement::ref clientElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setID("a"); + clientOp->setParentID("0"); + clientOp->setPos(1); + clientOp->setElement(clientElement); + WhiteboardInsertOperation::ref op = std::dynamic_pointer_cast<WhiteboardInsertOperation>(server.handleClientOperationReceived(clientOp)); + CPPUNIT_ASSERT_EQUAL(std::string("b"), op->getParentID()); + CPPUNIT_ASSERT_EQUAL(std::string("a"), op->getID()); + CPPUNIT_ASSERT_EQUAL(1, op->getPos()); + CPPUNIT_ASSERT_EQUAL(clientElement, std::dynamic_pointer_cast<WhiteboardEllipseElement>(op->getElement())); + } - void testSimpleOp1() { - WhiteboardServer server; - WhiteboardInsertOperation::ref firstOp = boost::make_shared<WhiteboardInsertOperation>(); - firstOp->setID("0"); - server.handleLocalOperationReceived(firstOp); - WhiteboardDeleteOperation::ref serverOp = boost::make_shared<WhiteboardDeleteOperation>(); - serverOp->setID("b"); - serverOp->setParentID("0"); - serverOp->setPos(1); - server.handleLocalOperationReceived(serverOp); - WhiteboardUpdateOperation::ref clientOp = boost::make_shared<WhiteboardUpdateOperation>(); - WhiteboardEllipseElement::ref clientElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setID("a"); - clientOp->setParentID("0"); - clientOp->setPos(1); - clientOp->setElement(clientElement); - WhiteboardDeleteOperation::ref op = boost::dynamic_pointer_cast<WhiteboardDeleteOperation>(server.handleClientOperationReceived(clientOp)); - CPPUNIT_ASSERT_EQUAL(std::string("b"), op->getParentID()); - CPPUNIT_ASSERT_EQUAL(std::string("a"), op->getID()); - CPPUNIT_ASSERT_EQUAL(-1, op->getPos()); - } + void testSimpleOp1() { + WhiteboardServer server; + WhiteboardInsertOperation::ref firstOp = std::make_shared<WhiteboardInsertOperation>(); + firstOp->setID("0"); + server.handleLocalOperationReceived(firstOp); + WhiteboardDeleteOperation::ref serverOp = std::make_shared<WhiteboardDeleteOperation>(); + serverOp->setID("b"); + serverOp->setParentID("0"); + serverOp->setPos(1); + server.handleLocalOperationReceived(serverOp); + WhiteboardUpdateOperation::ref clientOp = std::make_shared<WhiteboardUpdateOperation>(); + WhiteboardEllipseElement::ref clientElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setID("a"); + clientOp->setParentID("0"); + clientOp->setPos(1); + clientOp->setElement(clientElement); + WhiteboardDeleteOperation::ref op = std::dynamic_pointer_cast<WhiteboardDeleteOperation>(server.handleClientOperationReceived(clientOp)); + CPPUNIT_ASSERT_EQUAL(std::string("b"), op->getParentID()); + CPPUNIT_ASSERT_EQUAL(std::string("a"), op->getID()); + CPPUNIT_ASSERT_EQUAL(-1, op->getPos()); + } - void testSimpleOp2() { - WhiteboardServer server; - WhiteboardInsertOperation::ref firstOp = boost::make_shared<WhiteboardInsertOperation>(); - firstOp->setID("0"); - server.handleLocalOperationReceived(firstOp); - WhiteboardUpdateOperation::ref serverOp = boost::make_shared<WhiteboardUpdateOperation>(); - serverOp->setID("b"); - serverOp->setParentID("0"); - serverOp->setPos(1); - server.handleLocalOperationReceived(serverOp); - WhiteboardDeleteOperation::ref clientOp = boost::make_shared<WhiteboardDeleteOperation>(); - clientOp->setID("a"); - clientOp->setParentID("0"); - clientOp->setPos(1); - WhiteboardDeleteOperation::ref op = boost::dynamic_pointer_cast<WhiteboardDeleteOperation>(server.handleClientOperationReceived(clientOp)); - CPPUNIT_ASSERT_EQUAL(std::string("b"), op->getParentID()); - CPPUNIT_ASSERT_EQUAL(std::string("a"), op->getID()); - CPPUNIT_ASSERT_EQUAL(1, op->getPos()); - } + void testSimpleOp2() { + WhiteboardServer server; + WhiteboardInsertOperation::ref firstOp = std::make_shared<WhiteboardInsertOperation>(); + firstOp->setID("0"); + server.handleLocalOperationReceived(firstOp); + WhiteboardUpdateOperation::ref serverOp = std::make_shared<WhiteboardUpdateOperation>(); + serverOp->setID("b"); + serverOp->setParentID("0"); + serverOp->setPos(1); + server.handleLocalOperationReceived(serverOp); + WhiteboardDeleteOperation::ref clientOp = std::make_shared<WhiteboardDeleteOperation>(); + clientOp->setID("a"); + clientOp->setParentID("0"); + clientOp->setPos(1); + WhiteboardDeleteOperation::ref op = std::dynamic_pointer_cast<WhiteboardDeleteOperation>(server.handleClientOperationReceived(clientOp)); + CPPUNIT_ASSERT_EQUAL(std::string("b"), op->getParentID()); + CPPUNIT_ASSERT_EQUAL(std::string("a"), op->getID()); + CPPUNIT_ASSERT_EQUAL(1, op->getPos()); + } - void testFewSimpleOps() { - WhiteboardServer server; - WhiteboardInsertOperation::ref firstOp = boost::make_shared<WhiteboardInsertOperation>(); - firstOp->setID("0"); - server.handleLocalOperationReceived(firstOp); - WhiteboardInsertOperation::ref serverOp = boost::make_shared<WhiteboardInsertOperation>(); - serverOp->setID("a"); - serverOp->setParentID("0"); - serverOp->setPos(1); - server.handleLocalOperationReceived(serverOp); - serverOp = boost::make_shared<WhiteboardInsertOperation>(); - serverOp->setID("b"); - serverOp->setParentID("a"); - serverOp->setPos(2); - server.handleLocalOperationReceived(serverOp); - serverOp = boost::make_shared<WhiteboardInsertOperation>(); - serverOp->setID("c"); - serverOp->setParentID("b"); - serverOp->setPos(3); - server.handleLocalOperationReceived(serverOp); - WhiteboardInsertOperation::ref clientOp = boost::make_shared<WhiteboardInsertOperation>(); - WhiteboardEllipseElement::ref clientElement = boost::make_shared<WhiteboardEllipseElement>(0,0,0,0); - clientOp->setID("d"); - clientOp->setParentID("0"); - clientOp->setPos(1); - clientOp->setElement(clientElement); - WhiteboardInsertOperation::ref op = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(server.handleClientOperationReceived(clientOp)); - CPPUNIT_ASSERT_EQUAL(std::string("c"), op->getParentID()); - CPPUNIT_ASSERT_EQUAL(std::string("d"), op->getID()); - CPPUNIT_ASSERT_EQUAL(1, op->getPos()); - CPPUNIT_ASSERT_EQUAL(clientElement, boost::dynamic_pointer_cast<WhiteboardEllipseElement>(op->getElement())); - } + void testFewSimpleOps() { + WhiteboardServer server; + WhiteboardInsertOperation::ref firstOp = std::make_shared<WhiteboardInsertOperation>(); + firstOp->setID("0"); + server.handleLocalOperationReceived(firstOp); + WhiteboardInsertOperation::ref serverOp = std::make_shared<WhiteboardInsertOperation>(); + serverOp->setID("a"); + serverOp->setParentID("0"); + serverOp->setPos(1); + server.handleLocalOperationReceived(serverOp); + serverOp = std::make_shared<WhiteboardInsertOperation>(); + serverOp->setID("b"); + serverOp->setParentID("a"); + serverOp->setPos(2); + server.handleLocalOperationReceived(serverOp); + serverOp = std::make_shared<WhiteboardInsertOperation>(); + serverOp->setID("c"); + serverOp->setParentID("b"); + serverOp->setPos(3); + server.handleLocalOperationReceived(serverOp); + WhiteboardInsertOperation::ref clientOp = std::make_shared<WhiteboardInsertOperation>(); + WhiteboardEllipseElement::ref clientElement = std::make_shared<WhiteboardEllipseElement>(0,0,0,0); + clientOp->setID("d"); + clientOp->setParentID("0"); + clientOp->setPos(1); + clientOp->setElement(clientElement); + WhiteboardInsertOperation::ref op = std::dynamic_pointer_cast<WhiteboardInsertOperation>(server.handleClientOperationReceived(clientOp)); + CPPUNIT_ASSERT_EQUAL(std::string("c"), op->getParentID()); + CPPUNIT_ASSERT_EQUAL(std::string("d"), op->getID()); + CPPUNIT_ASSERT_EQUAL(1, op->getPos()); + CPPUNIT_ASSERT_EQUAL(clientElement, std::dynamic_pointer_cast<WhiteboardEllipseElement>(op->getElement())); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(WhiteboardServerTest); diff --git a/Swiften/Whiteboard/WhiteboardClient.cpp b/Swiften/Whiteboard/WhiteboardClient.cpp index c17b9f9..d7ed3ad 100644 --- a/Swiften/Whiteboard/WhiteboardClient.cpp +++ b/Swiften/Whiteboard/WhiteboardClient.cpp @@ -4,118 +4,126 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Whiteboard/WhiteboardClient.h> -#include <Swiften/Whiteboard/WhiteboardTransformer.h> -#include <boost/smart_ptr/make_shared.hpp> + #include <iostream> +#include <memory> + +#include <Swiften/Whiteboard/WhiteboardTransformer.h> namespace Swift { - WhiteboardOperation::ref WhiteboardClient::handleLocalOperationReceived(WhiteboardOperation::ref operation) { - localOperations_.push_back(operation); - - WhiteboardOperation::ref op; - WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(operation); - if (insertOp) { - op = boost::make_shared<WhiteboardInsertOperation>(*insertOp); - } - WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast<WhiteboardUpdateOperation>(operation); - if (updateOp) { - op = boost::make_shared<WhiteboardUpdateOperation>(*updateOp); - } - WhiteboardDeleteOperation::ref deleteOp = boost::dynamic_pointer_cast<WhiteboardDeleteOperation>(operation); - if (deleteOp) { - op = boost::make_shared<WhiteboardDeleteOperation>(*deleteOp); - } - - if (!bridge_.empty()) { - op->setParentID(bridge_.back()->getID()); - } - bridge_.push_back(op); - - if (lastSentOperationID_.empty()) - { - WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(operation); - if (insertOp) { - op = boost::make_shared<WhiteboardInsertOperation>(*insertOp); - } - WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast<WhiteboardUpdateOperation>(operation); - if (updateOp) { - op = boost::make_shared<WhiteboardUpdateOperation>(*updateOp); - } - WhiteboardDeleteOperation::ref deleteOp = boost::dynamic_pointer_cast<WhiteboardDeleteOperation>(operation); - if (deleteOp) { - op = boost::make_shared<WhiteboardDeleteOperation>(*deleteOp); - } - - - if (!serverOperations_.empty()) { - op->setParentID(serverOperations_.back()->getID()); - } - lastSentOperationID_ = operation->getID(); - return op; - } else { - return WhiteboardOperation::ref(); - } - } - - WhiteboardClient::Result WhiteboardClient::handleServerOperationReceived(WhiteboardOperation::ref operation) { - serverOperations_.push_back(operation); - Result result; -// if (localOperations_.empty()) {// || localOperations_.back()->getID() == operation->getParentID()) { - //Situation where client and server are in sync - if (localOperations_.size() == serverOperations_.size()-1) { - localOperations_.push_back(operation); -// clientOp = operation; - result.client = operation; - } else if (lastSentOperationID_ == operation->getID()) { - //Client received confirmation about own operation and it sends next operation to server - if (!bridge_.empty() && lastSentOperationID_ == bridge_.front()->getID()) { - bridge_.erase(bridge_.begin()); - } - - if (!bridge_.empty() && (bridge_.front())->getParentID() == lastSentOperationID_) { - lastSentOperationID_ = (bridge_.front())->getID(); - result.server = bridge_.front(); - } - if (!result.server) { - lastSentOperationID_.clear(); - } - } else { - std::list<WhiteboardOperation::ref>::iterator it = bridge_.begin(); - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> opPair; - WhiteboardOperation::ref temp; - opPair = WhiteboardTransformer::transform(*it, operation); - temp = opPair.first; - - *it = opPair.second; - std::string previousID = (*it)->getID(); - ++it; - for (; it != bridge_.end(); ++it) { - opPair = WhiteboardTransformer::transform(*it, temp); - temp = opPair.first; - *it = opPair.second; - (*it)->setParentID(previousID); - previousID = (*it)->getID(); - } - - temp->setParentID(localOperations_.back()->getID()); - localOperations_.push_back(temp); - result.client = temp; - } - - return result; - } - - void WhiteboardClient::print() { - std::list<WhiteboardOperation::ref>::iterator it; - std::cout << "Client" << std::endl; - for(it = localOperations_.begin(); it != localOperations_.end(); ++it) { - std::cout << (*it)->getID() << " " << (*it)->getPos() << std::endl; - } - - std::cout << "Server" << std::endl; - for(it = serverOperations_.begin(); it != serverOperations_.end(); ++it) { - std::cout << (*it)->getID() << " " << (*it)->getPos() << std::endl; - } - } + WhiteboardOperation::ref WhiteboardClient::handleLocalOperationReceived(WhiteboardOperation::ref operation) { + localOperations_.push_back(operation); + + WhiteboardOperation::ref op; + WhiteboardInsertOperation::ref insertOp = std::dynamic_pointer_cast<WhiteboardInsertOperation>(operation); + if (insertOp) { + op = std::make_shared<WhiteboardInsertOperation>(*insertOp); + } + WhiteboardUpdateOperation::ref updateOp = std::dynamic_pointer_cast<WhiteboardUpdateOperation>(operation); + if (updateOp) { + op = std::make_shared<WhiteboardUpdateOperation>(*updateOp); + } + WhiteboardDeleteOperation::ref deleteOp = std::dynamic_pointer_cast<WhiteboardDeleteOperation>(operation); + if (deleteOp) { + op = std::make_shared<WhiteboardDeleteOperation>(*deleteOp); + } + + if (!bridge_.empty()) { + op->setParentID(bridge_.back()->getID()); + } + bridge_.push_back(op); + + if (lastSentOperationID_.empty()) + { + WhiteboardInsertOperation::ref insertOp = std::dynamic_pointer_cast<WhiteboardInsertOperation>(operation); + if (insertOp) { + op = std::make_shared<WhiteboardInsertOperation>(*insertOp); + } + WhiteboardUpdateOperation::ref updateOp = std::dynamic_pointer_cast<WhiteboardUpdateOperation>(operation); + if (updateOp) { + op = std::make_shared<WhiteboardUpdateOperation>(*updateOp); + } + WhiteboardDeleteOperation::ref deleteOp = std::dynamic_pointer_cast<WhiteboardDeleteOperation>(operation); + if (deleteOp) { + op = std::make_shared<WhiteboardDeleteOperation>(*deleteOp); + } + + + if (!serverOperations_.empty()) { + op->setParentID(serverOperations_.back()->getID()); + } + lastSentOperationID_ = operation->getID(); + return op; + } else { + return WhiteboardOperation::ref(); + } + } + + WhiteboardClient::Result WhiteboardClient::handleServerOperationReceived(WhiteboardOperation::ref operation) { + serverOperations_.push_back(operation); + Result result; +// if (localOperations_.empty()) {// || localOperations_.back()->getID() == operation->getParentID()) { + //Situation where client and server are in sync + if (localOperations_.size() == serverOperations_.size()-1) { + localOperations_.push_back(operation); +// clientOp = operation; + result.client = operation; + } else if (lastSentOperationID_ == operation->getID()) { + //Client received confirmation about own operation and it sends next operation to server + if (!bridge_.empty() && lastSentOperationID_ == bridge_.front()->getID()) { + bridge_.erase(bridge_.begin()); + } + + if (!bridge_.empty() && (bridge_.front())->getParentID() == lastSentOperationID_) { + lastSentOperationID_ = (bridge_.front())->getID(); + result.server = bridge_.front(); + } + if (!result.server) { + lastSentOperationID_.clear(); + } + } else { + std::list<WhiteboardOperation::ref>::iterator it = bridge_.begin(); + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> opPair; + WhiteboardOperation::ref temp; + opPair = WhiteboardTransformer::transform(*it, operation); + temp = opPair.first; + + *it = opPair.second; + std::string previousID = (*it)->getID(); + ++it; + for (; it != bridge_.end(); ++it) { + opPair = WhiteboardTransformer::transform(*it, temp); + temp = opPair.first; + *it = opPair.second; + (*it)->setParentID(previousID); + previousID = (*it)->getID(); + } + + temp->setParentID(localOperations_.back()->getID()); + localOperations_.push_back(temp); + result.client = temp; + } + + return result; + } + + void WhiteboardClient::print() { + std::list<WhiteboardOperation::ref>::iterator it; + std::cout << "Client" << std::endl; + for(it = localOperations_.begin(); it != localOperations_.end(); ++it) { + std::cout << (*it)->getID() << " " << (*it)->getPos() << std::endl; + } + + std::cout << "Server" << std::endl; + for(it = serverOperations_.begin(); it != serverOperations_.end(); ++it) { + std::cout << (*it)->getID() << " " << (*it)->getPos() << std::endl; + } + } } diff --git a/Swiften/Whiteboard/WhiteboardClient.h b/Swiften/Whiteboard/WhiteboardClient.h index 2cc46a6..15870c6 100644 --- a/Swiften/Whiteboard/WhiteboardClient.h +++ b/Swiften/Whiteboard/WhiteboardClient.h @@ -4,34 +4,41 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Base/API.h> -#include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> #include <list> #include <utility> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> + namespace Swift { - class SWIFTEN_API WhiteboardClient { - public: - struct Result { - WhiteboardOperation::ref client; - WhiteboardOperation::ref server; - }; - /*! - * @return Operation to send - */ - WhiteboardOperation::ref handleLocalOperationReceived(WhiteboardOperation::ref operation); - /*! - * @return pair.first-element to handle locally, pair.second-element to send to server - */ - Result handleServerOperationReceived(WhiteboardOperation::ref operation); - void print(); + class SWIFTEN_API WhiteboardClient { + public: + struct Result { + WhiteboardOperation::ref client; + WhiteboardOperation::ref server; + }; + /*! + * @return Operation to send + */ + WhiteboardOperation::ref handleLocalOperationReceived(WhiteboardOperation::ref operation); + /*! + * @return pair.first-element to handle locally, pair.second-element to send to server + */ + Result handleServerOperationReceived(WhiteboardOperation::ref operation); + void print(); - private: - std::list<WhiteboardOperation::ref> localOperations_; - std::list<WhiteboardOperation::ref> serverOperations_; - std::list<WhiteboardOperation::ref> bridge_; - std::string lastSentOperationID_; - }; + private: + std::list<WhiteboardOperation::ref> localOperations_; + std::list<WhiteboardOperation::ref> serverOperations_; + std::list<WhiteboardOperation::ref> bridge_; + std::string lastSentOperationID_; + }; } diff --git a/Swiften/Whiteboard/WhiteboardResponder.cpp b/Swiften/Whiteboard/WhiteboardResponder.cpp index f72861f..f9df709 100644 --- a/Swiften/Whiteboard/WhiteboardResponder.cpp +++ b/Swiften/Whiteboard/WhiteboardResponder.cpp @@ -4,34 +4,41 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Whiteboard/WhiteboardResponder.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Whiteboard/WhiteboardSessionManager.h> +#include <memory> + +#include <Swiften/Queries/IQRouter.h> #include <Swiften/Whiteboard/IncomingWhiteboardSession.h> #include <Swiften/Whiteboard/WhiteboardSession.h> -#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Whiteboard/WhiteboardSessionManager.h> namespace Swift { - WhiteboardResponder::WhiteboardResponder(WhiteboardSessionManager* sessionManager, IQRouter* router) : SetResponder<WhiteboardPayload>(router), sessionManager_(sessionManager), router_(router) { - } + WhiteboardResponder::WhiteboardResponder(WhiteboardSessionManager* sessionManager, IQRouter* router) : SetResponder<WhiteboardPayload>(router), sessionManager_(sessionManager), router_(router) { + } - bool WhiteboardResponder::handleSetRequest(const JID& from, const JID& /*to*/, const std::string& id, boost::shared_ptr<WhiteboardPayload> payload) { - if (payload->getType() == WhiteboardPayload::SessionRequest) { - if (sessionManager_->getSession(from)) { - sendError(from, id, ErrorPayload::Conflict, ErrorPayload::Cancel); - } else { - sendResponse(from, id, boost::shared_ptr<WhiteboardPayload>()); - IncomingWhiteboardSession::ref session = boost::make_shared<IncomingWhiteboardSession>(from, router_); - sessionManager_->handleIncomingSession(session); - } - } else { - sendResponse(from, id, boost::shared_ptr<WhiteboardPayload>()); - WhiteboardSession::ref session = sessionManager_->getSession(from); - if (session != NULL) { - session->handleIncomingAction(payload); - } - } - return true; - } + bool WhiteboardResponder::handleSetRequest(const JID& from, const JID& /*to*/, const std::string& id, std::shared_ptr<WhiteboardPayload> payload) { + if (payload->getType() == WhiteboardPayload::SessionRequest) { + if (sessionManager_->getSession(from)) { + sendError(from, id, ErrorPayload::Conflict, ErrorPayload::Cancel); + } else { + sendResponse(from, id, std::shared_ptr<WhiteboardPayload>()); + IncomingWhiteboardSession::ref session = std::make_shared<IncomingWhiteboardSession>(from, router_); + sessionManager_->handleIncomingSession(session); + } + } else { + sendResponse(from, id, std::shared_ptr<WhiteboardPayload>()); + WhiteboardSession::ref session = sessionManager_->getSession(from); + if (session != nullptr) { + session->handleIncomingAction(payload); + } + } + return true; + } } diff --git a/Swiften/Whiteboard/WhiteboardResponder.h b/Swiften/Whiteboard/WhiteboardResponder.h index c05be23..ac44664 100644 --- a/Swiften/Whiteboard/WhiteboardResponder.h +++ b/Swiften/Whiteboard/WhiteboardResponder.h @@ -4,22 +4,29 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <Swiften/Queries/SetResponder.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/WhiteboardPayload.h> +#include <Swiften/Queries/SetResponder.h> namespace Swift { - class IQRouter; - class WhiteboardSessionManager; + class IQRouter; + class WhiteboardSessionManager; - class WhiteboardResponder : public SetResponder<WhiteboardPayload> { - public: - WhiteboardResponder(WhiteboardSessionManager* sessionManager, IQRouter* router); - bool handleSetRequest(const JID& from, const JID& /*to*/, const std::string& id, boost::shared_ptr<WhiteboardPayload> payload); + class SWIFTEN_API WhiteboardResponder : public SetResponder<WhiteboardPayload> { + public: + WhiteboardResponder(WhiteboardSessionManager* sessionManager, IQRouter* router); + bool handleSetRequest(const JID& from, const JID& /*to*/, const std::string& id, std::shared_ptr<WhiteboardPayload> payload); - private: - WhiteboardSessionManager* sessionManager_; - IQRouter* router_; - }; + private: + WhiteboardSessionManager* sessionManager_; + IQRouter* router_; + }; } diff --git a/Swiften/Whiteboard/WhiteboardServer.cpp b/Swiften/Whiteboard/WhiteboardServer.cpp index 94f8cff..4a2a315 100644 --- a/Swiften/Whiteboard/WhiteboardServer.cpp +++ b/Swiften/Whiteboard/WhiteboardServer.cpp @@ -4,46 +4,54 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Whiteboard/WhiteboardServer.h> -#include <Swiften/Whiteboard/WhiteboardTransformer.h> + #include <iostream> +#include <Swiften/Whiteboard/WhiteboardTransformer.h> + namespace Swift { - void WhiteboardServer::handleLocalOperationReceived(WhiteboardOperation::ref operation) { - operations_.push_back(operation); - } - - WhiteboardOperation::ref WhiteboardServer::handleClientOperationReceived(WhiteboardOperation::ref newOperation) { - std::list<WhiteboardOperation::ref>::reverse_iterator it; - if (operations_.empty() || newOperation->getParentID() == operations_.back()->getID()) { - operations_.push_back(newOperation); - return newOperation; - } - for (it = operations_.rbegin(); it != operations_.rend(); ++it) { - WhiteboardOperation::ref operation = *it; - while (newOperation->getParentID() == operation->getParentID()) { - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> tResult = WhiteboardTransformer::transform(newOperation, operation); - - if (it == operations_.rbegin()) { - operations_.push_back(tResult.second); - return tResult.second; - } else { - newOperation = tResult.second; - --it; - operation = *it; - } - - } - } - return WhiteboardOperation::ref(); - } - - void WhiteboardServer::print() { - std::list<WhiteboardOperation::ref>::iterator it; - std::cout << "Server:" << std::endl; - for(it = operations_.begin(); it != operations_.end(); ++it) { - std::cout << (*it)->getID() << " " << (*it)->getPos() << std::endl; - } - } + void WhiteboardServer::handleLocalOperationReceived(WhiteboardOperation::ref operation) { + operations_.push_back(operation); + } + + WhiteboardOperation::ref WhiteboardServer::handleClientOperationReceived(WhiteboardOperation::ref newOperation) { + std::list<WhiteboardOperation::ref>::reverse_iterator it; + if (operations_.empty() || newOperation->getParentID() == operations_.back()->getID()) { + operations_.push_back(newOperation); + return newOperation; + } + for (it = operations_.rbegin(); it != operations_.rend(); ++it) { + WhiteboardOperation::ref operation = *it; + while (newOperation->getParentID() == operation->getParentID()) { + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> tResult = WhiteboardTransformer::transform(newOperation, operation); + + if (it == operations_.rbegin()) { + operations_.push_back(tResult.second); + return tResult.second; + } else { + newOperation = tResult.second; + --it; + operation = *it; + } + + } + } + return WhiteboardOperation::ref(); + } + + void WhiteboardServer::print() { + std::list<WhiteboardOperation::ref>::iterator it; + std::cout << "Server:" << std::endl; + for(it = operations_.begin(); it != operations_.end(); ++it) { + std::cout << (*it)->getID() << " " << (*it)->getPos() << std::endl; + } + } } diff --git a/Swiften/Whiteboard/WhiteboardServer.h b/Swiften/Whiteboard/WhiteboardServer.h index 73e8d33..fcbdbe7 100644 --- a/Swiften/Whiteboard/WhiteboardServer.h +++ b/Swiften/Whiteboard/WhiteboardServer.h @@ -4,21 +4,27 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <list> + #include <Swiften/Base/API.h> #include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> -#include <list> - namespace Swift { - class SWIFTEN_API WhiteboardServer { - public: - void handleLocalOperationReceived(WhiteboardOperation::ref operation); - WhiteboardOperation::ref handleClientOperationReceived(WhiteboardOperation::ref operation); - void print(); + class SWIFTEN_API WhiteboardServer { + public: + void handleLocalOperationReceived(WhiteboardOperation::ref operation); + WhiteboardOperation::ref handleClientOperationReceived(WhiteboardOperation::ref operation); + void print(); - private: - std::list<WhiteboardOperation::ref> operations_; - }; + private: + std::list<WhiteboardOperation::ref> operations_; + }; } diff --git a/Swiften/Whiteboard/WhiteboardSession.cpp b/Swiften/Whiteboard/WhiteboardSession.cpp index cffcf07..c90475a 100644 --- a/Swiften/Whiteboard/WhiteboardSession.cpp +++ b/Swiften/Whiteboard/WhiteboardSession.cpp @@ -4,64 +4,69 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Whiteboard/WhiteboardSession.h> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/Elements/WhiteboardPayload.h> -#include <Swiften/Elements/ErrorPayload.h> +#include <memory> -#include <iostream> +#include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/WhiteboardPayload.h> +#include <Swiften/Queries/IQRouter.h> namespace Swift { - WhiteboardSession::WhiteboardSession(const JID& jid, IQRouter* router) : toJID_(jid), router_(router) { - } + WhiteboardSession::WhiteboardSession(const JID& jid, IQRouter* router) : toJID_(jid), router_(router) { + } - WhiteboardSession::~WhiteboardSession() { - } + WhiteboardSession::~WhiteboardSession() { + } - void WhiteboardSession::handleIncomingAction(boost::shared_ptr<WhiteboardPayload> payload) { - switch (payload->getType()) { - case WhiteboardPayload::Data: - handleIncomingOperation(payload->getOperation()); - return; - case WhiteboardPayload::SessionAccept: - onRequestAccepted(toJID_); - return; - case WhiteboardPayload::SessionTerminate: - onSessionTerminated(toJID_); - return; + void WhiteboardSession::handleIncomingAction(std::shared_ptr<WhiteboardPayload> payload) { + switch (payload->getType()) { + case WhiteboardPayload::Data: + handleIncomingOperation(payload->getOperation()); + return; + case WhiteboardPayload::SessionAccept: + onRequestAccepted(toJID_); + return; + case WhiteboardPayload::SessionTerminate: + onSessionTerminated(toJID_); + return; - //handled elsewhere - case WhiteboardPayload::SessionRequest: + //handled elsewhere + case WhiteboardPayload::SessionRequest: - case WhiteboardPayload::UnknownType: - return; - } - } + case WhiteboardPayload::UnknownType: + return; + } + } - void WhiteboardSession::sendElement(const WhiteboardElement::ref element) { - boost::shared_ptr<WhiteboardPayload> payload = boost::make_shared<WhiteboardPayload>(); - payload->setElement(element); - boost::shared_ptr<GenericRequest<WhiteboardPayload> > request = boost::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); - request->send(); - } + void WhiteboardSession::sendElement(const WhiteboardElement::ref element) { + std::shared_ptr<WhiteboardPayload> payload = std::make_shared<WhiteboardPayload>(); + payload->setElement(element); + std::shared_ptr<GenericRequest<WhiteboardPayload> > request = std::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); + request->send(); + } - void WhiteboardSession::sendPayload(boost::shared_ptr<WhiteboardPayload> payload) { - boost::shared_ptr<GenericRequest<WhiteboardPayload> > request = boost::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); - request->send(); - } + void WhiteboardSession::sendPayload(std::shared_ptr<WhiteboardPayload> payload) { + std::shared_ptr<GenericRequest<WhiteboardPayload> > request = std::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); + request->send(); + } - void WhiteboardSession::cancel() { - if (router_->isAvailable()) { - boost::shared_ptr<WhiteboardPayload> payload = boost::make_shared<WhiteboardPayload>(WhiteboardPayload::SessionTerminate); - boost::shared_ptr<GenericRequest<WhiteboardPayload> > request = boost::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); - request->send(); - } - onSessionTerminated(toJID_); - } + void WhiteboardSession::cancel() { + if (router_->isAvailable()) { + std::shared_ptr<WhiteboardPayload> payload = std::make_shared<WhiteboardPayload>(WhiteboardPayload::SessionTerminate); + std::shared_ptr<GenericRequest<WhiteboardPayload> > request = std::make_shared<GenericRequest<WhiteboardPayload> >(IQ::Set, toJID_, payload, router_); + request->send(); + } + onSessionTerminated(toJID_); + } - const JID& WhiteboardSession::getTo() const { - return toJID_; - } + const JID& WhiteboardSession::getTo() const { + return toJID_; + } } diff --git a/Swiften/Whiteboard/WhiteboardSession.h b/Swiften/Whiteboard/WhiteboardSession.h index 14fa632..1b5d039 100644 --- a/Swiften/Whiteboard/WhiteboardSession.h +++ b/Swiften/Whiteboard/WhiteboardSession.h @@ -4,52 +4,58 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Base/IDGenerator.h> -#include <Swiften/Queries/GenericRequest.h> #include <Swiften/Elements/Whiteboard/WhiteboardElement.h> #include <Swiften/Elements/Whiteboard/WhiteboardOperation.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class IQRouter; - class ErrorPayload; - class WhiteboardPayload; - - class SWIFTEN_API WhiteboardSession { - public: - typedef boost::shared_ptr<WhiteboardSession> ref; - - public: - WhiteboardSession(const JID& jid, IQRouter* router); - virtual ~WhiteboardSession(); - void handleIncomingAction(boost::shared_ptr<WhiteboardPayload> payload); - void sendElement(const WhiteboardElement::ref element); - virtual void sendOperation(WhiteboardOperation::ref operation) = 0; - void cancel(); - const JID& getTo() const; - - public: - boost::signal< void(const WhiteboardElement::ref element)> onElementReceived; - boost::signal< void(const WhiteboardOperation::ref operation)> onOperationReceived; - boost::signal< void(const JID& contact)> onSessionTerminated; - boost::signal< void(const JID& contact)> onRequestAccepted; - boost::signal< void(const JID& contact)> onRequestRejected; - - private: - virtual void handleIncomingOperation(WhiteboardOperation::ref operation) = 0; - - protected: - void sendPayload(boost::shared_ptr<WhiteboardPayload> payload); - - JID toJID_; - IQRouter* router_; - std::string lastOpID; - IDGenerator idGenerator; - }; + class IQRouter; + class WhiteboardPayload; + + class SWIFTEN_API WhiteboardSession { + public: + typedef std::shared_ptr<WhiteboardSession> ref; + + public: + WhiteboardSession(const JID& jid, IQRouter* router); + virtual ~WhiteboardSession(); + void handleIncomingAction(std::shared_ptr<WhiteboardPayload> payload); + void sendElement(const WhiteboardElement::ref element); + virtual void sendOperation(WhiteboardOperation::ref operation) = 0; + void cancel(); + const JID& getTo() const; + + public: + boost::signals2::signal< void(const WhiteboardElement::ref element)> onElementReceived; + boost::signals2::signal< void(const WhiteboardOperation::ref operation)> onOperationReceived; + boost::signals2::signal< void(const JID& contact)> onSessionTerminated; + boost::signals2::signal< void(const JID& contact)> onRequestAccepted; + boost::signals2::signal< void(const JID& contact)> onRequestRejected; + + private: + virtual void handleIncomingOperation(WhiteboardOperation::ref operation) = 0; + + protected: + void sendPayload(std::shared_ptr<WhiteboardPayload> payload); + + JID toJID_; + IQRouter* router_; + std::string lastOpID; + IDGenerator idGenerator; + }; } diff --git a/Swiften/Whiteboard/WhiteboardSessionManager.cpp b/Swiften/Whiteboard/WhiteboardSessionManager.cpp index c8e9a6a..59f6c47 100644 --- a/Swiften/Whiteboard/WhiteboardSessionManager.cpp +++ b/Swiften/Whiteboard/WhiteboardSessionManager.cpp @@ -4,108 +4,115 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Whiteboard/WhiteboardSessionManager.h> -#include <Swiften/Base/foreach.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/bind.hpp> + +#include <Swiften/Disco/EntityCapsProvider.h> +#include <Swiften/Presence/PresenceOracle.h> #include <Swiften/Queries/IQRouter.h> #include <Swiften/Whiteboard/WhiteboardResponder.h> -#include <Swiften/Presence/PresenceOracle.h> -#include "Swiften/Disco/EntityCapsProvider.h" namespace Swift { - WhiteboardSessionManager::WhiteboardSessionManager(IQRouter* router, StanzaChannel* stanzaChannel, PresenceOracle* presenceOracle, EntityCapsProvider* capsProvider) : router_(router), stanzaChannel_(stanzaChannel), presenceOracle_(presenceOracle), capsProvider_(capsProvider) { - responder = new WhiteboardResponder(this, router); - responder->start(); - stanzaChannel_->onPresenceReceived.connect(boost::bind(&WhiteboardSessionManager::handlePresenceReceived, this, _1)); - stanzaChannel_->onAvailableChanged.connect(boost::bind(&WhiteboardSessionManager::handleAvailableChanged, this, _1)); - } - - WhiteboardSessionManager::~WhiteboardSessionManager() { - responder->stop(); - delete responder; - } - - WhiteboardSession::ref WhiteboardSessionManager::getSession(const JID& to) { - if (sessions_.find(to) == sessions_.end()) { - return boost::shared_ptr<WhiteboardSession>(); - } - return sessions_[to]; - } - - OutgoingWhiteboardSession::ref WhiteboardSessionManager::createOutgoingSession(const JID& to) { - JID fullJID = to; - if (fullJID.isBare()) { - fullJID = getFullJID(fullJID); - } - OutgoingWhiteboardSession::ref session = boost::make_shared<OutgoingWhiteboardSession>(fullJID, router_); - sessions_[fullJID] = session; - session->onSessionTerminated.connect(boost::bind(&WhiteboardSessionManager::deleteSessionEntry, this, _1)); - session->onRequestRejected.connect(boost::bind(&WhiteboardSessionManager::deleteSessionEntry, this, _1)); - return session; - } - - WhiteboardSession::ref WhiteboardSessionManager::requestSession(const JID& to) { - WhiteboardSession::ref session = getSession(to); - if (!session) { - OutgoingWhiteboardSession::ref outgoingSession = createOutgoingSession(to); - outgoingSession->startSession(); - return outgoingSession; - } else { - return session; - } - } - - void WhiteboardSessionManager::handleIncomingSession(IncomingWhiteboardSession::ref session) { - sessions_[session->getTo()] = session; - session->onSessionTerminated.connect(boost::bind(&WhiteboardSessionManager::deleteSessionEntry, this, _1)); - onSessionRequest(session); - } - - JID WhiteboardSessionManager::getFullJID(const JID& bareJID) { - JID fullReceipientJID; - int priority = INT_MIN; - - //getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11 - std::vector<Presence::ref> presences = presenceOracle_->getAllPresence(bareJID); - - //iterate over them - foreach(Presence::ref pres, presences) { - if (pres->getPriority() > priority) { - // look up caps from the jid - DiscoInfo::ref info = capsProvider_->getCaps(pres->getFrom()); - if (info && info->hasFeature(DiscoInfo::WhiteboardFeature)) { - priority = pres->getPriority(); - fullReceipientJID = pres->getFrom(); - } - } - } - - return fullReceipientJID; - } - - void WhiteboardSessionManager::deleteSessionEntry(const JID& contact) { - sessions_.erase(contact); - } - - void WhiteboardSessionManager::handlePresenceReceived(Presence::ref presence) { - if (!presence->isAvailable()) { - WhiteboardSession::ref session = getSession(presence->getFrom()); - if (session) { - session->cancel(); - } - } - } - - void WhiteboardSessionManager::handleAvailableChanged(bool available) { - if (!available) { - std::map<JID, WhiteboardSession::ref> sessionsCopy = sessions_; - std::map<JID, WhiteboardSession::ref>::iterator it; - for (it = sessionsCopy.begin(); it != sessionsCopy.end(); ++it) { - it->second->cancel(); - } - } - } + WhiteboardSessionManager::WhiteboardSessionManager(IQRouter* router, StanzaChannel* stanzaChannel, PresenceOracle* presenceOracle, EntityCapsProvider* capsProvider) : router_(router), stanzaChannel_(stanzaChannel), presenceOracle_(presenceOracle), capsProvider_(capsProvider) { + responder = new WhiteboardResponder(this, router); + responder->start(); + stanzaChannel_->onPresenceReceived.connect(boost::bind(&WhiteboardSessionManager::handlePresenceReceived, this, _1)); + stanzaChannel_->onAvailableChanged.connect(boost::bind(&WhiteboardSessionManager::handleAvailableChanged, this, _1)); + } + + WhiteboardSessionManager::~WhiteboardSessionManager() { + responder->stop(); + delete responder; + } + + WhiteboardSession::ref WhiteboardSessionManager::getSession(const JID& to) { + if (sessions_.find(to) == sessions_.end()) { + return std::shared_ptr<WhiteboardSession>(); + } + return sessions_[to]; + } + + OutgoingWhiteboardSession::ref WhiteboardSessionManager::createOutgoingSession(const JID& to) { + JID fullJID = to; + if (fullJID.isBare()) { + fullJID = getFullJID(fullJID); + } + OutgoingWhiteboardSession::ref session = std::make_shared<OutgoingWhiteboardSession>(fullJID, router_); + sessions_[fullJID] = session; + session->onSessionTerminated.connect(boost::bind(&WhiteboardSessionManager::deleteSessionEntry, this, _1)); + session->onRequestRejected.connect(boost::bind(&WhiteboardSessionManager::deleteSessionEntry, this, _1)); + return session; + } + + WhiteboardSession::ref WhiteboardSessionManager::requestSession(const JID& to) { + WhiteboardSession::ref session = getSession(to); + if (!session) { + OutgoingWhiteboardSession::ref outgoingSession = createOutgoingSession(to); + outgoingSession->startSession(); + return outgoingSession; + } else { + return session; + } + } + + void WhiteboardSessionManager::handleIncomingSession(IncomingWhiteboardSession::ref session) { + sessions_[session->getTo()] = session; + session->onSessionTerminated.connect(boost::bind(&WhiteboardSessionManager::deleteSessionEntry, this, _1)); + onSessionRequest(session); + } + + JID WhiteboardSessionManager::getFullJID(const JID& bareJID) { + JID fullReceipientJID; + int priority = INT_MIN; + + //getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11 + std::vector<Presence::ref> presences = presenceOracle_->getAllPresence(bareJID); + + //iterate over them + for (const auto& pres : presences) { + if (pres->getPriority() > priority) { + // look up caps from the jid + DiscoInfo::ref info = capsProvider_->getCaps(pres->getFrom()); + if (info && info->hasFeature(DiscoInfo::WhiteboardFeature)) { + priority = pres->getPriority(); + fullReceipientJID = pres->getFrom(); + } + } + } + + return fullReceipientJID; + } + + void WhiteboardSessionManager::deleteSessionEntry(const JID& contact) { + sessions_.erase(contact); + } + + void WhiteboardSessionManager::handlePresenceReceived(Presence::ref presence) { + if (!presence->isAvailable()) { + WhiteboardSession::ref session = getSession(presence->getFrom()); + if (session) { + session->cancel(); + } + } + } + + void WhiteboardSessionManager::handleAvailableChanged(bool available) { + if (!available) { + std::map<JID, WhiteboardSession::ref> sessionsCopy = sessions_; + std::map<JID, WhiteboardSession::ref>::iterator it; + for (it = sessionsCopy.begin(); it != sessionsCopy.end(); ++it) { + it->second->cancel(); + } + } + } } diff --git a/Swiften/Whiteboard/WhiteboardSessionManager.h b/Swiften/Whiteboard/WhiteboardSessionManager.h index d06b856..4f14665 100644 --- a/Swiften/Whiteboard/WhiteboardSessionManager.h +++ b/Swiften/Whiteboard/WhiteboardSessionManager.h @@ -4,51 +4,58 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <map> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/JID/JID.h> #include <Swiften/Client/StanzaChannel.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Whiteboard/WhiteboardSession.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Queries/IQRouter.h> #include <Swiften/Whiteboard/IncomingWhiteboardSession.h> #include <Swiften/Whiteboard/OutgoingWhiteboardSession.h> +#include <Swiften/Whiteboard/WhiteboardSession.h> namespace Swift { - class IQRouter; - class WhiteboardResponder; - class PresenceOracle; - class EntityCapsProvider; - - class SWIFTEN_API WhiteboardSessionManager { - friend class WhiteboardResponder; - public: - WhiteboardSessionManager(IQRouter* router, StanzaChannel* stanzaChannel, PresenceOracle* presenceOracle, EntityCapsProvider* capsProvider); - ~WhiteboardSessionManager(); - - WhiteboardSession::ref getSession(const JID& to); - WhiteboardSession::ref requestSession(const JID& to); - - public: - boost::signal< void (IncomingWhiteboardSession::ref)> onSessionRequest; - - private: - JID getFullJID(const JID& bareJID); - OutgoingWhiteboardSession::ref createOutgoingSession(const JID& to); - void handleIncomingSession(IncomingWhiteboardSession::ref session); - void handlePresenceReceived(Presence::ref presence); - void handleAvailableChanged(bool available); - void deleteSessionEntry(const JID& contact); - - private: - std::map<JID, boost::shared_ptr<WhiteboardSession> > sessions_; - IQRouter* router_; - StanzaChannel* stanzaChannel_; - PresenceOracle* presenceOracle_; - EntityCapsProvider* capsProvider_; - WhiteboardResponder* responder; - }; + class IQRouter; + class WhiteboardResponder; + class PresenceOracle; + class EntityCapsProvider; + + class SWIFTEN_API WhiteboardSessionManager { + friend class WhiteboardResponder; + public: + WhiteboardSessionManager(IQRouter* router, StanzaChannel* stanzaChannel, PresenceOracle* presenceOracle, EntityCapsProvider* capsProvider); + ~WhiteboardSessionManager(); + + WhiteboardSession::ref getSession(const JID& to); + WhiteboardSession::ref requestSession(const JID& to); + + public: + boost::signals2::signal< void (IncomingWhiteboardSession::ref)> onSessionRequest; + + private: + JID getFullJID(const JID& bareJID); + OutgoingWhiteboardSession::ref createOutgoingSession(const JID& to); + void handleIncomingSession(IncomingWhiteboardSession::ref session); + void handlePresenceReceived(Presence::ref presence); + void handleAvailableChanged(bool available); + void deleteSessionEntry(const JID& contact); + + private: + std::map<JID, std::shared_ptr<WhiteboardSession> > sessions_; + IQRouter* router_; + StanzaChannel* stanzaChannel_; + PresenceOracle* presenceOracle_; + EntityCapsProvider* capsProvider_; + WhiteboardResponder* responder; + }; } diff --git a/Swiften/Whiteboard/WhiteboardTransformer.cpp b/Swiften/Whiteboard/WhiteboardTransformer.cpp index 8b9c927..1d519f4 100644 --- a/Swiften/Whiteboard/WhiteboardTransformer.cpp +++ b/Swiften/Whiteboard/WhiteboardTransformer.cpp @@ -4,210 +4,217 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/Whiteboard/WhiteboardTransformer.h> -#include <boost/smart_ptr/make_shared.hpp> + +#include <memory> namespace Swift { - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardOperation::ref clientOp, WhiteboardOperation::ref serverOp) { - WhiteboardInsertOperation::ref clientInsert = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(clientOp); - WhiteboardInsertOperation::ref serverInsert = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(serverOp); - WhiteboardUpdateOperation::ref clientUpdate = boost::dynamic_pointer_cast<WhiteboardUpdateOperation>(clientOp); - WhiteboardUpdateOperation::ref serverUpdate = boost::dynamic_pointer_cast<WhiteboardUpdateOperation>(serverOp); - WhiteboardDeleteOperation::ref clientDelete = boost::dynamic_pointer_cast<WhiteboardDeleteOperation>(clientOp); - WhiteboardDeleteOperation::ref serverDelete = boost::dynamic_pointer_cast<WhiteboardDeleteOperation>(serverOp); - if (clientInsert && serverInsert) { - return transform(clientInsert, serverInsert); - } else if (clientUpdate && serverUpdate) { - return transform(clientUpdate, serverUpdate); - } else if (clientInsert && serverUpdate) { - return transform(clientInsert, serverUpdate); - } else if (clientUpdate && serverInsert) { - return transform(clientUpdate, serverInsert); - } else if (clientDelete && serverDelete) { - return transform(clientDelete, serverDelete); - } else if (clientInsert && serverDelete) { - return transform(clientInsert, serverDelete); - } else if (clientDelete && serverInsert) { - return transform(clientDelete, serverInsert); - } else if (clientUpdate && serverDelete) { - return transform(clientUpdate, serverDelete); - } else if (clientDelete && serverUpdate) { - return transform(clientDelete, serverUpdate); - } else { - return std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref>(); - } - } - - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardInsertOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp) { - std::pair<WhiteboardInsertOperation::ref, WhiteboardInsertOperation::ref> result; - result.first = boost::make_shared<WhiteboardInsertOperation>(*serverOp); - result.first->setParentID(clientOp->getID()); - result.second = boost::make_shared<WhiteboardInsertOperation>(*clientOp); - result.second->setParentID(serverOp->getID()); - if (clientOp->getPos() <= serverOp->getPos()) { - result.first->setPos(result.first->getPos()+1); - } else { - result.second->setPos(result.second->getPos()+1); - } - return result; - } - - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp) { - std::pair<WhiteboardUpdateOperation::ref, WhiteboardUpdateOperation::ref> result; - result.first = boost::make_shared<WhiteboardUpdateOperation>(*serverOp); - result.first->setParentID(clientOp->getID()); - - if (clientOp->getPos() == serverOp->getPos()) { - result.second = boost::make_shared<WhiteboardUpdateOperation>(*serverOp); - result.second->setID(clientOp->getID()); - result.second->setParentID(serverOp->getID()); - } else { - result.second = boost::make_shared<WhiteboardUpdateOperation>(*clientOp); - result.second->setParentID(serverOp->getID()); - } - - if (clientOp->getPos() < serverOp->getPos() && clientOp->getNewPos() > serverOp->getPos()) { - result.first->setPos(result.first->getPos()-1); - if (clientOp->getNewPos() >= serverOp->getNewPos()) { - result.first->setNewPos(result.first->getNewPos()-1); - } - } else if (clientOp->getNewPos() >= serverOp->getNewPos()) { - result.first->setNewPos(result.first->getNewPos()-1); - } - - if (serverOp->getPos() < clientOp->getPos() && serverOp->getNewPos() > clientOp->getPos()) { - result.second->setPos(result.second->getPos()-1); - if (serverOp->getNewPos() >= clientOp->getNewPos()) { - result.second->setNewPos(result.second->getNewPos()-1); - } - } else if (serverOp->getNewPos() >= clientOp->getNewPos()) { - result.second->setNewPos(result.second->getNewPos()-1); - } - return result; - } - - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp) { - std::pair<WhiteboardInsertOperation::ref, WhiteboardUpdateOperation::ref> result; - result.first = boost::make_shared<WhiteboardInsertOperation>(*serverOp); - result.first->setParentID(clientOp->getID()); - result.second = boost::make_shared<WhiteboardUpdateOperation>(*clientOp); - result.second->setParentID(serverOp->getID()); - if (serverOp->getPos() <= clientOp->getPos()) { - result.second->setPos(result.second->getPos()+1); - } - return result; - } - - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardInsertOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp) { - std::pair<WhiteboardUpdateOperation::ref, WhiteboardInsertOperation::ref> result; - result.first = boost::make_shared<WhiteboardUpdateOperation>(*serverOp); - result.first->setParentID(clientOp->getID()); - result.second = boost::make_shared<WhiteboardInsertOperation>(*clientOp); - result.second->setParentID(serverOp->getID()); - if (serverOp->getPos() >= clientOp->getPos()) { - result.first->setPos(result.first->getPos()+1); - } - return result; - } - - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp) { - std::pair<WhiteboardDeleteOperation::ref, WhiteboardDeleteOperation::ref> result; - result.first = boost::make_shared<WhiteboardDeleteOperation>(*serverOp); - result.first->setParentID(clientOp->getID()); - result.second = boost::make_shared<WhiteboardDeleteOperation>(*clientOp); - result.second->setParentID(serverOp->getID()); - if (clientOp->getPos() == -1) { - result.second->setPos(-1); - } - if (serverOp->getPos() == -1) { - result.first->setPos(-1); - } - if (clientOp->getPos() < serverOp->getPos()) { - result.first->setPos(result.first->getPos()-1); - } else if (clientOp->getPos() > serverOp->getPos()) { - result.second->setPos(result.second->getPos()-1); - } else { - result.first->setPos(-1); - result.second->setPos(-1); - } - return result; - } - - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardInsertOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp) { - std::pair<WhiteboardDeleteOperation::ref, WhiteboardInsertOperation::ref> result; - result.first = boost::make_shared<WhiteboardDeleteOperation>(*serverOp); - result.first->setParentID(clientOp->getID()); - result.second = boost::make_shared<WhiteboardInsertOperation>(*clientOp); - result.second->setParentID(serverOp->getID()); - if (clientOp->getPos() <= serverOp->getPos()) { - result.first->setPos(result.first->getPos()+1); - } else if (serverOp->getPos() != -1) { - result.second->setPos(result.second->getPos()-1); - } - return result; - } - - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp) { - std::pair<WhiteboardInsertOperation::ref, WhiteboardDeleteOperation::ref> result; - result.first = boost::make_shared<WhiteboardInsertOperation>(*serverOp); - result.first->setParentID(clientOp->getID()); - result.second = boost::make_shared<WhiteboardDeleteOperation>(*clientOp); - result.second->setParentID(serverOp->getID()); - if (serverOp->getPos() <= clientOp->getPos()) { - result.second->setPos(result.second->getPos()+1); - } else if (clientOp->getPos() != -1) { - result.first->setPos(result.first->getPos()-1); - } - return result; - } - - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp) { - std::pair<WhiteboardDeleteOperation::ref, WhiteboardOperation::ref> result; - result.first = boost::make_shared<WhiteboardDeleteOperation>(*serverOp); - result.first->setParentID(clientOp->getID()); - WhiteboardUpdateOperation::ref updateOp = boost::make_shared<WhiteboardUpdateOperation>(*clientOp); - result.second = updateOp; - result.second->setParentID(serverOp->getID()); - if (clientOp->getPos() == serverOp->getPos()) { - WhiteboardDeleteOperation::ref deleteOp = boost::make_shared<WhiteboardDeleteOperation>(); - result.second = deleteOp; - result.second->setPos(-1); - result.second->setID(clientOp->getID()); - result.second->setParentID(serverOp->getID()); - deleteOp->setElementID(serverOp->getElementID()); - } else if (clientOp->getPos() > serverOp->getPos() && clientOp->getNewPos() <= serverOp->getPos()) { - result.second->setPos(result.second->getPos()-1); - } else if (clientOp->getPos() < serverOp->getPos() && clientOp->getNewPos() >= serverOp->getPos()) { - updateOp->setNewPos(updateOp->getNewPos()-1); - } else if (clientOp->getPos() > serverOp->getPos()) { - result.second->setPos(result.second->getPos()-1); - updateOp->setNewPos(updateOp->getNewPos()-1); - } - return result; - } - - std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp) { - std::pair<WhiteboardOperation::ref, WhiteboardDeleteOperation::ref> result; - WhiteboardUpdateOperation::ref updateOp = boost::make_shared<WhiteboardUpdateOperation>(*serverOp); - result.first = updateOp; - result.first->setParentID(clientOp->getID()); - result.second = boost::make_shared<WhiteboardDeleteOperation>(*clientOp); - result.second->setParentID(serverOp->getID()); - if (clientOp->getPos() == serverOp->getPos()) { - WhiteboardDeleteOperation::ref deleteOp = boost::make_shared<WhiteboardDeleteOperation>(); - result.first = deleteOp; - result.first->setPos(-1); - result.first->setID(serverOp->getID()); - result.first->setParentID(clientOp->getID()); - deleteOp->setElementID(clientOp->getElementID()); - } else if (clientOp->getPos() < serverOp->getPos() && clientOp->getPos() >= serverOp->getNewPos()) { - result.first->setPos(result.first->getPos()-1); - } else if (clientOp->getPos() > serverOp->getPos() && clientOp->getPos() <= serverOp->getNewPos()) { - updateOp->setNewPos(updateOp->getNewPos()-1); - } else if (clientOp->getPos() < serverOp->getPos()) { - result.first->setPos(result.first->getPos()-1); - updateOp->setNewPos(updateOp->getNewPos()-1); - } - return result; - } + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardOperation::ref clientOp, WhiteboardOperation::ref serverOp) { + WhiteboardInsertOperation::ref clientInsert = std::dynamic_pointer_cast<WhiteboardInsertOperation>(clientOp); + WhiteboardInsertOperation::ref serverInsert = std::dynamic_pointer_cast<WhiteboardInsertOperation>(serverOp); + WhiteboardUpdateOperation::ref clientUpdate = std::dynamic_pointer_cast<WhiteboardUpdateOperation>(clientOp); + WhiteboardUpdateOperation::ref serverUpdate = std::dynamic_pointer_cast<WhiteboardUpdateOperation>(serverOp); + WhiteboardDeleteOperation::ref clientDelete = std::dynamic_pointer_cast<WhiteboardDeleteOperation>(clientOp); + WhiteboardDeleteOperation::ref serverDelete = std::dynamic_pointer_cast<WhiteboardDeleteOperation>(serverOp); + if (clientInsert && serverInsert) { + return transform(clientInsert, serverInsert); + } else if (clientUpdate && serverUpdate) { + return transform(clientUpdate, serverUpdate); + } else if (clientInsert && serverUpdate) { + return transform(clientInsert, serverUpdate); + } else if (clientUpdate && serverInsert) { + return transform(clientUpdate, serverInsert); + } else if (clientDelete && serverDelete) { + return transform(clientDelete, serverDelete); + } else if (clientInsert && serverDelete) { + return transform(clientInsert, serverDelete); + } else if (clientDelete && serverInsert) { + return transform(clientDelete, serverInsert); + } else if (clientUpdate && serverDelete) { + return transform(clientUpdate, serverDelete); + } else if (clientDelete && serverUpdate) { + return transform(clientDelete, serverUpdate); + } else { + return std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref>(); + } + } + + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardInsertOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp) { + std::pair<WhiteboardInsertOperation::ref, WhiteboardInsertOperation::ref> result; + result.first = std::make_shared<WhiteboardInsertOperation>(*serverOp); + result.first->setParentID(clientOp->getID()); + result.second = std::make_shared<WhiteboardInsertOperation>(*clientOp); + result.second->setParentID(serverOp->getID()); + if (clientOp->getPos() <= serverOp->getPos()) { + result.first->setPos(result.first->getPos()+1); + } else { + result.second->setPos(result.second->getPos()+1); + } + return result; + } + + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp) { + std::pair<WhiteboardUpdateOperation::ref, WhiteboardUpdateOperation::ref> result; + result.first = std::make_shared<WhiteboardUpdateOperation>(*serverOp); + result.first->setParentID(clientOp->getID()); + + if (clientOp->getPos() == serverOp->getPos()) { + result.second = std::make_shared<WhiteboardUpdateOperation>(*serverOp); + result.second->setID(clientOp->getID()); + result.second->setParentID(serverOp->getID()); + } else { + result.second = std::make_shared<WhiteboardUpdateOperation>(*clientOp); + result.second->setParentID(serverOp->getID()); + } + + if (clientOp->getPos() < serverOp->getPos() && clientOp->getNewPos() > serverOp->getPos()) { + result.first->setPos(result.first->getPos()-1); + if (clientOp->getNewPos() >= serverOp->getNewPos()) { + result.first->setNewPos(result.first->getNewPos()-1); + } + } else if (clientOp->getNewPos() >= serverOp->getNewPos()) { + result.first->setNewPos(result.first->getNewPos()-1); + } + + if (serverOp->getPos() < clientOp->getPos() && serverOp->getNewPos() > clientOp->getPos()) { + result.second->setPos(result.second->getPos()-1); + if (serverOp->getNewPos() >= clientOp->getNewPos()) { + result.second->setNewPos(result.second->getNewPos()-1); + } + } else if (serverOp->getNewPos() >= clientOp->getNewPos()) { + result.second->setNewPos(result.second->getNewPos()-1); + } + return result; + } + + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp) { + std::pair<WhiteboardInsertOperation::ref, WhiteboardUpdateOperation::ref> result; + result.first = std::make_shared<WhiteboardInsertOperation>(*serverOp); + result.first->setParentID(clientOp->getID()); + result.second = std::make_shared<WhiteboardUpdateOperation>(*clientOp); + result.second->setParentID(serverOp->getID()); + if (serverOp->getPos() <= clientOp->getPos()) { + result.second->setPos(result.second->getPos()+1); + } + return result; + } + + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardInsertOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp) { + std::pair<WhiteboardUpdateOperation::ref, WhiteboardInsertOperation::ref> result; + result.first = std::make_shared<WhiteboardUpdateOperation>(*serverOp); + result.first->setParentID(clientOp->getID()); + result.second = std::make_shared<WhiteboardInsertOperation>(*clientOp); + result.second->setParentID(serverOp->getID()); + if (serverOp->getPos() >= clientOp->getPos()) { + result.first->setPos(result.first->getPos()+1); + } + return result; + } + + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp) { + std::pair<WhiteboardDeleteOperation::ref, WhiteboardDeleteOperation::ref> result; + result.first = std::make_shared<WhiteboardDeleteOperation>(*serverOp); + result.first->setParentID(clientOp->getID()); + result.second = std::make_shared<WhiteboardDeleteOperation>(*clientOp); + result.second->setParentID(serverOp->getID()); + if (clientOp->getPos() == -1) { + result.second->setPos(-1); + } + if (serverOp->getPos() == -1) { + result.first->setPos(-1); + } + if (clientOp->getPos() < serverOp->getPos()) { + result.first->setPos(result.first->getPos()-1); + } else if (clientOp->getPos() > serverOp->getPos()) { + result.second->setPos(result.second->getPos()-1); + } else { + result.first->setPos(-1); + result.second->setPos(-1); + } + return result; + } + + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardInsertOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp) { + std::pair<WhiteboardDeleteOperation::ref, WhiteboardInsertOperation::ref> result; + result.first = std::make_shared<WhiteboardDeleteOperation>(*serverOp); + result.first->setParentID(clientOp->getID()); + result.second = std::make_shared<WhiteboardInsertOperation>(*clientOp); + result.second->setParentID(serverOp->getID()); + if (clientOp->getPos() <= serverOp->getPos()) { + result.first->setPos(result.first->getPos()+1); + } else if (serverOp->getPos() != -1) { + result.second->setPos(result.second->getPos()-1); + } + return result; + } + + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp) { + std::pair<WhiteboardInsertOperation::ref, WhiteboardDeleteOperation::ref> result; + result.first = std::make_shared<WhiteboardInsertOperation>(*serverOp); + result.first->setParentID(clientOp->getID()); + result.second = std::make_shared<WhiteboardDeleteOperation>(*clientOp); + result.second->setParentID(serverOp->getID()); + if (serverOp->getPos() <= clientOp->getPos()) { + result.second->setPos(result.second->getPos()+1); + } else if (clientOp->getPos() != -1) { + result.first->setPos(result.first->getPos()-1); + } + return result; + } + + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp) { + std::pair<WhiteboardDeleteOperation::ref, WhiteboardOperation::ref> result; + result.first = std::make_shared<WhiteboardDeleteOperation>(*serverOp); + result.first->setParentID(clientOp->getID()); + WhiteboardUpdateOperation::ref updateOp = std::make_shared<WhiteboardUpdateOperation>(*clientOp); + result.second = updateOp; + result.second->setParentID(serverOp->getID()); + if (clientOp->getPos() == serverOp->getPos()) { + WhiteboardDeleteOperation::ref deleteOp = std::make_shared<WhiteboardDeleteOperation>(); + result.second = deleteOp; + result.second->setPos(-1); + result.second->setID(clientOp->getID()); + result.second->setParentID(serverOp->getID()); + deleteOp->setElementID(serverOp->getElementID()); + } else if (clientOp->getPos() > serverOp->getPos() && clientOp->getNewPos() <= serverOp->getPos()) { + result.second->setPos(result.second->getPos()-1); + } else if (clientOp->getPos() < serverOp->getPos() && clientOp->getNewPos() >= serverOp->getPos()) { + updateOp->setNewPos(updateOp->getNewPos()-1); + } else if (clientOp->getPos() > serverOp->getPos()) { + result.second->setPos(result.second->getPos()-1); + updateOp->setNewPos(updateOp->getNewPos()-1); + } + return result; + } + + std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> WhiteboardTransformer::transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp) { + std::pair<WhiteboardOperation::ref, WhiteboardDeleteOperation::ref> result; + WhiteboardUpdateOperation::ref updateOp = std::make_shared<WhiteboardUpdateOperation>(*serverOp); + result.first = updateOp; + result.first->setParentID(clientOp->getID()); + result.second = std::make_shared<WhiteboardDeleteOperation>(*clientOp); + result.second->setParentID(serverOp->getID()); + if (clientOp->getPos() == serverOp->getPos()) { + WhiteboardDeleteOperation::ref deleteOp = std::make_shared<WhiteboardDeleteOperation>(); + result.first = deleteOp; + result.first->setPos(-1); + result.first->setID(serverOp->getID()); + result.first->setParentID(clientOp->getID()); + deleteOp->setElementID(clientOp->getElementID()); + } else if (clientOp->getPos() < serverOp->getPos() && clientOp->getPos() >= serverOp->getNewPos()) { + result.first->setPos(result.first->getPos()-1); + } else if (clientOp->getPos() > serverOp->getPos() && clientOp->getPos() <= serverOp->getNewPos()) { + updateOp->setNewPos(updateOp->getNewPos()-1); + } else if (clientOp->getPos() < serverOp->getPos()) { + result.first->setPos(result.first->getPos()-1); + updateOp->setNewPos(updateOp->getNewPos()-1); + } + return result; + } } diff --git a/Swiften/Whiteboard/WhiteboardTransformer.h b/Swiften/Whiteboard/WhiteboardTransformer.h index 5811f9f..399e299 100644 --- a/Swiften/Whiteboard/WhiteboardTransformer.h +++ b/Swiften/Whiteboard/WhiteboardTransformer.h @@ -4,25 +4,32 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once +#include <utility> + +#include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> #include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h> -#include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> -#include <utility> namespace Swift { - class WhiteboardTransformer { - public: - static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardOperation::ref clientOp, WhiteboardOperation::ref serverOp); - static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardInsertOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp); - static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp); - static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp); - static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardInsertOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp); - static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp); - static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardInsertOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp); - static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp); - static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp); - static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp); - }; + class WhiteboardTransformer { + public: + static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardOperation::ref clientOp, WhiteboardOperation::ref serverOp); + static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardInsertOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp); + static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp); + static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp); + static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardInsertOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp); + static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp); + static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardInsertOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp); + static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp); + static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardDeleteOperation::ref serverOp); + static std::pair<WhiteboardOperation::ref, WhiteboardOperation::ref> transform(WhiteboardDeleteOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp); + }; } |
Swift