diff options
Diffstat (limited to 'Swiften')
674 files changed, 19255 insertions, 5630 deletions
diff --git a/Swiften/Avatars/AvatarManagerImpl.cpp b/Swiften/Avatars/AvatarManagerImpl.cpp index 78d94dc..7c3baa7 100644 --- a/Swiften/Avatars/AvatarManagerImpl.cpp +++ b/Swiften/Avatars/AvatarManagerImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -16,11 +16,11 @@ namespace Swift { -AvatarManagerImpl::AvatarManagerImpl(VCardManager* vcardManager, StanzaChannel* stanzaChannel, AvatarStorage* avatarStorage, MUCRegistry* mucRegistry) : avatarStorage(avatarStorage) { - vcardUpdateAvatarManager = new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, mucRegistry); +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); - vcardAvatarManager = new VCardAvatarManager(vcardManager, avatarStorage, mucRegistry); + vcardAvatarManager = new VCardAvatarManager(vcardManager, avatarStorage, crypto, mucRegistry); combinedAvatarProvider.addProvider(vcardAvatarManager); offlineAvatarManager = new OfflineAvatarManager(avatarStorage); diff --git a/Swiften/Avatars/AvatarManagerImpl.h b/Swiften/Avatars/AvatarManagerImpl.h index c2b8956..4f59fe5 100644 --- a/Swiften/Avatars/AvatarManagerImpl.h +++ b/Swiften/Avatars/AvatarManagerImpl.h @@ -17,10 +17,11 @@ namespace Swift { class VCardUpdateAvatarManager; class VCardAvatarManager; class OfflineAvatarManager; + class CryptoProvider; class AvatarManagerImpl : public AvatarManager { public: - AvatarManagerImpl(VCardManager*, StanzaChannel*, AvatarStorage*, MUCRegistry* = NULL); + AvatarManagerImpl(VCardManager*, StanzaChannel*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL); virtual ~AvatarManagerImpl(); virtual boost::filesystem::path getAvatarPath(const JID&) const; diff --git a/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp b/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp index 81dc12c..97edc73 100644 --- a/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp +++ b/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -13,13 +13,14 @@ #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/VCards/VCardStorage.h> #include <Swiften/MUC/MUCRegistry.h> #include <Swiften/Queries/IQRouter.h> #include <Swiften/Client/DummyStanzaChannel.h> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/StringCodecs/Hexify.h> using namespace Swift; @@ -35,53 +36,18 @@ class VCardAvatarManagerTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_END(); public: - class TestVCardStorage : public VCardStorage { - public: - 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; - } - - std::string getPhotoHash(const JID& jid) const { - if (photoHashes.find(jid) != photoHashes.end()) { - return photoHashes.find(jid)->second; - } - VCard::ref vCard = getVCard(jid); - if (vCard && !vCard->getPhoto().empty()) { - return Hexify::hexify(SHA1::getHash(vCard->getPhoto())); - } - else { - return ""; - } - } - - std::map<JID, std::string> photoHashes; - - private: - typedef std::map<JID, VCard::ref> VCardMap; - VCardMap vcards; - }; - 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 TestVCardStorage(); + vcardStorage = new VCardMemoryStorage(crypto.get()); vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage); avatar1 = createByteArray("abcdefg"); - avatar1Hash = Hexify::hexify(SHA1::getHash(avatar1)); + avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1)); user1 = JID("user1@bar.com/bla"); user2 = JID("user2@foo.com/baz"); } @@ -135,8 +101,9 @@ class VCardAvatarManagerTest : public CppUnit::TestFixture { void testGetAvatarHashKnownAvatarUnknownVCard() { boost::shared_ptr<VCardAvatarManager> testling = createManager(); - vcardStorage->photoHashes[user1.toBare()] = avatar1Hash; + avatarStorage->setAvatarForJID(user1, avatar1Hash); + std::string result = testling->getAvatarHash(user1); CPPUNIT_ASSERT_EQUAL(std::string(), result); @@ -153,7 +120,7 @@ class VCardAvatarManagerTest : public CppUnit::TestFixture { private: boost::shared_ptr<VCardAvatarManager> createManager() { - boost::shared_ptr<VCardAvatarManager> result(new VCardAvatarManager(vcardManager, avatarStorage, mucRegistry)); + boost::shared_ptr<VCardAvatarManager> result(new VCardAvatarManager(vcardManager, avatarStorage, crypto.get(), mucRegistry)); result->onAvatarChanged.connect(boost::bind(&VCardAvatarManagerTest::handleAvatarChanged, this, _1)); return result; } @@ -191,12 +158,13 @@ class VCardAvatarManagerTest : public CppUnit::TestFixture { DummyMUCRegistry* mucRegistry; AvatarMemoryStorage* avatarStorage; VCardManager* vcardManager; - TestVCardStorage* vcardStorage; + VCardMemoryStorage* vcardStorage; ByteArray avatar1; std::string avatar1Hash; std::vector<JID> changes; JID user1; JID user2; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardAvatarManagerTest); diff --git a/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp b/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp index 60e76f8..01b10a2 100644 --- a/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp +++ b/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -19,8 +19,9 @@ #include <Swiften/MUC/MUCRegistry.h> #include <Swiften/Queries/IQRouter.h> #include <Swiften/Client/DummyStanzaChannel.h> -#include <Swiften/StringCodecs/SHA1.h> #include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> using namespace Swift; @@ -37,19 +38,21 @@ class VCardUpdateAvatarManagerTest : public CppUnit::TestFixture { 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(); + vcardStorage = new VCardMemoryStorage(crypto.get()); vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage); avatar1 = createByteArray("abcdefg"); - avatar1Hash = Hexify::hexify(SHA1::getHash(avatar1)); + avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1)); user1 = JID("user1@bar.com/bla"); user2 = JID("user2@foo.com/baz"); } + void tearDown() { delete vcardManager; @@ -113,7 +116,7 @@ class VCardUpdateAvatarManagerTest : public CppUnit::TestFixture { vcardManager->requestVCard(JID("foo@bar.com")); stanzaChannel->onIQReceived(createVCardResult(ByteArray())); - CPPUNIT_ASSERT(!avatarStorage->hasAvatar(Hexify::hexify(SHA1::getHash(ByteArray())))); + CPPUNIT_ASSERT(!avatarStorage->hasAvatar(Hexify::hexify(crypto->getSHA1Hash(ByteArray())))); CPPUNIT_ASSERT_EQUAL(std::string(), testling->getAvatarHash(JID("foo@bar.com"))); } @@ -150,7 +153,7 @@ class VCardUpdateAvatarManagerTest : public CppUnit::TestFixture { private: boost::shared_ptr<VCardUpdateAvatarManager> createManager() { - boost::shared_ptr<VCardUpdateAvatarManager> result(new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, mucRegistry)); + boost::shared_ptr<VCardUpdateAvatarManager> result(new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto.get(), mucRegistry)); result->onAvatarChanged.connect(boost::bind(&VCardUpdateAvatarManagerTest::handleAvatarChanged, this, _1)); return result; } @@ -192,6 +195,7 @@ class VCardUpdateAvatarManagerTest : public CppUnit::TestFixture { std::vector<JID> changes; JID user1; JID user2; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardUpdateAvatarManagerTest); diff --git a/Swiften/Avatars/VCardAvatarManager.cpp b/Swiften/Avatars/VCardAvatarManager.cpp index ef1d293..8212a6e 100644 --- a/Swiften/Avatars/VCardAvatarManager.cpp +++ b/Swiften/Avatars/VCardAvatarManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -9,7 +9,7 @@ #include <boost/bind.hpp> #include <Swiften/Elements/VCard.h> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Avatars/AvatarStorage.h> #include <Swiften/MUC/MUCRegistry.h> @@ -18,7 +18,7 @@ namespace Swift { -VCardAvatarManager::VCardAvatarManager(VCardManager* vcardManager, AvatarStorage* avatarStorage, MUCRegistry* mucRegistry) : vcardManager_(vcardManager), avatarStorage_(avatarStorage), mucRegistry_(mucRegistry) { +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)); } @@ -36,7 +36,7 @@ std::string VCardAvatarManager::getAvatarHash(const JID& jid) const { if (!avatarStorage_->hasAvatar(hash)) { VCard::ref vCard = vcardManager_->getVCard(avatarJID); if (vCard) { - std::string newHash = Hexify::hexify(SHA1::getHash(vCard->getPhoto())); + 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. diff --git a/Swiften/Avatars/VCardAvatarManager.h b/Swiften/Avatars/VCardAvatarManager.h index ed2ba5d..9c6943e 100644 --- a/Swiften/Avatars/VCardAvatarManager.h +++ b/Swiften/Avatars/VCardAvatarManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -14,10 +14,11 @@ namespace Swift { class MUCRegistry; class AvatarStorage; class VCardManager; + class CryptoProvider; class SWIFTEN_API VCardAvatarManager : public AvatarProvider { public: - VCardAvatarManager(VCardManager*, AvatarStorage*, MUCRegistry* = NULL); + VCardAvatarManager(VCardManager*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL); std::string getAvatarHash(const JID&) const; @@ -28,6 +29,7 @@ namespace Swift { private: VCardManager* vcardManager_; AvatarStorage* avatarStorage_; + CryptoProvider* crypto_; MUCRegistry* mucRegistry_; }; } diff --git a/Swiften/Avatars/VCardUpdateAvatarManager.cpp b/Swiften/Avatars/VCardUpdateAvatarManager.cpp index 3c086d5..adbefd5 100644 --- a/Swiften/Avatars/VCardUpdateAvatarManager.cpp +++ b/Swiften/Avatars/VCardUpdateAvatarManager.cpp @@ -11,7 +11,7 @@ #include <Swiften/Client/StanzaChannel.h> #include <Swiften/Elements/VCardUpdate.h> #include <Swiften/VCards/GetVCardRequest.h> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Avatars/AvatarStorage.h> #include <Swiften/MUC/MUCRegistry.h> @@ -20,7 +20,7 @@ namespace Swift { -VCardUpdateAvatarManager::VCardUpdateAvatarManager(VCardManager* vcardManager, StanzaChannel* stanzaChannel, AvatarStorage* avatarStorage, MUCRegistry* mucRegistry) : vcardManager_(vcardManager), avatarStorage_(avatarStorage), mucRegistry_(mucRegistry) { +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)); @@ -54,7 +54,7 @@ void VCardUpdateAvatarManager::handleVCardChanged(const JID& from, VCard::ref vC setAvatarHash(from, ""); } else { - std::string hash = Hexify::hexify(SHA1::getHash(vCard->getPhoto())); + std::string hash = Hexify::hexify(crypto_->getSHA1Hash(vCard->getPhoto())); if (!avatarStorage_->hasAvatar(hash)) { avatarStorage_->addAvatar(hash, vCard->getPhoto()); } diff --git a/Swiften/Avatars/VCardUpdateAvatarManager.h b/Swiften/Avatars/VCardUpdateAvatarManager.h index 43e1d62..3409f99 100644 --- a/Swiften/Avatars/VCardUpdateAvatarManager.h +++ b/Swiften/Avatars/VCardUpdateAvatarManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -21,10 +21,11 @@ namespace Swift { class AvatarStorage; class StanzaChannel; class VCardManager; + class CryptoProvider; class SWIFTEN_API VCardUpdateAvatarManager : public AvatarProvider, public boost::bsignals::trackable { public: - VCardUpdateAvatarManager(VCardManager*, StanzaChannel*, AvatarStorage*, MUCRegistry* = NULL); + VCardUpdateAvatarManager(VCardManager*, StanzaChannel*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL); std::string getAvatarHash(const JID&) const; @@ -38,6 +39,7 @@ namespace Swift { 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 8f19446..388ad0a 100644 --- a/Swiften/Base/API.h +++ b/Swiften/Base/API.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Remko Tronçon + * Copyright (c) 2012-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -17,6 +17,8 @@ # else # define SWIFTEN_API __declspec(dllimport) # endif +# elif __GNUC__ >= 4 +# define SWIFTEN_API __attribute__((visibility("default"))) # else # define SWIFTEN_API # endif diff --git a/Swiften/Base/Algorithm.h b/Swiften/Base/Algorithm.h index 4e68e70..d5edab1 100644 --- a/Swiften/Base/Algorithm.h +++ b/Swiften/Base/Algorithm.h @@ -99,6 +99,11 @@ namespace Swift { 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); diff --git a/Swiften/Base/BoostRandomGenerator.h b/Swiften/Base/BoostRandomGenerator.h index b5a6cac..6065ff3 100644 --- a/Swiften/Base/BoostRandomGenerator.h +++ b/Swiften/Base/BoostRandomGenerator.h @@ -7,6 +7,7 @@ #pragma once #include <Swiften/Base/RandomGenerator.h> +#include <Swiften/Base/Override.h> #include <boost/random/mersenne_twister.hpp> @@ -15,7 +16,7 @@ namespace Swift { public: BoostRandomGenerator(); - int generateRandomInteger(int max); + int generateRandomInteger(int max) SWIFTEN_OVERRIDE; private: boost::mt19937 generator; diff --git a/Swiften/Base/ByteArray.cpp b/Swiften/Base/ByteArray.cpp index 6be96aa..466db5f 100644 --- a/Swiften/Base/ByteArray.cpp +++ b/Swiften/Base/ByteArray.cpp @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Remko Tronçon + * 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 <fstream> +#include <boost/numeric/conversion/cast.hpp> +#include <boost/filesystem/fstream.hpp> namespace Swift { static const int BUFFER_SIZE = 4096; -void readByteArrayFromFile(ByteArray& data, const std::string& file) { - std::ifstream input(file.c_str(), std::ios_base::in|std::ios_base::binary); +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 + input.gcount()); + data.resize(oldSize + boost::numeric_cast<size_t>(input.gcount())); } input.close(); } diff --git a/Swiften/Base/ByteArray.h b/Swiften/Base/ByteArray.h index 34b89d3..133b75f 100644 --- a/Swiften/Base/ByteArray.h +++ b/Swiften/Base/ByteArray.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -10,6 +10,7 @@ #include <string> #include <Swiften/Base/API.h> +#include <boost/filesystem/path.hpp> namespace Swift { typedef std::vector<unsigned char> ByteArray; @@ -26,7 +27,7 @@ namespace Swift { } inline ByteArray createByteArray(char c) { - return std::vector<unsigned char>(1, c); + return std::vector<unsigned char>(1, static_cast<unsigned char>(c)); } template<typename T, typename A> @@ -41,6 +42,6 @@ namespace Swift { SWIFTEN_API std::string byteArrayToString(const ByteArray& b); - SWIFTEN_API void readByteArrayFromFile(ByteArray&, const std::string& file); + SWIFTEN_API void readByteArrayFromFile(ByteArray&, const boost::filesystem::path& file); } diff --git a/Swiften/Base/DateTime.cpp b/Swiften/Base/DateTime.cpp index fae26d4..5d192c4 100644 --- a/Swiften/Base/DateTime.cpp +++ b/Swiften/Base/DateTime.cpp @@ -10,6 +10,7 @@ #include <boost/date_time/time_facet.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 <Swiften/Base/String.h> @@ -31,4 +32,8 @@ std::string dateTimeToString(const boost::posix_time::ptime& time) { 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)); +} + } diff --git a/Swiften/Base/DateTime.h b/Swiften/Base/DateTime.h index bc9eecb..891b170 100644 --- a/Swiften/Base/DateTime.h +++ b/Swiften/Base/DateTime.h @@ -20,4 +20,9 @@ namespace Swift { * 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); } diff --git a/Swiften/Base/Error.h b/Swiften/Base/Error.h index 906c1d9..d9f3b91 100644 --- a/Swiften/Base/Error.h +++ b/Swiften/Base/Error.h @@ -13,4 +13,4 @@ namespace Swift { public: virtual ~Error(); }; -}; +} diff --git a/Swiften/Base/Listenable.h b/Swiften/Base/Listenable.h new file mode 100644 index 0000000..445dfd7 --- /dev/null +++ b/Swiften/Base/Listenable.h @@ -0,0 +1,52 @@ +/* + * 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> +#include <boost/bind.hpp> +#include <algorithm> + +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; + }; +} + diff --git a/Swiften/Base/Log.cpp b/Swiften/Base/Log.cpp index 4132353..317798c 100644 --- a/Swiften/Base/Log.cpp +++ b/Swiften/Base/Log.cpp @@ -1,13 +1,43 @@ /* - * Copyright (c) 2010 Remko Tronçon + * 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/Log.h> +#include <cstdio> + + namespace Swift { -bool logging = false; +static Log::Severity logLevel = Log::warning; + +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); +} + +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; +} + +Log::Severity Log::getLogLevel() { + return logLevel; +} + +void Log::setLogLevel(Severity level) { + logLevel = level; +} } diff --git a/Swiften/Base/Log.h b/Swiften/Base/Log.h index 6d76dc6..a46860f 100644 --- a/Swiften/Base/Log.h +++ b/Swiften/Base/Log.h @@ -1,26 +1,44 @@ /* - * Copyright (c) 2010-2012 Remko Tronçon + * 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 <iostream> +#include <sstream> #include <Swiften/Base/API.h> namespace Swift { - extern SWIFTEN_API bool logging; - namespace LogDetail { - // Only here to be able to statically check the correctness of the severity levers - namespace Severity { - enum { - debug, info, warning, error + 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; + }; } #define SWIFT_LOG(severity) \ - if (!Swift::logging) {} else (void) LogDetail::Severity::severity, std::cerr << "[" << #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 << ". " diff --git a/Swiften/Base/Override.h b/Swiften/Base/Override.h new file mode 100644 index 0000000..6d9baaa --- /dev/null +++ b/Swiften/Base/Override.h @@ -0,0 +1,34 @@ +/* + * 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 new file mode 100644 index 0000000..2a49676 --- /dev/null +++ b/Swiften/Base/Path.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Base/Path.h> + +#include <Swiften/Base/Platform.h> +#include <Swiften/Base/String.h> + +using namespace Swift; + +boost::filesystem::path Swift::stringToPath(const std::string& path) { +#ifdef SWIFTEN_PLATFORM_WINDOWS + return boost::filesystem::path(convertStringToWString(path)); +#else + return boost::filesystem::path(path); +#endif +} + +std::string Swift::pathToString(const boost::filesystem::path& path) { +#ifdef SWIFTEN_PLATFORM_WINDOWS + return convertWStringToString(path.native()); +#else + return path.native(); +#endif +} diff --git a/Swiften/Base/Path.h b/Swiften/Base/Path.h new file mode 100644 index 0000000..ea99be9 --- /dev/null +++ b/Swiften/Base/Path.h @@ -0,0 +1,27 @@ +/* + * 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> +#include <boost/filesystem/path.hpp> +#include <string> + +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&); +} + + diff --git a/Swiften/Base/Paths.cpp b/Swiften/Base/Paths.cpp index edebc30..8ad1159 100644 --- a/Swiften/Base/Paths.cpp +++ b/Swiften/Base/Paths.cpp @@ -30,16 +30,17 @@ boost::filesystem::path Paths::getExecutablePath() { #elif defined(SWIFTEN_PLATFORM_LINUX) ByteArray path; path.resize(4096); - ssize_t size = readlink("/proc/self/exe", reinterpret_cast<char*>(vecptr(path)), path.size()); + 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) - ByteArray data; + std::vector<wchar_t> data; data.resize(2048); - GetModuleFileName(NULL, reinterpret_cast<char*>(vecptr(data)), data.size()); - return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(data)), data.size()).c_str()).parent_path(); + GetModuleFileNameW(NULL, vecptr(data), data.size()); + return boost::filesystem::path( + std::wstring(vecptr(data), data.size())).parent_path(); #endif return boost::filesystem::path(); } diff --git a/Swiften/Base/RandomGenerator.h b/Swiften/Base/RandomGenerator.h index 8f33020..eb5b84d 100644 --- a/Swiften/Base/RandomGenerator.h +++ b/Swiften/Base/RandomGenerator.h @@ -14,6 +14,10 @@ namespace Swift { public: virtual ~RandomGenerator(); + /** + * 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 new file mode 100644 index 0000000..5e3d89a --- /dev/null +++ b/Swiften/Base/Regex.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +/* + * Copyright (c) 2012 Maciej Niedzielski + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Base/Regex.h> + +#include <string> + +#include <boost/regex.hpp> + +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); + } + + } + +} + diff --git a/Swiften/IDN/IDNA.h b/Swiften/Base/Regex.h index 6ac51bf..6d12a60 100644 --- a/Swiften/IDN/IDNA.h +++ b/Swiften/Base/Regex.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,8 +11,9 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API IDNA { - public: - static std::string getEncoded(const std::string& s); - }; + + namespace Regex { + SWIFTEN_API std::string escape(const std::string& source); + } + } diff --git a/Swiften/Base/SConscript b/Swiften/Base/SConscript index 754164b..094059a 100644 --- a/Swiften/Base/SConscript +++ b/Swiften/Base/SConscript @@ -4,8 +4,10 @@ objects = swiften_env.SwiftenObject([ "ByteArray.cpp", "DateTime.cpp", "SafeByteArray.cpp", + "SafeAllocator.cpp", "Error.cpp", "Log.cpp", + "Path.cpp", "Paths.cpp", "String.cpp", "IDGenerator.cpp", @@ -14,5 +16,6 @@ objects = swiften_env.SwiftenObject([ "BoostRandomGenerator.cpp", "sleep.cpp", "URL.cpp", + "Regex.cpp" ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Base/SafeAllocator.cpp b/Swiften/Base/SafeAllocator.cpp new file mode 100644 index 0000000..d61d8b9 --- /dev/null +++ b/Swiften/Base/SafeAllocator.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Base/SafeByteArray.h> + +#include <Swiften/Base/Platform.h> +#ifdef SWIFTEN_PLATFORM_WINDOWS +#include <windows.h> +#endif + +namespace Swift { + +void secureZeroMemory(char* memory, size_t numberOfBytes) { +#ifdef SWIFTEN_PLATFORM_WINDOWS + SecureZeroMemory(memory, numberOfBytes); +#else + 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 9f9dd42..b01d77d 100644 --- a/Swiften/Base/SafeAllocator.h +++ b/Swiften/Base/SafeAllocator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -10,6 +10,8 @@ #include <algorithm> namespace Swift { + void secureZeroMemory(char* memory, size_t numberOfBytes); + template<typename T> class SafeAllocator : public std::allocator<T> { public: @@ -23,8 +25,10 @@ namespace Swift { ~SafeAllocator() throw() {} void deallocate (T* p, size_t num) { - std::fill(reinterpret_cast<char*>(p), reinterpret_cast<char*>(p + num), 0); + secureZeroMemory(reinterpret_cast<char*>(p), num); std::allocator<T>::deallocate(p, num); } + + private: }; -}; +} diff --git a/Swiften/Base/SafeByteArray.h b/Swiften/Base/SafeByteArray.h index dda51fe..b85373c 100644 --- a/Swiften/Base/SafeByteArray.h +++ b/Swiften/Base/SafeByteArray.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -31,7 +31,7 @@ namespace Swift { } inline SafeByteArray createSafeByteArray(char c) { - return SafeByteArray(1, c); + return SafeByteArray(1, static_cast<unsigned char>(c)); } inline SafeByteArray createSafeByteArray(const char* c, size_t n) { diff --git a/Swiften/Base/String.cpp b/Swiften/Base/String.cpp index 242b8e5..40ea2e1 100644 --- a/Swiften/Base/String.cpp +++ b/Swiften/Base/String.cpp @@ -1,15 +1,21 @@ /* - * Copyright (c) 2010 Remko Tronçon + * 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/Platform.h> + #include <cassert> #include <algorithm> #include <sstream> #include <iomanip> +#ifdef SWIFTEN_PLATFORM_WINDOWS +#include <windows.h> +#endif #include <Swiften/Base/String.h> +#include <Swiften/Base/ByteArray.h> namespace Swift { @@ -113,4 +119,35 @@ int String::convertHexStringToInt(const std::string& s) { 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 */); +} + +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 */); +} +#endif + } diff --git a/Swiften/Base/String.h b/Swiften/Base/String.h index de181a1..5a5642e 100644 --- a/Swiften/Base/String.h +++ b/Swiften/Base/String.h @@ -11,6 +11,7 @@ #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) @@ -32,7 +33,13 @@ namespace Swift { 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); +#endif class SWIFTEN_API makeString { public: diff --git a/Swiften/Base/UnitTest/PathTest.cpp b/Swiften/Base/UnitTest/PathTest.cpp new file mode 100644 index 0000000..f5f99e7 --- /dev/null +++ b/Swiften/Base/UnitTest/PathTest.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Base/Path.h> +#include <Swiften/Base/Platform.h> + +using namespace Swift; + +class PathTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(PathTest); + CPPUNIT_TEST(testStringToPath); + CPPUNIT_TEST(testPathToString); + CPPUNIT_TEST_SUITE_END(); + + public: + void testStringToPath() { +#ifdef SWIFTEN_PLATFORM_WINDOWS + 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()); +#endif + } + + 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/StringTest.cpp b/Swiften/Base/UnitTest/StringTest.cpp index b29f331..ffca98a 100644 --- a/Swiften/Base/UnitTest/StringTest.cpp +++ b/Swiften/Base/UnitTest/StringTest.cpp @@ -9,6 +9,7 @@ #include <string> #include <Swiften/Base/String.h> +#include <Swiften/Base/Platform.h> using namespace Swift; @@ -24,6 +25,10 @@ class StringTest : public CppUnit::TestFixture { CPPUNIT_TEST(testReplaceAll_ConsecutiveChars); CPPUNIT_TEST(testReplaceAll_MatchingReplace); CPPUNIT_TEST(testSplit); +#ifdef SWIFTEN_PLATFORM_WINDOWS + CPPUNIT_TEST(testConvertWStringToString); + CPPUNIT_TEST(testConvertStringToWString); +#endif CPPUNIT_TEST_SUITE_END(); public: @@ -109,6 +114,16 @@ class StringTest : public CppUnit::TestFixture { 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 testConvertStringToWString() { + CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == convertStringToWString(std::string("tron\xc3\xa7on"))); + } +#endif }; CPPUNIT_TEST_SUITE_REGISTRATION(StringTest); diff --git a/Swiften/Client/BlockList.cpp b/Swiften/Client/BlockList.cpp index 0b2fc12..3ee7864 100644 --- a/Swiften/Client/BlockList.cpp +++ b/Swiften/Client/BlockList.cpp @@ -6,8 +6,17 @@ #include <Swiften/Client/BlockList.h> +#include <algorithm> + using namespace Swift; 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()); +} diff --git a/Swiften/Client/BlockList.h b/Swiften/Client/BlockList.h index 39a211d..99c83c1 100644 --- a/Swiften/Client/BlockList.h +++ b/Swiften/Client/BlockList.h @@ -6,7 +6,7 @@ #pragma once -#include <set> +#include <vector> #include <Swiften/JID/JID.h> #include <Swiften/Base/boost_bsignals.h> @@ -15,15 +15,18 @@ namespace Swift { class BlockList { public: enum State { + Init, Requesting, Available, - Error, + Error }; virtual ~BlockList(); virtual State getState() const = 0; - virtual const std::set<JID>& getItems() const = 0; + virtual const std::vector<JID>& getItems() const = 0; + + bool isBlocked(const JID& jid) const; public: boost::signal<void ()> onStateChanged; diff --git a/Swiften/Client/BlockListImpl.cpp b/Swiften/Client/BlockListImpl.cpp index dfaaaf1..5950233 100644 --- a/Swiften/Client/BlockListImpl.cpp +++ b/Swiften/Client/BlockListImpl.cpp @@ -8,30 +8,47 @@ #include <Swiften/Base/foreach.h> +#include <algorithm> + using namespace Swift; -BlockListImpl::BlockListImpl() { +BlockListImpl::BlockListImpl() : state(Init) { } void BlockListImpl::setItems(const std::vector<JID>& items) { - this->items = std::set<JID>(items.begin(), items.end()); + foreach (const JID& jid, this->items) { + if (std::find(items.begin(), items.end(), jid) != items.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; } void BlockListImpl::addItem(const JID& item) { - if (items.insert(item).second) { + if (std::find(items.begin(), items.end(), item) == items.end()) { + items.push_back(item); onItemAdded(item); } } void BlockListImpl::removeItem(const JID& item) { - if (items.erase(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(); } } @@ -43,14 +60,13 @@ void BlockListImpl::addItems(const std::vector<JID>& items) { } void BlockListImpl::removeItems(const std::vector<JID>& items) { - foreach (const JID& item, items) { + std::vector<JID> itemsToRemove = items; + foreach (const JID& item, itemsToRemove) { removeItem(item); } } void BlockListImpl::removeAllItems() { - foreach (const JID& item, items) { - removeItem(item); - } + removeItems(items); } diff --git a/Swiften/Client/BlockListImpl.h b/Swiften/Client/BlockListImpl.h index ef08340..2a799ae 100644 --- a/Swiften/Client/BlockListImpl.h +++ b/Swiften/Client/BlockListImpl.h @@ -19,7 +19,7 @@ namespace Swift { void setState(State state); - virtual const std::set<JID>& getItems() const { + virtual const std::vector<JID>& getItems() const { return items; } @@ -32,6 +32,6 @@ namespace Swift { private: State state; - std::set<JID> items; + std::vector<JID> items; }; } diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp index 1a6c64b..f158370 100644 --- a/Swiften/Client/Client.cpp +++ b/Swiften/Client/Client.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2012 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -14,6 +14,7 @@ #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> @@ -30,6 +31,7 @@ #include <Swiften/Network/NetworkFactories.h> #include <Swiften/FileTransfer/FileTransferManagerImpl.h> #include <Swiften/Whiteboard/WhiteboardSessionManager.h> +#include <Swiften/Client/ClientBlockListManager.h> #ifndef SWIFT_EXPERIMENTAL_FT #include <Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h> #endif @@ -37,7 +39,7 @@ namespace Swift { Client::Client(const JID& jid, const SafeString& password, NetworkFactories* networkFactories, Storages* storages) : CoreClient(jid, password, networkFactories), storages(storages) { - memoryStorages = new MemoryStorages(); + memoryStorages = new MemoryStorages(networkFactories->getCryptoProvider()); softwareVersionResponder = new SoftwareVersionResponder(getIQRouter()); softwareVersionResponder->start(); @@ -52,14 +54,14 @@ Client::Client(const JID& jid, const SafeString& password, NetworkFactories* net stanzaChannelPresenceSender = new StanzaChannelPresenceSender(getStanzaChannel()); directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender); - discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender); + discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender, networkFactories->getCryptoProvider()); mucRegistry = new MUCRegistry(); mucManager = new MUCManager(getStanzaChannel(), getIQRouter(), directedPresenceSender, mucRegistry); vcardManager = new VCardManager(jid, getIQRouter(), getStorages()->getVCardStorage()); - avatarManager = new AvatarManagerImpl(vcardManager, getStanzaChannel(), getStorages()->getAvatarStorage(), mucRegistry); - capsManager = new CapsManager(getStorages()->getCapsStorage(), getStanzaChannel(), getIQRouter()); + 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); @@ -68,15 +70,19 @@ Client::Client(const JID& jid, const SafeString& password, NetworkFactories* net blindCertificateTrustChecker = new BlindCertificateTrustChecker(); jingleSessionManager = new JingleSessionManager(getIQRouter()); + blockListManager = new ClientBlockListManager(getIQRouter()); fileTransferManager = NULL; whiteboardSessionManager = NULL; #ifdef SWIFT_EXPERIMENTAL_WB whiteboardSessionManager = new WhiteboardSessionManager(getIQRouter(), getStanzaChannel(), presenceOracle, getEntityCapsProvider()); #endif + + pubsubManager = new PubSubManagerImpl(getStanzaChannel(), getIQRouter()); } Client::~Client() { + delete pubsubManager; delete whiteboardSessionManager; delete fileTransferManager; @@ -120,7 +126,18 @@ void Client::setSoftwareVersion(const std::string& name, const std::string& vers void Client::handleConnected() { #ifdef SWIFT_EXPERIMENTAL_FT - fileTransferManager = new FileTransferManagerImpl(getJID(), jingleSessionManager, getIQRouter(), getEntityCapsProvider(), presenceOracle, getNetworkFactories()->getConnectionFactory(), getNetworkFactories()->getConnectionServerFactory(), getNetworkFactories()->getTimerFactory(), getNetworkFactories()->getNATTraverser()); + 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 diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h index 126572a..9253074 100644 --- a/Swiften/Client/Client.h +++ b/Swiften/Client/Client.h @@ -37,6 +37,8 @@ namespace Swift { class JingleSessionManager; class FileTransferManager; class WhiteboardSessionManager; + class ClientBlockListManager; + class PubSubManager; /** * Provides the core functionality for writing XMPP client software. @@ -135,6 +137,10 @@ namespace Swift { ClientDiscoManager* getDiscoManager() const { return discoManager; } + + ClientBlockListManager* getClientBlockListManager() const { + return blockListManager; + } /** * Returns a FileTransferManager for the client. This is only available after the onConnected @@ -153,6 +159,11 @@ namespace Swift { void setAlwaysTrustCertificates(); WhiteboardSessionManager* getWhiteboardSessionManager() const; + + PubSubManager* getPubSubManager() const { + return pubsubManager; + } + public: /** @@ -188,6 +199,8 @@ namespace Swift { JingleSessionManager* jingleSessionManager; FileTransferManager* fileTransferManager; BlindCertificateTrustChecker* blindCertificateTrustChecker; - WhiteboardSessionManager* whiteboardSessionManager; + WhiteboardSessionManager* whiteboardSessionManager; + ClientBlockListManager* blockListManager; + PubSubManager* pubsubManager; }; } diff --git a/Swiften/Client/ClientBlockListManager.cpp b/Swiften/Client/ClientBlockListManager.cpp index 7222cea..6646a5c 100644 --- a/Swiften/Client/ClientBlockListManager.cpp +++ b/Swiften/Client/ClientBlockListManager.cpp @@ -66,11 +66,14 @@ namespace { } ClientBlockListManager::ClientBlockListManager(IQRouter* iqRouter) : iqRouter(iqRouter) { + } ClientBlockListManager::~ClientBlockListManager() { - unblockResponder->stop(); - blockResponder->stop(); + if (blockList && blockList->getState() == BlockList::Available) { + unblockResponder->stop(); + blockResponder->stop(); + } if (getRequest) { getRequest->onResponse.disconnect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); } @@ -88,13 +91,36 @@ boost::shared_ptr<BlockList> ClientBlockListManager::getBlockList() { return blockList; } +GenericRequest<BlockPayload>::ref ClientBlockListManager::createBlockJIDRequest(const JID& 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); +} + +GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockJIDRequest(const JID& 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); +} + +GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockAllRequest() { + 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->setState(BlockList::Available); blockList->setItems(payload->getItems()); + blockList->setState(BlockList::Available); blockResponder = boost::make_shared<BlockResponder>(blockList, iqRouter); blockResponder->start(); unblockResponder = boost::make_shared<UnblockResponder>(blockList, iqRouter); diff --git a/Swiften/Client/ClientBlockListManager.h b/Swiften/Client/ClientBlockListManager.h index 21d35e3..e8d4ac6 100644 --- a/Swiften/Client/ClientBlockListManager.h +++ b/Swiften/Client/ClientBlockListManager.h @@ -12,6 +12,7 @@ #include <Swiften/Elements/BlockPayload.h> #include <Swiften/Elements/BlockListPayload.h> #include <Swiften/Elements/UnblockPayload.h> +#include <Swiften/Elements/DiscoInfo.h> #include <Swiften/Queries/SetResponder.h> #include <Swiften/Queries/GenericRequest.h> #include <Swiften/Client/BlockList.h> @@ -25,13 +26,18 @@ namespace Swift { ClientBlockListManager(IQRouter *iqRouter); ~ClientBlockListManager(); - bool isSupported() const; - /** * 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); diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp index 48e38b9..f03cbaa 100644 --- a/Swiften/Client/ClientSession.cpp +++ b/Swiften/Client/ClientSession.cpp @@ -40,6 +40,7 @@ #include <Swiften/SASL/EXTERNALClientAuthenticator.h> #include <Swiften/SASL/SCRAMSHA1ClientAuthenticator.h> #include <Swiften/SASL/DIGESTMD5ClientAuthenticator.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Session/SessionStream.h> #include <Swiften/TLS/CertificateTrustChecker.h> #include <Swiften/TLS/ServerIdentityVerifier.h> @@ -56,10 +57,14 @@ namespace Swift { ClientSession::ClientSession( const JID& jid, - boost::shared_ptr<SessionStream> stream) : + 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), @@ -224,7 +229,7 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) { plus &= !finishMessage.empty(); } s << boost::uuids::random_generator()(); - SCRAMSHA1ClientAuthenticator* scramAuthenticator = new SCRAMSHA1ClientAuthenticator(s.str(), plus); + SCRAMSHA1ClientAuthenticator* scramAuthenticator = new SCRAMSHA1ClientAuthenticator(s.str(), plus, idnConverter, crypto); if (plus) { scramAuthenticator->setTLSChannelBindingData(finishMessage); } @@ -237,11 +242,11 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) { state = WaitingForCredentials; onNeedCredentials(); } - else if (streamFeatures->hasAuthenticationMechanism("DIGEST-MD5") && DIGESTMD5ClientAuthenticator::canBeUsed()) { + 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()); + authenticator = new DIGESTMD5ClientAuthenticator(localJID.getDomain(), s.str(), crypto); state = WaitingForCredentials; onNeedCredentials(); } @@ -378,7 +383,7 @@ void ClientSession::handleTLSEncrypted() { checkTrustOrFinish(certificateChain, verificationError); } else { - ServerIdentityVerifier identityVerifier(localJID); + ServerIdentityVerifier identityVerifier(localJID, idnConverter); if (!certificateChain.empty() && identityVerifier.certificateVerifies(certificateChain[0])) { continueAfterTLSEncrypted(); } diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h index 2553546..4b944fc 100644 --- a/Swiften/Client/ClientSession.h +++ b/Swiften/Client/ClientSession.h @@ -22,6 +22,8 @@ namespace Swift { class ClientAuthenticator; class CertificateTrustChecker; + class IDNConverter; + class CryptoProvider; class SWIFTEN_API ClientSession : public boost::enable_shared_from_this<ClientSession> { public: @@ -53,7 +55,7 @@ namespace Swift { SessionStartError, TLSClientCertificateError, TLSError, - StreamError, + StreamError } type; Error(Type type) : type(type) {} }; @@ -66,8 +68,8 @@ namespace Swift { ~ClientSession(); - static boost::shared_ptr<ClientSession> create(const JID& jid, boost::shared_ptr<SessionStream> stream) { - return boost::shared_ptr<ClientSession>(new ClientSession(jid, stream)); + 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 { @@ -92,7 +94,9 @@ namespace Swift { bool getStreamManagementEnabled() const { - return stanzaAckRequester_; + // Explicitly convert to bool. In C++11, it would be cleaner to + // compare to nullptr. + return static_cast<bool>(stanzaAckRequester_); } bool getRosterVersioningSupported() const { @@ -131,7 +135,9 @@ namespace Swift { private: ClientSession( const JID& jid, - boost::shared_ptr<SessionStream>); + boost::shared_ptr<SessionStream>, + IDNConverter* idnConverter, + CryptoProvider* crypto); void finishSession(Error::Type error); void finishSession(boost::shared_ptr<Swift::Error> error); @@ -161,6 +167,8 @@ namespace Swift { JID localJID; State state; boost::shared_ptr<SessionStream> stream; + IDNConverter* idnConverter; + CryptoProvider* crypto; bool allowPLAINOverNonTLS; bool useStreamCompression; UseTLS useTLS; diff --git a/Swiften/Client/ClientXMLTracer.cpp b/Swiften/Client/ClientXMLTracer.cpp index 405e3d1..b413f40 100644 --- a/Swiften/Client/ClientXMLTracer.cpp +++ b/Swiften/Client/ClientXMLTracer.cpp @@ -9,10 +9,16 @@ #include <iostream> #include <boost/bind.hpp> +#include <Swiften/Base/Platform.h> + namespace Swift { ClientXMLTracer::ClientXMLTracer(CoreClient* client, bool bosh) : bosh(bosh) { +#ifdef SWIFTEN_PLATFORM_WIN32 + beautifier = new XMLBeautifier(true, false); +#else beautifier = new XMLBeautifier(true, true); +#endif client->onDataRead.connect(boost::bind(&ClientXMLTracer::printData, this, '<', _1)); client->onDataWritten.connect(boost::bind(&ClientXMLTracer::printData, this, '>', _1)); } @@ -25,14 +31,14 @@ void ClientXMLTracer::printData(char direction, const SafeByteArray& data) { printLine(direction); if (bosh) { std::string line = byteArrayToString(ByteArray(data.begin(), data.end())); - size_t endOfHTTP = line.find("\r\n\r\n"); - if (false && endOfHTTP != std::string::npos) { - /* Disabled because it swallows bits of XML (namespaces, if I recall) */ - std::cerr << line.substr(0, endOfHTTP) << std::endl << beautifier->beautify(line.substr(endOfHTTP)) << std::endl; - } - else { +// 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; diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp index 5e19b4b..4438135 100644 --- a/Swiften/Client/CoreClient.cpp +++ b/Swiften/Client/CoreClient.cpp @@ -142,7 +142,7 @@ void CoreClient::connect(const ClientOptions& o) { } void CoreClient::bindSessionToStream() { - session_ = ClientSession::create(jid_, sessionStream_); + session_ = ClientSession::create(jid_, sessionStream_, networkFactories->getIDNConverter(), networkFactories->getCryptoProvider()); session_->setCertificateTrustChecker(certificateTrustChecker); session_->setUseStreamCompression(options.useStreamCompression); session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS); diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h index c9da0eb..eadfd9d 100644 --- a/Swiften/Client/CoreClient.h +++ b/Swiften/Client/CoreClient.h @@ -50,7 +50,6 @@ namespace Swift { public: /** * Constructs a client for the given JID with the given password. - * The given eventLoop will be used to post events to. */ CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories); ~CoreClient(); @@ -204,7 +203,7 @@ namespace Swift { /** * Called before onConnected signal is emmitted. */ - virtual void handleConnected() {}; + virtual void handleConnected() {} private: void handleConnectorFinished(boost::shared_ptr<Connection>, boost::shared_ptr<Error> error); diff --git a/Swiften/Client/MemoryStorages.cpp b/Swiften/Client/MemoryStorages.cpp index 703e9ff..885d74f 100644 --- a/Swiften/Client/MemoryStorages.cpp +++ b/Swiften/Client/MemoryStorages.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -13,8 +13,8 @@ namespace Swift { -MemoryStorages::MemoryStorages() { - vcardStorage = new VCardMemoryStorage(); +MemoryStorages::MemoryStorages(CryptoProvider* crypto) { + vcardStorage = new VCardMemoryStorage(crypto); capsStorage = new CapsMemoryStorage(); avatarStorage = new AvatarMemoryStorage(); rosterStorage = new RosterMemoryStorage(); diff --git a/Swiften/Client/MemoryStorages.h b/Swiften/Client/MemoryStorages.h index 403a89a..68ec285 100644 --- a/Swiften/Client/MemoryStorages.h +++ b/Swiften/Client/MemoryStorages.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -10,6 +10,7 @@ namespace Swift { class VCardMemoryStorage; + class CryptoProvider; /** * An implementation of Storages for storing all @@ -17,7 +18,7 @@ namespace Swift { */ class MemoryStorages : public Storages { public: - MemoryStorages(); + MemoryStorages(CryptoProvider*); ~MemoryStorages(); virtual VCardStorage* getVCardStorage() const; diff --git a/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp b/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp new file mode 100644 index 0000000..9010042 --- /dev/null +++ b/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <algorithm> + +#include <Swiften/Base/foreach.h> + +#include <Swiften/Client/StanzaChannel.h> +#include <Swiften/Client/DummyStanzaChannel.h> +#include <Swiften/Client/ClientBlockListManager.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Elements/IQ.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_REGISTRATION(ClientBlockListManagerTest); + diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp index a8cd53c..4ef6727 100644 --- a/Swiften/Client/UnitTest/ClientSessionTest.cpp +++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp @@ -11,6 +11,8 @@ #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/Client/ClientSession.h> #include <Swiften/Elements/Message.h> @@ -31,6 +33,8 @@ #include <Swiften/Elements/ResourceBind.h> #include <Swiften/TLS/SimpleCertificate.h> #include <Swiften/TLS/BlindCertificateTrustChecker.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> using namespace Swift; @@ -69,6 +73,8 @@ class ClientSessionTest : public CppUnit::TestFixture { 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; @@ -339,7 +345,7 @@ class ClientSessionTest : public CppUnit::TestFixture { private: boost::shared_ptr<ClientSession> createSession() { - boost::shared_ptr<ClientSession> session = ClientSession::create(JID("me@foo.com"), server); + 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); @@ -616,11 +622,13 @@ class ClientSessionTest : public CppUnit::TestFixture { 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_REGISTRATION(ClientSessionTest); diff --git a/Swiften/Client/UnitTest/NickResolverTest.cpp b/Swiften/Client/UnitTest/NickResolverTest.cpp index dfc90fe..a8b011c 100644 --- a/Swiften/Client/UnitTest/NickResolverTest.cpp +++ b/Swiften/Client/UnitTest/NickResolverTest.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -14,6 +20,8 @@ #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; @@ -34,11 +42,12 @@ class NickResolverTest : public CppUnit::TestFixture { 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(); + vCardStorage_ = new VCardMemoryStorage(crypto.get()); vCardManager_ = new VCardManager(ownJID_, iqRouter_, vCardStorage_); registry_ = new MUCRegistry(); resolver_ = new NickResolver(ownJID_, xmppRoster_, vCardManager_, registry_); @@ -144,7 +153,7 @@ class NickResolverTest : public CppUnit::TestFixture { MUCRegistry* registry_; NickResolver* resolver_; JID ownJID_; - + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(NickResolverTest); diff --git a/Swiften/Component/Component.cpp b/Swiften/Component/Component.cpp index af378a7..a53f514 100644 --- a/Swiften/Component/Component.cpp +++ b/Swiften/Component/Component.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -10,7 +10,7 @@ namespace Swift { -Component::Component(EventLoop* eventLoop, NetworkFactories* networkFactories, const JID& jid, const std::string& secret) : CoreComponent(eventLoop, networkFactories, jid, secret) { +Component::Component(const JID& jid, const std::string& secret, NetworkFactories* networkFactories) : CoreComponent(jid, secret, networkFactories) { softwareVersionResponder = new SoftwareVersionResponder(getIQRouter()); softwareVersionResponder->start(); } diff --git a/Swiften/Component/Component.h b/Swiften/Component/Component.h index f3ae9e8..3ead1a5 100644 --- a/Swiften/Component/Component.h +++ b/Swiften/Component/Component.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -20,7 +20,7 @@ namespace Swift { */ class SWIFTEN_API Component : public CoreComponent { public: - Component(EventLoop* eventLoop, NetworkFactories* networkFactories, const JID& jid, const std::string& secret); + Component(const JID& jid, const std::string& secret, NetworkFactories* networkFactories); ~Component(); /** diff --git a/Swiften/Component/ComponentConnector.cpp b/Swiften/Component/ComponentConnector.cpp index b7bdd34..0dd8e82 100644 --- a/Swiften/Component/ComponentConnector.cpp +++ b/Swiften/Component/ComponentConnector.cpp @@ -104,4 +104,4 @@ void ComponentConnector::handleTimeout() { finish(boost::shared_ptr<Connection>()); } -}; +} diff --git a/Swiften/Component/ComponentConnector.h b/Swiften/Component/ComponentConnector.h index 549457b..0e35ab2 100644 --- a/Swiften/Component/ComponentConnector.h +++ b/Swiften/Component/ComponentConnector.h @@ -62,4 +62,4 @@ namespace Swift { std::deque<HostAddress> addressQueryResults; boost::shared_ptr<Connection> currentConnection; }; -}; +} diff --git a/Swiften/Component/ComponentError.h b/Swiften/Component/ComponentError.h index 928af2a..9c54b53 100644 --- a/Swiften/Component/ComponentError.h +++ b/Swiften/Component/ComponentError.h @@ -16,7 +16,7 @@ namespace Swift { ConnectionWriteError, XMLError, AuthenticationFailedError, - UnexpectedElementError, + UnexpectedElementError }; ComponentError(Type type = UnknownError) : type_(type) {} diff --git a/Swiften/Component/ComponentHandshakeGenerator.cpp b/Swiften/Component/ComponentHandshakeGenerator.cpp index 79ba9b3..495d530 100644 --- a/Swiften/Component/ComponentHandshakeGenerator.cpp +++ b/Swiften/Component/ComponentHandshakeGenerator.cpp @@ -6,19 +6,19 @@ #include <Swiften/Component/ComponentHandshakeGenerator.h> #include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/StringCodecs/SHA1.h> #include <Swiften/Base/String.h> +#include <Swiften/Crypto/CryptoProvider.h> namespace Swift { -std::string ComponentHandshakeGenerator::getHandshake(const std::string& streamID, const std::string& secret) { +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(SHA1::getHash(createByteArray(concatenatedString))); + return Hexify::hexify(crypto->getSHA1Hash(createByteArray(concatenatedString))); } } diff --git a/Swiften/Component/ComponentHandshakeGenerator.h b/Swiften/Component/ComponentHandshakeGenerator.h index c897fdc..e0e3ef8 100644 --- a/Swiften/Component/ComponentHandshakeGenerator.h +++ b/Swiften/Component/ComponentHandshakeGenerator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,9 +11,11 @@ #include <Swiften/Base/API.h> namespace Swift { + class CryptoProvider; + class SWIFTEN_API ComponentHandshakeGenerator { public: - static std::string getHandshake(const std::string& streamID, const std::string& secret); + 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 3269f23..7925b23 100644 --- a/Swiften/Component/ComponentSession.cpp +++ b/Swiften/Component/ComponentSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -17,7 +17,7 @@ namespace Swift { -ComponentSession::ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream> stream) : jid(jid), secret(secret), stream(stream), state(Initial) { +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() { @@ -46,7 +46,7 @@ void ComponentSession::sendStanza(boost::shared_ptr<Stanza> stanza) { void ComponentSession::handleStreamStart(const ProtocolHeader& header) { checkState(WaitingForStreamStart); state = Authenticating; - stream->writeElement(ComponentHandshake::ref(new ComponentHandshake(ComponentHandshakeGenerator::getHandshake(header.getID(), secret)))); + stream->writeElement(ComponentHandshake::ref(new ComponentHandshake(ComponentHandshakeGenerator::getHandshake(header.getID(), secret, crypto)))); } void ComponentSession::handleElement(boost::shared_ptr<Element> element) { diff --git a/Swiften/Component/ComponentSession.h b/Swiften/Component/ComponentSession.h index 073c3f4..3103335 100644 --- a/Swiften/Component/ComponentSession.h +++ b/Swiften/Component/ComponentSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -20,6 +20,7 @@ namespace Swift { class ComponentAuthenticator; + class CryptoProvider; class SWIFTEN_API ComponentSession : public boost::enable_shared_from_this<ComponentSession> { public: @@ -35,15 +36,15 @@ namespace Swift { struct Error : public Swift::Error { enum Type { AuthenticationFailedError, - UnexpectedElementError, + 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) { - return boost::shared_ptr<ComponentSession>(new ComponentSession(jid, secret, stream)); + 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 { @@ -61,7 +62,7 @@ namespace Swift { boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; private: - ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream>); + 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); @@ -78,6 +79,7 @@ namespace Swift { JID jid; std::string secret; boost::shared_ptr<SessionStream> stream; + CryptoProvider* crypto; boost::shared_ptr<Swift::Error> error; State state; }; diff --git a/Swiften/Component/CoreComponent.cpp b/Swiften/Component/CoreComponent.cpp index e11d2b0..d2cc7aa 100644 --- a/Swiften/Component/CoreComponent.cpp +++ b/Swiften/Component/CoreComponent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -20,7 +20,7 @@ namespace Swift { -CoreComponent::CoreComponent(EventLoop* eventLoop, NetworkFactories* networkFactories, const JID& jid, const std::string& secret) : eventLoop(eventLoop), networkFactories(networkFactories), resolver_(eventLoop), jid_(jid), secret_(secret), disconnectRequested_(false) { +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)); @@ -44,7 +44,7 @@ CoreComponent::~CoreComponent() { void CoreComponent::connect(const std::string& host, int port) { assert(!connector_); - connector_ = ComponentConnector::create(host, port, &resolver_, networkFactories->getConnectionFactory(), networkFactories->getTimerFactory()); + 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(); @@ -67,7 +67,7 @@ void CoreComponent::handleConnectorFinished(boost::shared_ptr<Connection> connec sessionStream_->onDataRead.connect(boost::bind(&CoreComponent::handleDataRead, this, _1)); sessionStream_->onDataWritten.connect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); - session_ = ComponentSession::create(jid_, secret_, sessionStream_); + session_ = ComponentSession::create(jid_, secret_, sessionStream_, networkFactories->getCryptoProvider()); stanzaChannel_->setSession(session_); session_->onFinished.connect(boost::bind(&CoreComponent::handleSessionFinished, this, _1)); session_->start(); @@ -85,9 +85,9 @@ void CoreComponent::disconnect() { connector_->stop(); assert(!session_); } - assert(!session_); - assert(!sessionStream_); - assert(!connector_); + //assert(!session_); /* commenting out until we have time to refactor to be like CoreClient */ + //assert(!sessionStream_); + //assert(!connector_); disconnectRequested_ = false; } diff --git a/Swiften/Component/CoreComponent.h b/Swiften/Component/CoreComponent.h index 4f39ffd..63b68f6 100644 --- a/Swiften/Component/CoreComponent.h +++ b/Swiften/Component/CoreComponent.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,7 +11,6 @@ #include <Swiften/Base/API.h> #include <Swiften/Base/boost_bsignals.h> #include <Swiften/Base/Error.h> -#include <Swiften/Network/PlatformDomainNameResolver.h> #include <Swiften/Component/ComponentConnector.h> #include <Swiften/Component/ComponentSession.h> #include <Swiften/Component/ComponentError.h> @@ -26,6 +25,7 @@ #include <Swiften/Base/SafeByteArray.h> namespace Swift { + class EventLoop; class IQRouter; class NetworkFactories; class ComponentSession; @@ -43,7 +43,7 @@ namespace Swift { */ class SWIFTEN_API CoreComponent : public Entity { public: - CoreComponent(EventLoop* eventLoop, NetworkFactories* networkFactories, const JID& jid, const std::string& secret); + CoreComponent(const JID& jid, const std::string& secret, NetworkFactories* networkFactories); ~CoreComponent(); void connect(const std::string& host, int port); @@ -88,9 +88,7 @@ namespace Swift { void handleDataWritten(const SafeByteArray&); private: - EventLoop* eventLoop; NetworkFactories* networkFactories; - PlatformDomainNameResolver resolver_; JID jid_; std::string secret_; ComponentSessionStanzaChannel* stanzaChannel_; diff --git a/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp b/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp index fd8f6fc..280e46e 100644 --- a/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp +++ b/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -8,6 +8,8 @@ #include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Component/ComponentHandshakeGenerator.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> using namespace Swift; @@ -18,16 +20,22 @@ class ComponentHandshakeGeneratorTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_END(); public: + void setUp() { + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } + void testGetHandshake() { - std::string result = ComponentHandshakeGenerator::getHandshake("myid", "mysecret"); + std::string result = ComponentHandshakeGenerator::getHandshake("myid", "mysecret", crypto.get()); CPPUNIT_ASSERT_EQUAL(std::string("4011cd31f9b99ac089a0cd7ce297da7323fa2525"), result); } void testGetHandshake_SpecialChars() { - std::string result = ComponentHandshakeGenerator::getHandshake("&<", ">'\""); + std::string result = ComponentHandshakeGenerator::getHandshake("&<", ">'\"", crypto.get()); CPPUNIT_ASSERT_EQUAL(std::string("33631b3e0aaeb2a11c4994c917919324028873fe"), result); } + private: + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(ComponentHandshakeGeneratorTest); diff --git a/Swiften/Component/UnitTest/ComponentSessionTest.cpp b/Swiften/Component/UnitTest/ComponentSessionTest.cpp index 238d0b0..0533645 100644 --- a/Swiften/Component/UnitTest/ComponentSessionTest.cpp +++ b/Swiften/Component/UnitTest/ComponentSessionTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -14,6 +14,8 @@ #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> using namespace Swift; @@ -28,6 +30,7 @@ class ComponentSessionTest : public CppUnit::TestFixture { void setUp() { server = boost::make_shared<MockSessionStream>(); sessionFinishedReceived = false; + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); } void testStart() { @@ -70,7 +73,7 @@ class ComponentSessionTest : public CppUnit::TestFixture { private: boost::shared_ptr<ComponentSession> createSession() { - boost::shared_ptr<ComponentSession> session = ComponentSession::create(JID("service.foo.com"), "servicesecret", server); + 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; } @@ -210,8 +213,8 @@ class ComponentSessionTest : public CppUnit::TestFixture { boost::shared_ptr<MockSessionStream> server; bool sessionFinishedReceived; - bool needCredentials; boost::shared_ptr<Error> sessionFinishedError; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(ComponentSessionTest); diff --git a/Swiften/Compress/ZLibCodecompressor.cpp b/Swiften/Compress/ZLibCodecompressor.cpp index 125492a..85d0174 100644 --- a/Swiften/Compress/ZLibCodecompressor.cpp +++ b/Swiften/Compress/ZLibCodecompressor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -9,13 +9,14 @@ #include <cassert> #include <string.h> #include <zlib.h> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Compress/ZLibException.h> #include <Swiften/Compress/ZLibCodecompressor_Private.h> namespace Swift { -static const int CHUNK_SIZE = 1024; // If you change this, also change the unittest +static const size_t CHUNK_SIZE = 1024; // If you change this, also change the unittest ZLibCodecompressor::ZLibCodecompressor() : p(boost::make_shared<Private>()) { @@ -30,9 +31,9 @@ ZLibCodecompressor::~ZLibCodecompressor() { SafeByteArray ZLibCodecompressor::process(const SafeByteArray& input) { SafeByteArray output; - p->stream.avail_in = input.size(); + p->stream.avail_in = static_cast<unsigned int>(input.size()); p->stream.next_in = reinterpret_cast<Bytef*>(const_cast<unsigned char*>(vecptr(input))); - int outputPosition = 0; + size_t outputPosition = 0; do { output.resize(outputPosition + CHUNK_SIZE); p->stream.avail_out = CHUNK_SIZE; diff --git a/Swiften/Config/.gitignore b/Swiften/Config/.gitignore index 2ae0953..e7b484e 100644 --- a/Swiften/Config/.gitignore +++ b/Swiften/Config/.gitignore @@ -1,3 +1,5 @@ swiften-config swiften-config.h Paths.cpp +Path.cpp +String.cpp diff --git a/Swiften/Config/SConscript b/Swiften/Config/SConscript index 357a5e6..837884b 100644 --- a/Swiften/Config/SConscript +++ b/Swiften/Config/SConscript @@ -6,7 +6,7 @@ def replaceSwiftenPath(input) : return input.replace(env.Dir("#").abspath, "#") def cStringVariable(env, cVar, sconsVar) : - result = "const char* " + cVar + "[] = {\n" + result = "static const char* " + cVar + "[] = {\n" # FIXME: Probably not very robust for var in sconsVar.split(" ") : result += "\t\"" + env.subst(var).replace("\\", "\\\\") + "\",\n" @@ -17,23 +17,38 @@ def cStringVariable(env, cVar, sconsVar) : config_flags = "" swiften_env = env.Clone() -swiften_env.MergeFlags(swiften_env["SWIFTEN_FLAGS"]) -swiften_env.MergeFlags(swiften_env["SWIFTEN_DEP_FLAGS"]) +swiften_env.UseFlags(swiften_env["SWIFTEN_FLAGS"]) +swiften_env.UseFlags(swiften_env["SWIFTEN_DEP_FLAGS"]) -cppflags = replaceSwiftenPath(" ".join([swiften_env.subst("$_CPPDEFFLAGS"), swiften_env.subst("$_CPPINCFLAGS")])) +cppflags = replaceSwiftenPath(" ".join([ + 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")])) +libflags = replaceSwiftenPath(" ".join([ + 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() # Create a local copy of Paths.cpp to avoid a Swiften dependency -config_env.Install(".", "#/Swiften/Base/Paths.cpp") -config_env.MergeFlags(config_env["BOOST_FLAGS"]) -config_env.MergeFlags(config_env["PLATFORM_FLAGS"]) +config_env.Install(".", [ + "#/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" ]) diff --git a/Swiften/Config/swiften-config.cpp b/Swiften/Config/swiften-config.cpp index 81a8357..778134d 100644 --- a/Swiften/Config/swiften-config.cpp +++ b/Swiften/Config/swiften-config.cpp @@ -16,13 +16,14 @@ #include <Swiften/Base/Platform.h> #include <Swiften/Base/Paths.h> +#include <Swiften/Base/Path.h> #include <Swiften/Version.h> #include "swiften-config.h" using namespace Swift; -void printFlags(const std::vector<std::string>& flags) { +static void printFlags(const std::vector<std::string>& flags) { for (size_t i = 0; i < flags.size(); ++i) { if (i > 0) { std::cout << " "; @@ -90,12 +91,12 @@ int main(int argc, char* argv[]) { for(size_t i = 0; i < libs.size(); ++i) { if (inPlace) { std::string lib = libs[i]; - boost::replace_all(lib, "#", topSourcePath.string()); + boost::replace_all(lib, "#", pathToString(topSourcePath)); libs[i] = lib; } else { std::string lib = libs[i]; - boost::replace_all(lib, "#", (topInstallPath / "lib").string()); + boost::replace_all(lib, "#", pathToString(topInstallPath / "lib")); boost::erase_all(lib, "/Swiften"); libs[i] = lib; } @@ -103,12 +104,12 @@ int main(int argc, char* argv[]) { for(size_t i = 0; i < cflags.size(); ++i) { if (inPlace) { std::string cflag = cflags[i]; - boost::replace_all(cflag, "#", topSourcePath.string()); + boost::replace_all(cflag, "#", pathToString(topSourcePath)); cflags[i] = cflag; } else { std::string cflag = cflags[i]; - boost::replace_all(cflag, "#", (topInstallPath / "include").string()); + boost::replace_all(cflag, "#", pathToString(topInstallPath / "include")); cflags[i] = cflag; } } @@ -118,7 +119,7 @@ int main(int argc, char* argv[]) { if (vm.count("libs") > 0) { printFlags(libs); } - else if (vm.count("cflags") > 0) { + if (vm.count("cflags") > 0) { printFlags(cflags); } return 0; diff --git a/Swiften/Crypto/CommonCryptoCryptoProvider.cpp b/Swiften/Crypto/CommonCryptoCryptoProvider.cpp new file mode 100644 index 0000000..14f9284 --- /dev/null +++ b/Swiften/Crypto/CommonCryptoCryptoProvider.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Crypto/CommonCryptoCryptoProvider.h> + +#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> + +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; + } +} + +CommonCryptoCryptoProvider::CommonCryptoCryptoProvider() { +} + +CommonCryptoCryptoProvider::~CommonCryptoCryptoProvider() { +} + +Hash* CommonCryptoCryptoProvider::createSHA1() { + return new SHA1Hash(); +} + +Hash* CommonCryptoCryptoProvider::createMD5() { + return new MD5Hash(); +} + +ByteArray CommonCryptoCryptoProvider::getHMACSHA1(const SafeByteArray& key, const ByteArray& data) { + return getHMACSHA1Internal(key, data); +} + +ByteArray CommonCryptoCryptoProvider::getHMACSHA1(const ByteArray& key, const ByteArray& data) { + return getHMACSHA1Internal(key, data); +} + +bool CommonCryptoCryptoProvider::isMD5AllowedForCrypto() const { + return true; +} + diff --git a/Swiften/Crypto/CommonCryptoCryptoProvider.h b/Swiften/Crypto/CommonCryptoCryptoProvider.h new file mode 100644 index 0000000..f921e17 --- /dev/null +++ b/Swiften/Crypto/CommonCryptoCryptoProvider.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Base/Override.h> + +namespace Swift { + class CommonCryptoCryptoProvider : public CryptoProvider { + public: + CommonCryptoCryptoProvider(); + ~CommonCryptoCryptoProvider(); + + 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; + }; +} diff --git a/Swiften/Crypto/CryptoProvider.cpp b/Swiften/Crypto/CryptoProvider.cpp new file mode 100644 index 0000000..0189de4 --- /dev/null +++ b/Swiften/Crypto/CryptoProvider.cpp @@ -0,0 +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() {
+}
diff --git a/Swiften/Crypto/CryptoProvider.h b/Swiften/Crypto/CryptoProvider.h new file mode 100644 index 0000000..c1e1eb9 --- /dev/null +++ b/Swiften/Crypto/CryptoProvider.h @@ -0,0 +1,36 @@ +/* + * 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> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Crypto/Hash.h> + +namespace Swift { + class Hash; + + 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; + + // Convenience + template<typename T> ByteArray getSHA1Hash(const T& data) { + return boost::shared_ptr<Hash>(createSHA1())->update(data).getHash(); + } + + template<typename T> ByteArray getMD5Hash(const T& data) { + return boost::shared_ptr<Hash>(createMD5())->update(data).getHash(); + } + }; +} diff --git a/Swiften/Crypto/Hash.cpp b/Swiften/Crypto/Hash.cpp new file mode 100644 index 0000000..35c7e70 --- /dev/null +++ b/Swiften/Crypto/Hash.cpp @@ -0,0 +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() {
+}
diff --git a/Swiften/Crypto/Hash.h b/Swiften/Crypto/Hash.h new file mode 100644 index 0000000..37c6ec8 --- /dev/null +++ b/Swiften/Crypto/Hash.h @@ -0,0 +1,24 @@ +/*
+ * 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;
+ };
+}
diff --git a/Swiften/Crypto/OpenSSLCryptoProvider.cpp b/Swiften/Crypto/OpenSSLCryptoProvider.cpp new file mode 100644 index 0000000..9b1d544 --- /dev/null +++ b/Swiften/Crypto/OpenSSLCryptoProvider.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Crypto/OpenSSLCryptoProvider.h> + +#include <openssl/sha.h> +#include <openssl/md5.h> +#include <openssl/hmac.h> +#include <cassert> +#include <boost/numeric/conversion/cast.hpp> + +#include <Swiften/Crypto/Hash.h> +#include <Swiften/Base/ByteArray.h> + +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +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; + } +} + +OpenSSLCryptoProvider::OpenSSLCryptoProvider() { +} + +OpenSSLCryptoProvider::~OpenSSLCryptoProvider() { +} + +Hash* OpenSSLCryptoProvider::createSHA1() { + return new SHA1Hash(); +} + +Hash* OpenSSLCryptoProvider::createMD5() { + return new MD5Hash(); +} + +ByteArray OpenSSLCryptoProvider::getHMACSHA1(const SafeByteArray& key, const ByteArray& data) { + return getHMACSHA1Internal(key, data); +} + +ByteArray OpenSSLCryptoProvider::getHMACSHA1(const ByteArray& key, const ByteArray& data) { + return getHMACSHA1Internal(key, data); +} + +bool OpenSSLCryptoProvider::isMD5AllowedForCrypto() const { + return true; +} + diff --git a/Swiften/Crypto/OpenSSLCryptoProvider.h b/Swiften/Crypto/OpenSSLCryptoProvider.h new file mode 100644 index 0000000..9440aee --- /dev/null +++ b/Swiften/Crypto/OpenSSLCryptoProvider.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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(); + + 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; + }; +} diff --git a/Swiften/Crypto/PlatformCryptoProvider.cpp b/Swiften/Crypto/PlatformCryptoProvider.cpp new file mode 100644 index 0000000..ab0fa7b --- /dev/null +++ b/Swiften/Crypto/PlatformCryptoProvider.cpp @@ -0,0 +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;
+}
diff --git a/Swiften/Crypto/PlatformCryptoProvider.h b/Swiften/Crypto/PlatformCryptoProvider.h new file mode 100644 index 0000000..0721887 --- /dev/null +++ b/Swiften/Crypto/PlatformCryptoProvider.h @@ -0,0 +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();
+ }
+}
diff --git a/Swiften/Crypto/SConscript b/Swiften/Crypto/SConscript new file mode 100644 index 0000000..ce4bdae --- /dev/null +++ b/Swiften/Crypto/SConscript @@ -0,0 +1,28 @@ +Import("swiften_env", "env")
+
+
+objects = swiften_env.SwiftenObject([
+ "CryptoProvider.cpp",
+ "Hash.cpp"
+])
+
+myenv = swiften_env.Clone()
+if myenv["PLATFORM"] == "win32" :
+ objects += myenv.SwiftenObject(["WindowsCryptoProvider.cpp"])
+if myenv.get("HAVE_OPENSSL", False) :
+ 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"])
+
+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"),
+ ]))
diff --git a/Swiften/Crypto/UnitTest/CryptoProviderTest.cpp b/Swiften/Crypto/UnitTest/CryptoProviderTest.cpp new file mode 100644 index 0000000..1e2275a --- /dev/null +++ b/Swiften/Crypto/UnitTest/CryptoProviderTest.cpp @@ -0,0 +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
diff --git a/Swiften/Crypto/WindowsCryptoProvider.cpp b/Swiften/Crypto/WindowsCryptoProvider.cpp new file mode 100644 index 0000000..9ca4c14 --- /dev/null +++ b/Swiften/Crypto/WindowsCryptoProvider.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2012 Kevin Smith + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Crypto/WindowsCryptoProvider.h> + +#include <Windows.h> +#define SECURITY_WIN32 +#include <security.h> +#include <Wincrypt.h> +#include <cassert> +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Crypto/Hash.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/WindowsRegistry.h> + +using namespace Swift; + +struct WindowsCryptoProvider::Private { + 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; + }; + +#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; + }; +#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); + } +} + +WindowsCryptoProvider::WindowsCryptoProvider() { + p = boost::make_shared<Private>(); + if (!CryptAcquireContext(&p->context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + assert(false); + } +} + +WindowsCryptoProvider::~WindowsCryptoProvider() { + CryptReleaseContext(p->context, 0); +} + +Hash* WindowsCryptoProvider::createSHA1() { + return new WindowsHash(p->context, CALG_SHA1); +} + +Hash* WindowsCryptoProvider::createMD5() { + return new WindowsHash(p->context, CALG_MD5); +} + +bool WindowsCryptoProvider::isMD5AllowedForCrypto() const { + return !WindowsRegistry::isFIPSEnabled(); +} + +ByteArray WindowsCryptoProvider::getHMACSHA1(const SafeByteArray& key, const ByteArray& data) { + return getHMACSHA1Internal(key, data, this); +} + +ByteArray WindowsCryptoProvider::getHMACSHA1(const ByteArray& key, const ByteArray& data) { + return getHMACSHA1Internal(key, data, this); +} diff --git a/Swiften/Crypto/WindowsCryptoProvider.h b/Swiften/Crypto/WindowsCryptoProvider.h new file mode 100644 index 0000000..9418fc0 --- /dev/null +++ b/Swiften/Crypto/WindowsCryptoProvider.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Base/Override.h> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class WindowsCryptoProvider : public CryptoProvider, public boost::noncopyable { + public: + WindowsCryptoProvider(); + ~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; + + private: + struct Private; + boost::shared_ptr<Private> p; + }; +} diff --git a/Swiften/Disco/CapsInfoGenerator.cpp b/Swiften/Disco/CapsInfoGenerator.cpp index 6d84984..4332f76 100644 --- a/Swiften/Disco/CapsInfoGenerator.cpp +++ b/Swiften/Disco/CapsInfoGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,7 +11,7 @@ #include <Swiften/Base/foreach.h> #include <Swiften/Elements/DiscoInfo.h> #include <Swiften/Elements/FormField.h> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/StringCodecs/Base64.h> namespace { @@ -22,7 +22,7 @@ namespace { namespace Swift { -CapsInfoGenerator::CapsInfoGenerator(const std::string& node) : node_(node) { +CapsInfoGenerator::CapsInfoGenerator(const std::string& node, CryptoProvider* crypto) : node_(node), crypto_(crypto) { } CapsInfo CapsInfoGenerator::generateCapsInfo(const DiscoInfo& discoInfo) const { @@ -49,7 +49,7 @@ CapsInfo CapsInfoGenerator::generateCapsInfo(const DiscoInfo& discoInfo) const { continue; } serializedCaps += field->getName() + "<"; - std::vector<std::string> values(field->getRawValues()); + std::vector<std::string> values(field->getValues()); std::sort(values.begin(), values.end()); foreach(const std::string& value, values) { serializedCaps += value + "<"; @@ -57,7 +57,7 @@ CapsInfo CapsInfoGenerator::generateCapsInfo(const DiscoInfo& discoInfo) const { } } - std::string version(Base64::encode(SHA1::getHash(createByteArray(serializedCaps)))); + 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 62958e7..17a01dd 100644 --- a/Swiften/Disco/CapsInfoGenerator.h +++ b/Swiften/Disco/CapsInfoGenerator.h @@ -12,14 +12,16 @@ namespace Swift { class DiscoInfo; + class CryptoProvider; class SWIFTEN_API CapsInfoGenerator { public: - CapsInfoGenerator(const std::string& node); + CapsInfoGenerator(const std::string& node, CryptoProvider* crypto); CapsInfo generateCapsInfo(const DiscoInfo& discoInfo) const; private: std::string node_; + CryptoProvider* crypto_; }; } diff --git a/Swiften/Disco/CapsManager.cpp b/Swiften/Disco/CapsManager.cpp index 66eb47e..18f8745 100644 --- a/Swiften/Disco/CapsManager.cpp +++ b/Swiften/Disco/CapsManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -17,7 +17,7 @@ namespace Swift { -CapsManager::CapsManager(CapsStorage* capsStorage, StanzaChannel* stanzaChannel, IQRouter* iqRouter) : iqRouter(iqRouter), capsStorage(capsStorage), warnOnInvalidHash(true) { +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)); } @@ -51,7 +51,7 @@ void CapsManager::handleStanzaChannelAvailableChanged(bool available) { void CapsManager::handleDiscoInfoReceived(const JID& from, const std::string& hash, DiscoInfo::ref discoInfo, ErrorPayload::ref error) { requestedDiscoInfos.erase(hash); - if (error || !discoInfo || CapsInfoGenerator("").generateCapsInfo(*discoInfo.get()).getVersion() != 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; } diff --git a/Swiften/Disco/CapsManager.h b/Swiften/Disco/CapsManager.h index 9f1d83b..3529812 100644 --- a/Swiften/Disco/CapsManager.h +++ b/Swiften/Disco/CapsManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -22,10 +22,11 @@ namespace Swift { class IQRouter; class JID; class CapsStorage; + class CryptoProvider; class SWIFTEN_API CapsManager : public CapsProvider, public boost::bsignals::trackable { public: - CapsManager(CapsStorage*, StanzaChannel*, IQRouter*); + CapsManager(CapsStorage*, StanzaChannel*, IQRouter*, CryptoProvider*); DiscoInfo::ref getCaps(const std::string&) const; @@ -42,6 +43,7 @@ namespace Swift { private: IQRouter* iqRouter; + CryptoProvider* crypto; CapsStorage* capsStorage; bool warnOnInvalidHash; std::set<std::string> requestedDiscoInfos; diff --git a/Swiften/Disco/ClientDiscoManager.cpp b/Swiften/Disco/ClientDiscoManager.cpp index cca0144..f6683a8 100644 --- a/Swiften/Disco/ClientDiscoManager.cpp +++ b/Swiften/Disco/ClientDiscoManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -12,7 +12,7 @@ namespace Swift { -ClientDiscoManager::ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender) { +ClientDiscoManager::ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender, CryptoProvider* crypto) : crypto(crypto) { discoInfoResponder = new DiscoInfoResponder(iqRouter); discoInfoResponder->start(); this->presenceSender = new PayloadAddingPresenceSender(presenceSender); @@ -29,7 +29,7 @@ void ClientDiscoManager::setCapsNode(const std::string& node) { } void ClientDiscoManager::setDiscoInfo(const DiscoInfo& discoInfo) { - capsInfo = CapsInfo::ref(new CapsInfo(CapsInfoGenerator(capsNode).generateCapsInfo(discoInfo))); + capsInfo = CapsInfo::ref(new CapsInfo(CapsInfoGenerator(capsNode, crypto).generateCapsInfo(discoInfo))); discoInfoResponder->clearDiscoInfo(); discoInfoResponder->setDiscoInfo(discoInfo); discoInfoResponder->setDiscoInfo(capsInfo->getNode() + "#" + capsInfo->getVersion(), discoInfo); diff --git a/Swiften/Disco/ClientDiscoManager.h b/Swiften/Disco/ClientDiscoManager.h index 0cae40e..a9ed10a 100644 --- a/Swiften/Disco/ClientDiscoManager.h +++ b/Swiften/Disco/ClientDiscoManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -16,6 +16,7 @@ namespace Swift { class DiscoInfoResponder; class PayloadAddingPresenceSender; class PresenceSender; + class CryptoProvider; /** * Class responsible for managing outgoing disco information for a client. @@ -36,7 +37,7 @@ namespace Swift { * \param presenceSender the presence sender to which all outgoing presence * (with caps information) will be sent. */ - ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender); + ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender, CryptoProvider* crypto); ~ClientDiscoManager(); /** @@ -68,6 +69,7 @@ namespace Swift { private: PayloadAddingPresenceSender* presenceSender; + CryptoProvider* crypto; DiscoInfoResponder* discoInfoResponder; std::string capsNode; CapsInfo::ref capsInfo; diff --git a/Swiften/Disco/DiscoServiceWalker.cpp b/Swiften/Disco/DiscoServiceWalker.cpp index c8c3e1b..0f27111 100644 --- a/Swiften/Disco/DiscoServiceWalker.cpp +++ b/Swiften/Disco/DiscoServiceWalker.cpp @@ -35,6 +35,7 @@ void DiscoServiceWalker::endWalk() { request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, request)); } active_ = false; + onWalkAborted(); } } diff --git a/Swiften/Disco/DiscoServiceWalker.h b/Swiften/Disco/DiscoServiceWalker.h index 1853b57..ea55a78 100644 --- a/Swiften/Disco/DiscoServiceWalker.h +++ b/Swiften/Disco/DiscoServiceWalker.h @@ -49,6 +49,9 @@ namespace Swift { /** Emitted for each service found. */ boost::signal<void(const JID&, boost::shared_ptr<DiscoInfo>)> onServiceFound; + /** Emitted when walking is aborted. */ + boost::signal<void()> onWalkAborted; + /** Emitted when walking is complete.*/ boost::signal<void()> onWalkComplete; diff --git a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp index 52fdbaa..67d27c0 100644 --- a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp +++ b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -9,6 +9,8 @@ #include <Swiften/Elements/DiscoInfo.h> #include <Swiften/Disco/CapsInfoGenerator.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> using namespace Swift; @@ -19,6 +21,10 @@ class CapsInfoGeneratorTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_END(); 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")); @@ -27,7 +33,7 @@ class CapsInfoGeneratorTest : public CppUnit::TestFixture { discoInfo.addFeature("http://jabber.org/protocol/disco#info"); discoInfo.addFeature("http://jabber.org/protocol/muc"); - CapsInfoGenerator testling("http://code.google.com/p/exodus"); + 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()); @@ -45,40 +51,36 @@ class CapsInfoGeneratorTest : public CppUnit::TestFixture { discoInfo.addFeature("http://jabber.org/protocol/muc"); Form::ref extension(new Form(Form::ResultType)); - FormField::ref field = HiddenFormField::create("urn:xmpp:dataforms:softwareinfo"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "urn:xmpp:dataforms:softwareinfo"); field->setName("FORM_TYPE"); extension->addField(field); - std::vector<std::string> ipVersions; - ipVersions.push_back("ipv6"); - ipVersions.push_back("ipv4"); - field = ListMultiFormField::create(ipVersions); - field->addRawValue("ipv6"); - field->addRawValue("ipv4"); + field = boost::make_shared<FormField>(FormField::ListMultiType); + field->addValue("ipv6"); + field->addValue("ipv4"); field->setName("ip_version"); extension->addField(field); - field = TextSingleFormField::create("Psi"); - field->addRawValue("Psi"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Psi"); field->setName("software"); extension->addField(field); - field = TextSingleFormField::create("0.11"); - field->addRawValue("0.11"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "0.11"); field->setName("software_version"); extension->addField(field); - field = TextSingleFormField::create("Mac"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Mac"); field->setName("os"); - field->addRawValue("Mac"); extension->addField(field); - field = TextSingleFormField::create("10.5.1"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "10.5.1"); field->setName("os_version"); - field->addRawValue("10.5.1"); extension->addField(field); discoInfo.addExtension(extension); - CapsInfoGenerator testling("http://psi-im.org"); + CapsInfoGenerator testling("http://psi-im.org", crypto.get()); CapsInfo result = testling.generateCapsInfo(discoInfo); CPPUNIT_ASSERT_EQUAL(std::string("q07IKJEyjvHSyhy//CH0CxmKi8w="), result.getVersion()); } + + private: + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(CapsInfoGeneratorTest); diff --git a/Swiften/Disco/UnitTest/CapsManagerTest.cpp b/Swiften/Disco/UnitTest/CapsManagerTest.cpp index ca55c48..303fd78 100644 --- a/Swiften/Disco/UnitTest/CapsManagerTest.cpp +++ b/Swiften/Disco/UnitTest/CapsManagerTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -16,6 +16,8 @@ #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> using namespace Swift; @@ -41,18 +43,19 @@ class CapsManagerTest : public CppUnit::TestFixture { 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").generateCapsInfo(*discoInfo1.get())); - capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im").generateCapsInfo(*discoInfo1.get())); + 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").generateCapsInfo(*discoInfo2.get())); + 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", ""); } @@ -246,7 +249,7 @@ class CapsManagerTest : public CppUnit::TestFixture { private: boost::shared_ptr<CapsManager> createManager() { - boost::shared_ptr<CapsManager> manager(new CapsManager(storage, stanzaChannel, iqRouter)); + 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; @@ -281,6 +284,7 @@ class CapsManagerTest : public CppUnit::TestFixture { boost::shared_ptr<CapsInfo> capsInfo2; boost::shared_ptr<CapsInfo> legacyCapsInfo; JID user3; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(CapsManagerTest); diff --git a/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp b/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp index 0fd966d..940f043 100644 --- a/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp +++ b/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -14,6 +14,8 @@ #include <Swiften/Elements/CapsInfo.h> #include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Disco/CapsInfoGenerator.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> using namespace Swift; @@ -30,18 +32,20 @@ class EntityCapsManagerTest : public CppUnit::TestFixture { 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").generateCapsInfo(*discoInfo1.get())); - capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im").generateCapsInfo(*discoInfo1.get())); + 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").generateCapsInfo(*discoInfo2.get())); + 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", ""); } @@ -183,6 +187,7 @@ class EntityCapsManagerTest : public CppUnit::TestFixture { boost::shared_ptr<CapsInfo> legacyCapsInfo; JID user3; std::vector<JID> changes; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(EntityCapsManagerTest); diff --git a/Swiften/Elements/BlockListPayload.h b/Swiften/Elements/BlockListPayload.h index 25cb602..49df75f 100644 --- a/Swiften/Elements/BlockListPayload.h +++ b/Swiften/Elements/BlockListPayload.h @@ -14,7 +14,7 @@ namespace Swift { class BlockListPayload : public Payload { public: - BlockListPayload() { + BlockListPayload(const std::vector<JID>& items = std::vector<JID>()) : items(items) { } void addItem(const JID& item) { diff --git a/Swiften/Elements/BlockPayload.h b/Swiften/Elements/BlockPayload.h index 6dd5170..49a0463 100644 --- a/Swiften/Elements/BlockPayload.h +++ b/Swiften/Elements/BlockPayload.h @@ -14,7 +14,7 @@ namespace Swift { class BlockPayload : public Payload { public: - BlockPayload() { + BlockPayload(const std::vector<JID>& jids = std::vector<JID>()) : items(jids) { } void addItem(const JID& jid) { diff --git a/Swiften/Elements/Command.h b/Swiften/Elements/Command.h index 91ae5a3..5454d8d 100644 --- a/Swiften/Elements/Command.h +++ b/Swiften/Elements/Command.h @@ -26,7 +26,7 @@ namespace Swift { struct Note { enum Type {Info, Warn, Error}; - Note(std::string note, Type type) : note(note), type(type) {}; + Note(std::string note, Type type) : note(note), type(type) {} std::string note; Type type; diff --git a/Swiften/Elements/ContainerPayload.h b/Swiften/Elements/ContainerPayload.h new file mode 100644 index 0000000..e2a4682 --- /dev/null +++ b/Swiften/Elements/ContainerPayload.h @@ -0,0 +1,33 @@ +/* + * 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/Override.h> +#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) {} + + void setPayload(boost::shared_ptr<T> payload) { + this->payload = payload; + } + + boost::shared_ptr<T> getPayload() const { + return payload; + } + + private: + boost::shared_ptr<T> payload; + }; +} diff --git a/Swiften/Elements/Delay.h b/Swiften/Elements/Delay.h index f7c4570..f4376dc 100644 --- a/Swiften/Elements/Delay.h +++ b/Swiften/Elements/Delay.h @@ -15,14 +15,14 @@ namespace Swift { class Delay : public Payload { public: - Delay() {}; - Delay(const boost::posix_time::ptime& time, const JID& from = JID()) : time_(time), from_(from) {}; + 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_; diff --git a/Swiften/Elements/DiscoInfo.cpp b/Swiften/Elements/DiscoInfo.cpp index 1683916..f353c42 100644 --- a/Swiften/Elements/DiscoInfo.cpp +++ b/Swiften/Elements/DiscoInfo.cpp @@ -23,6 +23,7 @@ const std::string DiscoInfo::JingleTransportsS5BFeature = std::string("urn:xmpp: 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"); bool DiscoInfo::Identity::operator<(const Identity& other) const { if (category_ == other.category_) { diff --git a/Swiften/Elements/DiscoInfo.h b/Swiften/Elements/DiscoInfo.h index 3334ac8..3701096 100644 --- a/Swiften/Elements/DiscoInfo.h +++ b/Swiften/Elements/DiscoInfo.h @@ -34,6 +34,7 @@ namespace Swift { static const std::string Bytestream; static const std::string MessageDeliveryReceiptsFeature; static const std::string WhiteboardFeature; + static const std::string BlockingCommandFeature; class Identity { public: diff --git a/Swiften/Elements/Form.cpp b/Swiften/Elements/Form.cpp index cf9ecf6..c4ae410 100644 --- a/Swiften/Elements/Form.cpp +++ b/Swiften/Elements/Form.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,8 +11,10 @@ namespace Swift { std::string Form::getFormType() const { FormField::ref field = getField("FORM_TYPE"); - boost::shared_ptr<HiddenFormField> f = boost::dynamic_pointer_cast<HiddenFormField>(field); - return (f ? f->getValue() : ""); + if (field && field->getType() == FormField::HiddenType) { + return field->getValues().empty() ? "" : field->getValues()[0]; + } + return ""; } FormField::ref Form::getField(const std::string& name) const { diff --git a/Swiften/Elements/Form.h b/Swiften/Elements/Form.h index bd4a2aa..76ed674 100644 --- a/Swiften/Elements/Form.h +++ b/Swiften/Elements/Form.h @@ -35,6 +35,7 @@ namespace Swift { */ 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_; } @@ -50,9 +51,12 @@ namespace Swift { 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_; diff --git a/Swiften/Elements/FormField.cpp b/Swiften/Elements/FormField.cpp new file mode 100644 index 0000000..e9e4f77 --- /dev/null +++ b/Swiften/Elements/FormField.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + +using namespace Swift; + +FormField::~FormField() { +} + +std::string FormField::getTextMultiValue() const { + 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")); +} + +void FormField::setBoolValue(bool b) { + values.clear(); + values.push_back(b ? "1" : "0"); +} diff --git a/Swiften/Elements/FormField.h b/Swiften/Elements/FormField.h index e8fe3a0..f0bebd9 100644 --- a/Swiften/Elements/FormField.h +++ b/Swiften/Elements/FormField.h @@ -1,12 +1,9 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ -// FIXME: We currently keep 2 values: the raw values, and the actual value. -// We should only store the raw values, and deduce the actual values from this - #pragma once #include <vector> @@ -20,7 +17,25 @@ namespace Swift { public: typedef boost::shared_ptr<FormField> ref; - virtual ~FormField() {} + 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) {} @@ -48,67 +63,76 @@ namespace Swift { return options; } - const std::vector<std::string>& getRawValues() const { - return rawValues; + void clearOptions() { + options.clear(); } - void addRawValue(const std::string& value) { - rawValues.push_back(value); + const std::vector<std::string>& getValues() const { + return values; } - protected: - FormField() : required(false) {} + void addValue(const std::string& value) { + values.push_back(value); + } - private: - std::string name; - std::string label; - std::string description; - bool required; - std::vector<Option> options; - std::vector<std::string> rawValues; - }; + Type getType() const { + return type; + } - template<typename T> class GenericFormField : public FormField { - public: - const T& getValue() const { - return value; + void setType(Type type) { + this->type = type; } - void setValue(const T& value) { - this->value = value; + // 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: - GenericFormField() : value() {} - GenericFormField(const T& value) : value(value) {} private: - T value; - }; - -#define SWIFTEN_DECLARE_FORM_FIELD(name, valueType) \ - class name##FormField : public GenericFormField< valueType > { \ - public: \ - typedef boost::shared_ptr<name##FormField> ref; \ - static ref create(const valueType& value) { \ - return ref(new name##FormField(value)); \ - } \ - static ref create() { \ - return ref(new name##FormField()); \ - } \ - private: \ - name##FormField(valueType value) : GenericFormField< valueType >(value) {} \ - name##FormField() : GenericFormField< valueType >() {} \ + Type type; + std::string name; + std::string label; + std::string description; + bool required; + std::vector<Option> options; + std::vector<std::string> values; }; - SWIFTEN_DECLARE_FORM_FIELD(Boolean, bool); - SWIFTEN_DECLARE_FORM_FIELD(Fixed, std::string); - SWIFTEN_DECLARE_FORM_FIELD(Hidden, std::string); - SWIFTEN_DECLARE_FORM_FIELD(ListSingle, std::string); - SWIFTEN_DECLARE_FORM_FIELD(TextMulti, std::string); - SWIFTEN_DECLARE_FORM_FIELD(TextPrivate, std::string); - SWIFTEN_DECLARE_FORM_FIELD(TextSingle, std::string); - SWIFTEN_DECLARE_FORM_FIELD(JIDSingle, JID); - SWIFTEN_DECLARE_FORM_FIELD(JIDMulti, std::vector<JID>); - SWIFTEN_DECLARE_FORM_FIELD(ListMulti, std::vector<std::string>); } diff --git a/Swiften/Elements/IBB.h b/Swiften/Elements/IBB.h index 64c9f14..fb33eaf 100644 --- a/Swiften/Elements/IBB.h +++ b/Swiften/Elements/IBB.h @@ -21,11 +21,11 @@ namespace Swift { enum Action { Open, Close, - Data, + Data }; enum StanzaType { IQStanza, - MessageStanza, + MessageStanza }; IBB(Action action = Open, const std::string& streamID = "") : action(action), streamID(streamID), stanzaType(IQStanza), blockSize(-1), sequenceNumber(-1) { diff --git a/Swiften/Elements/Idle.h b/Swiften/Elements/Idle.h new file mode 100644 index 0000000..572eba2 --- /dev/null +++ b/Swiften/Elements/Idle.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 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 <boost/date_time/posix_time/posix_time_types.hpp> + +#include <Swiften/Elements/Payload.h> + +namespace Swift { + + class Idle : public Payload { + public: + typedef boost::shared_ptr<Idle> ref; + + public: + Idle() {} + Idle(boost::posix_time::ptime since) : since_(since) { + } + + void setSince(boost::posix_time::ptime since) { + since_ = since; + } + + boost::posix_time::ptime getSince() const { + return since_; + } + + private: + boost::posix_time::ptime since_; + }; + +} diff --git a/Swiften/Elements/JingleContentPayload.h b/Swiften/Elements/JingleContentPayload.h index 183b8eb..547fc70 100644 --- a/Swiften/Elements/JingleContentPayload.h +++ b/Swiften/Elements/JingleContentPayload.h @@ -23,7 +23,7 @@ namespace Swift { enum Creator { UnknownCreator, InitiatorCreator, - ResponderCreator, + ResponderCreator }; /*enum Senders { diff --git a/Swiften/Elements/JingleIBBTransportPayload.h b/Swiften/Elements/JingleIBBTransportPayload.h index 8c174f0..a329ff0 100644 --- a/Swiften/Elements/JingleIBBTransportPayload.h +++ b/Swiften/Elements/JingleIBBTransportPayload.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #pragma once #include <boost/shared_ptr.hpp> +#include <boost/optional.hpp> #include <string> #include <Swiften/Elements/JingleTransportPayload.h> @@ -18,7 +19,7 @@ namespace Swift { enum StanzaType { IQStanza, - MessageStanza, + MessageStanza }; void setStanzaType(StanzaType stanzaType) { @@ -29,16 +30,16 @@ namespace Swift { return stanzaType; } - int getBlockSize() const { + boost::optional<unsigned int> getBlockSize() const { return blockSize; } - void setBlockSize(int blockSize) { + void setBlockSize(unsigned int blockSize) { this->blockSize = blockSize; } private: - int blockSize; + boost::optional<unsigned int> blockSize; StanzaType stanzaType; }; } diff --git a/Swiften/Elements/JinglePayload.h b/Swiften/Elements/JinglePayload.h index 31d4448..5f12e90 100644 --- a/Swiften/Elements/JinglePayload.h +++ b/Swiften/Elements/JinglePayload.h @@ -15,8 +15,6 @@ #include <Swiften/Elements/Payload.h> #include <Swiften/Elements/JingleContentPayload.h> -#include <Swiften/Base/Log.h> - namespace Swift { class JinglePayload : public Payload { public: diff --git a/Swiften/Elements/JingleS5BTransportPayload.h b/Swiften/Elements/JingleS5BTransportPayload.h index 995933c..41bf809 100644 --- a/Swiften/Elements/JingleS5BTransportPayload.h +++ b/Swiften/Elements/JingleS5BTransportPayload.h @@ -20,7 +20,7 @@ namespace Swift { public: enum Mode { TCPMode, // default case - UDPMode, + UDPMode }; struct Candidate { @@ -28,7 +28,7 @@ namespace Swift { DirectType, // default case AssistedType, TunnelType, - ProxyType, + ProxyType }; Candidate() : priority(0), type(DirectType) {} diff --git a/Swiften/Elements/Last.h b/Swiften/Elements/Last.h index fe0323a..cb7e0c6 100644 --- a/Swiften/Elements/Last.h +++ b/Swiften/Elements/Last.h @@ -11,7 +11,7 @@ namespace Swift { class Last : public Payload { public: - Last(int seconds = 0) : seconds_(seconds) {}; + Last(int seconds = 0) : seconds_(seconds) {} int getSeconds() const {return seconds_;} void setSeconds(int seconds) {seconds_ = seconds;} diff --git a/Swiften/Elements/MUCInvitationPayload.h b/Swiften/Elements/MUCInvitationPayload.h index ebae61a..290c585 100644 --- a/Swiften/Elements/MUCInvitationPayload.h +++ b/Swiften/Elements/MUCInvitationPayload.h @@ -15,7 +15,7 @@ namespace Swift { class MUCInvitationPayload : public Payload { public: typedef boost::shared_ptr<MUCInvitationPayload> ref; - MUCInvitationPayload() : continuation_(false) { + MUCInvitationPayload() : continuation_(false), impromptu_(false) { } void setIsContinuation(bool b) { @@ -26,6 +26,14 @@ namespace Swift { return continuation_; } + void setIsImpromptu(bool b) { + impromptu_ = b; + } + + bool getIsImpromptu() const { + return impromptu_; + } + void setJID(const JID& jid) { jid_ = jid; } @@ -60,6 +68,7 @@ namespace Swift { private: bool continuation_; + bool impromptu_; JID jid_; std::string password_; std::string reason_; diff --git a/Swiften/Elements/Message.h b/Swiften/Elements/Message.h index 3b9145c..ea99814 100644 --- a/Swiften/Elements/Message.h +++ b/Swiften/Elements/Message.h @@ -38,8 +38,10 @@ namespace Swift { updatePayload(boost::make_shared<Subject>(subject)); } + // Explicitly convert to bool. In C++11, it would be cleaner to + // compare to nullptr. bool hasSubject() { - return getPayload<Subject>(); + return static_cast<bool>(getPayload<Subject>()); } std::string getBody() const { diff --git a/Swiften/Elements/PubSub.cpp b/Swiften/Elements/PubSub.cpp new file mode 100644 index 0000000..30a6376 --- /dev/null +++ b/Swiften/Elements/PubSub.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSub.h> + +using namespace Swift; + +PubSub::PubSub() { +} + +PubSub::~PubSub() { +} diff --git a/Swiften/Elements/PubSub.h b/Swiften/Elements/PubSub.h new file mode 100644 index 0000000..cd8bf43 --- /dev/null +++ b/Swiften/Elements/PubSub.h @@ -0,0 +1,21 @@ +/* + * 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/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(); + }; +} diff --git a/Swiften/Elements/PubSubAffiliation.cpp b/Swiften/Elements/PubSubAffiliation.cpp new file mode 100644 index 0000000..0b04494 --- /dev/null +++ b/Swiften/Elements/PubSubAffiliation.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubAffiliation.h> + +using namespace Swift; + +PubSubAffiliation::PubSubAffiliation() : type(None) { +} + +PubSubAffiliation::~PubSubAffiliation() { +} diff --git a/Swiften/Elements/PubSubAffiliation.h b/Swiften/Elements/PubSubAffiliation.h new file mode 100644 index 0000000..2ea9376 --- /dev/null +++ b/Swiften/Elements/PubSubAffiliation.h @@ -0,0 +1,53 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <string> + + + +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; + }; +} diff --git a/Swiften/Elements/PubSubAffiliations.cpp b/Swiften/Elements/PubSubAffiliations.cpp new file mode 100644 index 0000000..a53215d --- /dev/null +++ b/Swiften/Elements/PubSubAffiliations.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubAffiliations.h> + +using namespace Swift; + +PubSubAffiliations::PubSubAffiliations() { +} + +PubSubAffiliations::~PubSubAffiliations() { +} diff --git a/Swiften/Elements/PubSubAffiliations.h b/Swiften/Elements/PubSubAffiliations.h new file mode 100644 index 0000000..6a413fe --- /dev/null +++ b/Swiften/Elements/PubSubAffiliations.h @@ -0,0 +1,53 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubConfigure.cpp b/Swiften/Elements/PubSubConfigure.cpp new file mode 100644 index 0000000..b1a6cb3 --- /dev/null +++ b/Swiften/Elements/PubSubConfigure.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubConfigure.h> + +using namespace Swift; + +PubSubConfigure::PubSubConfigure() { +} + +PubSubConfigure::~PubSubConfigure() { +} diff --git a/Swiften/Elements/PubSubConfigure.h b/Swiften/Elements/PubSubConfigure.h new file mode 100644 index 0000000..ed91832 --- /dev/null +++ b/Swiften/Elements/PubSubConfigure.h @@ -0,0 +1,36 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> + +#include <Swiften/Elements/Form.h> + +namespace Swift { + class SWIFTEN_API PubSubConfigure : public Payload { + public: + + PubSubConfigure(); + + virtual ~PubSubConfigure(); + + boost::shared_ptr<Form> getData() const { + return data; + } + + void setData(boost::shared_ptr<Form> value) { + this->data = value ; + } + + + private: + boost::shared_ptr<Form> data; + }; +} diff --git a/Swiften/Elements/PubSubCreate.cpp b/Swiften/Elements/PubSubCreate.cpp new file mode 100644 index 0000000..9c60de3 --- /dev/null +++ b/Swiften/Elements/PubSubCreate.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubCreate.h> + +using namespace Swift; + +PubSubCreate::PubSubCreate() { +} + +PubSubCreate::~PubSubCreate() { +} diff --git a/Swiften/Elements/PubSubCreate.h b/Swiften/Elements/PubSubCreate.h new file mode 100644 index 0000000..4e4eb92 --- /dev/null +++ b/Swiften/Elements/PubSubCreate.h @@ -0,0 +1,47 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubDefault.cpp b/Swiften/Elements/PubSubDefault.cpp new file mode 100644 index 0000000..923d0ad --- /dev/null +++ b/Swiften/Elements/PubSubDefault.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubDefault.h> + +using namespace Swift; + +PubSubDefault::PubSubDefault() : type(None) { +} + +PubSubDefault::~PubSubDefault() { +} diff --git a/Swiften/Elements/PubSubDefault.h b/Swiften/Elements/PubSubDefault.h new file mode 100644 index 0000000..08326e7 --- /dev/null +++ b/Swiften/Elements/PubSubDefault.h @@ -0,0 +1,51 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubError.cpp b/Swiften/Elements/PubSubError.cpp new file mode 100644 index 0000000..db07972 --- /dev/null +++ b/Swiften/Elements/PubSubError.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubError.h> + +using namespace Swift; + +PubSubError::~PubSubError() { +} diff --git a/Swiften/Elements/PubSubError.h b/Swiften/Elements/PubSubError.h new file mode 100644 index 0000000..3748e44 --- /dev/null +++ b/Swiften/Elements/PubSubError.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#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 + }; + + 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) { + } + + virtual ~PubSubError(); + + Type getType() const { + return type; + } + + void setType(Type type) { + this->type = type; + } + + UnsupportedFeatureType getUnsupportedFeatureType() const { + return unsupportedType; + } + + void setUnsupportedFeatureType(UnsupportedFeatureType unsupportedType) { + this->unsupportedType = unsupportedType; + } + + private: + Type type; + UnsupportedFeatureType unsupportedType; + }; +} diff --git a/Swiften/Elements/PubSubEvent.cpp b/Swiften/Elements/PubSubEvent.cpp new file mode 100644 index 0000000..1b63134 --- /dev/null +++ b/Swiften/Elements/PubSubEvent.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEvent.h> + +using namespace Swift; + +PubSubEvent::PubSubEvent() { +} + +PubSubEvent::~PubSubEvent() { +} diff --git a/Swiften/Elements/PubSubEvent.h b/Swiften/Elements/PubSubEvent.h new file mode 100644 index 0000000..9ef6d89 --- /dev/null +++ b/Swiften/Elements/PubSubEvent.h @@ -0,0 +1,23 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> + +#include <Swiften/Elements/ContainerPayload.h> +#include <Swiften/Elements/PubSubEventPayload.h> + +namespace Swift { + class SWIFTEN_API PubSubEvent : public ContainerPayload<PubSubEventPayload> { + public: + PubSubEvent(); + virtual ~PubSubEvent(); + }; +} diff --git a/Swiften/Elements/PubSubEventAssociate.cpp b/Swiften/Elements/PubSubEventAssociate.cpp new file mode 100644 index 0000000..cb81b46 --- /dev/null +++ b/Swiften/Elements/PubSubEventAssociate.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventAssociate.h> + +using namespace Swift; + +PubSubEventAssociate::PubSubEventAssociate() { +} + +PubSubEventAssociate::~PubSubEventAssociate() { +} diff --git a/Swiften/Elements/PubSubEventAssociate.h b/Swiften/Elements/PubSubEventAssociate.h new file mode 100644 index 0000000..a752345 --- /dev/null +++ b/Swiften/Elements/PubSubEventAssociate.h @@ -0,0 +1,36 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <string> + + + +namespace Swift { + class SWIFTEN_API PubSubEventAssociate : public Payload { + public: + + PubSubEventAssociate(); + + virtual ~PubSubEventAssociate(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + + private: + std::string node; + }; +} diff --git a/Swiften/Elements/PubSubEventCollection.cpp b/Swiften/Elements/PubSubEventCollection.cpp new file mode 100644 index 0000000..a8b2a56 --- /dev/null +++ b/Swiften/Elements/PubSubEventCollection.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventCollection.h> + +using namespace Swift; + +PubSubEventCollection::PubSubEventCollection() { +} + +PubSubEventCollection::~PubSubEventCollection() { +} diff --git a/Swiften/Elements/PubSubEventCollection.h b/Swiften/Elements/PubSubEventCollection.h new file mode 100644 index 0000000..e4498aa --- /dev/null +++ b/Swiften/Elements/PubSubEventCollection.h @@ -0,0 +1,58 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> +#include <string> + +#include <Swiften/Elements/PubSubEventDisassociate.h> +#include <Swiften/Elements/PubSubEventAssociate.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; + }; +} diff --git a/Swiften/Elements/PubSubEventConfiguration.cpp b/Swiften/Elements/PubSubEventConfiguration.cpp new file mode 100644 index 0000000..93ce6a3 --- /dev/null +++ b/Swiften/Elements/PubSubEventConfiguration.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventConfiguration.h> + +using namespace Swift; + +PubSubEventConfiguration::PubSubEventConfiguration() { +} + +PubSubEventConfiguration::~PubSubEventConfiguration() { +} diff --git a/Swiften/Elements/PubSubEventConfiguration.h b/Swiften/Elements/PubSubEventConfiguration.h new file mode 100644 index 0000000..7ebfce1 --- /dev/null +++ b/Swiften/Elements/PubSubEventConfiguration.h @@ -0,0 +1,47 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> +#include <string> + +#include <Swiften/Elements/Form.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; + }; +} diff --git a/Swiften/Elements/PubSubEventDelete.cpp b/Swiften/Elements/PubSubEventDelete.cpp new file mode 100644 index 0000000..85bbf2e --- /dev/null +++ b/Swiften/Elements/PubSubEventDelete.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventDelete.h> + +using namespace Swift; + +PubSubEventDelete::PubSubEventDelete() { +} + +PubSubEventDelete::~PubSubEventDelete() { +} diff --git a/Swiften/Elements/PubSubEventDelete.h b/Swiften/Elements/PubSubEventDelete.h new file mode 100644 index 0000000..fecfb0e --- /dev/null +++ b/Swiften/Elements/PubSubEventDelete.h @@ -0,0 +1,47 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> +#include <string> + +#include <Swiften/Elements/PubSubEventRedirect.h> +#include <Swiften/Elements/PubSubEventPayload.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; + }; +} diff --git a/Swiften/Elements/PubSubEventDisassociate.cpp b/Swiften/Elements/PubSubEventDisassociate.cpp new file mode 100644 index 0000000..55e1c4e --- /dev/null +++ b/Swiften/Elements/PubSubEventDisassociate.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventDisassociate.h> + +using namespace Swift; + +PubSubEventDisassociate::PubSubEventDisassociate() { +} + +PubSubEventDisassociate::~PubSubEventDisassociate() { +} diff --git a/Swiften/Elements/PubSubEventDisassociate.h b/Swiften/Elements/PubSubEventDisassociate.h new file mode 100644 index 0000000..cad9843 --- /dev/null +++ b/Swiften/Elements/PubSubEventDisassociate.h @@ -0,0 +1,36 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <string> + + + +namespace Swift { + class SWIFTEN_API PubSubEventDisassociate : public Payload { + public: + + PubSubEventDisassociate(); + + virtual ~PubSubEventDisassociate(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + + private: + std::string node; + }; +} diff --git a/Swiften/Elements/PubSubEventItem.cpp b/Swiften/Elements/PubSubEventItem.cpp new file mode 100644 index 0000000..6bb3823 --- /dev/null +++ b/Swiften/Elements/PubSubEventItem.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventItem.h> + +using namespace Swift; + +PubSubEventItem::PubSubEventItem() { +} + +PubSubEventItem::~PubSubEventItem() { +} diff --git a/Swiften/Elements/PubSubEventItem.h b/Swiften/Elements/PubSubEventItem.h new file mode 100644 index 0000000..25ebc82 --- /dev/null +++ b/Swiften/Elements/PubSubEventItem.h @@ -0,0 +1,70 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubEventItems.cpp b/Swiften/Elements/PubSubEventItems.cpp new file mode 100644 index 0000000..01f3429 --- /dev/null +++ b/Swiften/Elements/PubSubEventItems.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventItems.h> + +using namespace Swift; + +PubSubEventItems::PubSubEventItems() { +} + +PubSubEventItems::~PubSubEventItems() { +} diff --git a/Swiften/Elements/PubSubEventItems.h b/Swiften/Elements/PubSubEventItems.h new file mode 100644 index 0000000..a121728 --- /dev/null +++ b/Swiften/Elements/PubSubEventItems.h @@ -0,0 +1,66 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +#include <Swiften/Elements/PubSubEventItem.h> +#include <Swiften/Elements/PubSubEventRetract.h> +#include <Swiften/Elements/PubSubEventPayload.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; + }; +} diff --git a/Swiften/Elements/PubSubEventPayload.cpp b/Swiften/Elements/PubSubEventPayload.cpp new file mode 100644 index 0000000..0019942 --- /dev/null +++ b/Swiften/Elements/PubSubEventPayload.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventPayload.h> + +using namespace Swift; + +PubSubEventPayload::~PubSubEventPayload() { +} diff --git a/Swiften/Elements/PubSubEventPayload.h b/Swiften/Elements/PubSubEventPayload.h new file mode 100644 index 0000000..81fb9a8 --- /dev/null +++ b/Swiften/Elements/PubSubEventPayload.h @@ -0,0 +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> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API PubSubEventPayload : public Payload { + public: + virtual ~PubSubEventPayload(); + }; +} diff --git a/Swiften/Elements/PubSubEventPurge.cpp b/Swiften/Elements/PubSubEventPurge.cpp new file mode 100644 index 0000000..3fd77ed --- /dev/null +++ b/Swiften/Elements/PubSubEventPurge.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventPurge.h> + +using namespace Swift; + +PubSubEventPurge::PubSubEventPurge() { +} + +PubSubEventPurge::~PubSubEventPurge() { +} diff --git a/Swiften/Elements/PubSubEventPurge.h b/Swiften/Elements/PubSubEventPurge.h new file mode 100644 index 0000000..5f04049 --- /dev/null +++ b/Swiften/Elements/PubSubEventPurge.h @@ -0,0 +1,36 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <string> + +#include <Swiften/Elements/PubSubEventPayload.h> + +namespace Swift { + class SWIFTEN_API PubSubEventPurge : public PubSubEventPayload { + public: + + PubSubEventPurge(); + + virtual ~PubSubEventPurge(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + + private: + std::string node; + }; +} diff --git a/Swiften/Elements/PubSubEventRedirect.cpp b/Swiften/Elements/PubSubEventRedirect.cpp new file mode 100644 index 0000000..adde8bc --- /dev/null +++ b/Swiften/Elements/PubSubEventRedirect.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventRedirect.h> + +using namespace Swift; + +PubSubEventRedirect::PubSubEventRedirect() { +} + +PubSubEventRedirect::~PubSubEventRedirect() { +} diff --git a/Swiften/Elements/PubSubEventRedirect.h b/Swiften/Elements/PubSubEventRedirect.h new file mode 100644 index 0000000..918c7f4 --- /dev/null +++ b/Swiften/Elements/PubSubEventRedirect.h @@ -0,0 +1,36 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <string> + + + +namespace Swift { + class SWIFTEN_API PubSubEventRedirect : public Payload { + public: + + PubSubEventRedirect(); + + virtual ~PubSubEventRedirect(); + + const std::string& getURI() const { + return uri; + } + + void setURI(const std::string& value) { + this->uri = value ; + } + + + private: + std::string uri; + }; +} diff --git a/Swiften/Elements/PubSubEventRetract.cpp b/Swiften/Elements/PubSubEventRetract.cpp new file mode 100644 index 0000000..bb3ebb1 --- /dev/null +++ b/Swiften/Elements/PubSubEventRetract.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventRetract.h> + +using namespace Swift; + +PubSubEventRetract::PubSubEventRetract() { +} + +PubSubEventRetract::~PubSubEventRetract() { +} diff --git a/Swiften/Elements/PubSubEventRetract.h b/Swiften/Elements/PubSubEventRetract.h new file mode 100644 index 0000000..3c2d9c4 --- /dev/null +++ b/Swiften/Elements/PubSubEventRetract.h @@ -0,0 +1,36 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <string> + + + +namespace Swift { + class SWIFTEN_API PubSubEventRetract : public Payload { + public: + + PubSubEventRetract(); + + virtual ~PubSubEventRetract(); + + const std::string& getID() const { + return id; + } + + void setID(const std::string& value) { + this->id = value ; + } + + + private: + std::string id; + }; +} diff --git a/Swiften/Elements/PubSubEventSubscription.cpp b/Swiften/Elements/PubSubEventSubscription.cpp new file mode 100644 index 0000000..fb069f9 --- /dev/null +++ b/Swiften/Elements/PubSubEventSubscription.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubEventSubscription.h> + +using namespace Swift; + +PubSubEventSubscription::PubSubEventSubscription() : subscription(None) { +} + +PubSubEventSubscription::~PubSubEventSubscription() { +} diff --git a/Swiften/Elements/PubSubEventSubscription.h b/Swiften/Elements/PubSubEventSubscription.h new file mode 100644 index 0000000..b74d4f5 --- /dev/null +++ b/Swiften/Elements/PubSubEventSubscription.h @@ -0,0 +1,81 @@ +/* + * 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/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 <Swiften/JID/JID.h> +#include <Swiften/Elements/PubSubEventPayload.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; + }; +} diff --git a/Swiften/Elements/PubSubItem.cpp b/Swiften/Elements/PubSubItem.cpp new file mode 100644 index 0000000..ae6206f --- /dev/null +++ b/Swiften/Elements/PubSubItem.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubItem.h> + +using namespace Swift; + +PubSubItem::PubSubItem() { +} + +PubSubItem::~PubSubItem() { +} diff --git a/Swiften/Elements/PubSubItem.h b/Swiften/Elements/PubSubItem.h new file mode 100644 index 0000000..93ff03a --- /dev/null +++ b/Swiften/Elements/PubSubItem.h @@ -0,0 +1,51 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubItems.cpp b/Swiften/Elements/PubSubItems.cpp new file mode 100644 index 0000000..f235e11 --- /dev/null +++ b/Swiften/Elements/PubSubItems.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubItems.h> + +using namespace Swift; + +PubSubItems::PubSubItems() { +} + +PubSubItems::~PubSubItems() { +} diff --git a/Swiften/Elements/PubSubItems.h b/Swiften/Elements/PubSubItems.h new file mode 100644 index 0000000..7cd279b --- /dev/null +++ b/Swiften/Elements/PubSubItems.h @@ -0,0 +1,71 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubOptions.cpp b/Swiften/Elements/PubSubOptions.cpp new file mode 100644 index 0000000..22c4054 --- /dev/null +++ b/Swiften/Elements/PubSubOptions.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOptions.h> + +using namespace Swift; + +PubSubOptions::PubSubOptions() { +} + +PubSubOptions::~PubSubOptions() { +} diff --git a/Swiften/Elements/PubSubOptions.h b/Swiften/Elements/PubSubOptions.h new file mode 100644 index 0000000..0e9483e --- /dev/null +++ b/Swiften/Elements/PubSubOptions.h @@ -0,0 +1,67 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> +#include <string> + +#include <Swiften/Elements/Form.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; + }; +} diff --git a/Swiften/Elements/PubSubOwnerAffiliation.cpp b/Swiften/Elements/PubSubOwnerAffiliation.cpp new file mode 100644 index 0000000..8dc8be6 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerAffiliation.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerAffiliation.h> + +using namespace Swift; + +PubSubOwnerAffiliation::PubSubOwnerAffiliation() : type(None) { +} + +PubSubOwnerAffiliation::~PubSubOwnerAffiliation() { +} diff --git a/Swiften/Elements/PubSubOwnerAffiliation.h b/Swiften/Elements/PubSubOwnerAffiliation.h new file mode 100644 index 0000000..68851d3 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerAffiliation.h @@ -0,0 +1,53 @@ +/* + * 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/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; + }; +} diff --git a/Swiften/Elements/PubSubOwnerAffiliations.cpp b/Swiften/Elements/PubSubOwnerAffiliations.cpp new file mode 100644 index 0000000..b87a78a --- /dev/null +++ b/Swiften/Elements/PubSubOwnerAffiliations.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerAffiliations.h> + +using namespace Swift; + +PubSubOwnerAffiliations::PubSubOwnerAffiliations() { +} + +PubSubOwnerAffiliations::~PubSubOwnerAffiliations() { +} diff --git a/Swiften/Elements/PubSubOwnerAffiliations.h b/Swiften/Elements/PubSubOwnerAffiliations.h new file mode 100644 index 0000000..75578df --- /dev/null +++ b/Swiften/Elements/PubSubOwnerAffiliations.h @@ -0,0 +1,52 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +#include <Swiften/Elements/PubSubOwnerPayload.h> +#include <Swiften/Elements/PubSubOwnerAffiliation.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; + }; +} diff --git a/Swiften/Elements/PubSubOwnerConfigure.cpp b/Swiften/Elements/PubSubOwnerConfigure.cpp new file mode 100644 index 0000000..8db923d --- /dev/null +++ b/Swiften/Elements/PubSubOwnerConfigure.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerConfigure.h> + +using namespace Swift; + +PubSubOwnerConfigure::PubSubOwnerConfigure() { +} + +PubSubOwnerConfigure::~PubSubOwnerConfigure() { +} diff --git a/Swiften/Elements/PubSubOwnerConfigure.h b/Swiften/Elements/PubSubOwnerConfigure.h new file mode 100644 index 0000000..d882ec4 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerConfigure.h @@ -0,0 +1,48 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> +#include <string> + +#include <Swiften/Elements/PubSubOwnerPayload.h> +#include <Swiften/Elements/Form.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; + }; +} diff --git a/Swiften/Elements/PubSubOwnerDefault.cpp b/Swiften/Elements/PubSubOwnerDefault.cpp new file mode 100644 index 0000000..ebb51a7 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerDefault.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerDefault.h> + +using namespace Swift; + +PubSubOwnerDefault::PubSubOwnerDefault() { +} + +PubSubOwnerDefault::~PubSubOwnerDefault() { +} diff --git a/Swiften/Elements/PubSubOwnerDefault.h b/Swiften/Elements/PubSubOwnerDefault.h new file mode 100644 index 0000000..1dbd3a2 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerDefault.h @@ -0,0 +1,37 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.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(); + + boost::shared_ptr<Form> getData() const { + return data; + } + + void setData(boost::shared_ptr<Form> value) { + this->data = value ; + } + + + private: + boost::shared_ptr<Form> data; + }; +} diff --git a/Swiften/Elements/PubSubOwnerDelete.cpp b/Swiften/Elements/PubSubOwnerDelete.cpp new file mode 100644 index 0000000..a785424 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerDelete.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerDelete.h> + +using namespace Swift; + +PubSubOwnerDelete::PubSubOwnerDelete() { +} + +PubSubOwnerDelete::~PubSubOwnerDelete() { +} diff --git a/Swiften/Elements/PubSubOwnerDelete.h b/Swiften/Elements/PubSubOwnerDelete.h new file mode 100644 index 0000000..c6bb3e9 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerDelete.h @@ -0,0 +1,47 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubOwnerPayload.cpp b/Swiften/Elements/PubSubOwnerPayload.cpp new file mode 100644 index 0000000..92c1dd2 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerPayload.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerPayload.h> + +using namespace Swift; + +PubSubOwnerPayload::~PubSubOwnerPayload() { +} diff --git a/Swiften/Elements/PubSubOwnerPayload.h b/Swiften/Elements/PubSubOwnerPayload.h new file mode 100644 index 0000000..a2ddaaa --- /dev/null +++ b/Swiften/Elements/PubSubOwnerPayload.h @@ -0,0 +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> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API PubSubOwnerPayload : public Payload { + public: + virtual ~PubSubOwnerPayload(); + }; +} diff --git a/Swiften/Elements/PubSubOwnerPubSub.cpp b/Swiften/Elements/PubSubOwnerPubSub.cpp new file mode 100644 index 0000000..022452d --- /dev/null +++ b/Swiften/Elements/PubSubOwnerPubSub.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerPubSub.h> + +using namespace Swift; + +PubSubOwnerPubSub::PubSubOwnerPubSub() { +} + +PubSubOwnerPubSub::~PubSubOwnerPubSub() { +} diff --git a/Swiften/Elements/PubSubOwnerPubSub.h b/Swiften/Elements/PubSubOwnerPubSub.h new file mode 100644 index 0000000..dd72abe --- /dev/null +++ b/Swiften/Elements/PubSubOwnerPubSub.h @@ -0,0 +1,21 @@ +/* + * 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/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(); + }; +} diff --git a/Swiften/Elements/PubSubOwnerPurge.cpp b/Swiften/Elements/PubSubOwnerPurge.cpp new file mode 100644 index 0000000..d0ac57d --- /dev/null +++ b/Swiften/Elements/PubSubOwnerPurge.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerPurge.h> + +using namespace Swift; + +PubSubOwnerPurge::PubSubOwnerPurge() { +} + +PubSubOwnerPurge::~PubSubOwnerPurge() { +} diff --git a/Swiften/Elements/PubSubOwnerPurge.h b/Swiften/Elements/PubSubOwnerPurge.h new file mode 100644 index 0000000..fc410f8 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerPurge.h @@ -0,0 +1,36 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <string> + +#include <Swiften/Elements/PubSubOwnerPayload.h> + +namespace Swift { + class SWIFTEN_API PubSubOwnerPurge : public PubSubOwnerPayload { + public: + + PubSubOwnerPurge(); + + virtual ~PubSubOwnerPurge(); + + const std::string& getNode() const { + return node; + } + + void setNode(const std::string& value) { + this->node = value ; + } + + + private: + std::string node; + }; +} diff --git a/Swiften/Elements/PubSubOwnerRedirect.cpp b/Swiften/Elements/PubSubOwnerRedirect.cpp new file mode 100644 index 0000000..164c216 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerRedirect.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerRedirect.h> + +using namespace Swift; + +PubSubOwnerRedirect::PubSubOwnerRedirect() { +} + +PubSubOwnerRedirect::~PubSubOwnerRedirect() { +} diff --git a/Swiften/Elements/PubSubOwnerRedirect.h b/Swiften/Elements/PubSubOwnerRedirect.h new file mode 100644 index 0000000..61db1d1 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerRedirect.h @@ -0,0 +1,36 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <string> + + + +namespace Swift { + class SWIFTEN_API PubSubOwnerRedirect : public Payload { + public: + + PubSubOwnerRedirect(); + + virtual ~PubSubOwnerRedirect(); + + const std::string& getURI() const { + return uri; + } + + void setURI(const std::string& value) { + this->uri = value ; + } + + + private: + std::string uri; + }; +} diff --git a/Swiften/Elements/PubSubOwnerSubscription.cpp b/Swiften/Elements/PubSubOwnerSubscription.cpp new file mode 100644 index 0000000..3334e36 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerSubscription.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerSubscription.h> + +using namespace Swift; + +PubSubOwnerSubscription::PubSubOwnerSubscription() : subscription(None) { +} + +PubSubOwnerSubscription::~PubSubOwnerSubscription() { +} diff --git a/Swiften/Elements/PubSubOwnerSubscription.h b/Swiften/Elements/PubSubOwnerSubscription.h new file mode 100644 index 0000000..1c302df --- /dev/null +++ b/Swiften/Elements/PubSubOwnerSubscription.h @@ -0,0 +1,51 @@ +/* + * 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/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; + }; +} diff --git a/Swiften/Elements/PubSubOwnerSubscriptions.cpp b/Swiften/Elements/PubSubOwnerSubscriptions.cpp new file mode 100644 index 0000000..a4deb59 --- /dev/null +++ b/Swiften/Elements/PubSubOwnerSubscriptions.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubOwnerSubscriptions.h> + +using namespace Swift; + +PubSubOwnerSubscriptions::PubSubOwnerSubscriptions() { +} + +PubSubOwnerSubscriptions::~PubSubOwnerSubscriptions() { +} diff --git a/Swiften/Elements/PubSubOwnerSubscriptions.h b/Swiften/Elements/PubSubOwnerSubscriptions.h new file mode 100644 index 0000000..08a2f5c --- /dev/null +++ b/Swiften/Elements/PubSubOwnerSubscriptions.h @@ -0,0 +1,52 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubPayload.cpp b/Swiften/Elements/PubSubPayload.cpp new file mode 100644 index 0000000..b529959 --- /dev/null +++ b/Swiften/Elements/PubSubPayload.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubPayload.h> + +using namespace Swift; + +PubSubPayload::~PubSubPayload() { +} diff --git a/Swiften/Elements/PubSubPayload.h b/Swiften/Elements/PubSubPayload.h new file mode 100644 index 0000000..476939b --- /dev/null +++ b/Swiften/Elements/PubSubPayload.h @@ -0,0 +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> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + class SWIFTEN_API PubSubPayload : public Payload { + public: + virtual ~PubSubPayload(); + }; +} diff --git a/Swiften/Elements/PubSubPublish.cpp b/Swiften/Elements/PubSubPublish.cpp new file mode 100644 index 0000000..2ee3880 --- /dev/null +++ b/Swiften/Elements/PubSubPublish.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubPublish.h> + +using namespace Swift; + +PubSubPublish::PubSubPublish() { +} + +PubSubPublish::~PubSubPublish() { +} diff --git a/Swiften/Elements/PubSubPublish.h b/Swiften/Elements/PubSubPublish.h new file mode 100644 index 0000000..1d99420 --- /dev/null +++ b/Swiften/Elements/PubSubPublish.h @@ -0,0 +1,52 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubRetract.cpp b/Swiften/Elements/PubSubRetract.cpp new file mode 100644 index 0000000..7e3676e --- /dev/null +++ b/Swiften/Elements/PubSubRetract.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubRetract.h> + +using namespace Swift; + +PubSubRetract::PubSubRetract() { +} + +PubSubRetract::~PubSubRetract() { +} diff --git a/Swiften/Elements/PubSubRetract.h b/Swiften/Elements/PubSubRetract.h new file mode 100644 index 0000000..e55897b --- /dev/null +++ b/Swiften/Elements/PubSubRetract.h @@ -0,0 +1,61 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubSubscribe.cpp b/Swiften/Elements/PubSubSubscribe.cpp new file mode 100644 index 0000000..4720321 --- /dev/null +++ b/Swiften/Elements/PubSubSubscribe.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubSubscribe.h> + +using namespace Swift; + +PubSubSubscribe::PubSubSubscribe() { +} + +PubSubSubscribe::~PubSubSubscribe() { +} diff --git a/Swiften/Elements/PubSubSubscribe.h b/Swiften/Elements/PubSubSubscribe.h new file mode 100644 index 0000000..e2cc4ae --- /dev/null +++ b/Swiften/Elements/PubSubSubscribe.h @@ -0,0 +1,58 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/PubSubSubscribeOptions.cpp b/Swiften/Elements/PubSubSubscribeOptions.cpp new file mode 100644 index 0000000..8770620 --- /dev/null +++ b/Swiften/Elements/PubSubSubscribeOptions.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubSubscribeOptions.h> + +using namespace Swift; + +PubSubSubscribeOptions::PubSubSubscribeOptions() { +} + +PubSubSubscribeOptions::~PubSubSubscribeOptions() { +} diff --git a/Swiften/Elements/PubSubSubscribeOptions.h b/Swiften/Elements/PubSubSubscribeOptions.h new file mode 100644 index 0000000..6612d82 --- /dev/null +++ b/Swiften/Elements/PubSubSubscribeOptions.h @@ -0,0 +1,36 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> + + + + +namespace Swift { + class SWIFTEN_API PubSubSubscribeOptions : public Payload { + public: + + PubSubSubscribeOptions(); + + virtual ~PubSubSubscribeOptions(); + + bool isRequired() const { + return required; + } + + void setRequired(bool value) { + this->required = value ; + } + + + private: + bool required; + }; +} diff --git a/Swiften/Elements/PubSubSubscription.cpp b/Swiften/Elements/PubSubSubscription.cpp new file mode 100644 index 0000000..a25fc06 --- /dev/null +++ b/Swiften/Elements/PubSubSubscription.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubSubscription.h> + +using namespace Swift; + +PubSubSubscription::PubSubSubscription() : subscription(None) { +} + +PubSubSubscription::~PubSubSubscription() { +} diff --git a/Swiften/Elements/PubSubSubscription.h b/Swiften/Elements/PubSubSubscription.h new file mode 100644 index 0000000..977cd55 --- /dev/null +++ b/Swiften/Elements/PubSubSubscription.h @@ -0,0 +1,82 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> +#include <string> + +#include <Swiften/Elements/PubSubSubscribeOptions.h> +#include <Swiften/Elements/PubSubPayload.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; + }; +} diff --git a/Swiften/Elements/PubSubSubscriptions.cpp b/Swiften/Elements/PubSubSubscriptions.cpp new file mode 100644 index 0000000..626e122 --- /dev/null +++ b/Swiften/Elements/PubSubSubscriptions.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubSubscriptions.h> + +using namespace Swift; + +PubSubSubscriptions::PubSubSubscriptions() { +} + +PubSubSubscriptions::~PubSubSubscriptions() { +} diff --git a/Swiften/Elements/PubSubSubscriptions.h b/Swiften/Elements/PubSubSubscriptions.h new file mode 100644 index 0000000..c7c19c5 --- /dev/null +++ b/Swiften/Elements/PubSubSubscriptions.h @@ -0,0 +1,53 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +#include <Swiften/Elements/PubSubSubscription.h> +#include <Swiften/Elements/PubSubPayload.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; + }; +} diff --git a/Swiften/Elements/PubSubUnsubscribe.cpp b/Swiften/Elements/PubSubUnsubscribe.cpp new file mode 100644 index 0000000..a4b8318 --- /dev/null +++ b/Swiften/Elements/PubSubUnsubscribe.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/PubSubUnsubscribe.h> + +using namespace Swift; + +PubSubUnsubscribe::PubSubUnsubscribe() { +} + +PubSubUnsubscribe::~PubSubUnsubscribe() { +} diff --git a/Swiften/Elements/PubSubUnsubscribe.h b/Swiften/Elements/PubSubUnsubscribe.h new file mode 100644 index 0000000..3969376 --- /dev/null +++ b/Swiften/Elements/PubSubUnsubscribe.h @@ -0,0 +1,56 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <string> + +#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; + }; +} diff --git a/Swiften/Elements/Replace.h b/Swiften/Elements/Replace.h index 230bce7..96935f5 100644 --- a/Swiften/Elements/Replace.h +++ b/Swiften/Elements/Replace.h @@ -15,7 +15,7 @@ namespace Swift { class Replace : public Payload { public: typedef boost::shared_ptr<Replace> ref; - Replace(const std::string& id = std::string()) : replaceID_(id) {}; + Replace(const std::string& id = std::string()) : replaceID_(id) {} const std::string& getID() const { return replaceID_; } diff --git a/Swiften/Elements/StanzaAck.cpp b/Swiften/Elements/StanzaAck.cpp new file mode 100644 index 0000000..5bcab73 --- /dev/null +++ b/Swiften/Elements/StanzaAck.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt 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; +} diff --git a/Swiften/Elements/StanzaAck.h b/Swiften/Elements/StanzaAck.h index 3aa2dfd..8fe64e0 100644 --- a/Swiften/Elements/StanzaAck.h +++ b/Swiften/Elements/StanzaAck.h @@ -1,13 +1,14 @@ /* - * Copyright (c) 2010 Remko Tronçon + * 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 <Swiften/Elements/Element.h> +#include <boost/shared_ptr.hpp> +#include <Swiften/Elements/Element.h> namespace Swift { class StanzaAck : public Element { @@ -16,15 +17,13 @@ namespace Swift { StanzaAck() : valid(false), handledStanzasCount(0) {} StanzaAck(unsigned int handledStanzasCount) : valid(true), handledStanzasCount(handledStanzasCount) {} + virtual ~StanzaAck(); unsigned int getHandledStanzasCount() const { return handledStanzasCount; } - void setHandledStanzasCount(int i) { - handledStanzasCount = i; - valid = true; - } + void setHandledStanzasCount(int i); bool isValid() const { return valid; diff --git a/Swiften/Elements/StatusShow.h b/Swiften/Elements/StatusShow.h index 3eeb44e..afa30de 100644 --- a/Swiften/Elements/StatusShow.h +++ b/Swiften/Elements/StatusShow.h @@ -8,6 +8,7 @@ #include <Swiften/Base/API.h> #include <Swiften/Elements/Payload.h> +#include <cassert> namespace Swift { class SWIFTEN_API StatusShow : public Payload { @@ -37,6 +38,7 @@ namespace Swift { case DND: return 3; case None: return 0; } + assert(false); return 0; } diff --git a/Swiften/Elements/StreamError.h b/Swiften/Elements/StreamError.h index 0d0551c..a58d3ae 100644 --- a/Swiften/Elements/StreamError.h +++ b/Swiften/Elements/StreamError.h @@ -41,7 +41,7 @@ namespace Swift { UndefinedCondition, UnsupportedEncoding, UnsupportedStanzaType, - UnsupportedVersion, + UnsupportedVersion }; StreamError(Type type = UndefinedCondition, const std::string& text = std::string()) : type_(type), text_(text) { } diff --git a/Swiften/Elements/StreamInitiationFileInfo.h b/Swiften/Elements/StreamInitiationFileInfo.h index 6569c3d..d7907b9 100644 --- a/Swiften/Elements/StreamInitiationFileInfo.h +++ b/Swiften/Elements/StreamInitiationFileInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -19,7 +19,7 @@ public: typedef boost::shared_ptr<StreamInitiationFileInfo> ref; public: - StreamInitiationFileInfo(const std::string& name = "", const std::string& description = "", int size = 0, + 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) {} @@ -39,11 +39,11 @@ public: return this->description; } - void setSize(const boost::uintmax_t size) { + void setSize(const unsigned long long size) { this->size = size; } - boost::uintmax_t getSize() const { + unsigned long long getSize() const { return this->size; } @@ -79,24 +79,24 @@ public: return supportsRangeRequests; } - void setRangeOffset(const int offset) { - supportsRangeRequests = offset >= 0 ? true : false; + void setRangeOffset(unsigned long long offset) { + supportsRangeRequests = true; rangeOffset = offset; } - boost::uintmax_t getRangeOffset() const { + unsigned long long getRangeOffset() const { return rangeOffset; } private: std::string name; std::string description; - boost::uintmax_t size; + unsigned long long size; std::string hash; boost::posix_time::ptime date; std::string algo; bool supportsRangeRequests; - boost::uintmax_t rangeOffset; + unsigned long long rangeOffset; }; } diff --git a/Swiften/Elements/UnblockPayload.h b/Swiften/Elements/UnblockPayload.h index b6593ab..c5e7c80 100644 --- a/Swiften/Elements/UnblockPayload.h +++ b/Swiften/Elements/UnblockPayload.h @@ -14,7 +14,7 @@ namespace Swift { class UnblockPayload : public Payload { public: - UnblockPayload() { + UnblockPayload(const std::vector<JID>& jids = std::vector<JID>()) : items(jids) { } void addItem(const JID& item) { diff --git a/Swiften/Elements/UnitTest/FormTest.cpp b/Swiften/Elements/UnitTest/FormTest.cpp index 1134182..3000c22 100644 --- a/Swiften/Elements/UnitTest/FormTest.cpp +++ b/Swiften/Elements/UnitTest/FormTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #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> @@ -23,13 +24,13 @@ class FormTest : public CppUnit::TestFixture { void testGetFormType() { Form form; - form.addField(FixedFormField::create("Foo")); + form.addField(boost::make_shared<FormField>(FormField::FixedType, "Foo")); - FormField::ref field = HiddenFormField::create("jabber:bot"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:bot"); field->setName("FORM_TYPE"); form.addField(field); - form.addField(FixedFormField::create("Bar")); + form.addField(boost::make_shared<FormField>(FormField::FixedType, "Bar")); CPPUNIT_ASSERT_EQUAL(std::string("jabber:bot"), form.getFormType()); } @@ -37,7 +38,7 @@ class FormTest : public CppUnit::TestFixture { void testGetFormType_InvalidFormType() { Form form; - FormField::ref field = FixedFormField::create("jabber:bot"); + FormField::ref field = boost::make_shared<FormField>(FormField::FixedType, "jabber:bot"); field->setName("FORM_TYPE"); form.addField(field); @@ -47,7 +48,7 @@ class FormTest : public CppUnit::TestFixture { void testGetFormType_NoFormType() { Form form; - form.addField(FixedFormField::create("Foo")); + form.addField(boost::make_shared<FormField>(FormField::FixedType, "Foo")); CPPUNIT_ASSERT_EQUAL(std::string(""), form.getFormType()); } diff --git a/Swiften/Elements/UserLocation.cpp b/Swiften/Elements/UserLocation.cpp new file mode 100644 index 0000000..f22973e --- /dev/null +++ b/Swiften/Elements/UserLocation.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/UserLocation.h> + +using namespace Swift; + +UserLocation::UserLocation() { +} + +UserLocation::~UserLocation() { +} diff --git a/Swiften/Elements/UserLocation.h b/Swiften/Elements/UserLocation.h new file mode 100644 index 0000000..2355838 --- /dev/null +++ b/Swiften/Elements/UserLocation.h @@ -0,0 +1,227 @@ +/* + * 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/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> + + + +namespace Swift { + 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< float >& getAltitude() const { + return altitude; + } + + void setAltitude(const boost::optional< float >& value) { + this->altitude = value ; + } + + const boost::optional< std::string >& getLocality() const { + return locality; + } + + void setLocality(const boost::optional< std::string >& value) { + this->locality = value ; + } + + const boost::optional< float >& getLatitude() const { + return latitude; + } + + void setLatitude(const boost::optional< float >& value) { + this->latitude = value ; + } + + const boost::optional< float >& getAccuracy() const { + return accuracy; + } + + void setAccuracy(const boost::optional< float >& value) { + this->accuracy = value ; + } + + const boost::optional< std::string >& getDescription() const { + return description; + } + + void setDescription(const boost::optional< std::string >& value) { + this->description = value ; + } + + const boost::optional< std::string >& getCountryCode() const { + return countryCode; + } + + void setCountryCode(const boost::optional< std::string >& value) { + this->countryCode = value ; + } + + const boost::optional< boost::posix_time::ptime >& getTimestamp() const { + return timestamp; + } + + void setTimestamp(const boost::optional< boost::posix_time::ptime >& value) { + this->timestamp = value ; + } + + const boost::optional< std::string >& getFloor() const { + return floor; + } + + void setFloor(const boost::optional< std::string >& value) { + this->floor = value ; + } + + const boost::optional< std::string >& getBuilding() const { + return building; + } + + void setBuilding(const boost::optional< std::string >& value) { + this->building = 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; + }; +} diff --git a/Swiften/Elements/VCard.h b/Swiften/Elements/VCard.h index f9822c9..84b6cfe 100644 --- a/Swiften/Elements/VCard.h +++ b/Swiften/Elements/VCard.h @@ -7,8 +7,10 @@ #pragma once #include <boost/shared_ptr.hpp> +#include <boost/date_time/posix_time/ptime.hpp> #include <string> +#include <Swiften/JID/JID.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/Elements/Payload.h> @@ -29,6 +31,71 @@ namespace Swift { 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; } @@ -78,8 +145,124 @@ namespace Swift { emailAddresses_.push_back(email); } + void clearEMailAddresses() { + emailAddresses_.clear(); + } + EMailAddress getPreferredEMailAddress() const; + void setBirthday(const boost::posix_time::ptime& birthday) { + birthday_ = birthday; + } + + const boost::posix_time::ptime& getBirthday() const { + return birthday_; + } + + const std::vector<Telephone>& getTelephones() const { + return telephones_; + } + + void addTelephone(const Telephone& phone) { + telephones_.push_back(phone); + } + + void clearTelephones() { + telephones_.clear(); + } + + const std::vector<Address>& getAddresses() const { + return addresses_; + } + + 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_; @@ -92,7 +275,17 @@ namespace Swift { 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/Whiteboard/WhiteboardOperation.h b/Swiften/Elements/Whiteboard/WhiteboardOperation.h index 02c6438..75f6e6a 100644 --- a/Swiften/Elements/Whiteboard/WhiteboardOperation.h +++ b/Swiften/Elements/Whiteboard/WhiteboardOperation.h @@ -14,7 +14,7 @@ namespace Swift { public: typedef boost::shared_ptr<WhiteboardOperation> ref; public: - virtual ~WhiteboardOperation(){}; + virtual ~WhiteboardOperation(){} std::string getID() const { return id_; diff --git a/Swiften/Entity/PayloadPersister.cpp b/Swiften/Entity/PayloadPersister.cpp index 729d36a..ace7b4a 100644 --- a/Swiften/Entity/PayloadPersister.cpp +++ b/Swiften/Entity/PayloadPersister.cpp @@ -42,7 +42,7 @@ boost::shared_ptr<Payload> PayloadPersister::loadPayload(const boost::filesystem try { if (boost::filesystem::exists(path)) { ByteArray data; - readByteArrayFromFile(data, path.string()); + readByteArrayFromFile(data, path); boost::shared_ptr<PayloadParser> parser(createParser()); PayloadParserTester tester(parser.get()); tester.parse(byteArrayToString(data)); diff --git a/Swiften/EventLoop/Cocoa/CocoaEvent.h b/Swiften/EventLoop/Cocoa/CocoaEvent.h index bede7ff..89d056f 100644 --- a/Swiften/EventLoop/Cocoa/CocoaEvent.h +++ b/Swiften/EventLoop/Cocoa/CocoaEvent.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -13,11 +13,18 @@ namespace Swift { class CocoaEventLoop; } +// Using deprecated declaration of instance vars in interface, because this +// is required for older runtimes (e.g. 32-bit Mac OS X) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-interface-ivars" + @interface CocoaEvent : NSObject { Swift::Event* event; Swift::CocoaEventLoop* eventLoop; } +#pragma clang diagnostic pop + // Takes ownership of event - (id) initWithEvent: (Swift::Event*) e eventLoop: (Swift::CocoaEventLoop*) el; - (void) process; diff --git a/Swiften/EventLoop/Cocoa/CocoaEvent.mm b/Swiften/EventLoop/Cocoa/CocoaEvent.mm index 049e3b6..7b1b4b0 100644 --- a/Swiften/EventLoop/Cocoa/CocoaEvent.mm +++ b/Swiften/EventLoop/Cocoa/CocoaEvent.mm @@ -2,7 +2,7 @@ #include <Swiften/EventLoop/Event.h> #include <Swiften/EventLoop/Cocoa/CocoaEventLoop.h> -@implementation CocoaEvent +@implementation CocoaEvent - (id) initWithEvent: (Swift::Event*) e eventLoop: (Swift::CocoaEventLoop*) el { self = [super init]; diff --git a/Swiften/EventLoop/EventLoop.cpp b/Swiften/EventLoop/EventLoop.cpp index cd4e461..502bc49 100644 --- a/Swiften/EventLoop/EventLoop.cpp +++ b/Swiften/EventLoop/EventLoop.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,13 +7,16 @@ #include <Swiften/EventLoop/EventLoop.h> #include <algorithm> -#include <boost/bind.hpp> #include <iostream> #include <cassert> +#include <boost/bind.hpp> +#include <boost/lambda/lambda.hpp> +#include <boost/lambda/bind.hpp> #include <boost/thread/locks.hpp> #include <Swiften/Base/Log.h> +namespace lambda = boost::lambda; namespace Swift { @@ -84,7 +87,7 @@ void EventLoop::postEvent(boost::function<void ()> callback, boost::shared_ptr<E void EventLoop::removeEventsFromOwner(boost::shared_ptr<EventOwner> owner) { boost::lock_guard<boost::mutex> lock(eventsMutex_); - events_.remove_if(HasOwner(owner)); + events_.remove_if(lambda::bind(&Event::owner, lambda::_1) == owner); } } diff --git a/Swiften/EventLoop/EventLoop.h b/Swiften/EventLoop/EventLoop.h index 4a602ae..587ba22 100644 --- a/Swiften/EventLoop/EventLoop.h +++ b/Swiften/EventLoop/EventLoop.h @@ -35,11 +35,6 @@ namespace Swift { void handleEvent(const Event& event); private: - struct HasOwner { - HasOwner(boost::shared_ptr<EventOwner> owner) : owner(owner) {} - bool operator()(const Event& event) const { return event.owner == owner; } - boost::shared_ptr<EventOwner> owner; - }; boost::mutex eventsMutex_; unsigned int nextEventID_; std::list<Event> events_; diff --git a/Swiften/EventLoop/SConscript b/Swiften/EventLoop/SConscript index b405f6b..8bef8fb 100644 --- a/Swiften/EventLoop/SConscript +++ b/Swiften/EventLoop/SConscript @@ -12,7 +12,7 @@ sources = [ objects = swiften_env.SwiftenObject(sources) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) -if swiften_env["PLATFORM"] == "darwin" : +if swiften_env["PLATFORM"] == "darwin" and swiften_env["target"] == "native": myenv = swiften_env.Clone() myenv.Append(CXXFLAGS = myenv["OBJCCFLAGS"]) objects = myenv.SwiftenObject([ diff --git a/Swiften/EventLoop/SimpleEventLoop.cpp b/Swiften/EventLoop/SimpleEventLoop.cpp index 63b8ba5..42a5481 100644 --- a/Swiften/EventLoop/SimpleEventLoop.cpp +++ b/Swiften/EventLoop/SimpleEventLoop.cpp @@ -14,8 +14,6 @@ namespace Swift { -void nop() {} - SimpleEventLoop::SimpleEventLoop() : isRunning_(true) { } diff --git a/Swiften/Examples/BenchTool/BenchTool.cpp b/Swiften/Examples/BenchTool/BenchTool.cpp index ba6cf84..9725b7e 100644 --- a/Swiften/Examples/BenchTool/BenchTool.cpp +++ b/Swiften/Examples/BenchTool/BenchTool.cpp @@ -20,13 +20,13 @@ using namespace Swift; -SimpleEventLoop eventLoop; -BoostNetworkFactories networkFactories(&eventLoop); -int numberOfConnectedClients = 0; -int numberOfInstances = 100; +static SimpleEventLoop eventLoop; +static BoostNetworkFactories networkFactories(&eventLoop); +static int numberOfConnectedClients = 0; +static int numberOfInstances = 100; -void handleConnected() { +static void handleConnected() { numberOfConnectedClients++; std::cout << "Connected " << numberOfConnectedClients << std::endl; } diff --git a/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp b/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp index 636a52a..df2a23d 100644 --- a/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp +++ b/Swiften/Examples/ConnectivityTest/ConnectivityTest.cpp @@ -21,15 +21,15 @@ using namespace Swift; enum ExitCodes {OK = 0, CANNOT_CONNECT, CANNOT_AUTH, NO_RESPONSE, DISCO_ERROR}; -SimpleEventLoop eventLoop; -BoostNetworkFactories networkFactories(&eventLoop); +static SimpleEventLoop eventLoop; +static BoostNetworkFactories networkFactories(&eventLoop); -Client* client = 0; -JID recipient; -int exitCode = CANNOT_CONNECT; -boost::bsignals::connection errorConnection; +static Client* client = 0; +static JID recipient; +static int exitCode = CANNOT_CONNECT; +static boost::bsignals::connection errorConnection; -void handleServerDiscoInfoResponse(boost::shared_ptr<DiscoInfo> /*info*/, ErrorPayload::ref error) { +static void handleServerDiscoInfoResponse(boost::shared_ptr<DiscoInfo> /*info*/, ErrorPayload::ref error) { if (!error) { errorConnection.disconnect(); client->disconnect(); @@ -41,14 +41,14 @@ void handleServerDiscoInfoResponse(boost::shared_ptr<DiscoInfo> /*info*/, ErrorP } } -void handleConnected() { +static void handleConnected() { exitCode = NO_RESPONSE; GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(JID(), client->getIQRouter()); discoInfoRequest->onResponse.connect(&handleServerDiscoInfoResponse); discoInfoRequest->send(); } -void handleDisconnected(const boost::optional<ClientError>&) { +static void handleDisconnected(const boost::optional<ClientError>&) { exitCode = CANNOT_AUTH; eventLoop.stop(); } diff --git a/Swiften/Examples/ConnectivityTest/SConscript b/Swiften/Examples/ConnectivityTest/SConscript index 7bc3892..55a0821 100644 --- a/Swiften/Examples/ConnectivityTest/SConscript +++ b/Swiften/Examples/ConnectivityTest/SConscript @@ -1,7 +1,7 @@ Import("env") myenv = env.Clone() -myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) -myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) tester = myenv.Program("ConnectivityTest", ["ConnectivityTest.cpp"]) diff --git a/Swiften/Examples/LinkLocalTool/SConscript b/Swiften/Examples/LinkLocalTool/SConscript index 788f5c1..18eb91f 100644 --- a/Swiften/Examples/LinkLocalTool/SConscript +++ b/Swiften/Examples/LinkLocalTool/SConscript @@ -1,8 +1,8 @@ Import("env") myenv = env.Clone() -myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) -myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) linkLocalTool = myenv.Program("LinkLocalTool", [ "main.cpp" diff --git a/Swiften/Examples/NetworkTool/main.cpp b/Swiften/Examples/NetworkTool/main.cpp index 00c12d2..10a0aa6 100644 --- a/Swiften/Examples/NetworkTool/main.cpp +++ b/Swiften/Examples/NetworkTool/main.cpp @@ -16,9 +16,9 @@ using namespace Swift; -SimpleEventLoop eventLoop; +static SimpleEventLoop eventLoop; -void handleGetPublicIPRequestResponse(const boost::optional<HostAddress>& result) { +static void handleGetPublicIPRequestResponse(const boost::optional<HostAddress>& result) { if (result) { std::cerr << "Result: " << result->toString() << std::endl;; } @@ -28,7 +28,7 @@ void handleGetPublicIPRequestResponse(const boost::optional<HostAddress>& result eventLoop.stop(); } -void handleGetForwardPortRequestResponse(const boost::optional<NATPortMapping>& result) { +static void handleGetForwardPortRequestResponse(const boost::optional<NATPortMapping>& result) { if (result) { std::cerr << "Result: " << result->getPublicPort() << " -> " << result->getLocalPort() << std::endl;; } @@ -38,7 +38,7 @@ void handleGetForwardPortRequestResponse(const boost::optional<NATPortMapping>& eventLoop.stop(); } -void handleRemovePortForwardingRequestResponse(bool result) { +static void handleRemovePortForwardingRequestResponse(bool result) { if (result) { std::cerr << "Result: OK" << std::endl; } @@ -58,7 +58,7 @@ int main(int argc, char* argv[]) { if (std::string(argv[1]) == "get-public-ip") { boost::shared_ptr<NATTraversalGetPublicIPRequest> query = natTraverser.createGetPublicIPRequest(); query->onResult.connect(boost::bind(&handleGetPublicIPRequestResponse, _1)); - query->run(); + query->start(); eventLoop.run(); } else if (std::string(argv[1]) == "add-port-forward") { @@ -67,7 +67,7 @@ int main(int argc, char* argv[]) { } 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->run(); + query->start(); eventLoop.run(); } else if (std::string(argv[1]) == "remove-port-forward") { @@ -76,7 +76,7 @@ int main(int argc, char* argv[]) { } 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->run(); + query->start(); eventLoop.run(); } else if (std::string(argv[1]) == "get-local-ip") { diff --git a/Swiften/Examples/ParserTester/SConscript b/Swiften/Examples/ParserTester/SConscript index 09cffc9..5c93552 100644 --- a/Swiften/Examples/ParserTester/SConscript +++ b/Swiften/Examples/ParserTester/SConscript @@ -1,7 +1,7 @@ Import("env") myenv = env.Clone() -myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) -myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) myenv.Program("ParserTester", ["ParserTester.cpp"]) diff --git a/Swiften/Examples/SendFile/ReceiveFile.cpp b/Swiften/Examples/SendFile/ReceiveFile.cpp index 39b3cc3..c777fee 100644 --- a/Swiften/Examples/SendFile/ReceiveFile.cpp +++ b/Swiften/Examples/SendFile/ReceiveFile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -10,6 +10,7 @@ #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> @@ -20,24 +21,22 @@ #include <Swiften/FileTransfer/IncomingFileTransferManager.h> #include <Swiften/FileTransfer/FileWriteBytestream.h> #include <Swiften/Jingle/JingleSessionManager.h> -#include <Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.h> -#include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> #include <Swiften/FileTransfer/FileTransferManager.h> using namespace Swift; -SimpleEventLoop eventLoop; -BoostNetworkFactories networkFactories(&eventLoop); +static SimpleEventLoop eventLoop; +static BoostNetworkFactories networkFactories(&eventLoop); -int exitCode = 2; +static int exitCode = 2; 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), jingleSessionManager(NULL), incomingFileTransferManager(NULL) { + 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)); @@ -64,8 +63,7 @@ class FileReceiver { private: void handleConnected() { - Swift::logging = true; - client->getFileTransferManager()->startListeningOnPort(9999); + Log::setLogLevel(Log::debug); client->getFileTransferManager()->onIncomingFileTransfer.connect(boost::bind(&FileReceiver::handleIncomingFileTransfer, this, _1)); DiscoInfo discoInfo; @@ -83,9 +81,9 @@ class FileReceiver { void handleIncomingFileTransfer(IncomingFileTransfer::ref transfer) { SWIFT_LOG(debug) << "foo" << std::endl; incomingFileTransfers.push_back(transfer); - transfer->accept(boost::make_shared<FileWriteBytestream>("out")); - //transfer->onFinished.connect(boost::bind(&FileReceiver::handleFileTransferFinished, this, _1)); - //transfer->start(); + 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>&) { @@ -93,16 +91,18 @@ class FileReceiver { exit(-1); } - /* - void handleFileTransferFinished(const boost::optional<FileTransferError>& error) { + 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; @@ -115,8 +115,6 @@ class FileReceiver { std::string password; Client* client; ClientXMLTracer* tracer; - JingleSessionManager* jingleSessionManager; - IncomingFileTransferManager* incomingFileTransferManager; std::vector<IncomingFileTransfer::ref> incomingFileTransfers; }; diff --git a/Swiften/Examples/SendFile/SConscript b/Swiften/Examples/SendFile/SConscript index d335513..e0f1256 100644 --- a/Swiften/Examples/SendFile/SConscript +++ b/Swiften/Examples/SendFile/SConscript @@ -1,8 +1,8 @@ Import("env") myenv = env.Clone() -myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) -myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) myenv.Program("SendFile", ["SendFile.cpp"]) myenv.Program("ReceiveFile", ["ReceiveFile.cpp"]) diff --git a/Swiften/Examples/SendFile/SendFile.cpp b/Swiften/Examples/SendFile/SendFile.cpp index a926170..b056842 100644 --- a/Swiften/Examples/SendFile/SendFile.cpp +++ b/Swiften/Examples/SendFile/SendFile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,6 +11,7 @@ #include <Swiften/Client/Client.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> @@ -25,20 +26,16 @@ #include <Swiften/FileTransfer/OutgoingFileTransfer.h> #include <Swiften/Jingle/JingleSessionManager.h> #include <Swiften/Disco/EntityCapsManager.h> -#include <Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.h> -#include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h> #include <Swiften/Base/ByteArray.h> -#include <Swiften/StringCodecs/MD5.h> -#include <Swiften/StringCodecs/SHA1.h> #include <Swiften/StringCodecs/Hexify.h> #include <Swiften/FileTransfer/FileTransferManager.h> using namespace Swift; -SimpleEventLoop eventLoop; -BoostNetworkFactories networkFactories(&eventLoop); +static SimpleEventLoop eventLoop; +static BoostNetworkFactories networkFactories(&eventLoop); -int exitCode = 2; +static int exitCode = 2; class FileSender { public: @@ -66,9 +63,8 @@ class FileSender { void handleConnected() { client->sendPresence(Presence::create()); - client->getFileTransferManager()->startListeningOnPort(19999); //ByteArray fileData; - //readByteArrayFromFile(fileData, file.string()); + //readByteArrayFromFile(fileData, file); // gather file information /*StreamInitiationFileInfo fileInfo; @@ -143,7 +139,7 @@ int main(int argc, char* argv[]) { JID sender(argv[1]); JID recipient(argv[3]); - Swift::logging = true; + Log::setLogLevel(Log::debug); FileSender fileSender(sender, std::string(argv[2]), recipient, boost::filesystem::path(argv[4])); fileSender.start(); { diff --git a/Swiften/Examples/SendMessage/SConscript b/Swiften/Examples/SendMessage/SConscript index 8907d25..0466187 100644 --- a/Swiften/Examples/SendMessage/SConscript +++ b/Swiften/Examples/SendMessage/SConscript @@ -1,7 +1,7 @@ Import("env") myenv = env.Clone() -myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) -myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) +myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) tester = myenv.Program("SendMessage", ["SendMessage.cpp"]) diff --git a/Swiften/Examples/SendMessage/SendMessage.cpp b/Swiften/Examples/SendMessage/SendMessage.cpp index 07e289e..2a3170f 100644 --- a/Swiften/Examples/SendMessage/SendMessage.cpp +++ b/Swiften/Examples/SendMessage/SendMessage.cpp @@ -18,17 +18,17 @@ using namespace Swift; -SimpleEventLoop eventLoop; -BoostNetworkFactories networkFactories(&eventLoop); +static SimpleEventLoop eventLoop; +static BoostNetworkFactories networkFactories(&eventLoop); -Client* client = 0; -JID recipient; -std::string messageBody; -int exitCode = 2; -boost::bsignals::connection errorConnection; +static Client* client = 0; +static JID recipient; +static std::string messageBody; +static int exitCode = 2; +static boost::bsignals::connection errorConnection; -void handleConnected() { +static void handleConnected() { boost::shared_ptr<Message> message(new Message()); message->setBody(messageBody); message->setTo(recipient); @@ -39,7 +39,7 @@ void handleConnected() { eventLoop.stop(); } -void handleDisconnected(const boost::optional<ClientError>&) { +static void handleDisconnected(const boost::optional<ClientError>&) { std::cerr << "Error!" << std::endl; exitCode = 1; eventLoop.stop(); diff --git a/Swiften/FileTransfer/ByteArrayReadBytestream.cpp b/Swiften/FileTransfer/ByteArrayReadBytestream.cpp new file mode 100644 index 0000000..4ba791f --- /dev/null +++ b/Swiften/FileTransfer/ByteArrayReadBytestream.cpp @@ -0,0 +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. + */ + +#include <Swiften/FileTransfer/ByteArrayReadBytestream.h> + +#include <boost/smart_ptr/make_shared.hpp> +#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; +} + +void ByteArrayReadBytestream::addData(const std::vector<unsigned char>& moreData) { + append(data, moreData); + onDataAvailable(); +} diff --git a/Swiften/FileTransfer/ByteArrayReadBytestream.h b/Swiften/FileTransfer/ByteArrayReadBytestream.h index 9311099..664698a 100644 --- a/Swiften/FileTransfer/ByteArrayReadBytestream.h +++ b/Swiften/FileTransfer/ByteArrayReadBytestream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,9 +7,7 @@ #pragma once #include <vector> -#include <boost/smart_ptr/make_shared.hpp> -#include <Swiften/Base/Algorithm.h> #include <Swiften/FileTransfer/ReadBytestream.h> #include <Swiften/Base/ByteArray.h> @@ -19,17 +17,7 @@ namespace Swift { ByteArrayReadBytestream(const std::vector<unsigned char>& data) : data(data), position(0), dataComplete(true) { } - virtual boost::shared_ptr<ByteArray> 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() + position, data.begin() + position + readSize); - - onRead(*result); - position += readSize; - return result; - } + virtual boost::shared_ptr<ByteArray> read(size_t size); virtual bool isFinished() const { return position >= data.size() && dataComplete; @@ -39,10 +27,7 @@ namespace Swift { dataComplete = b; } - void addData(const std::vector<unsigned char>& moreData) { - append(data, moreData); - onDataAvailable(); - } + void addData(const std::vector<unsigned char>& moreData); private: std::vector<unsigned char> data; diff --git a/Swiften/FileTransfer/ConnectivityManager.cpp b/Swiften/FileTransfer/ConnectivityManager.cpp deleted file mode 100644 index 7d25991..0000000 --- a/Swiften/FileTransfer/ConnectivityManager.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2011 Tobias Markmann - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. - */ - -#include "ConnectivityManager.h" - -#include <boost/bind.hpp> - -#include <Swiften/Base/foreach.h> -#include <Swiften/Base/Log.h> -#include <Swiften/Network/NetworkInterface.h> -#include <Swiften/Network/NATTraversalGetPublicIPRequest.h> -#include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h> -#include <Swiften/Network/NATTraverser.h> -#include <Swiften/Network/PlatformNetworkEnvironment.h> - -namespace Swift { - -ConnectivityManager::ConnectivityManager(NATTraverser* worker) : natTraversalWorker(worker) { - -} - -ConnectivityManager::~ConnectivityManager() { - std::set<int> leftOpenPorts = ports; - foreach(int port, leftOpenPorts) { - removeListeningPort(port); - } -} - -void ConnectivityManager::addListeningPort(int port) { - ports.insert(port); - boost::shared_ptr<NATTraversalGetPublicIPRequest> getIPRequest = natTraversalWorker->createGetPublicIPRequest(); - if (getIPRequest) { - getIPRequest->onResult.connect(boost::bind(&ConnectivityManager::natTraversalGetPublicIPResult, this, _1)); - getIPRequest->run(); - } - - boost::shared_ptr<NATTraversalForwardPortRequest> forwardPortRequest = natTraversalWorker->createForwardPortRequest(port, port); - if (forwardPortRequest) { - forwardPortRequest->onResult.connect(boost::bind(&ConnectivityManager::natTraversalForwardPortResult, this, _1)); - forwardPortRequest->run(); - } -} - -void ConnectivityManager::removeListeningPort(int port) { - SWIFT_LOG(debug) << "remove listening port " << port << std::endl; - ports.erase(port); - boost::shared_ptr<NATTraversalRemovePortForwardingRequest> removePortForwardingRequest = natTraversalWorker->createRemovePortForwardingRequest(port, port); - if (removePortForwardingRequest) { - removePortForwardingRequest->run(); - } -} - -std::vector<HostAddressPort> ConnectivityManager::getHostAddressPorts() const { - PlatformNetworkEnvironment env; - std::vector<HostAddressPort> results; - - std::vector<HostAddress> addresses; - - std::vector<NetworkInterface> networkInterfaces; - foreach (const NetworkInterface& iface, networkInterfaces) { - foreach (const HostAddress& address, iface.getAddresses()) { - foreach (int port, ports) { - results.push_back(HostAddressPort(address, port)); - } - } - } - - return results; -} - -std::vector<HostAddressPort> ConnectivityManager::getAssistedHostAddressPorts() const { - std::vector<HostAddressPort> results; - - if (publicAddress) { - foreach (int port, ports) { - results.push_back(HostAddressPort(publicAddress.get(), port)); - } - } - - return results; -} - -void ConnectivityManager::natTraversalGetPublicIPResult(boost::optional<HostAddress> address) { - if (address) { - publicAddress = address; - SWIFT_LOG(debug) << "Public IP discovered as " << publicAddress.get().toString() << "." << std::endl; - } else { - SWIFT_LOG(debug) << "No public IP discoverable." << std::endl; - } -} - -void ConnectivityManager::natTraversalForwardPortResult(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; - } -} - - -} diff --git a/Swiften/FileTransfer/ConnectivityManager.h b/Swiften/FileTransfer/ConnectivityManager.h deleted file mode 100644 index c094c02..0000000 --- a/Swiften/FileTransfer/ConnectivityManager.h +++ /dev/null @@ -1,45 +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 <vector> -#include <set> - -#include <boost/optional.hpp> - -#include <Swiften/Network/HostAddressPort.h> -#include <Swiften/Network/NATTraverser.h> -#include <Swiften/Network/NATTraversalForwardPortRequest.h> -#include <Swiften/Network/NATPortMapping.h> - -namespace Swift { - -class NATTraverser; - -class ConnectivityManager { -public: - ConnectivityManager(NATTraverser*); - ~ConnectivityManager(); -public: - void addListeningPort(int port); - void removeListeningPort(int port); - - std::vector<HostAddressPort> getHostAddressPorts() const; - std::vector<HostAddressPort> getAssistedHostAddressPorts() const; - -private: - void natTraversalGetPublicIPResult(boost::optional<HostAddress> address); - void natTraversalForwardPortResult(boost::optional<NATPortMapping> mapping); - -private: - NATTraverser* natTraversalWorker; - - std::set<int> ports; - boost::optional<HostAddress> publicAddress; -}; - -} diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp new file mode 100644 index 0000000..af87fd2 --- /dev/null +++ b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/DefaultFileTransferTransporter.h> + +#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/FileTransfer/LocalJingleTransportCandidateGenerator.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> +#include <Swiften/FileTransfer/IBBSendSession.h> +#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/FileTransfer/TransportSession.h> +#include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Queries/GenericRequest.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)); +} + +DefaultFileTransferTransporter::~DefaultFileTransferTransporter() { + delete remoteCandidateSelector; + delete localCandidateGenerator; +} + +void DefaultFileTransferTransporter::initialize() { + s5bSessionID = s5bRegistry->generateSessionID(); +} + +void DefaultFileTransferTransporter::initialize(const std::string& s5bSessionID) { + this->s5bSessionID = s5bSessionID; +} + +void DefaultFileTransferTransporter::startGeneratingLocalCandidates() { + localCandidateGenerator->start(); +} + +void DefaultFileTransferTransporter::stopGeneratingLocalCandidates() { + localCandidateGenerator->stop(); +} + +void DefaultFileTransferTransporter::handleLocalCandidatesGenerated( + const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { + s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), true); + onLocalCandidatesGenerated(s5bSessionID, candidates); +} + +void DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished( + const boost::optional<JingleS5BTransportPayload::Candidate>& candidate, + boost::shared_ptr<SOCKS5BytestreamClientSession> session) { + remoteS5BClientSession = session; + onRemoteCandidateSelectFinished(s5bSessionID, candidate); +} + + +void DefaultFileTransferTransporter::addRemoteCandidates( + const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { + remoteCandidateSelector->setSOCKS5DstAddr(getSOCKS5DstAddr()); + remoteCandidateSelector->addCandidates(candidates); +} + +void DefaultFileTransferTransporter::startTryingRemoteCandidates() { + remoteCandidateSelector->startSelectingCandidate(); +} + +void DefaultFileTransferTransporter::stopTryingRemoteCandidates() { + 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::stopActivatingProxy() { + // TODO + assert(false); +} + +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); +} + +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); +} + +boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( + boost::shared_ptr<ReadBytestream> stream) { + closeLocalSession(); + return boost::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( + remoteS5BClientSession, stream); +} + +boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( + boost::shared_ptr<WriteBytestream> stream) { + closeLocalSession(); + return boost::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>(); +} + + +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>(); + } +} + +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::string DefaultFileTransferTransporter::getSOCKS5DstAddr() const { + return Hexify::hexify(crypto->getSHA1Hash( + createSafeByteArray(s5bSessionID + initiator.toString() + initiator.toString()))); +} + +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(); + } +} + +void DefaultFileTransferTransporter::closeRemoteSession() { + if (remoteS5BClientSession) { + remoteS5BClientSession->stop(); + remoteS5BClientSession.reset(); + } +} diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporter.h b/Swiften/FileTransfer/DefaultFileTransferTransporter.h new file mode 100644 index 0000000..ef982c0 --- /dev/null +++ b/Swiften/FileTransfer/DefaultFileTransferTransporter.h @@ -0,0 +1,102 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.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 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(); + + + virtual void initialize(); + virtual void initialize(const std::string& s5bSessionID); + + virtual void startGeneratingLocalCandidates() SWIFTEN_OVERRIDE; + virtual void stopGeneratingLocalCandidates() SWIFTEN_OVERRIDE; + + virtual void addRemoteCandidates( + const std::vector<JingleS5BTransportPayload::Candidate>&) SWIFTEN_OVERRIDE; + virtual void startTryingRemoteCandidates() SWIFTEN_OVERRIDE; + virtual void stopTryingRemoteCandidates() SWIFTEN_OVERRIDE; + + virtual void startActivatingProxy(const JID& jid); + virtual void stopActivatingProxy(); + + 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; + + 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(); + + 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; + }; +} + diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp new file mode 100644 index 0000000..4c8a55e --- /dev/null +++ b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h> + +#include <Swiften/FileTransfer/DefaultFileTransferTransporter.h> + +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) +{ +} + +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; +} + +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; +} diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h new file mode 100644 index 0000000..b5e8f95 --- /dev/null +++ b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h @@ -0,0 +1,51 @@ +/* + * 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/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 SWIFTEN_API DefaultFileTransferTransporterFactory : public FileTransferTransporterFactory { + public: + DefaultFileTransferTransporterFactory( + SOCKS5BytestreamRegistry*, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + IDGenerator* idGenerator, + ConnectionFactory*, + TimerFactory*, + CryptoProvider*, + IQRouter*); + virtual ~DefaultFileTransferTransporterFactory(); + + 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; + + private: + SOCKS5BytestreamRegistry* s5bRegistry; + SOCKS5BytestreamServerManager* s5bServerManager; + SOCKS5BytestreamProxiesManager* s5bProxiesManager; + IDGenerator* idGenerator; + ConnectionFactory* connectionFactory; + TimerFactory* timerFactory; + CryptoProvider* cryptoProvider; + IQRouter* iqRouter; + }; +} diff --git a/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGenerator.cpp b/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGenerator.cpp deleted file mode 100644 index 4b205cb..0000000 --- a/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGenerator.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2011 Tobias Markmann - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. - */ - -#include "DefaultLocalJingleTransportCandidateGenerator.h" - -#include <vector> - -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> - -#include <Swiften/Base/foreach.h> -#include <Swiften/Base/Log.h> -#include <Swiften/Elements/JingleIBBTransportPayload.h> -#include <Swiften/Elements/JingleS5BTransportPayload.h> -#include <Swiften/FileTransfer/ConnectivityManager.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamProxy.h> - -namespace Swift { - -DefaultLocalJingleTransportCandidateGenerator::DefaultLocalJingleTransportCandidateGenerator(ConnectivityManager* connectivityManager, SOCKS5BytestreamRegistry* s5bRegistry, SOCKS5BytestreamProxy* s5bProxy, JID& ownJID) : connectivityManager(connectivityManager), s5bRegistry(s5bRegistry), s5bProxy(s5bProxy), ownJID(ownJID) { -} - -DefaultLocalJingleTransportCandidateGenerator::~DefaultLocalJingleTransportCandidateGenerator() { -} - -void DefaultLocalJingleTransportCandidateGenerator::generateLocalTransportCandidates(JingleTransportPayload::ref transportPayload) { - if (boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transportPayload)) { - JingleTransportPayload::ref payL = boost::make_shared<JingleTransportPayload>(); - payL->setSessionID(transportPayload->getSessionID()); - onLocalTransportCandidatesGenerated(payL); - } - if (boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transportPayload)) { - JingleS5BTransportPayload::ref payL = boost::make_shared<JingleS5BTransportPayload>(); - payL->setSessionID(transportPayload->getSessionID()); - payL->setMode(JingleS5BTransportPayload::TCPMode); - - const unsigned long localPreference = 0; - - // get direct candidates - std::vector<HostAddressPort> directCandidates = connectivityManager->getHostAddressPorts(); - foreach(HostAddressPort addressPort, directCandidates) { - JingleS5BTransportPayload::Candidate candidate; - candidate.type = JingleS5BTransportPayload::Candidate::DirectType; - candidate.jid = ownJID; - candidate.hostPort = addressPort; - candidate.priority = 65536 * 126 + localPreference; - candidate.cid = idGenerator.generateID(); - payL->addCandidate(candidate); - } - - // get assissted candidates - std::vector<HostAddressPort> assisstedCandidates = connectivityManager->getAssistedHostAddressPorts(); - foreach(HostAddressPort addressPort, assisstedCandidates) { - JingleS5BTransportPayload::Candidate candidate; - candidate.type = JingleS5BTransportPayload::Candidate::AssistedType; - candidate.jid = ownJID; - candidate.hostPort = addressPort; - candidate.priority = 65536 * 120 + localPreference; - candidate.cid = idGenerator.generateID(); - payL->addCandidate(candidate); - } - - // get proxy candidates - std::vector<S5BProxyRequest::ref> proxyCandidates = s5bProxy->getS5BProxies(); - foreach(S5BProxyRequest::ref proxy, proxyCandidates) { - 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 + localPreference; - candidate.cid = idGenerator.generateID(); - payL->addCandidate(candidate); - } - } - - onLocalTransportCandidatesGenerated(payL); - } - -} - -bool DefaultLocalJingleTransportCandidateGenerator::isActualCandidate(JingleTransportPayload::ref transportPayload) { - if (!transportPayload.get()) return false; - return false; -} - -int DefaultLocalJingleTransportCandidateGenerator::getPriority(JingleTransportPayload::ref /* transportPayload */) { - return 0; -} - -JingleTransport::ref DefaultLocalJingleTransportCandidateGenerator::selectTransport(JingleTransportPayload::ref /* transportPayload */) { - return JingleTransport::ref(); -} - -} diff --git a/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGenerator.h b/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGenerator.h deleted file mode 100644 index 7d45491..0000000 --- a/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGenerator.h +++ /dev/null @@ -1,39 +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/FileTransfer/LocalJingleTransportCandidateGenerator.h> - -#include <Swiften/Base/IDGenerator.h> -#include <Swiften/JID/JID.h> - -namespace Swift { - -class SOCKS5BytestreamRegistry; -class SOCKS5BytestreamProxy; -class ConnectivityManager; - -class DefaultLocalJingleTransportCandidateGenerator : public LocalJingleTransportCandidateGenerator { -public: - DefaultLocalJingleTransportCandidateGenerator(ConnectivityManager* connectivityManager, SOCKS5BytestreamRegistry* s5bRegistry, SOCKS5BytestreamProxy* s5bProxy, JID& ownJID); - virtual ~DefaultLocalJingleTransportCandidateGenerator(); - - virtual void generateLocalTransportCandidates(JingleTransportPayload::ref); - - virtual bool isActualCandidate(JingleTransportPayload::ref); - virtual int getPriority(JingleTransportPayload::ref); - virtual JingleTransport::ref selectTransport(JingleTransportPayload::ref); - -private: - IDGenerator idGenerator; - ConnectivityManager* connectivityManager; - SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamProxy* s5bProxy; - JID ownJID; -}; - -} diff --git a/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.cpp b/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.cpp deleted file mode 100644 index ed0386e..0000000 --- a/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2011 Tobias Markmann - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. - */ - -#include "DefaultLocalJingleTransportCandidateGeneratorFactory.h" - -#include <Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGenerator.h> -#include <Swiften/Base/Log.h> - -namespace Swift { - -DefaultLocalJingleTransportCandidateGeneratorFactory::DefaultLocalJingleTransportCandidateGeneratorFactory(ConnectivityManager* connectivityManager, SOCKS5BytestreamRegistry* s5bRegistry, SOCKS5BytestreamProxy* s5bProxy, const JID& ownJID) : connectivityManager(connectivityManager), s5bRegistry(s5bRegistry), s5bProxy(s5bProxy), ownJID(ownJID) { -} - -DefaultLocalJingleTransportCandidateGeneratorFactory::~DefaultLocalJingleTransportCandidateGeneratorFactory() { -} - -LocalJingleTransportCandidateGenerator* DefaultLocalJingleTransportCandidateGeneratorFactory::createCandidateGenerator() { - return new DefaultLocalJingleTransportCandidateGenerator(connectivityManager, s5bRegistry, s5bProxy, ownJID); -} - - -} diff --git a/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.h b/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.h deleted file mode 100644 index 511d0a1..0000000 --- a/Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.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 <Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h> - -#include <Swiften/JID/JID.h> - -namespace Swift { - -class ConnectivityManager; -class SOCKS5BytestreamRegistry; -class SOCKS5BytestreamProxy; - -class DefaultLocalJingleTransportCandidateGeneratorFactory : public LocalJingleTransportCandidateGeneratorFactory{ -public: - DefaultLocalJingleTransportCandidateGeneratorFactory(ConnectivityManager* connectivityManager, SOCKS5BytestreamRegistry* s5bRegistry, SOCKS5BytestreamProxy* s5bProxy, const JID& ownJID); - virtual ~DefaultLocalJingleTransportCandidateGeneratorFactory(); - - LocalJingleTransportCandidateGenerator* createCandidateGenerator(); - -private: - ConnectivityManager* connectivityManager; - SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamProxy* s5bProxy; - JID ownJID; -}; - -} diff --git a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.cpp b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.cpp deleted file mode 100644 index 32b4df8..0000000 --- a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2011 Tobias Markmann - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. - */ - -#include "DefaultRemoteJingleTransportCandidateSelector.h" - -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/bind.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> - -namespace Swift { - -DefaultRemoteJingleTransportCandidateSelector::DefaultRemoteJingleTransportCandidateSelector(ConnectionFactory* connectionFactory, TimerFactory* timerFactory) : connectionFactory(connectionFactory), timerFactory(timerFactory) { -} - -DefaultRemoteJingleTransportCandidateSelector::~DefaultRemoteJingleTransportCandidateSelector() { -} - -void DefaultRemoteJingleTransportCandidateSelector::addRemoteTransportCandidates(JingleTransportPayload::ref transportPayload) { - JingleS5BTransportPayload::ref s5bPayload; - transportSID = transportPayload->getSessionID(); - if ((s5bPayload = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transportPayload))) { - foreach(JingleS5BTransportPayload::Candidate c, s5bPayload->getCandidates()) { - candidates.push(c); - } - } -} - -void DefaultRemoteJingleTransportCandidateSelector::selectCandidate() { - tryNextCandidate(true); -} - -void DefaultRemoteJingleTransportCandidateSelector::tryNextCandidate(bool error) { - if (error) { - if (s5bSession) { - SWIFT_LOG(debug) << "failed to connect" << std::endl; - } - if (candidates.empty()) { - // failed to connect to any of the candidates - // issue an error - SWIFT_LOG(debug) << "out of candidates )=" << std::endl; - JingleS5BTransportPayload::ref failed = boost::make_shared<JingleS5BTransportPayload>(); - failed->setCandidateError(true); - failed->setSessionID(transportSID); - onRemoteTransportCandidateSelectFinished(failed); - } else { - lastCandidate = candidates.top(); - // only try direct or assisted for now - if (lastCandidate.type == JingleS5BTransportPayload::Candidate::DirectType || - lastCandidate.type == JingleS5BTransportPayload::Candidate::AssistedType || lastCandidate.type == JingleS5BTransportPayload::Candidate::ProxyType ) { - // create connection - connection = connectionFactory->createConnection(); - s5bSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, lastCandidate.hostPort, SOCKS5BytestreamRegistry::getHostname(transportSID, requester, target), timerFactory); - - // bind onReady to this method - s5bSession->onSessionReady.connect(boost::bind(&DefaultRemoteJingleTransportCandidateSelector::tryNextCandidate, this, _1)); - - std::string candidateType; - if (lastCandidate.type == JingleS5BTransportPayload::Candidate::DirectType) { - candidateType = "direct"; - } else if (lastCandidate.type == JingleS5BTransportPayload::Candidate::AssistedType) { - candidateType = "assisted"; - } else if (lastCandidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { - candidateType = "proxy"; - } - - // initiate connect - SWIFT_LOG(debug) << "try to connect to candidate of type " << candidateType << " : " << lastCandidate.hostPort.toString() << std::endl; - s5bSession->start(); - - // that's it. we're gonna be called back - candidates.pop(); - } else { - s5bSession.reset(); - candidates.pop(); - tryNextCandidate(true); - } - } - } else { - // we have a working connection, hooray - JingleS5BTransportPayload::ref success = boost::make_shared<JingleS5BTransportPayload>(); - success->setCandidateUsed(lastCandidate.cid); - success->setSessionID(transportSID); - onRemoteTransportCandidateSelectFinished(success); - } -} - -void DefaultRemoteJingleTransportCandidateSelector::setMinimumPriority(int priority) { - SWIFT_LOG(debug) << "priority: " << priority << std::endl; -} - -void DefaultRemoteJingleTransportCandidateSelector::setRequesterTargtet(const JID& requester, const JID& target) { - this->requester = requester; - this->target = target; -} - -SOCKS5BytestreamClientSession::ref DefaultRemoteJingleTransportCandidateSelector::getS5BSession() { - return s5bSession; -} - -bool DefaultRemoteJingleTransportCandidateSelector::isActualCandidate(JingleTransportPayload::ref /* transportPayload */) { - return false; -} - -int DefaultRemoteJingleTransportCandidateSelector::getPriority(JingleTransportPayload::ref /* transportPayload */) { - return 0; -} - -JingleTransport::ref DefaultRemoteJingleTransportCandidateSelector::selectTransport(JingleTransportPayload::ref /* transportPayload */) { - return JingleTransport::ref(); -} - -} diff --git a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.h b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.h deleted file mode 100644 index 255acd9..0000000 --- a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.h +++ /dev/null @@ -1,58 +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 <queue> -#include <vector> - -#include <boost/shared_ptr.hpp> - -#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 DefaultRemoteJingleTransportCandidateSelector : public RemoteJingleTransportCandidateSelector { -public: - DefaultRemoteJingleTransportCandidateSelector(ConnectionFactory*, TimerFactory*); - virtual ~DefaultRemoteJingleTransportCandidateSelector(); - - virtual void addRemoteTransportCandidates(JingleTransportPayload::ref); - virtual void selectCandidate(); - virtual void setMinimumPriority(int); - void setRequesterTargtet(const JID& requester, const JID& target); - virtual SOCKS5BytestreamClientSession::ref getS5BSession(); - - virtual bool isActualCandidate(JingleTransportPayload::ref); - virtual int getPriority(JingleTransportPayload::ref); - virtual JingleTransport::ref selectTransport(JingleTransportPayload::ref); - -private: - void tryNextCandidate(bool error); - -private: - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; - - std::priority_queue<JingleS5BTransportPayload::Candidate, std::vector<JingleS5BTransportPayload::Candidate>, JingleS5BTransportPayload::CompareCandidate> candidates; - - std::string transportSID; - boost::shared_ptr<Connection> connection; - boost::shared_ptr<SOCKS5BytestreamClientSession> s5bSession; - JingleS5BTransportPayload::Candidate lastCandidate; - JID requester; - JID target; -}; - -} diff --git a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.cpp b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.cpp deleted file mode 100644 index 8ebbf46..0000000 --- a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2011 Tobias Markmann - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. - */ - -#include "DefaultRemoteJingleTransportCandidateSelectorFactory.h" - -#include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.h> - -#include <Swiften/Base/Log.h> - -namespace Swift { - -DefaultRemoteJingleTransportCandidateSelectorFactory::DefaultRemoteJingleTransportCandidateSelectorFactory(ConnectionFactory* connectionFactory, TimerFactory* timerFactory) : connectionFactory(connectionFactory), timerFactory(timerFactory) { -} - -DefaultRemoteJingleTransportCandidateSelectorFactory::~DefaultRemoteJingleTransportCandidateSelectorFactory() { -} - -RemoteJingleTransportCandidateSelector* DefaultRemoteJingleTransportCandidateSelectorFactory::createCandidateSelector() { - return new DefaultRemoteJingleTransportCandidateSelector(connectionFactory, timerFactory); -} - -} diff --git a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h deleted file mode 100644 index ca29e1f..0000000 --- a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.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/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h> - -namespace Swift { - -class ConnectionFactory; -class TimerFactory; - -class DefaultRemoteJingleTransportCandidateSelectorFactory : public RemoteJingleTransportCandidateSelectorFactory { -public: - DefaultRemoteJingleTransportCandidateSelectorFactory(ConnectionFactory*, TimerFactory*); - virtual ~DefaultRemoteJingleTransportCandidateSelectorFactory(); - - RemoteJingleTransportCandidateSelector* createCandidateSelector(); - -private: - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; -}; - -} diff --git a/Swiften/FileTransfer/FileReadBytestream.cpp b/Swiften/FileTransfer/FileReadBytestream.cpp index a8946a0..4257f8b 100644 --- a/Swiften/FileTransfer/FileReadBytestream.cpp +++ b/Swiften/FileTransfer/FileReadBytestream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #include <boost/filesystem/fstream.hpp> #include <cassert> #include <boost/smart_ptr/make_shared.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/FileTransfer/FileReadBytestream.h> #include <Swiften/Base/ByteArray.h> @@ -30,8 +31,8 @@ boost::shared_ptr<ByteArray> FileReadBytestream::read(size_t size) { boost::shared_ptr<ByteArray> result = boost::make_shared<ByteArray>(); result->resize(size); assert(stream->good()); - stream->read(reinterpret_cast<char*>(vecptr(*result)), size); - result->resize(stream->gcount()); + 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; } diff --git a/Swiften/FileTransfer/FileTransfer.cpp b/Swiften/FileTransfer/FileTransfer.cpp new file mode 100644 index 0000000..c11e8e4 --- /dev/null +++ b/Swiften/FileTransfer/FileTransfer.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/FileTransfer.h> + +using namespace Swift; + +FileTransfer::FileTransfer() { +} + +FileTransfer::~FileTransfer() { +} + +void FileTransfer::setFileInfo(const std::string& name, boost::uintmax_t size) { + filename = name; + fileSizeInBytes = size; +} diff --git a/Swiften/FileTransfer/FileTransfer.h b/Swiften/FileTransfer/FileTransfer.h index 336c51c..c01aadb 100644 --- a/Swiften/FileTransfer/FileTransfer.h +++ b/Swiften/FileTransfer/FileTransfer.h @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #pragma once #include <boost/cstdint.hpp> @@ -14,46 +20,51 @@ #include <Swiften/FileTransfer/FileTransferError.h> namespace Swift { + class FileTransfer { + public: + struct State { + enum Type { + Initial, + WaitingForStart, + Negotiating, + WaitingForAccept, + Transferring, + Canceled, + Failed, + Finished + }; -class FileTransfer { -public: - struct State { - enum FTState { - Canceled, - Failed, - Finished, - Negotiating, - Transferring, - WaitingForStart, - WaitingForAccept, - }; - - FTState state; - std::string message; - - State(FTState state) : state(state), message("") {} - State(FTState state, std::string message) : state(state), message(message) {} - }; + State(Type type, const std::string& message = "") : type(type), message(message) {} -public: - typedef boost::shared_ptr<FileTransfer> ref; + Type type; + std::string message; + }; + typedef boost::shared_ptr<FileTransfer> ref; -public: - boost::uintmax_t fileSizeInBytes; - std::string filename; - std::string algo; - std::string hash; + public: + FileTransfer(); + virtual ~FileTransfer(); -public: - virtual void cancel() = 0; + virtual void cancel() = 0; -public: - boost::signal<void (int /* proccessedBytes */)> onProcessedBytes; - boost::signal<void (State)> onStateChange; - boost::signal<void (boost::optional<FileTransferError>)> onFinished; + const std::string& getFileName() const { + return filename; + } -public: - virtual ~FileTransfer() {} -}; + 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; + }; } diff --git a/Swiften/FileTransfer/FileTransferError.h b/Swiften/FileTransfer/FileTransferError.h index 6a6b454..eb1e8f8 100644 --- a/Swiften/FileTransfer/FileTransferError.h +++ b/Swiften/FileTransfer/FileTransferError.h @@ -13,7 +13,7 @@ namespace Swift { UnknownError, PeerError, ReadError, - ClosedError, + ClosedError }; FileTransferError(Type type = UnknownError) : type(type) {} diff --git a/Swiften/FileTransfer/FileTransferManager.h b/Swiften/FileTransfer/FileTransferManager.h index 30d9faf..3b793c5 100644 --- a/Swiften/FileTransfer/FileTransferManager.h +++ b/Swiften/FileTransfer/FileTransferManager.h @@ -4,30 +4,46 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #pragma once #include <string> -#include <boost/filesystem.hpp> +#include <boost/filesystem/path.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/boost_bsignals.h> #include <Swiften/JID/JID.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> #include <Swiften/FileTransfer/OutgoingFileTransfer.h> #include <Swiften/FileTransfer/IncomingFileTransfer.h> namespace Swift { class ReadBytestream; - class S5BProxyRequest; class SWIFTEN_API FileTransferManager { public: virtual ~FileTransferManager(); - virtual void startListeningOnPort(int port) = 0; - - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer(const JID& to, const boost::filesystem::path& filepath, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream) = 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) = 0; + 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; }; diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp index 84b2061..b832d7e 100644 --- a/Swiften/FileTransfer/FileTransferManagerImpl.cpp +++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp @@ -4,24 +4,30 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Base/foreach.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/SOCKS5BytestreamProxyFinder.h> -#include <Swiften/FileTransfer/ConnectivityManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> #include <Swiften/FileTransfer/OutgoingFileTransferManager.h> #include <Swiften/FileTransfer/IncomingFileTransferManager.h> -#include <Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.h> -#include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h> +#include <Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamProxy.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> #include <Swiften/Presence/PresenceOracle.h> #include <Swiften/Elements/Presence.h> #include <Swiften/Network/ConnectionFactory.h> @@ -33,52 +39,64 @@ namespace Swift { -FileTransferManagerImpl::FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, NATTraverser* natTraverser) : ownJID(ownFullJID), jingleSM(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), presenceOracle(presOracle), connectionServerFactory(connectionServerFactory), bytestreamServer(NULL), s5bProxyFinder(NULL) { +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()); - connectivityManager = new ConnectivityManager(natTraverser); bytestreamRegistry = new SOCKS5BytestreamRegistry(); - bytestreamProxy = new SOCKS5BytestreamProxy(connectionFactory, timerFactory); - - localCandidateGeneratorFactory = new DefaultLocalJingleTransportCandidateGeneratorFactory(connectivityManager, bytestreamRegistry, bytestreamProxy, ownFullJID); - remoteCandidateSelectorFactory = new DefaultRemoteJingleTransportCandidateSelectorFactory(connectionFactory, timerFactory); - outgoingFTManager = new OutgoingFileTransferManager(jingleSM, iqRouter, capsProvider, remoteCandidateSelectorFactory, localCandidateGeneratorFactory, bytestreamRegistry, bytestreamProxy); - incomingFTManager = new IncomingFileTransferManager(jingleSM, iqRouter, remoteCandidateSelectorFactory, localCandidateGeneratorFactory, bytestreamRegistry, bytestreamProxy, timerFactory); + 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); } FileTransferManagerImpl::~FileTransferManagerImpl() { - if (s5bProxyFinder) { - s5bProxyFinder->stop(); - delete s5bProxyFinder; - } - if (bytestreamServer) { - bytestreamServer->stop(); - delete bytestreamServer; - } + delete s5bServerManager; delete incomingFTManager; delete outgoingFTManager; - delete remoteCandidateSelectorFactory; - delete localCandidateGeneratorFactory; - delete connectivityManager; + delete transporterFactory; } -void FileTransferManagerImpl::startListeningOnPort(int port) { - // TODO: create a server for each interface we're on - SWIFT_LOG(debug) << "Start listening on port " << port << " and hope it's not in use." << std::endl; - boost::shared_ptr<ConnectionServer> server = connectionServerFactory->createConnectionServer(HostAddress("0.0.0.0"), port); - server->start(); - bytestreamServer = new SOCKS5BytestreamServer(server, bytestreamRegistry); - bytestreamServer->start(); - connectivityManager->addListeningPort(port); - - s5bProxyFinder = new SOCKS5BytestreamProxyFinder(ownJID.getDomain(), iqRouter); - s5bProxyFinder->onProxyFound.connect(boost::bind(&FileTransferManagerImpl::addS5BProxy, this, _1)); - s5bProxyFinder->start(); +void FileTransferManagerImpl::start() { } -void FileTransferManagerImpl::addS5BProxy(S5BProxyRequest::ref proxy) { - bytestreamProxy->addS5BProxy(proxy); +void FileTransferManagerImpl::stop() { + s5bServerManager->stop(); } boost::optional<JID> FileTransferManagerImpl::highestPriorityJIDSupportingFileTransfer(const JID& bareJID) { @@ -104,19 +122,31 @@ boost::optional<JID> FileTransferManagerImpl::highestPriorityJIDSupportingFileTr return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>(); } -OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer(const JID& to, const boost::filesystem::path& filepath, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream) { +OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer( + const JID& to, + const boost::filesystem::path& filepath, + const std::string& description, + boost::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(); #else - std::string filename = filepath.filename().string(); + 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); + 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) { +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); @@ -134,7 +164,7 @@ OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer(co } } - return outgoingFTManager->createOutgoingFileTransfer(ownJID, receipient, bytestream, fileInfo); + return outgoingFTManager->createOutgoingFileTransfer(ownJID, receipient, bytestream, fileInfo, config); } } diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.h b/Swiften/FileTransfer/FileTransferManagerImpl.h index ecc692d..addbbd7 100644 --- a/Swiften/FileTransfer/FileTransferManagerImpl.h +++ b/Swiften/FileTransfer/FileTransferManagerImpl.h @@ -4,53 +4,84 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * 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 <string> -#include <boost/filesystem.hpp> +#include <boost/filesystem/path.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/optional.hpp> +#include <Swiften/Base/API.h> +#include <Swiften/Base/Override.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> namespace Swift { - class Client; class ConnectionFactory; class ConnectionServerFactory; - class ConnectivityManager; + class SOCKS5BytestreamServerManager; class EntityCapsProvider; class IQRouter; class IncomingFileTransferManager; class JingleSessionManager; - class LocalJingleTransportCandidateGeneratorFactory; class OutgoingFileTransferManager; class NATTraverser; class PresenceOracle; class ReadBytestream; - class RemoteJingleTransportCandidateSelectorFactory; + class FileTransferTransporterFactory; class SOCKS5BytestreamRegistry; - class SOCKS5BytestreamServer; - class SOCKS5BytestreamProxy; + class SOCKS5BytestreamProxiesManager; class TimerFactory; - class SOCKS5BytestreamProxyFinder; + class CryptoProvider; + class NetworkEnvironment; - class FileTransferManagerImpl : public FileTransferManager { + 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, NATTraverser* natTraverser); + 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(); - void startListeningOnPort(int port); - void addS5BProxy(S5BProxyRequest::ref proxy); + 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; - OutgoingFileTransfer::ref createOutgoingFileTransfer(const JID& to, const boost::filesystem::path& filepath, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream); - 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); + void start(); + void stop(); private: boost::optional<JID> highestPriorityJIDSupportingFileTransfer(const JID& bareJID); @@ -60,19 +91,13 @@ namespace Swift { OutgoingFileTransferManager* outgoingFTManager; IncomingFileTransferManager* incomingFTManager; - RemoteJingleTransportCandidateSelectorFactory* remoteCandidateSelectorFactory; - LocalJingleTransportCandidateGeneratorFactory* localCandidateGeneratorFactory; - JingleSessionManager* jingleSM; + FileTransferTransporterFactory* transporterFactory; IQRouter* iqRouter; EntityCapsProvider* capsProvider; PresenceOracle* presenceOracle; - - ConnectionServerFactory* connectionServerFactory; + IDGenerator idGenerator; SOCKS5BytestreamRegistry* bytestreamRegistry; - SOCKS5BytestreamServer* bytestreamServer; - SOCKS5BytestreamProxy* bytestreamProxy; - ConnectivityManager* connectivityManager; - SOCKS5BytestreamProxyFinder* s5bProxyFinder; + SOCKS5BytestreamProxiesManager* bytestreamProxy; + SOCKS5BytestreamServerManager* s5bServerManager; }; - } diff --git a/Swiften/FileTransfer/FileTransferOptions.cpp b/Swiften/FileTransfer/FileTransferOptions.cpp new file mode 100644 index 0000000..af816ec --- /dev/null +++ b/Swiften/FileTransfer/FileTransferOptions.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/FileTransferOptions.h> + +using namespace Swift; + +FileTransferOptions::~FileTransferOptions() { +} diff --git a/Swiften/FileTransfer/FileTransferOptions.h b/Swiften/FileTransfer/FileTransferOptions.h new file mode 100644 index 0000000..304ced8 --- /dev/null +++ b/Swiften/FileTransfer/FileTransferOptions.h @@ -0,0 +1,32 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> + +namespace Swift { + class SWIFTEN_API FileTransferOptions { + public: + FileTransferOptions() : allowInBand(false) { + } + + ~FileTransferOptions(); + + FileTransferOptions& withInBandAllowed(bool b) { + allowInBand = b; + return *this; + } + + bool isInBandAllowed() const { + return allowInBand; + } + + private: + bool allowInBand; + }; +} diff --git a/Swiften/FileTransfer/FileTransferTransporter.cpp b/Swiften/FileTransfer/FileTransferTransporter.cpp new file mode 100644 index 0000000..30966c4 --- /dev/null +++ b/Swiften/FileTransfer/FileTransferTransporter.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/FileTransferTransporter.h> + +using namespace Swift; + +FileTransferTransporter::~FileTransferTransporter() { +} diff --git a/Swiften/FileTransfer/FileTransferTransporter.h b/Swiften/FileTransfer/FileTransferTransporter.h new file mode 100644 index 0000000..b7b7090 --- /dev/null +++ b/Swiften/FileTransfer/FileTransferTransporter.h @@ -0,0 +1,55 @@ +/* + * 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 <boost/optional/optional_fwd.hpp> + +#include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/Base/API.h> +#include <Swiften/Base/boost_bsignals.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; + }; +} diff --git a/Swiften/FileTransfer/FileTransferTransporterFactory.cpp b/Swiften/FileTransfer/FileTransferTransporterFactory.cpp new file mode 100644 index 0000000..0acc016 --- /dev/null +++ b/Swiften/FileTransfer/FileTransferTransporterFactory.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/FileTransferTransporterFactory.h> + +using namespace Swift; + +FileTransferTransporterFactory::~FileTransferTransporterFactory() { +} diff --git a/Swiften/FileTransfer/FileTransferTransporterFactory.h b/Swiften/FileTransfer/FileTransferTransporterFactory.h new file mode 100644 index 0000000..f7f9acc --- /dev/null +++ b/Swiften/FileTransfer/FileTransferTransporterFactory.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <Swiften/Base/API.h> + +namespace Swift { + class JID; + class FileTransferTransporter; + + 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; + }; +} diff --git a/Swiften/FileTransfer/FileWriteBytestream.cpp b/Swiften/FileTransfer/FileWriteBytestream.cpp index 6a22c6a..6c11eb0 100644 --- a/Swiften/FileTransfer/FileWriteBytestream.cpp +++ b/Swiften/FileTransfer/FileWriteBytestream.cpp @@ -1,11 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <boost/filesystem/fstream.hpp> #include <cassert> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/FileTransfer/FileWriteBytestream.h> @@ -22,11 +23,14 @@ FileWriteBytestream::~FileWriteBytestream() { } 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]), data.size()); + stream->write(reinterpret_cast<const char*>(&data[0]), boost::numeric_cast<std::streamsize>(data.size())); onWrite(data); } diff --git a/Swiften/FileTransfer/IBBReceiveSession.cpp b/Swiften/FileTransfer/IBBReceiveSession.cpp index 1a2bb3a..3aa6fdc 100644 --- a/Swiften/FileTransfer/IBBReceiveSession.cpp +++ b/Swiften/FileTransfer/IBBReceiveSession.cpp @@ -27,7 +27,7 @@ class IBBReceiveSession::IBBResponder : public SetResponder<IBB> { if (from == session->from && ibb->getStreamID() == session->id) { if (ibb->getAction() == IBB::Data) { if (sequenceNumber == ibb->getSequenceNumber()) { - session->onDataReceived(ibb->getData()); + session->bytestream->write(ibb->getData()); receivedSize += ibb->getData().size(); sequenceNumber++; sendResponse(from, id, IBB::ref()); @@ -62,7 +62,7 @@ class IBBReceiveSession::IBBResponder : public SetResponder<IBB> { private: IBBReceiveSession* session; int sequenceNumber; - size_t receivedSize; + unsigned long long receivedSize; }; @@ -70,12 +70,14 @@ IBBReceiveSession::IBBReceiveSession( const std::string& id, const JID& from, const JID& to, - size_t size, + 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()); diff --git a/Swiften/FileTransfer/IBBReceiveSession.h b/Swiften/FileTransfer/IBBReceiveSession.h index f075fe2..23d9648 100644 --- a/Swiften/FileTransfer/IBBReceiveSession.h +++ b/Swiften/FileTransfer/IBBReceiveSession.h @@ -25,7 +25,8 @@ namespace Swift { const std::string& id, const JID& from, const JID& to, - size_t size, + unsigned long long size, + boost::shared_ptr<WriteBytestream> bytestream, IQRouter* router); ~IBBReceiveSession(); @@ -40,7 +41,6 @@ namespace Swift { return to; } - boost::signal<void (const std::vector<unsigned char>&)> onDataReceived; boost::signal<void (boost::optional<FileTransferError>)> onFinished; private: @@ -54,7 +54,8 @@ namespace Swift { std::string id; JID from; JID to; - size_t size; + unsigned long long size; + boost::shared_ptr<WriteBytestream> bytestream; IQRouter* router; IBBResponder* responder; bool active; diff --git a/Swiften/FileTransfer/IBBSendSession.cpp b/Swiften/FileTransfer/IBBSendSession.cpp index c24cc0a..d8b7c7b 100644 --- a/Swiften/FileTransfer/IBBSendSession.cpp +++ b/Swiften/FileTransfer/IBBSendSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #include <Swiften/FileTransfer/IBBSendSession.h> #include <boost/bind.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/ByteArray.h> #include <Swiften/Queries/IQRouter.h> @@ -15,7 +16,21 @@ 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) { +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)); } @@ -24,7 +39,8 @@ IBBSendSession::~IBBSendSession() { } void IBBSendSession::start() { - IBBRequest::ref request = IBBRequest::create(from, to, IBB::createIBBOpen(id, blockSize), router); + 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(); diff --git a/Swiften/FileTransfer/IBBSendSession.h b/Swiften/FileTransfer/IBBSendSession.h index a535382..f6ba7b3 100644 --- a/Swiften/FileTransfer/IBBSendSession.h +++ b/Swiften/FileTransfer/IBBSendSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -22,7 +22,12 @@ namespace Swift { class SWIFTEN_API IBBSendSession { public: - IBBSendSession(const std::string& id, const JID& from, const JID& to, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* router); + IBBSendSession( + const std::string& id, + const JID& from, + const JID& to, + boost::shared_ptr<ReadBytestream> bytestream, + IQRouter* router); ~IBBSendSession(); void start(); @@ -36,12 +41,12 @@ namespace Swift { return to; } - void setBlockSize(int blockSize) { + void setBlockSize(unsigned int blockSize) { this->blockSize = blockSize; } boost::signal<void (boost::optional<FileTransferError>)> onFinished; - boost::signal<void (int)> onBytesSent; + boost::signal<void (size_t)> onBytesSent; private: void handleIBBResponse(IBB::ref, ErrorPayload::ref); @@ -55,7 +60,7 @@ namespace Swift { JID to; boost::shared_ptr<ReadBytestream> bytestream; IQRouter* router; - int blockSize; + unsigned int blockSize; int sequenceNumber; bool active; bool waitingForData; diff --git a/Swiften/FileTransfer/IncomingFileTransfer.h b/Swiften/FileTransfer/IncomingFileTransfer.h index 5b53d54..698a588 100644 --- a/Swiften/FileTransfer/IncomingFileTransfer.h +++ b/Swiften/FileTransfer/IncomingFileTransfer.h @@ -9,18 +9,22 @@ #include <boost/shared_ptr.hpp> #include <Swiften/Base/boost_bsignals.h> -#include <Swiften/JID/JID.h> #include <Swiften/FileTransfer/FileTransfer.h> -#include <Swiften/FileTransfer/WriteBytestream.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(WriteBytestream::ref) = 0; + virtual void accept( + boost::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 22e8bf9..d40c5de 100644 --- a/Swiften/FileTransfer/IncomingFileTransferManager.cpp +++ b/Swiften/FileTransfer/IncomingFileTransferManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -18,9 +18,17 @@ namespace Swift { -IncomingFileTransferManager::IncomingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, - RemoteJingleTransportCandidateSelectorFactory* remoteFactory, - LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, TimerFactory* timerFactory) : jingleSessionManager(jingleSessionManager), router(router), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), timerFactory(timerFactory) { +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); } @@ -28,16 +36,19 @@ IncomingFileTransferManager::~IncomingFileTransferManager() { jingleSessionManager->removeIncomingSessionHandler(this); } -bool IncomingFileTransferManager::handleIncomingJingleSession(JingleSession::ref session, const std::vector<JingleContentPayload::ref>& contents, const JID& recipient) { +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<JingleIBBTransportPayload>() || content->getTransport<JingleS5BTransportPayload>()) { - + 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, remoteFactory, localFactory, router, bytestreamRegistry, bytestreamProxy, timerFactory); + IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>( + recipient, session, content, transporterFactory, timerFactory, crypto); onIncomingFileTransfer(transfer); - } else { + } + else { std::cerr << "Received a file-transfer request with no description or more than one file!" << std::endl; session->sendTerminate(JinglePayload::Reason::FailedApplication); } diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.h b/Swiften/FileTransfer/IncomingFileTransferManager.h index 2d1c07f..9570def 100644 --- a/Swiften/FileTransfer/IncomingFileTransferManager.h +++ b/Swiften/FileTransfer/IncomingFileTransferManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -15,29 +15,33 @@ namespace Swift { class IQRouter; class JingleSessionManager; - class RemoteJingleTransportCandidateSelectorFactory; - class LocalJingleTransportCandidateGeneratorFactory; - class SOCKS5BytestreamRegistry; - class SOCKS5BytestreamProxy; + class FileTransferTransporterFactory; class TimerFactory; + class CryptoProvider; class IncomingFileTransferManager : public IncomingJingleSessionHandler { public: - IncomingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, TimerFactory* timerFactory); + 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); + bool handleIncomingJingleSession( + JingleSession::ref session, + const std::vector<JingleContentPayload::ref>& contents, + const JID& recipient); private: JingleSessionManager* jingleSessionManager; IQRouter* router; - RemoteJingleTransportCandidateSelectorFactory* remoteFactory; - LocalJingleTransportCandidateGeneratorFactory* localFactory; - SOCKS5BytestreamRegistry* bytestreamRegistry; - SOCKS5BytestreamProxy* bytestreamProxy; + FileTransferTransporterFactory* transporterFactory; TimerFactory* timerFactory; + CryptoProvider* crypto; }; } diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp index 808ff58..b64e333 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,510 +11,384 @@ #include <Swiften/Base/Log.h> #include <Swiften/Base/foreach.h> +#include <Swiften/Jingle/JingleSession.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/Elements/JingleFileTransferHash.h> -#include <Swiften/Elements/S5BProxyRequest.h> #include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h> -#include <Swiften/FileTransfer/JingleIncomingIBBTransport.h> -#include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> -#include <Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamProxy.h> +#include <Swiften/FileTransfer/FileTransferTransporter.h> +#include <Swiften/FileTransfer/FileTransferTransporterFactory.h> +#include <Swiften/FileTransfer/WriteBytestream.h> +#include <Swiften/Elements/JingleFileTransferDescription.h> #include <Swiften/Network/TimerFactory.h> #include <Swiften/Queries/GenericRequest.h> +#include <Swiften/FileTransfer/TransportSession.h> -namespace Swift { +using namespace Swift; + +// TODO: ALlow terminate when already terminated. IncomingJingleFileTransfer::IncomingJingleFileTransfer( - const JID& ourJID, + const JID& toJID, JingleSession::ref session, JingleContentPayload::ref content, - RemoteJingleTransportCandidateSelectorFactory* candidateSelectorFactory, - LocalJingleTransportCandidateGeneratorFactory* candidateGeneratorFactory, - IQRouter* router, - SOCKS5BytestreamRegistry* registry, - SOCKS5BytestreamProxy* proxy, - TimerFactory* timerFactory) : - ourJID(ourJID), - session(session), - router(router), + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto) : + JingleFileTransfer(session, toJID, transporterFactory), initialContent(content), + crypto(crypto), state(Initial), receivedBytes(0), - s5bRegistry(registry), - s5bProxy(proxy), - remoteTransportCandidateSelectFinished(false), - localTransportCandidateSelectFinished(false), - serverSession(0) { - - candidateSelector = candidateSelectorFactory->createCandidateSelector(); - candidateSelector->onRemoteTransportCandidateSelectFinished.connect(boost::bind(&IncomingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1)); - - candidateGenerator = candidateGeneratorFactory->createCandidateGenerator(); - candidateGenerator->onLocalTransportCandidatesGenerated.connect(boost::bind(&IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1)); - - session->onTransportInfoReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleTransportInfoReceived, this, _1, _2)); - session->onTransportReplaceReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleTransportReplaceReceived, this, _1, _2)); - session->onSessionTerminateReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleSessionTerminateReceived, this, _1)); - session->onSessionInfoReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleSessionInfoReceived, this, _1)); - + hashCalculator(NULL) { description = initialContent->getDescription<JingleFileTransferDescription>(); assert(description); assert(description->getOffers().size() == 1); StreamInitiationFileInfo fileInfo = description->getOffers().front(); - fileSizeInBytes = fileInfo.getSize(); - filename = fileInfo.getName(); + setFileInfo(fileInfo.getName(), fileInfo.getSize()); hash = fileInfo.getHash(); - algo = fileInfo.getAlgo(); + hashAlgorithm = fileInfo.getAlgo(); waitOnHashTimer = timerFactory->createTimer(5000); - waitOnHashTimer->onTick.connect(boost::bind(&IncomingJingleFileTransfer::finishOffTransfer, this)); + waitOnHashTimerTickedConnection = waitOnHashTimer->onTick.connect( + boost::bind(&IncomingJingleFileTransfer::handleWaitOnHashTimerTicked, this)); } IncomingJingleFileTransfer::~IncomingJingleFileTransfer() { - stream->onWrite.disconnect(boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); - delete hashCalculator; - - session->onSessionTerminateReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleSessionTerminateReceived, this, _1)); - session->onTransportReplaceReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleTransportReplaceReceived, this, _1, _2)); - session->onTransportInfoReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleTransportInfoReceived, this, _1, _2)); - - candidateGenerator->onLocalTransportCandidatesGenerated.disconnect(boost::bind(&IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1)); - delete candidateGenerator; - - candidateSelector->onRemoteTransportCandidateSelectFinished.disconnect(boost::bind(&IncomingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1)); - delete candidateSelector; } -void IncomingJingleFileTransfer::accept(WriteBytestream::ref stream) { +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; - hashCalculator = new IncrementalBytestreamHashCalculator( algo == "md5" || hash.empty() , algo == "sha-1" || hash.empty() ); - stream->onWrite.connect(boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); - stream->onWrite.connect(boost::bind(&IncomingJingleFileTransfer::handleWriteStreamDataReceived, this, _1)); - onStateChange(FileTransfer::State(FileTransfer::State::Negotiating)); - if (JingleIBBTransportPayload::ref ibbTransport = initialContent->getTransport<JingleIBBTransportPayload>()) { - SWIFT_LOG(debug) << "Got IBB transport payload!" << std::endl; - setActiveTransport(createIBBTransport(ibbTransport)); - session->sendAccept(getContentID(), initialContent->getDescriptions()[0], ibbTransport); - } - else if (JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>()) { + 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; - state = CreatingInitialTransports; - s5bSessionID = s5bTransport->getSessionID().empty() ? idGenerator.generateID() : s5bTransport->getSessionID(); - s5bDestination = SOCKS5BytestreamRegistry::getHostname(s5bSessionID, ourJID, session->getInitiator()); - s5bRegistry->addWriteBytestream(s5bDestination, stream); - fillCandidateMap(theirCandidates, s5bTransport); - candidateSelector->addRemoteTransportCandidates(s5bTransport); - candidateSelector->setRequesterTargtet(session->getInitiator(), ourJID); - s5bTransport->setSessionID(s5bSessionID); - candidateGenerator->generateLocalTransportCandidates(s5bTransport); + 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); } } -const JID& IncomingJingleFileTransfer::getSender() const { - return session->getInitiator(); -} - -const JID& IncomingJingleFileTransfer::getRecipient() const { - return ourJID; -} - void IncomingJingleFileTransfer::cancel() { - session->sendTerminate(JinglePayload::Reason::Cancel); - - if (activeTransport) activeTransport->stop(); - if (serverSession) serverSession->stop(); - if (clientSession) clientSession->stop(); - onStateChange(FileTransfer::State(FileTransfer::State::Canceled)); -} - -void IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated(JingleTransportPayload::ref candidates) { - if (state == CreatingInitialTransports) { - if (JingleS5BTransportPayload::ref s5bCandidates = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(candidates)) { - //localTransportCandidateSelectFinished = true; - //JingleS5BTransportPayload::ref emptyCandidates = boost::make_shared<JingleS5BTransportPayload>(); - //emptyCandidates->setSessionID(s5bCandidates->getSessionID()); - fillCandidateMap(ourCandidates, s5bCandidates); - session->sendAccept(getContentID(), initialContent->getDescriptions()[0], s5bCandidates); - - state = NegotiatingTransport; - candidateSelector->selectCandidate(); - } - } - else { - SWIFT_LOG(debug) << "Unhandled state!" << std::endl; - } -} - - -void IncomingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished(JingleTransportPayload::ref transport) { SWIFT_LOG(debug) << std::endl; - if (state == Terminated) { - return; - } - if (JingleS5BTransportPayload::ref s5bPayload = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transport)) { - //remoteTransportCandidateSelectFinished = true; - //selectedRemoteTransportCandidate = transport; - ourCandidate = s5bPayload; - //checkCandidateSelected(); - decideOnUsedTransport(); - session->sendTransportInfo(getContentID(), s5bPayload); - } - else { - SWIFT_LOG(debug) << "Expected something different here." << std::endl; - } + terminate(state == Initial ? JinglePayload::Reason::Decline : JinglePayload::Reason::Cancel); } -void IncomingJingleFileTransfer::checkCandidateSelected() { - assert(false); - if (localTransportCandidateSelectFinished && remoteTransportCandidateSelectFinished) { - if (candidateGenerator->isActualCandidate(selectedLocalTransportCandidate) && candidateSelector->isActualCandidate(selectedRemoteTransportCandidate)) { - if (candidateGenerator->getPriority(selectedLocalTransportCandidate) > candidateSelector->getPriority(selectedRemoteTransportCandidate)) { - setActiveTransport(candidateGenerator->selectTransport(selectedLocalTransportCandidate)); - } - else { - setActiveTransport(candidateSelector->selectTransport(selectedRemoteTransportCandidate)); - } - } - else if (candidateSelector->isActualCandidate(selectedRemoteTransportCandidate)) { - setActiveTransport(candidateSelector->selectTransport(selectedRemoteTransportCandidate)); - } - else if (candidateGenerator->isActualCandidate(selectedLocalTransportCandidate)) { - setActiveTransport(candidateGenerator->selectTransport(selectedLocalTransportCandidate)); - } - else { - state = WaitingForFallbackOrTerminate; - } - } -} +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; } -void IncomingJingleFileTransfer::setActiveTransport(JingleTransport::ref transport) { - state = Transferring; - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); - activeTransport = transport; - activeTransport->onDataReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleTransportDataReceived, this, _1)); - activeTransport->onFinished.connect(boost::bind(&IncomingJingleFileTransfer::handleTransferFinished, this, _1)); - activeTransport->start(); -} + fillCandidateMap(localCandidates, candidates); -bool IncomingJingleFileTransfer::verifyReceviedData() { - if (algo.empty() || hash.empty()) { - SWIFT_LOG(debug) << "no verification possible, skipping" << std::endl; - return true; - } else { - if (algo == "sha-1") { - SWIFT_LOG(debug) << "verify data via SHA-1 hash: " << (hash == hashCalculator->getSHA1String()) << std::endl; - return hash == hashCalculator->getSHA1String(); - } - else if (algo == "md5") { - SWIFT_LOG(debug) << "verify data via MD5 hash: " << (hash == hashCalculator->getMD5String()) << std::endl; - return hash == hashCalculator->getMD5String(); - } - else { - SWIFT_LOG(debug) << "no verification possible, skipping" << std::endl; - return true; - } + 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); -void IncomingJingleFileTransfer::finishOffTransfer() { - if (verifyReceviedData()) { - onStateChange(FileTransfer::State(FileTransfer::State::Finished)); - session->sendTerminate(JinglePayload::Reason::Success); - } else { - onStateChange(FileTransfer::State(FileTransfer::State::Failed, "Verification failed.")); - session->sendTerminate(JinglePayload::Reason::MediaError); - } - state = Terminated; - waitOnHashTimer->stop(); + setState(TryingCandidates); + transporter->startTryingRemoteCandidates(); } + void IncomingJingleFileTransfer::handleSessionInfoReceived(JinglePayload::ref jinglePayload) { - if (state == Terminated) { - return; - } + SWIFT_LOG(debug) << std::endl; + JingleFileTransferHash::ref transferHash = jinglePayload->getPayload<JingleFileTransferHash>(); if (transferHash) { - SWIFT_LOG(debug) << "Recevied hash information." << std::endl; + SWIFT_LOG(debug) << "Received hash information." << std::endl; + waitOnHashTimer->stop(); if (transferHash->getHashes().find("sha-1") != transferHash->getHashes().end()) { - algo = "sha-1"; + hashAlgorithm = "sha-1"; hash = transferHash->getHashes().find("sha-1")->second; } else if (transferHash->getHashes().find("md5") != transferHash->getHashes().end()) { - algo = "md5"; + hashAlgorithm = "md5"; hash = transferHash->getHashes().find("md5")->second; } - checkIfAllDataReceived(); + if (state == WaitingForHash) { + checkHashAndTerminate(); + } + } + else { + SWIFT_LOG(debug) << "Ignoring unknown session info" << std::endl; } } void IncomingJingleFileTransfer::handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason) { - SWIFT_LOG(debug) << "session terminate received" << std::endl; - if (activeTransport) activeTransport->stop(); - if (reason && reason.get().type == JinglePayload::Reason::Cancel) { - onStateChange(FileTransfer::State(FileTransfer::State::Canceled, "Other user canceled the transfer.")); + 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)); + } +} + +void IncomingJingleFileTransfer::checkHashAndTerminate() { + if (verifyData()) { + terminate(JinglePayload::Reason::Success); } - else if (reason && reason.get().type == JinglePayload::Reason::Success) { - /*if (verifyReceviedData()) { - onStateChange(FileTransfer::State(FileTransfer::State::Finished)); - } else { - onStateChange(FileTransfer::State(FileTransfer::State::Failed, "Verification failed.")); - }*/ + else { + SWIFT_LOG(warning) << "Hash verification failed" << std::endl; + terminate(JinglePayload::Reason::MediaError); } - state = Terminated; } void IncomingJingleFileTransfer::checkIfAllDataReceived() { - if (receivedBytes == fileSizeInBytes) { + if (receivedBytes == getFileSizeInBytes()) { SWIFT_LOG(debug) << "All data received." << std::endl; if (hash.empty()) { - SWIFT_LOG(debug) << "No hash information yet. Waiting 5 seconds on hash info." << std::endl; + SWIFT_LOG(debug) << "No hash information yet. Waiting a while on hash info." << std::endl; + setState(WaitingForHash); waitOnHashTimer->start(); - } else { - SWIFT_LOG(debug) << "We already have hash info using " << algo << " algorithm. Finishing off transfer." << std::endl; - finishOffTransfer(); + } + else { + checkHashAndTerminate(); } } - else if (receivedBytes > fileSizeInBytes) { + else if (receivedBytes > getFileSizeInBytes()) { SWIFT_LOG(debug) << "We got more than we could handle!" << std::endl; + terminate(JinglePayload::Reason::MediaError); } } -void IncomingJingleFileTransfer::handleTransportDataReceived(const std::vector<unsigned char>& data) { - SWIFT_LOG(debug) << data.size() << " bytes received" << std::endl; - onProcessedBytes(data.size()); - stream->write(data); +void IncomingJingleFileTransfer::handleWriteStreamDataReceived( + const std::vector<unsigned char>& data) { + hashCalculator->feedData(data); receivedBytes += data.size(); checkIfAllDataReceived(); } -void IncomingJingleFileTransfer::handleWriteStreamDataReceived(const std::vector<unsigned char>& data) { - receivedBytes += data.size(); - checkIfAllDataReceived(); -} - -void IncomingJingleFileTransfer::useOurCandidateChoiceForTransfer(JingleS5BTransportPayload::Candidate candidate) { +void IncomingJingleFileTransfer::handleTransportReplaceReceived( + const JingleContentID& content, JingleTransportPayload::ref transport) { SWIFT_LOG(debug) << std::endl; - if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { - // get proxy client session from remoteCandidateSelector - clientSession = candidateSelector->getS5BSession(); - - // wait on <activated/> transport-info - } else { - // ask s5b client - clientSession = candidateSelector->getS5BSession(); - if (clientSession) { - state = Transferring; - SWIFT_LOG(debug) << clientSession->getAddressPort().toString() << std::endl; - clientSession->onBytesReceived.connect(boost::bind(boost::ref(onProcessedBytes), _1)); - clientSession->onFinished.connect(boost::bind(&IncomingJingleFileTransfer::handleTransferFinished, this, _1)); - clientSession->startReceiving(stream); - } else { - SWIFT_LOG(debug) << "No S5B client session found!!!" << std::endl; - } + if (state != WaitingForFallbackOrTerminate) { + SWIFT_LOG(warning) << "Incorrect state" << std::endl; + return; } -} -void IncomingJingleFileTransfer::useTheirCandidateChoiceForTransfer(JingleS5BTransportPayload::Candidate candidate) { - SWIFT_LOG(debug) << std::endl; + if (JingleIBBTransportPayload::ref ibbTransport = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transport)) { + SWIFT_LOG(debug) << "transport replaced with IBB" << std::endl; - if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { - // get proxy client session from s5bRegistry - clientSession = s5bProxy->createSOCKS5BytestreamClientSession(candidate.hostPort, SOCKS5BytestreamRegistry::getHostname(s5bSessionID, ourJID, session->getInitiator())); - clientSession->onSessionReady.connect(boost::bind(&IncomingJingleFileTransfer::proxySessionReady, this, candidate.jid, _1)); - clientSession->start(); - - // on reply send activate - } else { - // ask s5b server - serverSession = s5bRegistry->getConnectedSession(s5bDestination); - if (serverSession) { - state = Transferring; - serverSession->onBytesReceived.connect(boost::bind(boost::ref(onProcessedBytes), _1)); - serverSession->onFinished.connect(boost::bind(&IncomingJingleFileTransfer::handleTransferFinished, this, _1)); - serverSession->startTransfer(); - } else { - SWIFT_LOG(debug) << "No S5B server session found!!!" << 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); } } -void IncomingJingleFileTransfer::fillCandidateMap(CandidateMap& map, JingleS5BTransportPayload::ref s5bPayload) { - map.clear(); - foreach (JingleS5BTransportPayload::Candidate candidate, s5bPayload->getCandidates()) { - map[candidate.cid] = candidate; - } +JingleContentID IncomingJingleFileTransfer::getContentID() const { + return JingleContentID(initialContent->getName(), initialContent->getCreator()); } - -void IncomingJingleFileTransfer::decideOnUsedTransport() { - if (ourCandidate && theirCandidate) { - if (ourCandidate->hasCandidateError() && theirCandidate->hasCandidateError()) { - state = WaitingForFallbackOrTerminate; - return; - } - std::string our_cid = ourCandidate->getCandidateUsed(); - std::string their_cid = theirCandidate->getCandidateUsed(); - if (ourCandidate->hasCandidateError() && !their_cid.empty()) { - useTheirCandidateChoiceForTransfer(ourCandidates[their_cid]); - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); - } - else if (theirCandidate->hasCandidateError() && !our_cid.empty()) { - useOurCandidateChoiceForTransfer(theirCandidates[our_cid]); - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); - } - else if (!our_cid.empty() && !their_cid.empty()) { - // compare priorites, if same they win - if (ourCandidates.find(their_cid) == ourCandidates.end() || theirCandidates.find(our_cid) == theirCandidates.end()) { - SWIFT_LOG(debug) << "Didn't recognize candidate IDs!" << std::endl; - session->sendTerminate(JinglePayload::Reason::FailedTransport); - onStateChange(FileTransfer::State(FileTransfer::State::Canceled, "Failed to negotiate candidate.")); - onFinished(FileTransferError(FileTransferError::PeerError)); - return; - } - - JingleS5BTransportPayload::Candidate our_candidate = theirCandidates[our_cid]; - JingleS5BTransportPayload::Candidate their_candidate = ourCandidates[their_cid]; - if (our_candidate.priority > their_candidate.priority) { - useOurCandidateChoiceForTransfer(our_candidate); - } - else if (our_candidate.priority < their_candidate.priority) { - useTheirCandidateChoiceForTransfer(their_candidate); - } - else { - useTheirCandidateChoiceForTransfer(their_candidate); - } - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); - } - else { - assert(false); - } - } else { - SWIFT_LOG(debug) << "Can't make a transport decision yet." << std::endl; +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; } } -void IncomingJingleFileTransfer::proxySessionReady(const JID& proxy, bool error) { - if (error) { - // indicate proxy error - } else { - // activate proxy - activateProxySession(proxy); - } +void IncomingJingleFileTransfer::handleWaitOnHashTimerTicked() { + SWIFT_LOG(debug) << std::endl; + waitOnHashTimer->stop(); + terminate(JinglePayload::Reason::Success); } -void IncomingJingleFileTransfer::activateProxySession(const JID &proxy) { - S5BProxyRequest::ref proxyRequest = boost::make_shared<S5BProxyRequest>(); - proxyRequest->setSID(s5bSessionID); - proxyRequest->setActivate(session->getInitiator()); +const JID& IncomingJingleFileTransfer::getSender() const { + return getInitiator(); +} + +const JID& IncomingJingleFileTransfer::getRecipient() const { + return getResponder(); +} - boost::shared_ptr<GenericRequest<S5BProxyRequest> > request = boost::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Set, proxy, proxyRequest, router); - request->onResponse.connect(boost::bind(&IncomingJingleFileTransfer::handleActivateProxySessionResult, this, _1, _2)); - request->send(); +void IncomingJingleFileTransfer::setState(State state) { + SWIFT_LOG(debug) << state << std::endl; + this->state = state; + onStateChanged(FileTransfer::State(getExternalState(state))); } -void IncomingJingleFileTransfer::handleActivateProxySessionResult(boost::shared_ptr<S5BProxyRequest> /*request*/, ErrorPayload::ref error) { +void IncomingJingleFileTransfer::setFinishedState( + FileTransfer::State::Type type, const boost::optional<FileTransferError>& error) { SWIFT_LOG(debug) << std::endl; - if (error) { - SWIFT_LOG(debug) << "ERROR" << std::endl; - } else { - // send activated to other jingle party - JingleS5BTransportPayload::ref proxyActivate = boost::make_shared<JingleS5BTransportPayload>(); - proxyActivate->setActivated(theirCandidate->getCandidateUsed()); - session->sendTransportInfo(getContentID(), proxyActivate); - - // start transferring - clientSession->onBytesReceived.connect(boost::bind(boost::ref(onProcessedBytes), _1)); - clientSession->onFinished.connect(boost::bind(&IncomingJingleFileTransfer::handleTransferFinished, this, _1)); - clientSession->startReceiving(stream); - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); + this->state = Finished; + onStateChanged(type); + onFinished(error); +} + +void IncomingJingleFileTransfer::handleTransferFinished(boost::optional<FileTransferError> error) { + if (error && state != WaitingForHash) { + terminate(JinglePayload::Reason::MediaError); } } -void IncomingJingleFileTransfer::handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref transport) { - SWIFT_LOG(debug) << "transport info received" << std::endl; - if (state == Terminated) { - return; +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; } - if (JingleS5BTransportPayload::ref s5bPayload = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transport)) { - if (!s5bPayload->getActivated().empty()) { - if (ourCandidate->getCandidateUsed() == s5bPayload->getActivated()) { - clientSession->onBytesReceived.connect(boost::bind(boost::ref(onProcessedBytes), _1)); - clientSession->onFinished.connect(boost::bind(&IncomingJingleFileTransfer::handleTransferFinished, this, _1)); - clientSession->startReceiving(stream); - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); - } else { - SWIFT_LOG(debug) << "ourCandidateChoice doesn't match activated proxy candidate!" << std::endl; - JingleS5BTransportPayload::ref proxyError = boost::make_shared<JingleS5BTransportPayload>(); - proxyError->setProxyError(true); - proxyError->setSessionID(s5bSessionID); - session->sendTransportInfo(getContentID(), proxyError); - } - } else { - theirCandidate = s5bPayload; - decideOnUsedTransport(); - } + assert(false); + return FileTransfer::State::Initial; +} + +void IncomingJingleFileTransfer::stopAll() { + if (state != Initial) { + writeStreamDataReceivedConnection.disconnect(); + delete hashCalculator; } - else { - SWIFT_LOG(debug) << "Expected something different here." << std::endl; + 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; } - /*localTransportCandidateSelectFinished = true; - selectedLocalTransportCandidate = transport; - if (candidateGenerator->isActualCandidate(transport)) { - candidateSelector->setMinimumPriority(candidateGenerator->getPriority(transport)); - }*/ - //checkCandidateSelected(); } -void IncomingJingleFileTransfer::handleTransportReplaceReceived(const JingleContentID& content, JingleTransportPayload::ref transport) { - if (state == Terminated) { - return; +bool IncomingJingleFileTransfer::hasPriorityOnCandidateTie() const { + return false; +} + +void IncomingJingleFileTransfer::fallback() { + if (options.isInBandAllowed()) { + setState(WaitingForFallbackOrTerminate); } - if (JingleIBBTransportPayload::ref ibbTransport = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transport)) { - SWIFT_LOG(debug) << "transport replaced with IBB" << std::endl; - setActiveTransport(createIBBTransport(ibbTransport)); - session->sendTransportAccept(content, ibbTransport); - } else { - SWIFT_LOG(debug) << "transport replaced failed" << std::endl; - session->sendTransportReject(content, transport); + else { + terminate(JinglePayload::Reason::ConnectivityError); + } +} + +void IncomingJingleFileTransfer::startTransferViaRemoteCandidate() { + SWIFT_LOG(debug) << std::endl; + + if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setState(WaitingForPeerProxyActivate); + } + else { + startTransferring(createRemoteCandidateSession()); } } -void IncomingJingleFileTransfer::stopActiveTransport() { - if (activeTransport) { - activeTransport->stop(); - activeTransport->onDataReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleTransportDataReceived, this, _1)); +void IncomingJingleFileTransfer::startTransferViaLocalCandidate() { + SWIFT_LOG(debug) << std::endl; + + if (theirCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setState(WaitingForLocalProxyActivate); + transporter->startActivatingProxy(theirCandidateChoice->jid); + } + else { + startTransferring(createLocalCandidateSession()); } } -JingleIncomingIBBTransport::ref IncomingJingleFileTransfer::createIBBTransport(JingleIBBTransportPayload::ref ibbTransport) { - // TODO: getOffer() -> getOffers correction - return boost::make_shared<JingleIncomingIBBTransport>(session->getInitiator(), getRecipient(), ibbTransport->getSessionID(), description->getOffers()[0].getSize(), router); + +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(); } -JingleContentID IncomingJingleFileTransfer::getContentID() const { - return JingleContentID(initialContent->getName(), initialContent->getCreator()); +bool IncomingJingleFileTransfer::isWaitingForPeerProxyActivate() const { + return state == WaitingForPeerProxyActivate; } -void IncomingJingleFileTransfer::handleTransferFinished(boost::optional<FileTransferError> error) { - if (state == Terminated) { - return; - } +bool IncomingJingleFileTransfer::isWaitingForLocalProxyActivate() const { + return state == WaitingForLocalProxyActivate; +} - if (error) { - session->sendTerminate(JinglePayload::Reason::ConnectivityError); - onStateChange(FileTransfer::State(FileTransfer::State::Failed)); - onFinished(error); - } - // +bool IncomingJingleFileTransfer::isTryingCandidates() const { + return state == TryingCandidates; +} + +boost::shared_ptr<TransportSession> IncomingJingleFileTransfer::createLocalCandidateSession() { + return transporter->createLocalCandidateSession(stream); } +boost::shared_ptr<TransportSession> IncomingJingleFileTransfer::createRemoteCandidateSession() { + return transporter->createRemoteCandidateSession(stream); +} + +void IncomingJingleFileTransfer::terminate(JinglePayload::Reason::Type reason) { + SWIFT_LOG(debug) << reason << std::endl; + + 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 0731e04..a691d5b 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.h +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -8,127 +8,112 @@ #include <boost/shared_ptr.hpp> #include <boost/cstdint.hpp> +#include <string> #include <Swiften/Base/API.h> -#include <Swiften/Base/IDGenerator.h> -#include <Swiften/Network/Timer.h> -#include <Swiften/Jingle/JingleSession.h> +#include <Swiften/Base/Override.h> #include <Swiften/Jingle/JingleContentID.h> #include <Swiften/FileTransfer/IncomingFileTransfer.h> -#include <Swiften/FileTransfer/JingleTransport.h> -#include <Swiften/FileTransfer/JingleIncomingIBBTransport.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> -#include <Swiften/Elements/JingleContentPayload.h> -#include <Swiften/Elements/JingleFileTransferDescription.h> -#include <Swiften/Elements/JingleIBBTransportPayload.h> +#include <Swiften/FileTransfer/JingleFileTransfer.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> -#include <Swiften/Elements/S5BProxyRequest.h> -#include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> namespace Swift { - class IQRouter; - class RemoteJingleTransportCandidateSelectorFactory; - class LocalJingleTransportCandidateGeneratorFactory; - class RemoteJingleTransportCandidateSelector; - class LocalJingleTransportCandidateGenerator; - class SOCKS5BytestreamRegistry; - class SOCKS5BytestreamProxy; + 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 { + class SWIFTEN_API IncomingJingleFileTransfer : public IncomingFileTransfer, public JingleFileTransfer { public: typedef boost::shared_ptr<IncomingJingleFileTransfer> ref; - enum State { - Initial, - CreatingInitialTransports, - NegotiatingTransport, - Transferring, - WaitingForFallbackOrTerminate, - Terminated - }; IncomingJingleFileTransfer( - const JID& recipient, - JingleSession::ref, - JingleContentPayload::ref content, - RemoteJingleTransportCandidateSelectorFactory*, - LocalJingleTransportCandidateGeneratorFactory*, - IQRouter* router, - SOCKS5BytestreamRegistry* bytestreamRegistry, - SOCKS5BytestreamProxy* bytestreamProxy, - TimerFactory*); + const JID& recipient, + boost::shared_ptr<JingleSession>, + boost::shared_ptr<JingleContentPayload> content, + FileTransferTransporterFactory*, + TimerFactory*, + CryptoProvider*); ~IncomingJingleFileTransfer(); - virtual void accept(WriteBytestream::ref); - virtual const JID& getSender() const; - virtual const JID& getRecipient() const; + virtual void accept(boost::shared_ptr<WriteBytestream>, const FileTransferOptions&) SWIFTEN_OVERRIDE; void cancel(); private: - void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason>); - void handleSessionInfoReceived(JinglePayload::ref); - void handleTransportReplaceReceived(const JingleContentID&, JingleTransportPayload::ref); - void handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref); - void handleLocalTransportCandidatesGenerated(JingleTransportPayload::ref candidates); - void handleRemoteTransportCandidateSelectFinished(JingleTransportPayload::ref candidate); - void setActiveTransport(JingleTransport::ref transport); - void handleTransportDataReceived(const std::vector<unsigned char>& data); + 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(); - JingleIncomingIBBTransport::ref createIBBTransport(JingleIBBTransportPayload::ref ibbTransport); - JingleContentID getContentID() const; + virtual JingleContentID getContentID() const SWIFTEN_OVERRIDE; void checkIfAllDataReceived(); - bool verifyReceviedData(); - void finishOffTransfer(); + bool verifyData(); + void handleWaitOnHashTimerTicked(); void handleTransferFinished(boost::optional<FileTransferError>); private: - typedef std::map<std::string, JingleS5BTransportPayload::Candidate> CandidateMap; + 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: - void activateProxySession(const JID &proxy); - void handleActivateProxySessionResult(boost::shared_ptr<S5BProxyRequest> request, ErrorPayload::ref error); - void proxySessionReady(const JID& proxy, bool error); private: - void useOurCandidateChoiceForTransfer(JingleS5BTransportPayload::Candidate candidate); - void useTheirCandidateChoiceForTransfer(JingleS5BTransportPayload::Candidate candidate); - void decideOnUsedTransport(); - void fillCandidateMap(CandidateMap& map, JingleS5BTransportPayload::ref s5bPayload); - - private: - JID ourJID; - JingleSession::ref session; - IQRouter* router; - JingleContentPayload::ref initialContent; + boost::shared_ptr<JingleContentPayload> initialContent; + CryptoProvider* crypto; State state; - JingleFileTransferDescription::ref description; - WriteBytestream::ref stream; + boost::shared_ptr<JingleFileTransferDescription> description; + boost::shared_ptr<WriteBytestream> stream; boost::uintmax_t receivedBytes; IncrementalBytestreamHashCalculator* hashCalculator; - Timer::ref waitOnHashTimer; - IDGenerator idGenerator; - - RemoteJingleTransportCandidateSelector* candidateSelector; - LocalJingleTransportCandidateGenerator* candidateGenerator; - SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamProxy* s5bProxy; - bool remoteTransportCandidateSelectFinished; - JingleTransportPayload::ref selectedRemoteTransportCandidate; - bool localTransportCandidateSelectFinished; - JingleTransportPayload::ref selectedLocalTransportCandidate; - - JingleS5BTransportPayload::ref ourCandidate; - JingleS5BTransportPayload::ref theirCandidate; - CandidateMap ourCandidates; - CandidateMap theirCandidates; - SOCKS5BytestreamClientSession::ref clientSession; - std::string s5bDestination; - std::string s5bSessionID; - SOCKS5BytestreamServerSession* serverSession; + boost::shared_ptr<Timer> waitOnHashTimer; + std::string hashAlgorithm; + std::string hash; + FileTransferOptions options; - JingleTransport::ref activeTransport; + boost::bsignals::scoped_connection writeStreamDataReceivedConnection; + boost::bsignals::scoped_connection waitOnHashTimerTickedConnection; + boost::bsignals::connection transferFinishedConnection; }; } diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp index 6b53a1b..601a97f 100644 --- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp +++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp @@ -4,17 +4,23 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + + #include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h> #include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/StringCodecs/MD5.h> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/Crypto/CryptoProvider.h> namespace Swift { -IncrementalBytestreamHashCalculator::IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1) { - md5Hasher = doMD5 ? new MD5() : NULL; - sha1Hasher = doSHA1 ? new SHA1() : NULL; +IncrementalBytestreamHashCalculator::IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1, CryptoProvider* crypto) { + md5Hasher = doMD5 ? crypto->createMD5() : NULL; + sha1Hasher = doSHA1 ? crypto->createSHA1() : NULL; } IncrementalBytestreamHashCalculator::~IncrementalBytestreamHashCalculator() { @@ -41,21 +47,19 @@ void IncrementalBytestreamHashCalculator::feedData(const SafeByteArray& data) { }*/ std::string IncrementalBytestreamHashCalculator::getSHA1String() { - if (sha1Hasher) { - ByteArray result = sha1Hasher->getHash(); - return Hexify::hexify(result); - } else { - return std::string(); + assert(sha1Hasher); + if (!sha1Hash) { + sha1Hash = Hexify::hexify(sha1Hasher->getHash()); } + return *sha1Hash; } std::string IncrementalBytestreamHashCalculator::getMD5String() { - if (md5Hasher) { - ByteArray result = md5Hasher->getHash(); - return Hexify::hexify(result); - } else { - return std::string(); + assert(md5Hasher); + if (!md5Hash) { + md5Hash = Hexify::hexify(md5Hasher->getHash()); } + return *md5Hash; } } diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h index 64f4b5f..7b4e124 100644 --- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h +++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h @@ -4,30 +4,40 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #pragma once +#include <string> + #include <Swiften/Base/ByteArray.h> #include <Swiften/Base/SafeByteArray.h> +#include <boost/optional.hpp> namespace Swift { - -class MD5; -class SHA1; - -class IncrementalBytestreamHashCalculator { -public: - IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1); - ~IncrementalBytestreamHashCalculator(); - - void feedData(const ByteArray& data); - //void feedData(const SafeByteArray& data); - - std::string getSHA1String(); - std::string getMD5String(); - -private: - MD5* md5Hasher; - SHA1* sha1Hasher; -}; + 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; + }; } diff --git a/Swiften/FileTransfer/JingleFileTransfer.cpp b/Swiften/FileTransfer/JingleFileTransfer.cpp new file mode 100644 index 0000000..6eecaa2 --- /dev/null +++ b/Swiften/FileTransfer/JingleFileTransfer.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/Crypto/CryptoProvider.h> +#include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/Jingle/JingleSession.h> +#include <Swiften/FileTransfer/FileTransferTransporter.h> +#include <Swiften/Base/Log.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); + +} + +JingleFileTransfer::~JingleFileTransfer() { + 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; + } +} + +/* +std::string JingleFileTransfer::getS5BDstAddr(const JID& requester, const JID& target) const { + return Hexify::hexify(crypto->getSHA1Hash( + createSafeByteArray(s5bSessionID + requester.toString() + target.toString()))); +} +*/ + +const JID& JingleFileTransfer::getInitiator() const { + return session->getInitiator(); +} + +const JID& JingleFileTransfer::getResponder() const { + 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; + } +} + +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); + } +} + +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(); +} + +// 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(); + } + } + } +} + +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()); + } +} + +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; + } +} + +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)); +} + diff --git a/Swiften/FileTransfer/JingleFileTransfer.h b/Swiften/FileTransfer/JingleFileTransfer.h new file mode 100644 index 0000000..ee646c1 --- /dev/null +++ b/Swiften/FileTransfer/JingleFileTransfer.h @@ -0,0 +1,93 @@ +/* + * 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> + +#include <boost/shared_ptr.hpp> +#include <vector> +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/FileTransfer/FileTransfer.h> +#include <Swiften/Jingle/AbstractJingleSessionListener.h> +#include <Swiften/Jingle/JingleContentID.h> + +namespace Swift { + class CryptoProvider; + class IQRouter; + class RemoteJingleTransportCandidateSelector; + class LocalJingleTransportCandidateGenerator; + 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(); + + 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: + 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; + + 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::string candidateSelectRequestID; + bool ourCandidateSelectFinished; + boost::optional<JingleS5BTransportPayload::Candidate> ourCandidateChoice; + bool theirCandidateSelectFinished; + boost::optional<JingleS5BTransportPayload::Candidate> theirCandidateChoice; + CandidateMap localCandidates; + + boost::shared_ptr<TransportSession> transportSession; + + boost::bsignals::scoped_connection localTransportCandidatesGeneratedConnection; + boost::bsignals::scoped_connection remoteTransportCandidateSelectFinishedConnection; + boost::bsignals::scoped_connection proxyActivatedConnection; + }; +} diff --git a/Swiften/FileTransfer/JingleIncomingIBBTransport.cpp b/Swiften/FileTransfer/JingleIncomingIBBTransport.cpp deleted file mode 100644 index ccca641..0000000 --- a/Swiften/FileTransfer/JingleIncomingIBBTransport.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/FileTransfer/JingleIncomingIBBTransport.h> - -namespace Swift { - -JingleIncomingIBBTransport::JingleIncomingIBBTransport(const JID& from, const JID& to, const std::string& id, size_t size, IQRouter* router) : ibbSession(id, from, to, size, router) { - ibbSession.onDataReceived.connect(boost::ref(onDataReceived)); - ibbSession.onFinished.connect(boost::ref(onFinished)); -} - -void JingleIncomingIBBTransport::start() { - ibbSession.start(); -} - -void JingleIncomingIBBTransport::stop() { - ibbSession.stop(); -} - -} diff --git a/Swiften/FileTransfer/JingleIncomingIBBTransport.h b/Swiften/FileTransfer/JingleIncomingIBBTransport.h deleted file mode 100644 index be18a2d..0000000 --- a/Swiften/FileTransfer/JingleIncomingIBBTransport.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2011 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/JingleTransport.h> -#include <Swiften/FileTransfer/IBBReceiveSession.h> - -namespace Swift { - class JingleIncomingIBBTransport : public JingleTransport { - public: - typedef boost::shared_ptr<JingleIncomingIBBTransport> ref; - - JingleIncomingIBBTransport(const JID& from, const JID& to, const std::string& id, size_t size, IQRouter* router); - - virtual void start(); - virtual void stop(); - - private: - IBBReceiveSession ibbSession; - }; -} diff --git a/Swiften/FileTransfer/JingleTransport.h b/Swiften/FileTransfer/JingleTransport.h deleted file mode 100644 index fa296e8..0000000 --- a/Swiften/FileTransfer/JingleTransport.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include <boost/shared_ptr.hpp> - -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/FileTransfer/FileTransfer.h> - -namespace Swift { - class JingleTransport { - public: - typedef boost::shared_ptr<JingleTransport> ref; - - virtual ~JingleTransport(); - - virtual void start() = 0; - virtual void stop() = 0; - - boost::signal<void (const std::vector<unsigned char>&)> onDataReceived; - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - }; -} diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp index 852902b..53ad53a 100644 --- a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp +++ b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp @@ -1,14 +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 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> +#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> + +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) { +} + LocalJingleTransportCandidateGenerator::~LocalJingleTransportCandidateGenerator() { + SWIFT_LOG_ASSERT(!s5bServerInitializeRequest, warning) << std::endl; +} + +void LocalJingleTransportCandidateGenerator::start() { + assert(!s5bServerInitializeRequest); + s5bServerInitializeRequest = s5bServerManager->createInitializeRequest(); + s5bServerInitializeRequest->onFinished.connect( + boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); + + s5bServerInitializeRequest->start(); +} + +void LocalJingleTransportCandidateGenerator::stop() { + if (s5bServerInitializeRequest) { + s5bServerInitializeRequest->stop(); + s5bServerInitializeRequest.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); +} + +/*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(); +}*/ + } diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h index 14c128a..02dfef5 100644 --- a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h +++ b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h @@ -1,30 +1,54 @@ /* - * 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 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * 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/boost_bsignals.h> +#include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> -#include <Swiften/Base/API.h> -#include <Swiften/Elements/JingleTransportPayload.h> -#include <Swiften/FileTransfer/JingleTransport.h> +#include <Swiften/Base/IDGenerator.h> +#include <Swiften/Base/Override.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Elements/JingleS5BTransportPayload.h> namespace Swift { - class SWIFTEN_API LocalJingleTransportCandidateGenerator { + class SOCKS5BytestreamServerManager; + class SOCKS5BytestreamProxiesManager; + class SOCKS5BytestreamServerInitializeRequest; + class JingleS5BTransportPayload; + + class LocalJingleTransportCandidateGenerator { public: + LocalJingleTransportCandidateGenerator( + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + const JID& ownJID, + IDGenerator* idGenerator); virtual ~LocalJingleTransportCandidateGenerator(); - /** - * Should call onLocalTransportCandidatesGenerated if it has finished discovering local candidates. - */ - virtual void generateLocalTransportCandidates(JingleTransportPayload::ref) = 0; - virtual bool isActualCandidate(JingleTransportPayload::ref) = 0; - virtual int getPriority(JingleTransportPayload::ref) = 0; - virtual JingleTransport::ref selectTransport(JingleTransportPayload::ref) = 0; + virtual void start(); + virtual void stop(); + + boost::signal<void (const std::vector<JingleS5BTransportPayload::Candidate>&)> onLocalTransportCandidatesGenerated; + + private: + void handleS5BServerInitialized(bool success); + void checkS5BCandidatesReady(); - boost::signal<void (JingleTransportPayload::ref)> onLocalTransportCandidatesGenerated; + private: + SOCKS5BytestreamServerManager* s5bServerManager; + SOCKS5BytestreamProxiesManager* s5bProxy; + JID ownJID; + IDGenerator* idGenerator; + boost::shared_ptr<SOCKS5BytestreamServerInitializeRequest> s5bServerInitializeRequest; }; } diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.cpp b/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.cpp deleted file mode 100644 index a1e3874..0000000 --- a/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h> - -namespace Swift { - -LocalJingleTransportCandidateGeneratorFactory::~LocalJingleTransportCandidateGeneratorFactory() { -} - -} diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h b/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h deleted file mode 100644 index 422e006..0000000 --- a/Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2011 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> - -namespace Swift { - class LocalJingleTransportCandidateGenerator; - - class SWIFTEN_API LocalJingleTransportCandidateGeneratorFactory { - public: - virtual ~LocalJingleTransportCandidateGeneratorFactory(); - - virtual LocalJingleTransportCandidateGenerator* createCandidateGenerator() = 0; - }; -} diff --git a/Swiften/FileTransfer/OutgoingFileTransfer.h b/Swiften/FileTransfer/OutgoingFileTransfer.h index 1ec1ae3..59dc718 100644 --- a/Swiften/FileTransfer/OutgoingFileTransfer.h +++ b/Swiften/FileTransfer/OutgoingFileTransfer.h @@ -18,6 +18,5 @@ namespace Swift { virtual ~OutgoingFileTransfer(); virtual void start() = 0; - virtual void stop() = 0; }; } diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp index 6f23bb7..4b3c6b5 100644 --- a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp +++ b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp @@ -4,7 +4,13 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "OutgoingFileTransferManager.h" +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/OutgoingFileTransferManager.h> #include <boost/smart_ptr/make_shared.hpp> @@ -17,7 +23,15 @@ namespace Swift { -OutgoingFileTransferManager::OutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy) { +OutgoingFileTransferManager::OutgoingFileTransferManager( + JingleSessionManager* jingleSessionManager, + IQRouter* router, + FileTransferTransporterFactory* transporterFactory, + CryptoProvider* crypto) : + jingleSessionManager(jingleSessionManager), + iqRouter(router), + transporterFactory(transporterFactory), + crypto(crypto) { idGenerator = new IDGenerator(); } @@ -25,22 +39,24 @@ OutgoingFileTransferManager::~OutgoingFileTransferManager() { delete idGenerator; } -boost::shared_ptr<OutgoingFileTransfer> OutgoingFileTransferManager::createOutgoingFileTransfer(const JID& from, const JID& receipient, boost::shared_ptr<ReadBytestream> readBytestream, const StreamInitiationFileInfo& fileInfo) { - // check if receipient support Jingle FT - - - JingleSessionImpl::ref jingleSession = boost::make_shared<JingleSessionImpl>(from, receipient, idGenerator->generateID(), iqRouter); - - //jsManager->getSession(receipient, idGenerator->generateID()); - assert(jingleSession); - jsManager->registerOutgoingSession(from, jingleSession); - boost::shared_ptr<OutgoingJingleFileTransfer> jingleFT = boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(jingleSession, remoteFactory, localFactory, iqRouter, idGenerator, from, receipient, readBytestream, fileInfo, bytestreamRegistry, bytestreamProxy)); - - // otherwise try SI - - // else fail - - return jingleFT; +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)); } } diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.h b/Swiften/FileTransfer/OutgoingFileTransferManager.h index c686001..17a489d 100644 --- a/Swiften/FileTransfer/OutgoingFileTransferManager.h +++ b/Swiften/FileTransfer/OutgoingFileTransferManager.h @@ -4,43 +4,49 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #pragma once #include <boost/shared_ptr.hpp> -#include <Swiften/JID/JID.h> - namespace Swift { - -class JingleSessionManager; -class IQRouter; -class EntityCapsProvider; -class RemoteJingleTransportCandidateSelectorFactory; -class LocalJingleTransportCandidateGeneratorFactory; -class OutgoingFileTransfer; -class JID; -class IDGenerator; -class ReadBytestream; -class StreamInitiationFileInfo; -class SOCKS5BytestreamRegistry; -class SOCKS5BytestreamProxy; - -class OutgoingFileTransferManager { -public: - OutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy); - ~OutgoingFileTransferManager(); - - boost::shared_ptr<OutgoingFileTransfer> createOutgoingFileTransfer(const JID& from, const JID& to, boost::shared_ptr<ReadBytestream>, const StreamInitiationFileInfo&); - -private: - JingleSessionManager* jsManager; - IQRouter* iqRouter; - EntityCapsProvider* capsProvider; - RemoteJingleTransportCandidateSelectorFactory* remoteFactory; - LocalJingleTransportCandidateGeneratorFactory* localFactory; - IDGenerator *idGenerator; - SOCKS5BytestreamRegistry* bytestreamRegistry; - SOCKS5BytestreamProxy* bytestreamProxy; -}; - + 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; + }; } diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp index e22260e..7bcee4b 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp @@ -4,399 +4,340 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "OutgoingJingleFileTransfer.h" +/* + * Copyright (C) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +// 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 <boost/bind.hpp> #include <boost/smart_ptr/make_shared.hpp> +#include <boost/typeof/typeof.hpp> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Base/foreach.h> #include <Swiften/Base/IDGenerator.h> #include <Swiften/Jingle/JingleContentID.h> +#include <Swiften/Jingle/JingleSession.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/Queries/GenericRequest.h> -#include <Swiften/FileTransfer/IBBSendSession.h> #include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h> -#include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> -#include <Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamProxy.h> -#include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/FileTransfer/FileTransferTransporter.h> +#include <Swiften/FileTransfer/FileTransferTransporterFactory.h> +#include <Swiften/FileTransfer/ReadBytestream.h> +#include <Swiften/FileTransfer/TransportSession.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Base/Log.h> -namespace Swift { - -OutgoingJingleFileTransfer::OutgoingJingleFileTransfer(JingleSession::ref session, - RemoteJingleTransportCandidateSelectorFactory* remoteFactory, - LocalJingleTransportCandidateGeneratorFactory* localFactory, - IQRouter* router, - IDGenerator *idGenerator, - const JID& fromJID, - const JID& toJID, - boost::shared_ptr<ReadBytestream> readStream, - const StreamInitiationFileInfo &fileInfo, - SOCKS5BytestreamRegistry* bytestreamRegistry, - SOCKS5BytestreamProxy* bytestreamProxy) : - session(session), router(router), idGenerator(idGenerator), fromJID(fromJID), toJID(toJID), readStream(readStream), fileInfo(fileInfo), s5bRegistry(bytestreamRegistry), s5bProxy(bytestreamProxy), serverSession(NULL), contentID(JingleContentID(idGenerator->generateID(), JingleContentPayload::InitiatorCreator)), canceled(false) { - session->onSessionAcceptReceived.connect(boost::bind(&OutgoingJingleFileTransfer::handleSessionAcceptReceived, this, _1, _2, _3)); - session->onSessionTerminateReceived.connect(boost::bind(&OutgoingJingleFileTransfer::handleSessionTerminateReceived, this, _1)); - session->onTransportInfoReceived.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransportInfoReceived, this, _1, _2)); - session->onTransportAcceptReceived.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransportAcceptReceived, this, _1, _2)); - fileSizeInBytes = fileInfo.getSize(); - filename = fileInfo.getName(); - - localCandidateGenerator = localFactory->createCandidateGenerator(); - localCandidateGenerator->onLocalTransportCandidatesGenerated.connect(boost::bind(&OutgoingJingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1)); - - remoteCandidateSelector = remoteFactory->createCandidateSelector(); - remoteCandidateSelector->onRemoteTransportCandidateSelectFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1)); +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); - this->readStream->onRead.connect(boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); + hashCalculator = new IncrementalBytestreamHashCalculator(true, true, crypto); + stream->onRead.connect( + boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); } OutgoingJingleFileTransfer::~OutgoingJingleFileTransfer() { - readStream->onRead.disconnect(boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); + stream->onRead.disconnect( + boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); delete hashCalculator; } void OutgoingJingleFileTransfer::start() { - onStateChange(FileTransfer::State(FileTransfer::State::WaitingForStart)); - - s5bSessionID = s5bRegistry->generateSessionID(); - SWIFT_LOG(debug) << "S5B SessionID: " << s5bSessionID << std::endl; - - //s5bProxy->connectToProxies(s5bSessionID); + SWIFT_LOG(debug) << std::endl; + if (state != Initial) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - JingleS5BTransportPayload::ref transport = boost::make_shared<JingleS5BTransportPayload>(); - localCandidateGenerator->generateLocalTransportCandidates(transport); + setTransporter(transporterFactory->createInitiatorTransporter(getInitiator(), getResponder())); + setState(GeneratingInitialLocalCandidates); + transporter->startGeneratingLocalCandidates(); } -void OutgoingJingleFileTransfer::stop() { - +void OutgoingJingleFileTransfer::cancel() { + terminate(JinglePayload::Reason::Cancel); } -void OutgoingJingleFileTransfer::cancel() { - canceled = true; - session->sendTerminate(JinglePayload::Reason::Cancel); +void OutgoingJingleFileTransfer::terminate(JinglePayload::Reason::Type reason) { + SWIFT_LOG(debug) << reason << std::endl; - if (ibbSession) { - ibbSession->stop(); + if (state != Initial && state != GeneratingInitialLocalCandidates && state != Finished) { + session->sendTerminate(reason); } - SOCKS5BytestreamServerSession *serverSession = s5bRegistry->getConnectedSession(SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID)); - if (serverSession) { - serverSession->stop(); - } - if (clientSession) { - clientSession->stop(); - } - onStateChange(FileTransfer::State(FileTransfer::State::Canceled)); + stopAll(); + setFinishedState(getExternalFinishedState(reason), getFileTransferError(reason)); } -void OutgoingJingleFileTransfer::handleSessionAcceptReceived(const JingleContentID& id, JingleDescription::ref /* decription */, JingleTransportPayload::ref transportPayload) { - if (canceled) { - return; - } - onStateChange(FileTransfer::State(FileTransfer::State::Negotiating)); - - JingleIBBTransportPayload::ref ibbPayload; - JingleS5BTransportPayload::ref s5bPayload; - if ((ibbPayload = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transportPayload))) { - ibbSession = boost::make_shared<IBBSendSession>(ibbPayload->getSessionID(), fromJID, toJID, readStream, router); - ibbSession->setBlockSize(ibbPayload->getBlockSize()); - ibbSession->onBytesSent.connect(boost::bind(boost::ref(onProcessedBytes), _1)); - ibbSession->onFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1)); - ibbSession->start(); - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); - } - else if ((s5bPayload = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transportPayload))) { - fillCandidateMap(theirCandidates, s5bPayload); - remoteCandidateSelector->setRequesterTargtet(toJID, session->getInitiator()); - remoteCandidateSelector->addRemoteTransportCandidates(s5bPayload); - remoteCandidateSelector->selectCandidate(); +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 { - // TODO: error handling - SWIFT_LOG(debug) << "Unknown transport payload! Try replaceing with IBB." << std::endl; - replaceTransportWithIBB(id); + SWIFT_LOG(debug) << "Unknown transport payload. Falling back." << std::endl; + fallback(); } } void OutgoingJingleFileTransfer::handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason) { - if (canceled) { - return; - } + SWIFT_LOG(debug) << std::endl; + if (state == Finished) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - if (ibbSession) { - ibbSession->stop(); - } - if (clientSession) { - clientSession->stop(); + stopAll(); + if (reason && reason->type == JinglePayload::Reason::Cancel) { + setFinishedState(FileTransfer::State::Canceled, FileTransferError(FileTransferError::PeerError)); } - if (serverSession) { - serverSession->stop(); - } - - if (reason.is_initialized() && reason.get().type == JinglePayload::Reason::Cancel) { - onStateChange(FileTransfer::State(FileTransfer::State::Canceled)); - onFinished(FileTransferError(FileTransferError::PeerError)); - } else if (reason.is_initialized() && reason.get().type == JinglePayload::Reason::Success) { - onStateChange(FileTransfer::State(FileTransfer::State::Finished)); - onFinished(boost::optional<FileTransferError>()); - } else { - onStateChange(FileTransfer::State(FileTransfer::State::Failed)); - onFinished(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)); } - canceled = true; } -void OutgoingJingleFileTransfer::handleTransportAcceptReceived(const JingleContentID& /* contentID */, JingleTransportPayload::ref transport) { - if (canceled) { - return; - } +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)) { - ibbSession = boost::make_shared<IBBSendSession>(ibbPayload->getSessionID(), fromJID, toJID, readStream, router); - ibbSession->setBlockSize(ibbPayload->getBlockSize()); - ibbSession->onBytesSent.connect(boost::bind(boost::ref(onProcessedBytes), _1)); - ibbSession->onFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1)); - ibbSession->start(); - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); - } else { - // error handling - SWIFT_LOG(debug) << "Replacing with anything other than IBB isn't supported yet." << std::endl; - session->sendTerminate(JinglePayload::Reason::FailedTransport); - onStateChange(FileTransfer::State(FileTransfer::State::Failed)); + 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); } } -void OutgoingJingleFileTransfer::startTransferViaOurCandidateChoice(JingleS5BTransportPayload::Candidate candidate) { - SWIFT_LOG(debug) << "Transferring data using our candidate." << std::endl; - if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { - // get proxy client session from remoteCandidateSelector - clientSession = remoteCandidateSelector->getS5BSession(); - - // wait on <activated/> transport-info - } else { - clientSession = remoteCandidateSelector->getS5BSession(); - clientSession->onBytesSent.connect(boost::bind(boost::ref(onProcessedBytes), _1)); - clientSession->onFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1)); - clientSession->startSending(readStream); - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); - } - assert(clientSession); -} +void OutgoingJingleFileTransfer::sendSessionInfoHash() { + SWIFT_LOG(debug) << std::endl; -void OutgoingJingleFileTransfer::startTransferViaTheirCandidateChoice(JingleS5BTransportPayload::Candidate candidate) { - SWIFT_LOG(debug) << "Transferring data using their candidate." << std::endl; - if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { - // connect to proxy - clientSession = s5bProxy->createSOCKS5BytestreamClientSession(candidate.hostPort, SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID)); - clientSession->onSessionReady.connect(boost::bind(&OutgoingJingleFileTransfer::proxySessionReady, this, candidate.jid, _1)); - clientSession->start(); - - // on reply send activate - - } else { - serverSession = s5bRegistry->getConnectedSession(SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID)); - serverSession->onBytesSent.connect(boost::bind(boost::ref(onProcessedBytes), _1)); - serverSession->onFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1)); - serverSession->startTransfer(); - } - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); + JingleFileTransferHash::ref hashElement = boost::make_shared<JingleFileTransferHash>(); + hashElement->setHash("sha-1", hashCalculator->getSHA1String()); + hashElement->setHash("md5", hashCalculator->getMD5String()); + session->sendInfo(hashElement); } -// decide on candidates according to http://xmpp.org/extensions/xep-0260.html#complete -void OutgoingJingleFileTransfer::decideOnCandidates() { - if (ourCandidateChoice && theirCandidateChoice) { - std::string our_cid = ourCandidateChoice->getCandidateUsed(); - std::string their_cid = theirCandidateChoice->getCandidateUsed(); - if (ourCandidateChoice->hasCandidateError() && theirCandidateChoice->hasCandidateError()) { - replaceTransportWithIBB(contentID); - } - else if (!our_cid.empty() && theirCandidateChoice->hasCandidateError()) { - // use our candidate - startTransferViaOurCandidateChoice(theirCandidates[our_cid]); - } - else if (!their_cid.empty() && ourCandidateChoice->hasCandidateError()) { - // use their candidate - startTransferViaTheirCandidateChoice(ourCandidates[their_cid]); - } - else if (!our_cid.empty() && !their_cid.empty()) { - // compare priorites, if same we win - if (ourCandidates.find(their_cid) == ourCandidates.end() || theirCandidates.find(our_cid) == theirCandidates.end()) { - SWIFT_LOG(debug) << "Didn't recognize candidate IDs!" << std::endl; - session->sendTerminate(JinglePayload::Reason::FailedTransport); - onStateChange(FileTransfer::State(FileTransfer::State::Failed)); - onFinished(FileTransferError(FileTransferError::PeerError)); - return; - } - - JingleS5BTransportPayload::Candidate ourCandidate = theirCandidates[our_cid]; - JingleS5BTransportPayload::Candidate theirCandidate = ourCandidates[their_cid]; - if (ourCandidate.priority > theirCandidate.priority) { - startTransferViaOurCandidateChoice(ourCandidate); - } - else if (ourCandidate.priority < theirCandidate.priority) { - startTransferViaTheirCandidateChoice(theirCandidate); - } - else { - startTransferViaOurCandidateChoice(ourCandidate); - } - } - } else { - SWIFT_LOG(debug) << "Can't make a decision yet!" << std::endl; +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); } -void OutgoingJingleFileTransfer::fillCandidateMap(CandidateMap& map, JingleS5BTransportPayload::ref s5bPayload) { - map.clear(); - foreach (JingleS5BTransportPayload::Candidate candidate, s5bPayload->getCandidates()) { - map[candidate.cid] = candidate; +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); } } -void OutgoingJingleFileTransfer::proxySessionReady(const JID& proxy, bool error) { +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) { - // indicate proxy error - } else { - // activate proxy - activateProxySession(proxy); + terminate(JinglePayload::Reason::ConnectivityError); + } + else { + sendSessionInfoHash(); + terminate(JinglePayload::Reason::Success); } } -void OutgoingJingleFileTransfer::activateProxySession(const JID& proxy) { - S5BProxyRequest::ref proxyRequest = boost::make_shared<S5BProxyRequest>(); - proxyRequest->setSID(s5bSessionID); - proxyRequest->setActivate(toJID); +void OutgoingJingleFileTransfer::startTransferring(boost::shared_ptr<TransportSession> transportSession) { + SWIFT_LOG(debug) << std::endl; - 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(); + 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(); } -void OutgoingJingleFileTransfer::handleActivateProxySessionResult(boost::shared_ptr<S5BProxyRequest> /*request*/, ErrorPayload::ref error) { - if (error) { - SWIFT_LOG(debug) << "ERROR" << std::endl; - } else { - // send activated to other jingle party - JingleS5BTransportPayload::ref proxyActivate = boost::make_shared<JingleS5BTransportPayload>(); - proxyActivate->setActivated(theirCandidateChoice->getCandidateUsed()); - session->sendTransportInfo(contentID, proxyActivate); - - // start transferring - clientSession->onBytesSent.connect(boost::bind(boost::ref(onProcessedBytes), _1)); - clientSession->onFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1)); - clientSession->startSending(readStream); - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); - } + +void OutgoingJingleFileTransfer::setState(State state) { + SWIFT_LOG(debug) << state << std::endl; + this->state = state; + onStateChanged(FileTransfer::State(getExternalState(state))); } -void OutgoingJingleFileTransfer::sendSessionInfoHash() { +void OutgoingJingleFileTransfer::setFinishedState( + FileTransfer::State::Type type, const boost::optional<FileTransferError>& error) { SWIFT_LOG(debug) << std::endl; - JingleFileTransferHash::ref hashElement = boost::make_shared<JingleFileTransferHash>(); - hashElement->setHash("sha-1", hashCalculator->getSHA1String()); - hashElement->setHash("md5", hashCalculator->getMD5String()); - session->sendInfo(hashElement); + this->state = Finished; + onStateChanged(type); + onFinished(error); } -void OutgoingJingleFileTransfer::handleTransportInfoReceived(const JingleContentID& /* contentID */, JingleTransportPayload::ref transport) { - if (canceled) { - return; - } - if (JingleS5BTransportPayload::ref s5bPayload = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transport)) { - if (s5bPayload->hasCandidateError() || !s5bPayload->getCandidateUsed().empty()) { - theirCandidateChoice = s5bPayload; - decideOnCandidates(); - } else if(!s5bPayload->getActivated().empty()) { - if (ourCandidateChoice->getCandidateUsed() == s5bPayload->getActivated()) { - clientSession->onBytesSent.connect(boost::bind(boost::ref(onProcessedBytes), _1)); - clientSession->onFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1)); - clientSession->startSending(readStream); - onStateChange(FileTransfer::State(FileTransfer::State::Transferring)); - } else { - SWIFT_LOG(debug) << "ourCandidateChoice doesn't match activated proxy candidate!" << std::endl; - JingleS5BTransportPayload::ref proxyError = boost::make_shared<JingleS5BTransportPayload>(); - proxyError->setProxyError(true); - proxyError->setSessionID(s5bSessionID); - session->sendTransportInfo(contentID, proxyError); - } - } +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; } -void OutgoingJingleFileTransfer::handleLocalTransportCandidatesGenerated(JingleTransportPayload::ref payload) { - if (canceled) { - return; +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; } - JingleFileTransferDescription::ref description = boost::make_shared<JingleFileTransferDescription>(); - description->addOffer(fileInfo); + if (state != Initial) { + delete transporter; + } +} - JingleTransportPayload::ref transport; - if (JingleIBBTransportPayload::ref ibbTransport = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(payload)) { - ibbTransport->setBlockSize(4096); - ibbTransport->setSessionID(idGenerator->generateID()); - transport = ibbTransport; +void OutgoingJingleFileTransfer::startTransferViaRemoteCandidate() { + SWIFT_LOG(debug) << std::endl; + + if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setState(WaitingForPeerProxyActivate); + } + else { + transportSession = createRemoteCandidateSession(); + startTransferringIfCandidateAcknowledged(); } - else if (JingleS5BTransportPayload::ref s5bTransport = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(payload)) { - //fillCandidateMap(ourCandidates, s5bTransport); - //s5bTransport->setSessionID(s5bSessionID); +} - JingleS5BTransportPayload::ref emptyCandidates = boost::make_shared<JingleS5BTransportPayload>(); - emptyCandidates->setSessionID(s5bTransport->getSessionID()); - fillCandidateMap(ourCandidates, emptyCandidates); +void OutgoingJingleFileTransfer::startTransferViaLocalCandidate() { + SWIFT_LOG(debug) << std::endl; - transport = emptyCandidates; - s5bRegistry->addReadBytestream(SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID), readStream); + if (theirCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setState(WaitingForLocalProxyActivate); + transporter->startActivatingProxy(theirCandidateChoice->jid); + } + else { + transportSession = createLocalCandidateSession(); + startTransferringIfCandidateAcknowledged(); + } +} + +void OutgoingJingleFileTransfer::startTransferringIfCandidateAcknowledged() { + if (candidateAcknowledged) { + startTransferring(transportSession); } else { - SWIFT_LOG(debug) << "Unknown tranport payload: " << typeid(*payload).name() << std::endl; - return; + setState(WaitingForCandidateAcknowledge); } - session->sendInitiate(contentID, description, transport); - onStateChange(FileTransfer::State(FileTransfer::State::WaitingForAccept)); } -void OutgoingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished(JingleTransportPayload::ref payload) { - if (canceled) { - return; +void OutgoingJingleFileTransfer::handleTransportInfoAcknowledged(const std::string& id) { + if (id == candidateSelectRequestID) { + candidateAcknowledged = true; } - if (JingleS5BTransportPayload::ref s5bPayload = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(payload)) { - ourCandidateChoice = s5bPayload; - session->sendTransportInfo(contentID, s5bPayload); - decideOnCandidates(); + if (state == WaitingForCandidateAcknowledge) { + startTransferring(transportSession); } } -void OutgoingJingleFileTransfer::replaceTransportWithIBB(const JingleContentID& id) { - SWIFT_LOG(debug) << "Both parties failed. Replace transport with IBB." << std::endl; - JingleIBBTransportPayload::ref ibbTransport = boost::make_shared<JingleIBBTransportPayload>(); - ibbTransport->setBlockSize(4096); - ibbTransport->setSessionID(idGenerator->generateID()); - session->sendTransportReplace(id, ibbTransport); +JingleContentID OutgoingJingleFileTransfer::getContentID() const { + return contentID; } -void OutgoingJingleFileTransfer::handleTransferFinished(boost::optional<FileTransferError> error) { - if (error) { - session->sendTerminate(JinglePayload::Reason::ConnectivityError); - onStateChange(FileTransfer::State(FileTransfer::State::Failed)); - onFinished(error); - } else { - sendSessionInfoHash(); - /* - session->terminate(JinglePayload::Reason::Success); - onStateChange(FileTransfer::State(FileTransfer::State::Finished)); - */ - } - // +bool OutgoingJingleFileTransfer::hasPriorityOnCandidateTie() const { + return true; +} + +bool OutgoingJingleFileTransfer::isWaitingForPeerProxyActivate() const { + return state == WaitingForPeerProxyActivate; +} + +bool OutgoingJingleFileTransfer::isWaitingForLocalProxyActivate() const { + return state == WaitingForLocalProxyActivate; } +bool OutgoingJingleFileTransfer::isTryingCandidates() const { + return state == TryingCandidates; } + +boost::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createLocalCandidateSession() { + return transporter->createLocalCandidateSession(stream); +} + +boost::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createRemoteCandidateSession() { + return transporter->createRemoteCandidateSession(stream); +} + diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h index e18b5c3..d1f4dc4 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h @@ -4,113 +4,110 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #pragma once #include <boost/shared_ptr.hpp> +#include <boost/optional/optional.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Elements/JingleContentPayload.h> -#include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/Base/Override.h> +#include <Swiften/Jingle/JingleContentID.h> #include <Swiften/Elements/StreamInitiationFileInfo.h> -#include <Swiften/Elements/S5BProxyRequest.h> -#include <Swiften/Elements/ErrorPayload.h> #include <Swiften/FileTransfer/OutgoingFileTransfer.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> -#include <Swiften/Jingle/JingleContentID.h> -#include <Swiften/Jingle/JingleSession.h> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/FileTransfer/JingleFileTransfer.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> namespace Swift { - -class RemoteJingleTransportCandidateSelectorFactory; -class RemoteJingleTransportCandidateSelector; -class LocalJingleTransportCandidateGeneratorFactory; -class LocalJingleTransportCandidateGenerator; -class IQRouter; -class ReadBytestream; -class IBBSendSession; -class IDGenerator; -class IncrementalBytestreamHashCalculator; -class SOCKS5BytestreamRegistry; -class SOCKS5BytestreamProxy; - -class SWIFTEN_API OutgoingJingleFileTransfer : public OutgoingFileTransfer { -public: - OutgoingJingleFileTransfer(JingleSession::ref, - RemoteJingleTransportCandidateSelectorFactory*, - LocalJingleTransportCandidateGeneratorFactory*, - IQRouter*, - IDGenerator*, - const JID& from, - const JID& to, - boost::shared_ptr<ReadBytestream>, - const StreamInitiationFileInfo&, - SOCKS5BytestreamRegistry*, - SOCKS5BytestreamProxy*); - virtual ~OutgoingJingleFileTransfer(); - - void start(); - void stop(); - - void cancel(); - -private: - void handleSessionAcceptReceived(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref); - void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason); - void handleTransportAcceptReceived(const JingleContentID&, JingleTransportPayload::ref); - void handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref); - - void handleLocalTransportCandidatesGenerated(JingleTransportPayload::ref); - void handleRemoteTransportCandidateSelectFinished(JingleTransportPayload::ref); - -private: - void replaceTransportWithIBB(const JingleContentID&); - void handleTransferFinished(boost::optional<FileTransferError>); - void activateProxySession(const JID &proxy); - void handleActivateProxySessionResult(boost::shared_ptr<S5BProxyRequest> request, ErrorPayload::ref error); - void proxySessionReady(const JID& proxy, bool error); - -private: - typedef std::map<std::string, JingleS5BTransportPayload::Candidate> CandidateMap; - -private: - void startTransferViaOurCandidateChoice(JingleS5BTransportPayload::Candidate); - void startTransferViaTheirCandidateChoice(JingleS5BTransportPayload::Candidate); - void decideOnCandidates(); - void fillCandidateMap(CandidateMap& map, JingleS5BTransportPayload::ref s5bPayload); - -private: - void sendSessionInfoHash(); - -private: - JingleSession::ref session; - RemoteJingleTransportCandidateSelector* remoteCandidateSelector; - LocalJingleTransportCandidateGenerator* localCandidateGenerator; - - IQRouter* router; - IDGenerator* idGenerator; - JID fromJID; - JID toJID; - boost::shared_ptr<ReadBytestream> readStream; - StreamInitiationFileInfo fileInfo; - IncrementalBytestreamHashCalculator *hashCalculator; - - boost::shared_ptr<IBBSendSession> ibbSession; - - JingleS5BTransportPayload::ref ourCandidateChoice; - JingleS5BTransportPayload::ref theirCandidateChoice; - CandidateMap ourCandidates; - CandidateMap theirCandidates; - - SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamProxy* s5bProxy; - SOCKS5BytestreamClientSession::ref clientSession; - SOCKS5BytestreamServerSession* serverSession; - JingleContentID contentID; - std::string s5bSessionID; - - bool canceled; -}; + 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; + }; } diff --git a/Swiften/FileTransfer/OutgoingSIFileTransfer.cpp b/Swiften/FileTransfer/OutgoingSIFileTransfer.cpp index fc0a551..1c60469 100644 --- a/Swiften/FileTransfer/OutgoingSIFileTransfer.cpp +++ b/Swiften/FileTransfer/OutgoingSIFileTransfer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -16,10 +16,11 @@ namespace Swift { -OutgoingSIFileTransfer::OutgoingSIFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, int 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) { +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)); @@ -28,12 +29,14 @@ void OutgoingSIFileTransfer::start() { 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 response, ErrorPayload::ref error) { +void OutgoingSIFileTransfer::handleStreamInitiationRequestResponse(StreamInitiation::ref, ErrorPayload::ref) { + /* if (error) { finish(FileTransferError()); } @@ -54,26 +57,31 @@ void OutgoingSIFileTransfer::handleStreamInitiationRequestResponse(StreamInitiat ibbSession->start(); } } + */ } -void OutgoingSIFileTransfer::handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref error) { +void OutgoingSIFileTransfer::handleBytestreamsRequestResponse(Bytestreams::ref, ErrorPayload::ref) { + /* if (error) { finish(FileTransferError()); } + */ //socksServer->onTransferFinished.connect(); } -void OutgoingSIFileTransfer::finish(boost::optional<FileTransferError> error) { +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> error) { - finish(error); +void OutgoingSIFileTransfer::handleIBBSessionFinished(boost::optional<FileTransferError>) { + //finish(error); } } diff --git a/Swiften/FileTransfer/OutgoingSIFileTransfer.h b/Swiften/FileTransfer/OutgoingSIFileTransfer.h index 584eb60..79da339 100644 --- a/Swiften/FileTransfer/OutgoingSIFileTransfer.h +++ b/Swiften/FileTransfer/OutgoingSIFileTransfer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -25,7 +25,7 @@ namespace Swift { class OutgoingSIFileTransfer : public OutgoingFileTransfer { public: - OutgoingSIFileTransfer(const std::string& id, const JID& from, const JID& to, const std::string& name, int size, const std::string& description, boost::shared_ptr<ReadBytestream> bytestream, IQRouter* iqRouter, SOCKS5BytestreamServer* socksServer); + 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(); @@ -43,7 +43,7 @@ namespace Swift { JID from; JID to; std::string name; - int size; + unsigned long long size; std::string description; boost::shared_ptr<ReadBytestream> bytestream; IQRouter* iqRouter; diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp index 338f221..1e96b22 100644 --- a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp +++ b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp @@ -1,14 +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 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. */ #include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> -namespace Swift { +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/bind.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> + +using namespace Swift; + +RemoteJingleTransportCandidateSelector::RemoteJingleTransportCandidateSelector( + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory) : + connectionFactory(connectionFactory), + timerFactory(timerFactory) { +} RemoteJingleTransportCandidateSelector::~RemoteJingleTransportCandidateSelector() { } +void RemoteJingleTransportCandidateSelector::addCandidates( + const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { + foreach(JingleS5BTransportPayload::Candidate c, candidates) { + this->candidates.push(c); + } +} + +void RemoteJingleTransportCandidateSelector::startSelectingCandidate() { + tryNextCandidate(); +} + +void RemoteJingleTransportCandidateSelector::stopSelectingCandidate() { + 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(); + } + } +} + +void RemoteJingleTransportCandidateSelector::handleSessionReady(bool error) { + sessionReadyConnection.disconnect(); + if (error) { + s5bSession.reset(); + tryNextCandidate(); + } + else { + onCandidateSelectFinished(lastCandidate, s5bSession); + } +} + +void RemoteJingleTransportCandidateSelector::setSOCKS5DstAddr(const std::string& socks5DstAddr) { + this->socks5DstAddr = socks5DstAddr; } diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h index 487747c..66ab4b2 100644 --- a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h +++ b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h @@ -1,34 +1,61 @@ /* - * 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 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +/* + * 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/boost_bsignals.h> +#include <queue> +#include <vector> + +#include <boost/shared_ptr.hpp> -#include <Swiften/Base/API.h> +#include <Swiften/Base/Override.h> #include <Swiften/JID/JID.h> -#include <Swiften/Elements/JingleTransportPayload.h> -#include <Swiften/FileTransfer/JingleTransport.h> +#include <Swiften/Network/Connection.h> #include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> +#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> +#include <Swiften/Elements/JingleS5BTransportPayload.h> + namespace Swift { - class SWIFTEN_API RemoteJingleTransportCandidateSelector { + class ConnectionFactory; + class TimerFactory; + + class RemoteJingleTransportCandidateSelector { public: + RemoteJingleTransportCandidateSelector(ConnectionFactory*, TimerFactory*); virtual ~RemoteJingleTransportCandidateSelector(); - virtual void addRemoteTransportCandidates(JingleTransportPayload::ref) = 0; - virtual void selectCandidate() = 0; - virtual void setMinimumPriority(int) = 0; - virtual void setRequesterTargtet(const JID&, const JID&) {} - virtual SOCKS5BytestreamClientSession::ref getS5BSession() { return SOCKS5BytestreamClientSession::ref(); } + 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); - virtual bool isActualCandidate(JingleTransportPayload::ref) = 0; - virtual int getPriority(JingleTransportPayload::ref) = 0; - virtual JingleTransport::ref selectTransport(JingleTransportPayload::ref) = 0; + private: + ConnectionFactory* connectionFactory; + TimerFactory* timerFactory; - boost::signal<void (JingleTransportPayload::ref)> onRemoteTransportCandidateSelectFinished; - }; + 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; + }; } diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.cpp b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.cpp deleted file mode 100644 index 36b7cba..0000000 --- a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h> - -namespace Swift { - -RemoteJingleTransportCandidateSelectorFactory::~RemoteJingleTransportCandidateSelectorFactory() { -} - -} diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h deleted file mode 100644 index 4980b0c..0000000 --- a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2011 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> - -namespace Swift { - class RemoteJingleTransportCandidateSelector; - - class SWIFTEN_API RemoteJingleTransportCandidateSelectorFactory { - public: - virtual ~RemoteJingleTransportCandidateSelectorFactory(); - - virtual RemoteJingleTransportCandidateSelector* createCandidateSelector() = 0; - }; -} diff --git a/Swiften/FileTransfer/SConscript b/Swiften/FileTransfer/SConscript index 4e79992..6c29ea6 100644 --- a/Swiften/FileTransfer/SConscript +++ b/Swiften/FileTransfer/SConscript @@ -1,6 +1,7 @@ Import("swiften_env", "env") sources = [ + "ByteArrayReadBytestream.cpp", "OutgoingFileTransfer.cpp", "OutgoingSIFileTransfer.cpp", "OutgoingJingleFileTransfer.cpp", @@ -8,32 +9,33 @@ sources = [ "IncomingFileTransfer.cpp", "IncomingJingleFileTransfer.cpp", "IncomingFileTransferManager.cpp", + "JingleFileTransfer.cpp", + "FileTransferOptions.cpp", + "FileTransferTransporter.cpp", + "FileTransferTransporterFactory.cpp", + "DefaultFileTransferTransporter.cpp", + "DefaultFileTransferTransporterFactory.cpp", "RemoteJingleTransportCandidateSelector.cpp", - "RemoteJingleTransportCandidateSelectorFactory.cpp", "LocalJingleTransportCandidateGenerator.cpp", - "LocalJingleTransportCandidateGeneratorFactory.cpp", - "DefaultRemoteJingleTransportCandidateSelectorFactory.cpp", - "DefaultLocalJingleTransportCandidateGeneratorFactory.cpp", - "DefaultRemoteJingleTransportCandidateSelector.cpp", - "DefaultLocalJingleTransportCandidateGenerator.cpp", - "JingleTransport.cpp", - "JingleIncomingIBBTransport.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", - "SOCKS5BytestreamProxy.cpp", + "SOCKS5BytestreamProxiesManager.cpp", "SOCKS5BytestreamProxyFinder.cpp", "IBBSendSession.cpp", "IBBReceiveSession.cpp", "FileTransferManager.cpp", "FileTransferManagerImpl.cpp", "IncrementalBytestreamHashCalculator.cpp", - "ConnectivityManager.cpp", ] swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources)) diff --git a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp index cd555e5..b371078 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp @@ -4,15 +4,21 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #include "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/Concat.h> #include <Swiften/Base/Log.h> -#include <Swiften/StringCodecs/SHA1.h> #include <Swiften/StringCodecs/Hexify.h> #include <Swiften/FileTransfer/BytestreamException.h> #include <Swiften/Network/TimerFactory.h> @@ -20,25 +26,39 @@ 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) { - connection->onConnectFinished.connect(boost::bind(&SOCKS5BytestreamClientSession::handleConnectFinished, this, _1)); - connection->onDisconnected.connect(boost::bind(&SOCKS5BytestreamClientSession::handleDisconnected, this, _1)); +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)); + weFailedTimeout->onTick.connect( + boost::bind(&SOCKS5BytestreamClientSession::handleWeFailedTimeout, this)); +} + +SOCKS5BytestreamClientSession::~SOCKS5BytestreamClientSession() { } 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); } void SOCKS5BytestreamClientSession::stop() { - connection->disconnect(); - connection->onDataWritten.disconnect(boost::bind(&SOCKS5BytestreamClientSession::sendData, this)); - connection->onDataRead.disconnect(boost::bind(&SOCKS5BytestreamClientSession::handleDataRead, this, _1)); + SWIFT_LOG(debug) << std::endl; + if (state == Finished) { + return; + } + closeConnection(); readBytestream.reset(); state = Finished; } @@ -127,7 +147,7 @@ void SOCKS5BytestreamClientSession::authenticate() { SWIFT_LOG(debug) << std::endl; SafeByteArray header = createSafeByteArray("\x05\x01\x00\x03", 4); SafeByteArray message = header; - append(message, createSafeByteArray(destination.size())); + 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 @@ -151,7 +171,8 @@ void SOCKS5BytestreamClientSession::startSending(boost::shared_ptr<ReadBytestrea if (state == Ready) { state = Writing; readBytestream = readStream; - connection->onDataWritten.connect(boost::bind(&SOCKS5BytestreamClientSession::sendData, this)); + dataWrittenConnection = connection->onDataWritten.connect( + boost::bind(&SOCKS5BytestreamClientSession::sendData, this)); sendData(); } else { SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl; @@ -165,7 +186,7 @@ HostAddressPort SOCKS5BytestreamClientSession::getAddressPort() const { void SOCKS5BytestreamClientSession::sendData() { if (!readBytestream->isFinished()) { try { - boost::shared_ptr<ByteArray> dataToSend = readBytestream->read(chunkSize); + boost::shared_ptr<ByteArray> dataToSend = readBytestream->read(boost::numeric_cast<size_t>(chunkSize)); connection->write(createSafeByteArray(*dataToSend)); onBytesSent(dataToSend->size()); } @@ -179,10 +200,9 @@ void SOCKS5BytestreamClientSession::sendData() { } void SOCKS5BytestreamClientSession::finish(bool error) { + SWIFT_LOG(debug) << std::endl; weFailedTimeout->stop(); - connection->disconnect(); - connection->onDataWritten.disconnect(boost::bind(&SOCKS5BytestreamClientSession::sendData, this)); - connection->onDataRead.disconnect(boost::bind(&SOCKS5BytestreamClientSession::handleDataRead, this, _1)); + closeConnection(); readBytestream.reset(); if (state == Initial || state == Hello || state == Authenticating) { onSessionReady(true); @@ -198,13 +218,17 @@ void SOCKS5BytestreamClientSession::finish(bool error) { } 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(); - connection->onDataRead.connect(boost::bind(&SOCKS5BytestreamClientSession::handleDataRead, this, _1)); process(); } } @@ -233,4 +257,12 @@ void SOCKS5BytestreamClientSession::handleWeFailedTimeout() { finish(true); } +void SOCKS5BytestreamClientSession::closeConnection() { + connectFinishedConnection.disconnect(); + dataWrittenConnection.disconnect(); + dataReadConnection.disconnect(); + disconnectedConnection.disconnect(); + connection->disconnect(); +} + } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h index 0b9790d..287cf3b 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h @@ -38,14 +38,19 @@ public: Ready, Writing, Reading, - Finished, + Finished }; public: typedef boost::shared_ptr<SOCKS5BytestreamClientSession> ref; public: - SOCKS5BytestreamClientSession(boost::shared_ptr<Connection> connection, const HostAddressPort&, const std::string&, TimerFactory*); + SOCKS5BytestreamClientSession( + boost::shared_ptr<Connection> connection, + const HostAddressPort&, + const std::string&, + TimerFactory*); + ~SOCKS5BytestreamClientSession(); void start(); void stop(); @@ -58,8 +63,8 @@ public: boost::signal<void (bool /*error*/)> onSessionReady; boost::signal<void (boost::optional<FileTransferError>)> onFinished; - boost::signal<void (int)> onBytesSent; - boost::signal<void (int)> onBytesReceived; + boost::signal<void (size_t)> onBytesSent; + boost::signal<void (size_t)> onBytesReceived; private: void process(); @@ -73,6 +78,7 @@ private: void finish(bool error); void sendData(); + void closeConnection(); private: boost::shared_ptr<Connection> connection; @@ -89,6 +95,11 @@ private: boost::shared_ptr<ReadBytestream> readBytestream; Timer::ref weFailedTimeout; + + boost::bsignals::connection connectFinishedConnection; + boost::bsignals::connection dataWrittenConnection; + boost::bsignals::connection dataReadConnection; + boost::bsignals::connection disconnectedConnection; }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxy.cpp b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp index 9599fd1..0b94763 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxy.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp @@ -4,7 +4,7 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include "SOCKS5BytestreamProxy.h" +#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> #include <boost/smart_ptr/make_shared.hpp> @@ -14,19 +14,19 @@ namespace Swift { -SOCKS5BytestreamProxy::SOCKS5BytestreamProxy(ConnectionFactory *connFactory, TimerFactory *timeFactory) : connectionFactory(connFactory), timerFactory(timeFactory) { +SOCKS5BytestreamProxiesManager::SOCKS5BytestreamProxiesManager(ConnectionFactory *connFactory, TimerFactory *timeFactory) : connectionFactory(connFactory), timerFactory(timeFactory) { } -void SOCKS5BytestreamProxy::addS5BProxy(S5BProxyRequest::ref proxy) { +void SOCKS5BytestreamProxiesManager::addS5BProxy(S5BProxyRequest::ref proxy) { localS5BProxies.push_back(proxy); } -const std::vector<S5BProxyRequest::ref>& SOCKS5BytestreamProxy::getS5BProxies() const { +const std::vector<S5BProxyRequest::ref>& SOCKS5BytestreamProxiesManager::getS5BProxies() const { return localS5BProxies; } -void SOCKS5BytestreamProxy::connectToProxies(const std::string& sessionID) { +void SOCKS5BytestreamProxiesManager::connectToProxies(const std::string& sessionID) { SWIFT_LOG(debug) << "session ID: " << sessionID << std::endl; ProxyJIDClientSessionMap clientSessions; @@ -41,7 +41,7 @@ void SOCKS5BytestreamProxy::connectToProxies(const std::string& sessionID) { proxySessions[sessionID] = clientSessions; } -boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxy::getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID) { +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>(); @@ -64,7 +64,7 @@ boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxy::getProxy return activeSession; } -boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxy::createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr) { +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; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h new file mode 100644 index 0000000..f3fed80 --- /dev/null +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <string> +#include <vector> + +#include <Swiften/Base/API.h> +#include <Swiften/Elements/S5BProxyRequest.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Network/ConnectionFactory.h> +#include <Swiften/Network/TimerFactory.h> + +namespace Swift { + class SOCKS5BytestreamProxiesDiscoverRequest; + + /** + * - manages list of working S5B proxies + * - creates initial connections (for the candidates you provide) + */ + class SWIFTEN_API SOCKS5BytestreamProxiesManager { + public: + SOCKS5BytestreamProxiesManager(ConnectionFactory*, TimerFactory*); + + boost::shared_ptr<SOCKS5BytestreamProxiesDiscoverRequest> createDiscoverProxiesRequest(); + + void addS5BProxy(S5BProxyRequest::ref); + const std::vector<S5BProxyRequest::ref>& getS5BProxies() const; + + void connectToProxies(const std::string& sessionID); + boost::shared_ptr<SOCKS5BytestreamClientSession> getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID); + + boost::shared_ptr<SOCKS5BytestreamClientSession> createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr); + + private: + ConnectionFactory* connectionFactory; + TimerFactory* timerFactory; + + typedef std::map<JID, boost::shared_ptr<SOCKS5BytestreamClientSession> > ProxyJIDClientSessionMap; + std::map<std::string, ProxyJIDClientSessionMap> proxySessions; + + std::vector<S5BProxyRequest::ref> localS5BProxies; + }; + +} diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxy.h b/Swiften/FileTransfer/SOCKS5BytestreamProxy.h deleted file mode 100644 index 59ff50c..0000000 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxy.h +++ /dev/null @@ -1,47 +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 <string> -#include <vector> - -#include <Swiften/Base/API.h> -#include <Swiften/Elements/S5BProxyRequest.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Network/ConnectionFactory.h> -#include <Swiften/Network/TimerFactory.h> - -namespace Swift { - -/** - * - manages list of working S5B proxies - * - creates initial connections (for the candidates you provide) - */ -class SWIFTEN_API SOCKS5BytestreamProxy { -public: - SOCKS5BytestreamProxy(ConnectionFactory*, TimerFactory*); - - void addS5BProxy(S5BProxyRequest::ref); - const std::vector<S5BProxyRequest::ref>& getS5BProxies() const; - - void connectToProxies(const std::string& sessionID); - boost::shared_ptr<SOCKS5BytestreamClientSession> getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID); - - boost::shared_ptr<SOCKS5BytestreamClientSession> createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr); - -private: - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; - - typedef std::map<JID, boost::shared_ptr<SOCKS5BytestreamClientSession> > ProxyJIDClientSessionMap; - std::map<std::string, ProxyJIDClientSessionMap> proxySessions; - - std::vector<S5BProxyRequest::ref> localS5BProxies; -}; - -} diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h index 071e03a..8265157 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h @@ -18,25 +18,25 @@ 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; -}; + 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; + }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp index ffc4298..cf4794c 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,62 +11,28 @@ #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/Log.h> #include <Swiften/Base/foreach.h> -#include <Swiften/StringCodecs/SHA1.h> -#include <Swiften/StringCodecs/Hexify.h> namespace Swift { SOCKS5BytestreamRegistry::SOCKS5BytestreamRegistry() { } -void SOCKS5BytestreamRegistry::addReadBytestream(const std::string& destination, boost::shared_ptr<ReadBytestream> byteStream) { - readBytestreams[destination] = byteStream; -} - -void SOCKS5BytestreamRegistry::removeReadBytestream(const std::string& destination) { - readBytestreams.erase(destination); -} - -boost::shared_ptr<ReadBytestream> SOCKS5BytestreamRegistry::getReadBytestream(const std::string& destination) const { - ReadBytestreamMap::const_iterator i = readBytestreams.find(destination); - if (i != readBytestreams.end()) { - return i->second; +void SOCKS5BytestreamRegistry::setHasBytestream(const std::string& destination, bool b) { + if (b) { + availableBytestreams.insert(destination); + } + else { + availableBytestreams.erase(destination); } - return boost::shared_ptr<ReadBytestream>(); -} - -void SOCKS5BytestreamRegistry::addWriteBytestream(const std::string& destination, boost::shared_ptr<WriteBytestream> byteStream) { - writeBytestreams[destination] = byteStream; -} - -void SOCKS5BytestreamRegistry::removeWriteBytestream(const std::string& destination) { - writeBytestreams.erase(destination); } -boost::shared_ptr<WriteBytestream> SOCKS5BytestreamRegistry::getWriteBytestream(const std::string& destination) const { - WriteBytestreamMap::const_iterator i = writeBytestreams.find(destination); - if (i != writeBytestreams.end()) { - return i->second; - } - return boost::shared_ptr<WriteBytestream>(); +bool SOCKS5BytestreamRegistry::hasBytestream(const std::string& destination) const { + return availableBytestreams.find(destination) != availableBytestreams.end(); } std::string SOCKS5BytestreamRegistry::generateSessionID() { return idGenerator.generateID(); } -SOCKS5BytestreamServerSession* SOCKS5BytestreamRegistry::getConnectedSession(const std::string& destination) { - if (serverSessions.find(destination) != serverSessions.end()) { - return serverSessions[destination]; - } else { - SWIFT_LOG(debug) << "No active connction for stream ID " << destination << " found!" << std::endl; - return NULL; - } -} - -std::string SOCKS5BytestreamRegistry::getHostname(const std::string& sessionID, const JID& requester, const JID& target) { - return Hexify::hexify(SHA1::getHash(createSafeByteArray(sessionID + requester.toString() + target.toString()))); -} - } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h index 6d89e27..4c05e47 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h @@ -1,65 +1,35 @@ /* - * Copyright (c) 2010 Remko Tronçon + * 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 <map> #include <string> -#include <vector> #include <set> #include <Swiften/Base/API.h> #include <Swiften/Base/IDGenerator.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/S5BProxyRequest.h> -#include <Swiften/FileTransfer/ReadBytestream.h> -#include <Swiften/FileTransfer/WriteBytestream.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> -#include <Swiften/Network/HostAddressPort.h> namespace Swift { + class SOCKS5BytestreamServerSession; + class SWIFTEN_API SOCKS5BytestreamRegistry { public: SOCKS5BytestreamRegistry(); - boost::shared_ptr<ReadBytestream> getReadBytestream(const std::string& destination) const; - void addReadBytestream(const std::string& destination, boost::shared_ptr<ReadBytestream> byteStream); - void removeReadBytestream(const std::string& destination); - - boost::shared_ptr<WriteBytestream> getWriteBytestream(const std::string& destination) const; - void addWriteBytestream(const std::string& destination, boost::shared_ptr<WriteBytestream> byteStream); - void removeWriteBytestream(const std::string& destination); + 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(); - /** - * Start an actual transfer. - */ - SOCKS5BytestreamServerSession* getConnectedSession(const std::string& destination); - - public: - static std::string getHostname(const std::string& sessionID, const JID& requester, const JID& target); - private: - friend class SOCKS5BytestreamServerSession; - - typedef std::map<std::string, boost::shared_ptr<ReadBytestream> > ReadBytestreamMap; - ReadBytestreamMap readBytestreams; - - typedef std::map<std::string, boost::shared_ptr<WriteBytestream> > WriteBytestreamMap; - WriteBytestreamMap writeBytestreams; - - std::map<std::string, SOCKS5BytestreamServerSession*> serverSessions; - + std::set<std::string> availableBytestreams; IDGenerator idGenerator; }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp index 90fed7a..f491918 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -9,14 +9,19 @@ #include <boost/bind.hpp> #include <Swiften/Base/Log.h> +#include <Swiften/Base/foreach.h> #include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> namespace Swift { -SOCKS5BytestreamServer::SOCKS5BytestreamServer(boost::shared_ptr<ConnectionServer> connectionServer, SOCKS5BytestreamRegistry* registry) : connectionServer(connectionServer), registry(registry) { +SOCKS5BytestreamServer::SOCKS5BytestreamServer( + boost::shared_ptr<ConnectionServer> connectionServer, + SOCKS5BytestreamRegistry* registry) : + connectionServer(connectionServer), + registry(registry) { } void SOCKS5BytestreamServer::start() { @@ -25,22 +30,17 @@ void SOCKS5BytestreamServer::start() { void SOCKS5BytestreamServer::stop() { connectionServer->onNewConnection.disconnect(boost::bind(&SOCKS5BytestreamServer::handleNewConnection, this, _1)); -} - -void SOCKS5BytestreamServer::addReadBytestream(const std::string& id, const JID& from, const JID& to, boost::shared_ptr<ReadBytestream> byteStream) { - registry->addReadBytestream(getSOCKSDestinationAddress(id, from, to), byteStream); -} - -void SOCKS5BytestreamServer::removeReadBytestream(const std::string& id, const JID& from, const JID& to) { - registry->removeReadBytestream(getSOCKSDestinationAddress(id, from, to)); -} - -std::string SOCKS5BytestreamServer::getSOCKSDestinationAddress(const std::string& id, const JID& from, const JID& to) { - return Hexify::hexify(SHA1::getHash(createByteArray(id + from.toString() + to.toString()))); + foreach (boost::shared_ptr<SOCKS5BytestreamServerSession> 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(new SOCKS5BytestreamServerSession(connection, registry)); + 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(); } @@ -49,5 +49,21 @@ HostAddressPort SOCKS5BytestreamServer::getAddressPort() const { 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; +} + +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)); +} + } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServer.h b/Swiften/FileTransfer/SOCKS5BytestreamServer.h index 6bb598e..71605c4 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServer.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -17,26 +17,24 @@ namespace Swift { class SOCKS5BytestreamServerSession; + class CryptoProvider; class SOCKS5BytestreamServer { public: - SOCKS5BytestreamServer(boost::shared_ptr<ConnectionServer> connectionServer, SOCKS5BytestreamRegistry* registry); + SOCKS5BytestreamServer( + boost::shared_ptr<ConnectionServer> connectionServer, + SOCKS5BytestreamRegistry* registry); HostAddressPort getAddressPort() const; void start(); void stop(); - void addReadBytestream(const std::string& id, const JID& from, const JID& to, boost::shared_ptr<ReadBytestream> byteStream); - void removeReadBytestream(const std::string& id, const JID& from, const JID& to); - - /*protected: - boost::shared_ptr<ReadBytestream> getBytestream(const std::string& dest);*/ + std::vector< boost::shared_ptr<SOCKS5BytestreamServerSession> > getSessions(const std::string& id) const; private: void handleNewConnection(boost::shared_ptr<Connection> connection); - - static std::string getSOCKSDestinationAddress(const std::string& id, const JID& from, const JID& to); + void handleSessionFinished(boost::shared_ptr<SOCKS5BytestreamServerSession>); private: friend class SOCKS5BytestreamServerSession; diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.cpp new file mode 100644 index 0000000..38735de --- /dev/null +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.cpp @@ -0,0 +1,39 @@ +/* + * 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 new file mode 100644 index 0000000..aa073fc --- /dev/null +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerInitializeRequest.h @@ -0,0 +1,33 @@ +/* + * 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 new file mode 100644 index 0000000..1d65d27 --- /dev/null +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2012 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> + +#include <boost/smart_ptr/make_shared.hpp> +#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/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> + +using namespace Swift; + +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) { +} + +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; +} + + +boost::shared_ptr<SOCKS5BytestreamServerInitializeRequest> SOCKS5BytestreamServerManager::createInitializeRequest() { + return boost::make_shared<SOCKS5BytestreamServerInitializeRequest>(this); +} + +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::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> SOCKS5BytestreamServerManager::getAssistedHostAddressPorts() const { + std::vector<HostAddressPort> result; + if (publicAddress && portMapping) { + result.push_back(HostAddressPort(*publicAddress, portMapping->getPublicPort())); + } + return result; +} + +bool SOCKS5BytestreamServerManager::isInitialized() const { + 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(); + } + } +} + +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; + } + + publicAddress = address; + + getPublicIPRequest->stop(); + getPublicIPRequest.reset(); + + checkInitializeFinished(); +} + +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; + } + + portMapping = mapping; + + forwardPortRequest->stop(); + forwardPortRequest.reset(); + + checkInitializeFinished(); +} + +void SOCKS5BytestreamServerManager::checkInitializeFinished() { + assert(state == Initializing); + if (!getPublicIPRequest && !forwardPortRequest) { + state = Initialized; + onInitialized(true); + } +} diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h new file mode 100644 index 0000000..248a9b9 --- /dev/null +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012-2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <vector> +#include <boost/shared_ptr.hpp> + +#include <Swiften/Base/boost_bsignals.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; + }; +} + diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp index 4412d0b..12a0f12 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <boost/bind.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <iostream> #include <Swiften/Base/ByteArray.h> @@ -14,54 +15,61 @@ #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/Concat.h> #include <Swiften/Base/Log.h> +#include <Swiften/Network/HostAddressPort.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> #include <Swiften/FileTransfer/BytestreamException.h> namespace Swift { -SOCKS5BytestreamServerSession::SOCKS5BytestreamServerSession(boost::shared_ptr<Connection> connection, SOCKS5BytestreamRegistry* bytestreams) : connection(connection), bytestreams(bytestreams), state(Initial), chunkSize(131072), waitingForData(false) { - connection->onDisconnected.connect(boost::bind(&SOCKS5BytestreamServerSession::handleDisconnected, this, _1)); +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)); } SOCKS5BytestreamServerSession::~SOCKS5BytestreamServerSession() { if (state != Finished && state != Initial) { - std::cerr << "Warning: SOCKS5BytestremServerSession unfinished" << std::endl; + std::cerr << "Warning: SOCKS5BytestreamServerSession unfinished" << std::endl; finish(false); } } void SOCKS5BytestreamServerSession::start() { SWIFT_LOG(debug) << std::endl; - connection->onDataRead.connect(boost::bind(&SOCKS5BytestreamServerSession::handleDataRead, this, _1)); + dataReadConnection = connection->onDataRead.connect( + boost::bind(&SOCKS5BytestreamServerSession::handleDataRead, this, _1)); state = WaitingForAuthentication; } void SOCKS5BytestreamServerSession::stop() { - connection->onDataWritten.disconnect(boost::bind(&SOCKS5BytestreamServerSession::sendData, this)); - connection->onDataRead.disconnect(boost::bind(&SOCKS5BytestreamServerSession::handleDataRead, this, _1)); - connection->disconnect(); - if (readBytestream) { - readBytestream->onDataAvailable.disconnect(boost::bind(&SOCKS5BytestreamServerSession::handleDataAvailable, this)); - } - state = Finished; + finish(false); } -void SOCKS5BytestreamServerSession::startTransfer() { - if (state == ReadyForTransfer) { - if (readBytestream) { - state = WritingData; - connection->onDataWritten.connect(boost::bind(&SOCKS5BytestreamServerSession::sendData, this)); - sendData(); - } - else if(writeBytestream) { - state = ReadingData; - writeBytestream->write(unprocessedData); - onBytesReceived(unprocessedData.size()); - unprocessedData.clear(); - } - } else { - SWIFT_LOG(debug) << "Not ready for transfer!" << std::endl; - } +void SOCKS5BytestreamServerSession::startSending(boost::shared_ptr<ReadBytestream> stream) { + if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!" << std::endl; return; } + + 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; } + + writeBytestream = stream; + state = ReadingData; + writeBytestream->write(unprocessedData); + onBytesReceived(unprocessedData.size()); + unprocessedData.clear(); } HostAddressPort SOCKS5BytestreamServerSession::getAddressPort() const { @@ -86,9 +94,7 @@ void SOCKS5BytestreamServerSession::handleDataAvailable() { void SOCKS5BytestreamServerSession::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); - } + finish(error); } void SOCKS5BytestreamServerSession::process() { @@ -127,29 +133,22 @@ void SOCKS5BytestreamServerSession::process() { SWIFT_LOG(debug) << "Junk after authentication mechanism" << std::endl; } unprocessedData.clear(); - std::string streamID = byteArrayToString(requestID); - readBytestream = bytestreams->getReadBytestream(streamID); - writeBytestream = bytestreams->getWriteBytestream(streamID); + streamID = byteArrayToString(requestID); + bool hasBytestream = bytestreams->hasBytestream(streamID); SafeByteArray result = createSafeByteArray("\x05", 1); - result.push_back((readBytestream || writeBytestream) ? 0x0 : 0x4); + result.push_back(hasBytestream ? 0x0 : 0x4); append(result, createByteArray("\x00\x03", 2)); - result.push_back(static_cast<char>(requestID.size())); + result.push_back(boost::numeric_cast<unsigned char>(requestID.size())); append(result, concat(requestID, createByteArray("\x00\x00", 2))); - if (!readBytestream && !writeBytestream) { + 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 " << (readBytestream ? "Readstream" : "Writestream") << ". Sent OK." << std::endl; + SWIFT_LOG(debug) << "Found stream. Sent OK." << std::endl; connection->write(result); - bytestreams->serverSessions[streamID] = this; state = ReadyForTransfer; - - if (readBytestream) { - readBytestream->onDataAvailable.connect(boost::bind(&SOCKS5BytestreamServerSession::handleDataAvailable, this)); - } - } } } @@ -159,7 +158,7 @@ void SOCKS5BytestreamServerSession::process() { void SOCKS5BytestreamServerSession::sendData() { if (!readBytestream->isFinished()) { try { - SafeByteArray dataToSend = createSafeByteArray(*readBytestream->read(chunkSize)); + SafeByteArray dataToSend = createSafeByteArray(*readBytestream->read(boost::numeric_cast<size_t>(chunkSize))); if (!dataToSend.empty()) { connection->write(dataToSend); onBytesSent(dataToSend.size()); @@ -179,9 +178,15 @@ void SOCKS5BytestreamServerSession::sendData() { } void SOCKS5BytestreamServerSession::finish(bool error) { - connection->onDataWritten.disconnect(boost::bind(&SOCKS5BytestreamServerSession::sendData, this)); - connection->onDataRead.disconnect(boost::bind(&SOCKS5BytestreamServerSession::handleDataRead, this, _1)); - connection->onDisconnected.disconnect(boost::bind(&SOCKS5BytestreamServerSession::handleDisconnected, this, _1)); + 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) { diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h index 4cbda7c..762db8b 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h @@ -30,7 +30,7 @@ namespace Swift { ReadyForTransfer, ReadingData, WritingData, - Finished, + Finished }; SOCKS5BytestreamServerSession(boost::shared_ptr<Connection> connection, SOCKS5BytestreamRegistry* registry); @@ -43,12 +43,18 @@ namespace Swift { void start(); void stop(); - void startTransfer(); + 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 (int)> onBytesSent; - boost::signal<void (int)> onBytesReceived; + 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); @@ -64,8 +70,15 @@ namespace Swift { 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; + }; } diff --git a/Swiften/FileTransfer/TransportSession.cpp b/Swiften/FileTransfer/TransportSession.cpp new file mode 100644 index 0000000..154cb89 --- /dev/null +++ b/Swiften/FileTransfer/TransportSession.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/TransportSession.h> + +using namespace Swift; + +TransportSession::~TransportSession() { +} diff --git a/Swiften/FileTransfer/TransportSession.h b/Swiften/FileTransfer/TransportSession.h new file mode 100644 index 0000000..e5a90db --- /dev/null +++ b/Swiften/FileTransfer/TransportSession.h @@ -0,0 +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 <Swiften/Base/Override.h> +#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(); + + virtual void start() = 0; + virtual void stop() = 0; + + boost::signal<void (size_t)> onBytesSent; + boost::signal<void (boost::optional<FileTransferError>)> onFinished; + }; +} diff --git a/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h b/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h index ae06cd3..26adb05 100644 --- a/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h +++ b/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h @@ -7,28 +7,41 @@ #pragma once #include <string> -#include <boost/filesystem.hpp> +#include <boost/filesystem/path.hpp> #include <boost/date_time/posix_time/posix_time.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>) { + 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>) { + 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 startListeningOnPort(int) { - } - virtual void addS5BProxy(boost::shared_ptr<S5BProxyRequest>) { } diff --git a/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp b/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp index c62636d..339e245 100644 --- a/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp @@ -13,6 +13,7 @@ #include <Swiften/Base/ByteArray.h> #include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/FileTransfer/ByteArrayWriteBytestream.h> #include <Swiften/Queries/IQRouter.h> #include <Swiften/Client/DummyStanzaChannel.h> @@ -35,6 +36,7 @@ class IBBReceiveSessionTest : public CppUnit::TestFixture { stanzaChannel = new DummyStanzaChannel(); iqRouter = new IQRouter(stanzaChannel); finished = false; + bytestream = boost::make_shared<ByteArrayWriteBytestream>(); } void tearDown() { @@ -61,7 +63,7 @@ class IBBReceiveSessionTest : public CppUnit::TestFixture { 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") == receivedData); + CPPUNIT_ASSERT(createByteArray("abc") == bytestream->getData()); CPPUNIT_ASSERT(!finished); testling->stop(); @@ -76,7 +78,7 @@ class IBBReceiveSessionTest : public CppUnit::TestFixture { 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") == receivedData); + CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); CPPUNIT_ASSERT(!finished); testling->stop(); @@ -118,7 +120,7 @@ class IBBReceiveSessionTest : public CppUnit::TestFixture { 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") == receivedData); + CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); CPPUNIT_ASSERT(finished); CPPUNIT_ASSERT(!error); @@ -161,8 +163,7 @@ class IBBReceiveSessionTest : public CppUnit::TestFixture { } IBBReceiveSession* createSession(const std::string& from, const std::string& id, size_t size = 0x1000) { - IBBReceiveSession* session = new IBBReceiveSession(id, JID(from), JID(), size, iqRouter); - session->onDataReceived.connect(boost::bind(&IBBReceiveSessionTest::handleDataReceived, this, _1)); + IBBReceiveSession* session = new IBBReceiveSession(id, JID(from), JID(), size, bytestream, iqRouter); session->onFinished.connect(boost::bind(&IBBReceiveSessionTest::handleFinished, this, _1)); return session; } @@ -173,16 +174,12 @@ class IBBReceiveSessionTest : public CppUnit::TestFixture { this->error = error; } - void handleDataReceived(const std::vector<unsigned char>& data) { - receivedData.insert(receivedData.end(), data.begin(), data.end()); - } - private: DummyStanzaChannel* stanzaChannel; IQRouter* iqRouter; bool finished; boost::optional<FileTransferError> error; - std::vector<unsigned char> receivedData; + boost::shared_ptr<ByteArrayWriteBytestream> bytestream; }; CPPUNIT_TEST_SUITE_REGISTRATION(IBBReceiveSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp index 4c6ae72..669ed80 100644 --- a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp @@ -4,12 +4,19 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #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/Elements/IBB.h> @@ -17,142 +24,67 @@ #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/FileTransfer/ByteArrayWriteBytestream.h> #include <Swiften/FileTransfer/IncomingJingleFileTransfer.h> -#include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> -#include <Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamProxy.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> #include <Swiften/Jingle/FakeJingleSession.h> #include <Swiften/Network/DummyTimerFactory.h> #include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/Network/DummyConnectionFactory.h> #include <Swiften/Network/PlatformNATTraversalWorker.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 FakeRemoteJingleTransportCandidateSelector : public RemoteJingleTransportCandidateSelector { - void addRemoteTransportCandidates(JingleTransportPayload::ref cand) { - candidate = cand; - } - - void selectCandidate() { - boost::shared_ptr<JingleS5BTransportPayload> payload = 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 FakeRemoteJingleTransportCandidateSelectorFactory : public RemoteJingleTransportCandidateSelectorFactory { -public: - virtual ~FakeRemoteJingleTransportCandidateSelectorFactory() { - - } - - virtual RemoteJingleTransportCandidateSelector* createCandidateSelector() { - return new FakeRemoteJingleTransportCandidateSelector(); - } -}; - -class FakeLocalJingleTransportCandidateGenerator : public LocalJingleTransportCandidateGenerator { -public: - virtual void generateLocalTransportCandidates(JingleTransportPayload::ref payload) { - JingleS5BTransportPayload::ref payL = make_shared<JingleS5BTransportPayload>(); - payL->setSessionID(payload->getSessionID()); - onLocalTransportCandidatesGenerated(payL); - } - - void emitonLocalTransportCandidatesGenerated(JingleTransportPayload::ref payload) { - onLocalTransportCandidatesGenerated(payload); - } - - virtual bool isActualCandidate(JingleTransportPayload::ref) { - return false; - } - - virtual int getPriority(JingleTransportPayload::ref) { - return 0; - } - - virtual JingleTransport::ref selectTransport(JingleTransportPayload::ref) { - return JingleTransport::ref(); - } -}; - -class FakeLocalJingleTransportCandidateGeneratorFactory : public LocalJingleTransportCandidateGeneratorFactory { -public: - virtual LocalJingleTransportCandidateGenerator* createCandidateGenerator() { - return new FakeLocalJingleTransportCandidateGenerator(); - } -}; - class IncomingJingleFileTransferTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(IncomingJingleFileTransferTest); - CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept); - CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks); - CPPUNIT_TEST(test_AcceptFailingS5BFallsBackToIBB); + //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 make_shared<IncomingJingleFileTransfer>(ourJID, shared_ptr<JingleSession>(fakeJingleSession), jingleContentPayload, fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, bytestreamRegistry, bytestreamProxy, timerFactory); - } + // 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; - } + // 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(); - fakeJingleSession = new 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 SOCKS5BytestreamProxy(connectionFactory, timerFactory); + 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 bytestreamProxy; + // delete connectionFactory; + // delete timerFactory; + // delete bytestreamRegistry; + // delete iqRouter; + // delete stanzaChannel; delete eventLoop; } // Tests whether IncomingJingleFileTransfer would accept a IBB only file transfer. +#if 0 void test_AcceptOnyIBBSendsSessionAccept() { //1. create your test incoming file transfer shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); @@ -217,7 +149,7 @@ public: CPPUNIT_ASSERT(s5bPayload->hasCandidateError()); // indicate transport replace (Romeo) - fakeJingleSession->onTransportReplaceReceived(getContentID(), addJingleIBBPayload()); + session->onTransportReplaceReceived(getContentID(), addJingleIBBPayload()); FakeJingleSession::AcceptTransportCall acceptTransportCall = getCall<FakeJingleSession::AcceptTransportCall>(2); @@ -259,15 +191,18 @@ private: 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(index < session->calledCommands.size()); + T* cmd = boost::get<T>(&session->calledCommands[index]); CPPUNIT_ASSERT(cmd); return *cmd; } +#endif private: EventLoop* eventLoop; - FakeJingleSession* fakeJingleSession; + boost::shared_ptr<CryptoProvider> crypto; + boost::shared_ptr<FakeJingleSession> session; +#if 0 shared_ptr<JingleContentPayload> jingleContentPayload; shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; @@ -275,8 +210,9 @@ private: IQRouter* iqRouter; SOCKS5BytestreamRegistry* bytestreamRegistry; DummyConnectionFactory* connectionFactory; - SOCKS5BytestreamProxy* bytestreamProxy; + SOCKS5BytestreamProxiesManager* bytestreamProxy; DummyTimerFactory* timerFactory; +#endif }; CPPUNIT_TEST_SUITE_REGISTRATION(IncomingJingleFileTransferTest); diff --git a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp index 0c324bf..16b1225 100644 --- a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp +++ b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -13,21 +19,18 @@ #include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> #include <Swiften/Jingle/FakeJingleSession.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> -#include <Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h> -#include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> #include <Swiften/Queries/IQRouter.h> #include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamProxy.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.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/EventLoop/DummyEventLoop.h> #include <Swiften/Network/PlatformNATTraversalWorker.h> @@ -35,11 +38,14 @@ #include <Swiften/Network/DummyConnection.h> #include <Swiften/Network/ConnectionFactory.h> #include <Swiften/Network/DummyConnectionFactory.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/Base/Log.h> #include <iostream> +#if 0 using namespace Swift; class OFakeRemoteJingleTransportCandidateSelector : public RemoteJingleTransportCandidateSelector { @@ -87,16 +93,8 @@ public: class OFakeLocalJingleTransportCandidateGenerator : public LocalJingleTransportCandidateGenerator { public: - virtual void generateLocalTransportCandidates(JingleTransportPayload::ref /* payload */) { - //JingleTransportPayload::ref payL = make_shared<JingleTransportPayload>(); - //payL->setSessionID(payload->getSessionID()); - JingleS5BTransportPayload::ref payL = boost::make_shared<JingleS5BTransportPayload>(); - - onLocalTransportCandidatesGenerated(payL); - } - - void emitonLocalTransportCandidatesGenerated(JingleTransportPayload::ref payload) { - onLocalTransportCandidatesGenerated(payload); + void emitonLocalTransportCandidatesGenerated(const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { + onLocalTransportCandidatesGenerated(candidates); } virtual bool isActualCandidate(JingleTransportPayload::ref) { @@ -110,6 +108,16 @@ public: 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 { @@ -144,7 +152,7 @@ public: 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)); + 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) { @@ -154,6 +162,7 @@ public: } 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>(); @@ -164,7 +173,7 @@ public: timerFactory = new DummyTimerFactory(); connectionFactory = new DummyConnectionFactory(eventLoop); s5bRegistry = new SOCKS5BytestreamRegistry(); - s5bProxy = new SOCKS5BytestreamProxy(connectionFactory, timerFactory); + s5bProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory); data.clear(); for (int n=0; n < 1024 * 1024; ++n) { @@ -275,9 +284,11 @@ private: IDGenerator* idGen; EventLoop *eventLoop; SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamProxy* s5bProxy; + SOCKS5BytestreamProxiesManager* s5bProxy; DummyTimerFactory* timerFactory; DummyConnectionFactory* connectionFactory; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(OutgoingJingleFileTransferTest); +#endif diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp index 5fe096a..78ea8ed 100644 --- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp @@ -30,10 +30,12 @@ #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; -boost::mt19937 randomGen; +static boost::mt19937 randomGen; class SOCKS5BytestreamClientSessionTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(SOCKS5BytestreamClientSessionTest); @@ -44,15 +46,13 @@ class SOCKS5BytestreamClientSessionTest : public CppUnit::TestFixture { CPPUNIT_TEST(testReadBytestream); CPPUNIT_TEST_SUITE_END(); - const HostAddressPort destinationAddressPort; - const std::string destination; - public: - SOCKS5BytestreamClientSessionTest() : destinationAddressPort(HostAddressPort(HostAddress("127.0.0.1"), 8888)), - destination(SOCKS5BytestreamRegistry::getHostname("foo", JID("requester@example.com/test"), JID("target@example.com/test"))), eventLoop(NULL), timerFactory(NULL) { } + SOCKS5BytestreamClientSessionTest() : destinationAddressPort(HostAddressPort(HostAddress("127.0.0.1"), 8888)) {} void setUp() { - randomGen.seed(time(NULL)); + 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); @@ -82,7 +82,7 @@ public: serverRespondHelloOK(); eventLoop->processEvents(); CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); - CPPUNIT_ASSERT_EQUAL(createByteArray(destination.size()), createByteArray(helper.unprocessedInput[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)); @@ -128,7 +128,7 @@ public: serverRespondHelloOK(); eventLoop->processEvents(); CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); - CPPUNIT_ASSERT_EQUAL(createByteArray(destination.size()), createByteArray(helper.unprocessedInput[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)); @@ -205,7 +205,7 @@ private: boost::variate_generator<boost::mt19937&, boost::uniform_int<> > randomByte(randomGen, dist); ByteArray result(len); for (size_t i=0; i < len; ++i ) { - result[i] = randomByte(); + result[i] = static_cast<unsigned char>(randomByte()); } return result; } @@ -221,7 +221,7 @@ private: void serverRespondRequestOK() { boost::shared_ptr<SafeByteArray> dataToSend = createSafeByteArrayRef("\x05\x00\x00\x03", 4); - append(*dataToSend, createSafeByteArray(destination.size())); + append(*dataToSend, createSafeByteArray(static_cast<char>(destination.size()))); append(*dataToSend, createSafeByteArray(destination)); append(*dataToSend, createSafeByteArray("\x00", 1)); connection->onDataRead(dataToSend); @@ -229,7 +229,7 @@ private: void serverRespondRequestFail() { boost::shared_ptr<SafeByteArray> correctData = createSafeByteArrayRef("\x05\x00\x00\x03", 4); - append(*correctData, createSafeByteArray(destination.size())); + append(*correctData, createSafeByteArray(static_cast<char>(destination.size()))); append(*correctData, createSafeByteArray(destination)); append(*correctData, createSafeByteArray("\x00", 1)); @@ -297,10 +297,13 @@ private: }; 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; }; CPPUNIT_TEST_SUITE_REGISTRATION(SOCKS5BytestreamClientSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp index 6dec37f..7af546f 100644 --- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp @@ -72,11 +72,11 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture { void testRequest() { boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->addReadBytestream("abcdef", stream1); + bytestreams->setHasBytestream("abcdef", true); authenticate(); ByteArray hostname(createByteArray("abcdef")); - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(hostname.size()), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + 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)); } @@ -86,18 +86,18 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture { authenticate(); ByteArray hostname(createByteArray("abcdef")); - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(hostname.size()), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + 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->addReadBytestream("abcdef", stream1); + bytestreams->setHasBytestream("abcdef", true); authenticate(); request("abcdef"); eventLoop->processEvents(); - testling->startTransfer(); + testling->startSending(stream1); skipHeader("abcdef"); eventLoop->processEvents(); @@ -109,11 +109,11 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture { boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); testling->setChunkSize(3); StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->addReadBytestream("abcdef", stream1); + bytestreams->setHasBytestream("abcdef", true); authenticate(); request("abcdef"); eventLoop->processEvents(); - testling->startTransfer(); + testling->startSending(stream1); eventLoop->processEvents(); skipHeader("abcdef"); CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); @@ -125,11 +125,11 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture { testling->setChunkSize(3); stream1->setDataComplete(false); StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->addReadBytestream("abcdef", stream1); + bytestreams->setHasBytestream("abcdef", true); authenticate(); request("abcdef"); eventLoop->processEvents(); - testling->startTransfer(); + testling->startSending(stream1); eventLoop->processEvents(); skipHeader("abcdef"); CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); @@ -144,11 +144,11 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture { testling->setChunkSize(3); stream1->setDataComplete(false); StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->addReadBytestream("abcdef", stream1); + bytestreams->setHasBytestream("abcdef", true); authenticate(); request("abcdef"); eventLoop->processEvents(); - testling->startTransfer(); + testling->startSending(stream1); eventLoop->processEvents(); skipHeader("abcdef"); @@ -173,11 +173,11 @@ class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture { } void request(const std::string& hostname) { - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(hostname.size()), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + 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) { - int headerSize = 7 + hostname.size(); + size_t headerSize = 7 + hostname.size(); receivedData = createByteArray(&receivedData[headerSize], receivedData.size() - headerSize); } diff --git a/Swiften/History/HistoryStorage.h b/Swiften/History/HistoryStorage.h index fcf28b5..6d24d15 100644 --- a/Swiften/History/HistoryStorage.h +++ b/Swiften/History/HistoryStorage.h @@ -21,7 +21,7 @@ namespace Swift { * Messages are stored using localtime timestamps. */ public: - virtual ~HistoryStorage() {}; + 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; diff --git a/Swiften/History/SConscript b/Swiften/History/SConscript index 44b3cc4..ac3cf3b 100644 --- a/Swiften/History/SConscript +++ b/Swiften/History/SConscript @@ -3,7 +3,6 @@ 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_ASYNC", {})) if myenv["experimental"]: objects = myenv.SwiftenObject([ diff --git a/Swiften/History/SQLiteHistoryStorage.cpp b/Swiften/History/SQLiteHistoryStorage.cpp index 04bd00f..dda8766 100644 --- a/Swiften/History/SQLiteHistoryStorage.cpp +++ b/Swiften/History/SQLiteHistoryStorage.cpp @@ -1,16 +1,17 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <iostream> #include <boost/lexical_cast.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <sqlite3.h> -#include <3rdParty/SQLiteAsync/sqlite3async.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); @@ -25,14 +26,12 @@ inline std::string getEscapedString(const std::string& s) { namespace Swift { -SQLiteHistoryStorage::SQLiteHistoryStorage(const std::string& file) : db_(0) { - sqlite3async_initialize(NULL, false); - +SQLiteHistoryStorage::SQLiteHistoryStorage(const boost::filesystem::path& file) : db_(0) { thread_ = new boost::thread(boost::bind(&SQLiteHistoryStorage::run, this)); - sqlite3_open_v2(file.c_str(), &db_, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "sqlite3async"); + sqlite3_open(pathToString(file).c_str(), &db_); if (!db_) { - std::cerr << "Error opening database " << file << std::endl; + std::cerr << "Error opening database " << pathToString(file) << std::endl; } char* errorMessage; @@ -50,7 +49,6 @@ SQLiteHistoryStorage::SQLiteHistoryStorage(const std::string& file) : db_(0) { } SQLiteHistoryStorage::~SQLiteHistoryStorage() { - sqlite3async_shutdown(); sqlite3_close(db_); delete thread_; } @@ -78,8 +76,8 @@ void SQLiteHistoryStorage::addMessage(const HistoryMessage& message) { 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<int> selfID = getIDFromJID(selfJID.toBare()); - boost::optional<int> contactID = getIDFromJID(contactJID.toBare()); + boost::optional<long long> selfID = getIDFromJID(selfJID.toBare()); + boost::optional<long long> contactID = getIDFromJID(contactJID.toBare()); if (!selfID || !contactID) { // JIDs missing from the database @@ -111,7 +109,7 @@ std::vector<HistoryMessage> SQLiteHistoryStorage::getMessagesFromDate(const JID& " AND time<" + boost::lexical_cast<std::string>(upperBound) + ")"; } - int r = sqlite3_prepare(db_, selectQuery.c_str(), selectQuery.size(), &selectStatement, NULL); + 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; } @@ -157,8 +155,8 @@ std::vector<HistoryMessage> SQLiteHistoryStorage::getMessagesFromDate(const JID& return result; } -int SQLiteHistoryStorage::getIDForJID(const JID& jid) { - boost::optional<int> id = getIDFromJID(jid); +long long SQLiteHistoryStorage::getIDForJID(const JID& jid) { + boost::optional<long long> id = getIDFromJID(jid); if (id) { return *id; } @@ -167,7 +165,7 @@ int SQLiteHistoryStorage::getIDForJID(const JID& jid) { } } -int SQLiteHistoryStorage::addJID(const JID& 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); @@ -178,11 +176,11 @@ int SQLiteHistoryStorage::addJID(const JID& jid) { return sqlite3_last_insert_rowid(db_); } -boost::optional<JID> SQLiteHistoryStorage::getJIDFromID(int id) const { +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(), selectQuery.size(), &selectStatement, NULL); + 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; } @@ -194,17 +192,17 @@ boost::optional<JID> SQLiteHistoryStorage::getJIDFromID(int id) const { return result; } -boost::optional<int> SQLiteHistoryStorage::getIDFromJID(const JID& jid) const { - boost::optional<int> 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() + "'"); - int r = sqlite3_prepare(db_, selectQuery.c_str(), selectQuery.size(), &selectStatement, NULL); + 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<int>(sqlite3_column_int(selectStatement, 0)); + result = boost::optional<long long>(sqlite3_column_int(selectStatement, 0)); } sqlite3_finalize(selectStatement); return result; @@ -215,7 +213,7 @@ ContactsMap SQLiteHistoryStorage::getContacts(const JID& selfJID, HistoryMessage sqlite3_stmt* selectStatement; // get id - boost::optional<int> id = getIDFromJID(selfJID); + boost::optional<long long> id = getIDFromJID(selfJID); if (!id) { return result; } @@ -231,7 +229,7 @@ ContactsMap SQLiteHistoryStorage::getContacts(const JID& selfJID, HistoryMessage query += " AND message LIKE '%" + getEscapedString(keyword) + "%'"; } - int r = sqlite3_prepare(db_, query.c_str(), query.size(), &selectStatement, NULL); + 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; } @@ -280,8 +278,8 @@ ContactsMap SQLiteHistoryStorage::getContacts(const JID& selfJID, HistoryMessage 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<int> selfID = getIDFromJID(selfJID.toBare()); - boost::optional<int> contactID = getIDFromJID(contactJID.toBare()); + boost::optional<long long> selfID = getIDFromJID(selfJID.toBare()); + boost::optional<long long> contactID = getIDFromJID(contactJID.toBare()); if (!selfID || !contactID) { // JIDs missing from the database @@ -310,7 +308,7 @@ boost::gregorian::date SQLiteHistoryStorage::getNextDateWithLogs(const JID& self 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(), selectQuery.size(), &selectStatement, NULL); + 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; } @@ -347,8 +345,8 @@ std::vector<HistoryMessage> SQLiteHistoryStorage::getMessagesFromPreviousDate(co } boost::posix_time::ptime SQLiteHistoryStorage::getLastTimeStampFromMUC(const JID& selfJID, const JID& mucJID) const { - boost::optional<int> selfID = getIDFromJID(selfJID.toBare()); - boost::optional<int> 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 @@ -361,7 +359,7 @@ boost::posix_time::ptime SQLiteHistoryStorage::getLastTimeStampFromMUC(const JID 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(), selectQuery.size(), &selectStatement, NULL); + 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; } @@ -379,7 +377,6 @@ boost::posix_time::ptime SQLiteHistoryStorage::getLastTimeStampFromMUC(const JID } void SQLiteHistoryStorage::run() { - sqlite3async_run(); } } diff --git a/Swiften/History/SQLiteHistoryStorage.h b/Swiften/History/SQLiteHistoryStorage.h index 782334a..2c1ba7a 100644 --- a/Swiften/History/SQLiteHistoryStorage.h +++ b/Swiften/History/SQLiteHistoryStorage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -8,15 +8,17 @@ #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 SQLiteHistoryStorage : public HistoryStorage { + class SWIFTEN_API SQLiteHistoryStorage : public HistoryStorage { public: - SQLiteHistoryStorage(const std::string& file); + SQLiteHistoryStorage(const boost::filesystem::path& file); ~SQLiteHistoryStorage(); void addMessage(const HistoryMessage& message); @@ -29,11 +31,11 @@ namespace Swift { private: void run(); boost::gregorian::date getNextDateWithLogs(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date, bool reverseOrder) const; - int getIDForJID(const JID&); - int addJID(const JID&); + long long getIDForJID(const JID&); + long long addJID(const JID&); - boost::optional<JID> getJIDFromID(int id) const; - boost::optional<int> getIDFromJID(const JID& jid) const; + boost::optional<JID> getJIDFromID(long long id) const; + boost::optional<long long> getIDFromJID(const JID& jid) const; sqlite3* db_; boost::thread* thread_; diff --git a/Swiften/IDN/ICUConverter.cpp b/Swiften/IDN/ICUConverter.cpp new file mode 100644 index 0000000..18ff231 --- /dev/null +++ b/Swiften/IDN/ICUConverter.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012-2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/IDN/ICUConverter.h> + +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma clang diagnostic ignored "-Wheader-hygiene" +#include <unicode/uidna.h> +#include <unicode/usprep.h> +#include <unicode/ucnv.h> +#include <unicode/ustring.h> + + #include <boost/numeric/conversion/cast.hpp> + +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); + } +} + +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)); +} + +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))); +} + +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); +} + +} diff --git a/Swiften/IDN/ICUConverter.h b/Swiften/IDN/ICUConverter.h index c476b54..8ba9bb5 100644 --- a/Swiften/IDN/ICUConverter.h +++ b/Swiften/IDN/ICUConverter.h @@ -1,77 +1,22 @@ /* - * Copyright (c) 2012 Remko Tronçon + * Copyright (c) 2012-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once -#pragma GCC diagnostic ignored "-Wold-style-cast" - -#include <unicode/ustring.h> -#include <cassert> #include <string> -#include <vector> -#include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Base/API.h> +#include <Swiften/Base/Override.h> +#include <Swiften/IDN/IDNConverter.h> namespace Swift { - - class ICUConverter { + class SWIFTEN_API ICUConverter : public IDNConverter { public: - typedef std::vector<UChar, SafeAllocator<UChar> > ICUString; - - template<typename T> - ICUString convertToICUString(const T& s) { - ICUString result; - result.resize(s.size()); - UErrorCode status = U_ZERO_ERROR; - int icuResultLength = result.size(); - u_strFromUTF8Lenient(vecptr(result), result.size(), &icuResultLength, toConstCharArray(s), s.size(), &status); - if (status == U_BUFFER_OVERFLOW_ERROR) { - status = U_ZERO_ERROR; - result.resize(icuResultLength); - u_strFromUTF8Lenient(vecptr(result), result.size(), &icuResultLength, toConstCharArray(s), s.size(), &status); - } - if (U_FAILURE(status)) { - return ICUString(); - } - result.resize(icuResultLength); - return result; - } - - std::string convertToString(const ICUString& input) { - return std::string(vecptr(convertToArray(input))); - } + virtual std::string getStringPrepared(const std::string& s, StringPrepProfile profile) SWIFTEN_OVERRIDE; + virtual SafeByteArray getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) SWIFTEN_OVERRIDE; - std::vector<char, SafeAllocator<char> > convertToArray(const ICUString& input) { - std::vector<char, SafeAllocator<char> > result; - result.resize(input.size()); - UErrorCode status = U_ZERO_ERROR; - int inputLength = result.size(); - u_strToUTF8(vecptr(result), result.size(), &inputLength, vecptr(input), input.size(), &status); - if (status == U_BUFFER_OVERFLOW_ERROR) { - status = U_ZERO_ERROR; - result.resize(inputLength); - u_strToUTF8(vecptr(result), result.size(), &inputLength, vecptr(input), input.size(), &status); - } - if (U_FAILURE(status)) { - return std::vector<char, SafeAllocator<char> >(); - } - - result.resize(inputLength + 1); - result[result.size() - 1] = '\0'; - return result; - } - - private: - static const char* toConstCharArray(const std::string& input) { - return input.c_str(); - } - - static const char* toConstCharArray(const std::vector<unsigned char, SafeAllocator<unsigned char> >& input) { - return reinterpret_cast<const char*>(vecptr(input)); - } + virtual std::string getIDNAEncoded(const std::string& s) SWIFTEN_OVERRIDE; }; - } diff --git a/Swiften/IDN/IDNA.cpp b/Swiften/IDN/IDNA.cpp deleted file mode 100644 index f2ac8fb..0000000 --- a/Swiften/IDN/IDNA.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/IDN/IDNA.h> - -#include <vector> -#include <cstdlib> -#if defined(HAVE_ICU) -#pragma GCC diagnostic ignored "-Wold-style-cast" -#include <Swiften/IDN/ICUConverter.h> -#include <unicode/uidna.h> -#elif defined(HAVE_LIBIDN) -#include <stringprep.h> -#include <idna.h> -#endif -#include <Swiften/Base/ByteArray.h> -#include <boost/shared_ptr.hpp> - -namespace Swift { - -std::string IDNA::getEncoded(const std::string& domain) { -#if defined(HAVE_ICU) - UErrorCode status = U_ZERO_ERROR; - ICUConverter converter; - - ICUConverter::ICUString icuInput = converter.convertToICUString(domain); - ICUConverter::ICUString icuResult; - icuResult.resize(icuInput.size()); - UParseError parseError; - int icuResultLength = uidna_IDNToASCII(vecptr(icuInput), icuInput.size(), vecptr(icuResult), icuResult.size(), UIDNA_DEFAULT, &parseError, &status); - if (status == U_BUFFER_OVERFLOW_ERROR) { - status = U_ZERO_ERROR; - icuResult.resize(icuResultLength); - icuResultLength = uidna_IDNToASCII(vecptr(icuInput), icuInput.size(), vecptr(icuResult), icuResult.size(), UIDNA_DEFAULT, &parseError, &status); - } - if (U_FAILURE(status)) { - return domain; - } - icuResult.resize(icuResultLength); - - return converter.convertToString(icuResult); - -#elif defined(HAVE_LIBIDN) - - - 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; - } -#endif -} - -} diff --git a/Swiften/FileTransfer/JingleTransport.cpp b/Swiften/IDN/IDNConverter.cpp index c507922..7705812 100644 --- a/Swiften/FileTransfer/JingleTransport.cpp +++ b/Swiften/IDN/IDNConverter.cpp @@ -1,15 +1,14 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ -#include <Swiften/FileTransfer/JingleTransport.h> +#include <Swiften/IDN/IDNConverter.h> namespace Swift { -JingleTransport::~JingleTransport() { - +IDNConverter::~IDNConverter() { } } diff --git a/Swiften/IDN/IDNConverter.h b/Swiften/IDN/IDNConverter.h new file mode 100644 index 0000000..c55d969 --- /dev/null +++ b/Swiften/IDN/IDNConverter.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <string> +#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; + }; +} diff --git a/Swiften/IDN/LibIDNConverter.cpp b/Swiften/IDN/LibIDNConverter.cpp new file mode 100644 index 0000000..c4a1c18 --- /dev/null +++ b/Swiften/IDN/LibIDNConverter.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2012-2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/IDN/LibIDNConverter.h> + +extern "C" { + #include <stringprep.h> + #include <idna.h> +} + +#include <vector> +#include <cassert> +#include <cstdlib> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/SafeAllocator.h> +#include <boost/shared_ptr.hpp> + +using namespace Swift; + +namespace { + static const int 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 0; + } + + 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(); + } + } +} + +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)); +} + +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::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; + } +} + +} diff --git a/Swiften/IDN/LibIDNConverter.h b/Swiften/IDN/LibIDNConverter.h new file mode 100644 index 0000000..23f6bbd --- /dev/null +++ b/Swiften/IDN/LibIDNConverter.h @@ -0,0 +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. + */ + +#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; + + virtual std::string getIDNAEncoded(const std::string& s) SWIFTEN_OVERRIDE; + }; +} + diff --git a/Swiften/IDN/PlatformIDNConverter.cpp b/Swiften/IDN/PlatformIDNConverter.cpp new file mode 100644 index 0000000..6d9cff7 --- /dev/null +++ b/Swiften/IDN/PlatformIDNConverter.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/IDN/PlatformIDNConverter.h> +#if defined(HAVE_LIBIDN) +#include <Swiften/IDN/LibIDNConverter.h> +#elif defined(HAVE_ICU) +#include <Swiften/IDN/ICUConverter.h> +#endif + +namespace Swift { + +IDNConverter* PlatformIDNConverter::create() { +#if defined(HAVE_LIBIDN) + return new LibIDNConverter(); +#elif defined(HAVE_ICU) + return new ICUConverter(); +#else +#error "No IDN implementation" + return 0; +#endif +} + +} diff --git a/Swiften/IDN/PlatformIDNConverter.h b/Swiften/IDN/PlatformIDNConverter.h new file mode 100644 index 0000000..4b1025b --- /dev/null +++ b/Swiften/IDN/PlatformIDNConverter.h @@ -0,0 +1,17 @@ +/* + * 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> + +namespace Swift { + class IDNConverter; + + namespace PlatformIDNConverter { + SWIFTEN_API IDNConverter* create(); + } +} diff --git a/Swiften/IDN/SConscript b/Swiften/IDN/SConscript index 1433318..9d3b8f9 100644 --- a/Swiften/IDN/SConscript +++ b/Swiften/IDN/SConscript @@ -1,20 +1,26 @@ Import("swiften_env", "env") + +objects = swiften_env.SwiftenObject(["IDNConverter.cpp"]) + myenv = swiften_env.Clone() if myenv.get("HAVE_ICU") : myenv.MergeFlags(swiften_env["ICU_FLAGS"]) myenv.Append(CPPDEFINES = ["HAVE_ICU"]) -elif myenv.get("HAVE_LIBIDN") : + 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"]) -objects = myenv.SwiftenObject([ - "StringPrep.cpp", - "IDNA.cpp", - ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) -env.Append(UNITTEST_SOURCES = [ - File("UnitTest/StringPrepTest.cpp"), - File("UnitTest/IDNATest.cpp"), - ]) +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"), + ])) + + diff --git a/Swiften/IDN/StringPrep.cpp b/Swiften/IDN/StringPrep.cpp deleted file mode 100644 index dfaba06..0000000 --- a/Swiften/IDN/StringPrep.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/IDN/StringPrep.h> - -#if defined(HAVE_ICU) -#pragma GCC diagnostic ignored "-Wold-style-cast" -#include <Swiften/IDN/ICUConverter.h> -#include <unicode/usprep.h> -#include <unicode/ucnv.h> -#elif defined(HAVE_LIBIDN) -extern "C" { - #include <stringprep.h> -}; -#endif - -#include <vector> -#include <cassert> -#include <Swiften/Base/SafeAllocator.h> -#include <boost/shared_ptr.hpp> - -using namespace Swift; - -#if defined(HAVE_ICU) - -namespace { - static UStringPrepProfileType getICUProfileType(StringPrep::Profile profile) { - switch(profile) { - case StringPrep::NamePrep: return USPREP_RFC3491_NAMEPREP; break; - case StringPrep::XMPPNodePrep: return USPREP_RFC3920_NODEPREP; break; - case StringPrep::XMPPResourcePrep: return USPREP_RFC3920_RESOURCEPREP; break; - case StringPrep::SASLPrep: return USPREP_RFC4013_SASLPREP; break; - } - assert(false); - return USPREP_RFC3491_NAMEPREP; - } - - template<typename StringType> - std::vector<char, SafeAllocator<char> > getStringPrepared(const StringType& s, StringPrep::Profile profile) { - UErrorCode status = U_ZERO_ERROR; - ICUConverter converter; - - boost::shared_ptr<UStringPrepProfile> icuProfile(usprep_openByType(getICUProfileType(profile), &status), usprep_close); - assert(U_SUCCESS(status)); - - ICUConverter::ICUString icuInput = converter.convertToICUString(s); - ICUConverter::ICUString icuResult; - UParseError parseError; - icuResult.resize(icuInput.size()); - int icuResultLength = usprep_prepare(icuProfile.get(), vecptr(icuInput), icuInput.size(), vecptr(icuResult), icuResult.size(), USPREP_ALLOW_UNASSIGNED, &parseError, &status); icuResult.resize(icuResultLength); - if (status == U_BUFFER_OVERFLOW_ERROR) { - status = U_ZERO_ERROR; - icuResult.resize(icuResultLength); - icuResultLength = usprep_prepare(icuProfile.get(), vecptr(icuInput), icuInput.size(), vecptr(icuResult), icuResult.size(), USPREP_ALLOW_UNASSIGNED, &parseError, &status); icuResult.resize(icuResultLength); - } - if (U_FAILURE(status)) { - return std::vector<char, SafeAllocator<char> >(); - } - icuResult.resize(icuResultLength); - - return converter.convertToArray(icuResult); - } -} - -namespace Swift { - -std::string StringPrep::getPrepared(const std::string& s, Profile profile) { - if (s.empty()) { - return ""; - } - std::vector<char, SafeAllocator<char> > preparedData = getStringPrepared(s, profile); - if (preparedData.empty()) { - throw std::exception(); - } - return std::string(vecptr(preparedData)); -} - -SafeByteArray StringPrep::getPrepared(const SafeByteArray& s, Profile profile) { - if (s.empty()) { - return SafeByteArray(); - } - std::vector<char, SafeAllocator<char> > preparedData = getStringPrepared(s, profile); - if (preparedData.empty()) { - throw std::exception(); - } - return createSafeByteArray(reinterpret_cast<const char*>(vecptr(preparedData))); -} - -} - -//////////////////////////////////////////////////////////////////////////////// - -#elif defined(HAVE_LIBIDN) - -namespace { - static const int MAX_STRINGPREP_SIZE = 1024; - - const Stringprep_profile* getLibIDNProfile(StringPrep::Profile profile) { - switch(profile) { - case StringPrep::NamePrep: return stringprep_nameprep; break; - case StringPrep::XMPPNodePrep: return stringprep_xmpp_nodeprep; break; - case StringPrep::XMPPResourcePrep: return stringprep_xmpp_resourceprep; break; - case StringPrep::SASLPrep: return stringprep_saslprep; break; - } - assert(false); - return 0; - } - - template<typename StringType, typename ContainerType> - ContainerType getStringPrepared(const StringType& s, StringPrep::Profile 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(); - } - } -} - -namespace Swift { - -std::string StringPrep::getPrepared(const std::string& s, Profile profile) { - std::vector<char> preparedData = getStringPrepared< std::string, std::vector<char> >(s, profile); - if (preparedData.empty()) { - throw std::exception(); - } - return std::string(vecptr(preparedData)); -} - -SafeByteArray StringPrep::getPrepared(const SafeByteArray& s, Profile profile) { - std::vector<char, SafeAllocator<char> > preparedData = getStringPrepared<SafeByteArray, std::vector<char, SafeAllocator<char> > >(s, profile); - if (preparedData.empty()) { - throw std::exception(); - } - return createSafeByteArray(reinterpret_cast<const char*>(vecptr(preparedData))); -} - -} - -#endif - diff --git a/Swiften/IDN/StringPrep.h b/Swiften/IDN/StringPrep.h deleted file mode 100644 index 688600c..0000000 --- a/Swiften/IDN/StringPrep.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. - */ - -#pragma once - -#include <string> -#include <Swiften/Base/API.h> -#include <Swiften/Base/SafeByteArray.h> - -namespace Swift { - class SWIFTEN_API StringPrep { - public: - enum Profile { - NamePrep, - XMPPNodePrep, - XMPPResourcePrep, - SASLPrep, - }; - - static std::string getPrepared(const std::string& s, Profile profile); - static SafeByteArray getPrepared(const SafeByteArray& s, Profile profile); - }; -} diff --git a/Swiften/IDN/UnitTest/IDNATest.cpp b/Swiften/IDN/UnitTest/IDNATest.cpp deleted file mode 100644 index 09e79c8..0000000 --- a/Swiften/IDN/UnitTest/IDNATest.cpp +++ /dev/null @@ -1,35 +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 <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> - -#include <Swiften/IDN/IDNA.h> - -using namespace Swift; - -class IDNATest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IDNATest); - CPPUNIT_TEST(testGetEncoded); - CPPUNIT_TEST(testGetEncoded_International); - CPPUNIT_TEST_SUITE_END(); - - public: - void testGetEncoded() { - std::string result = IDNA::getEncoded("www.swift.im"); - - CPPUNIT_ASSERT_EQUAL(std::string("www.swift.im"), result); - } - - void testGetEncoded_International() { - std::string result = IDNA::getEncoded("www.tron\xc3\x87on.com"); - - CPPUNIT_ASSERT_EQUAL(std::string("www.xn--tronon-zua.com"), result); - } -}; - -CPPUNIT_TEST_SUITE_REGISTRATION(IDNATest); - diff --git a/Swiften/IDN/UnitTest/IDNConverterTest.cpp b/Swiften/IDN/UnitTest/IDNConverterTest.cpp new file mode 100644 index 0000000..285cf4b --- /dev/null +++ b/Swiften/IDN/UnitTest/IDNConverterTest.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <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(); + + public: + void setUp() { + testling = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); + } + + void testStringPrep() { + std::string result = testling->getStringPrepared("tron\xc3\x87on", IDNConverter::NamePrep); + + CPPUNIT_ASSERT_EQUAL(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)); + } + + void testGetEncoded() { + std::string result = testling->getIDNAEncoded("www.swift.im"); + CPPUNIT_ASSERT_EQUAL(std::string("www.swift.im"), result); + } + + void testGetEncoded_International() { + std::string result = testling->getIDNAEncoded("www.tron\xc3\x87on.com"); + CPPUNIT_ASSERT_EQUAL(std::string("www.xn--tronon-zua.com"), result); + } + + + private: + boost::shared_ptr<IDNConverter> testling; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(IDNConverterTest); diff --git a/Swiften/IDN/UnitTest/StringPrepTest.cpp b/Swiften/IDN/UnitTest/StringPrepTest.cpp deleted file mode 100644 index beab01e..0000000 --- a/Swiften/IDN/UnitTest/StringPrepTest.cpp +++ /dev/null @@ -1,34 +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 <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> - -#include "Swiften/IDN/StringPrep.h" - -using namespace Swift; - -class StringPrepTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StringPrepTest); - CPPUNIT_TEST(testStringPrep); - CPPUNIT_TEST(testStringPrep_Empty); - CPPUNIT_TEST_SUITE_END(); - - public: - void testStringPrep() { - std::string result = StringPrep::getPrepared("tron\xc3\x87on", StringPrep::NamePrep); - - CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), result); - } - - void testStringPrep_Empty() { - CPPUNIT_ASSERT_EQUAL(std::string(""), StringPrep::getPrepared("", StringPrep::NamePrep)); - CPPUNIT_ASSERT_EQUAL(std::string(""), StringPrep::getPrepared("", StringPrep::XMPPNodePrep)); - CPPUNIT_ASSERT_EQUAL(std::string(""), StringPrep::getPrepared("", StringPrep::XMPPResourcePrep)); - } -}; - -CPPUNIT_TEST_SUITE_REGISTRATION(StringPrepTest); diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp index f195f6f..0f2d8d1 100644 --- a/Swiften/JID/JID.cpp +++ b/Swiften/JID/JID.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -18,11 +18,17 @@ #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/StringPrep.h> +#include <Swiften/IDN/IDNConverter.h> +#ifndef SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER +#include <boost/shared_ptr.hpp> +#include <Swiften/IDN/PlatformIDNConverter.h> +#endif using namespace Swift; @@ -37,6 +43,19 @@ static PrepCache resourcePrepCache; static const std::list<char> escapedChars = boost::assign::list_of(' ')('"')('&')('\'')('/')('<')('>')('@')(':'); +static IDNConverter* idnConverter = NULL; + +#ifndef SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER +namespace { + struct IDNInitializer { + IDNInitializer() : defaultIDNConverter(PlatformIDNConverter::create()) { + idnConverter = defaultIDNConverter.get(); + } + boost::shared_ptr<IDNConverter> defaultIDNConverter; + } initializer; +} +#endif + static std::string getEscaped(char c) { return makeString() << '\\' << std::hex << static_cast<int>(c); } @@ -111,6 +130,8 @@ struct EscapedCharacterFormatter { }; #endif +namespace Swift { + JID::JID(const char* jid) : valid_(true) { assert(jid); initializeFromString(std::string(jid)); @@ -160,42 +181,58 @@ void JID::nameprepAndSetComponents(const std::string& node, const std::string& d valid_ = false; return; } - try { #ifndef SWIFTEN_CACHE_JID_PREP - node_ = StringPrep::getPrepared(node, StringPrep::NamePrep); - domain_ = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep); - resource_ = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep); + 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); + boost::mutex::scoped_lock lock(namePrepCacheMutex); - std::pair<PrepCache::iterator, bool> r; + std::pair<PrepCache::iterator, bool> r; - r = nodePrepCache.insert(std::make_pair(node, std::string())); - if (r.second) { - r.first->second = StringPrep::getPrepared(node, StringPrep::NamePrep); + r = nodePrepCache.insert(std::make_pair(node, std::string())); + if (r.second) { + try { + r.first->second = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); } - node_ = r.first->second; - - r = domainPrepCache.insert(std::make_pair(domain, std::string())); - if (r.second) { - r.first->second = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep); + catch (...) { + nodePrepCache.erase(r.first); + valid_ = false; + return; } - domain_ = r.first->second; + } + node_ = r.first->second; - r = resourcePrepCache.insert(std::make_pair(resource, std::string())); - if (r.second) { - r.first->second = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep); + r = domainPrepCache.insert(std::make_pair(domain, std::string())); + if (r.second) { + try { + r.first->second = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep); } - resource_ = r.first->second; -#endif + catch (...) { + domainPrepCache.erase(r.first); + valid_ = false; + return; + } + } + domain_ = r.first->second; - if (domain_.empty()) { + 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; } } - catch (const std::exception&) { + resource_ = r.first->second; +#endif + + if (domain_.empty()) { valid_ = false; + return; } } @@ -271,3 +308,19 @@ std::string JID::getUnescapedNode() const { return result; //return boost::find_format_all_copy(node_, EscapedCharacterFinder(), EscapedCharacterFormatter()); } + +void JID::setIDNConverter(IDNConverter* converter) { + idnConverter = converter; +} + +std::ostream& operator<<(std::ostream& os, const JID& j) { + os << j.toString(); + return os; +} + +boost::optional<JID> JID::parse(const std::string& s) { + JID jid(s); + return jid.isValid() ? jid : boost::optional<JID>(); +} + +} diff --git a/Swiften/JID/JID.h b/Swiften/JID/JID.h index 779610b..126a7b1 100644 --- a/Swiften/JID/JID.h +++ b/Swiften/JID/JID.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,12 +7,14 @@ #pragma once #include <string> -//#include <iosfwd> -#include <iostream> +#include <iosfwd> #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 ). @@ -148,10 +150,7 @@ namespace Swift { return compare(b, Swift::JID::WithResource) < 0; } - friend std::ostream& operator<<(std::ostream& os, const Swift::JID& j) { - os << j.toString(); - return os; - } + 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; @@ -161,6 +160,19 @@ namespace Swift { 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&); @@ -172,4 +184,7 @@ namespace Swift { bool hasResource_; std::string resource_; }; + + SWIFTEN_API std::ostream& operator<<(std::ostream& os, const Swift::JID& j); } + diff --git a/Swiften/JID/UnitTest/JIDTest.cpp b/Swiften/JID/UnitTest/JIDTest.cpp index 81d24ea..72ca884 100644 --- a/Swiften/JID/UnitTest/JIDTest.cpp +++ b/Swiften/JID/UnitTest/JIDTest.cpp @@ -24,6 +24,7 @@ class JIDTest : public CppUnit::TestFixture 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); @@ -137,6 +138,11 @@ class JIDTest : public CppUnit::TestFixture 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"); diff --git a/Swiften/Jingle/AbstractJingleSessionListener.cpp b/Swiften/Jingle/AbstractJingleSessionListener.cpp new file mode 100644 index 0000000..eaa1a47 --- /dev/null +++ b/Swiften/Jingle/AbstractJingleSessionListener.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Jingle/AbstractJingleSessionListener.h> + +#include <Swiften/Base/Log.h> + +using namespace Swift; + +void AbstractJingleSessionListener::handleSessionAcceptReceived(const JingleContentID&, boost::shared_ptr<JingleDescription>, boost::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(warning) << "Unimplemented" << std::endl; +} + +void AbstractJingleSessionListener::handleSessionInfoReceived(boost::shared_ptr<JinglePayload>) { + SWIFT_LOG(warning) << "Unimplemented" << std::endl; +} + +void AbstractJingleSessionListener::handleSessionTerminateReceived(boost::optional<JinglePayload::Reason>) { + SWIFT_LOG(warning) << "Unimplemented" << std::endl; +} + +void AbstractJingleSessionListener::handleTransportAcceptReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(warning) << "Unimplemented" << std::endl; +} + +void AbstractJingleSessionListener::handleTransportInfoReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(warning) << "Unimplemented" << std::endl; +} + +void AbstractJingleSessionListener::handleTransportRejectReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(warning) << "Unimplemented" << std::endl; +} + +void AbstractJingleSessionListener::handleTransportReplaceReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(warning) << "Unimplemented" << std::endl; +} + +void AbstractJingleSessionListener::handleTransportInfoAcknowledged(const std::string&) { +} diff --git a/Swiften/Jingle/AbstractJingleSessionListener.h b/Swiften/Jingle/AbstractJingleSessionListener.h new file mode 100644 index 0000000..4f76675 --- /dev/null +++ b/Swiften/Jingle/AbstractJingleSessionListener.h @@ -0,0 +1,26 @@ +/* + * 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> +#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; + }; +} + diff --git a/Swiften/Jingle/FakeJingleSession.cpp b/Swiften/Jingle/FakeJingleSession.cpp index 82ec631..1df106a 100644 --- a/Swiften/Jingle/FakeJingleSession.cpp +++ b/Swiften/Jingle/FakeJingleSession.cpp @@ -33,8 +33,9 @@ void FakeJingleSession::sendAccept(const JingleContentID& id, JingleDescription: calledCommands.push_back(AcceptCall(id, desc, payload)); } -void FakeJingleSession::sendTransportInfo(const JingleContentID& id, JingleTransportPayload::ref payload) { +std::string FakeJingleSession::sendTransportInfo(const JingleContentID& id, JingleTransportPayload::ref payload) { calledCommands.push_back(InfoTransportCall(id, payload)); + return idGenerator.generateID(); } void FakeJingleSession::sendTransportAccept(const JingleContentID& id, JingleTransportPayload::ref payload) { diff --git a/Swiften/Jingle/FakeJingleSession.h b/Swiften/Jingle/FakeJingleSession.h index ec5cb09..651ac5f 100644 --- a/Swiften/Jingle/FakeJingleSession.h +++ b/Swiften/Jingle/FakeJingleSession.h @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #pragma once #include <boost/shared_ptr.hpp> @@ -12,7 +18,9 @@ #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> @@ -79,16 +87,17 @@ namespace Swift { FakeJingleSession(const JID& initiator, const std::string& id); virtual ~FakeJingleSession(); - 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 = JingleTransportPayload::ref()); - virtual void 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); + 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; }; } diff --git a/Swiften/Jingle/JingleSession.cpp b/Swiften/Jingle/JingleSession.cpp index eb649f3..7e09014 100644 --- a/Swiften/Jingle/JingleSession.cpp +++ b/Swiften/Jingle/JingleSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,8 +7,12 @@ #include <Swiften/Jingle/JingleSession.h> #include <boost/smart_ptr/make_shared.hpp> +#include <algorithm> +#include <boost/function.hpp> -namespace Swift { +#include <Swiften/Base/foreach.h> + +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 @@ -18,5 +22,3 @@ JingleSession::JingleSession(const JID& initiator, const std::string& id) : init JingleSession::~JingleSession() { } - -} diff --git a/Swiften/Jingle/JingleSession.h b/Swiften/Jingle/JingleSession.h index 150ad79..8307311 100644 --- a/Swiften/Jingle/JingleSession.h +++ b/Swiften/Jingle/JingleSession.h @@ -1,24 +1,26 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once +#include <string> +#include <vector> #include <boost/shared_ptr.hpp> #include <boost/optional.hpp> -#include <string> - +#include <Swiften/Base/Listenable.h> #include <Swiften/Base/boost_bsignals.h> #include <Swiften/JID/JID.h> #include <Swiften/Elements/JinglePayload.h> namespace Swift { + class JingleSessionListener; class JingleContentID; - class JingleSession { + class JingleSession : public Listenable<JingleSessionListener> { public: typedef boost::shared_ptr<JingleSession> ref; @@ -32,26 +34,19 @@ namespace Swift { 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 void sendTransportInfo(const JingleContentID&, 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; - public: - boost::signal<void (const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref)> onSessionAcceptReceived; - boost::signal<void (JinglePayload::ref)> onSessionInfoReceived; - boost::signal<void (boost::optional<JinglePayload::Reason>)> onSessionTerminateReceived; - boost::signal<void (const JingleContentID&, JingleTransportPayload::ref)> onTransportAcceptReceived; - boost::signal<void (const JingleContentID&, JingleTransportPayload::ref)> onTransportInfoReceived; - boost::signal<void (const JingleContentID&, JingleTransportPayload::ref)> onTransportRejectReceived; - boost::signal<void (const JingleContentID&, JingleTransportPayload::ref)> onTransportReplaceReceived; - private: JID initiator; std::string id; + std::vector<JingleSessionListener*> listeners; }; } diff --git a/Swiften/Jingle/JingleSessionImpl.cpp b/Swiften/Jingle/JingleSessionImpl.cpp index 98c5196..ff22d11 100644 --- a/Swiften/Jingle/JingleSessionImpl.cpp +++ b/Swiften/Jingle/JingleSessionImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,17 +7,19 @@ #include <Swiften/Jingle/JingleSessionImpl.h> #include <boost/smart_ptr/make_shared.hpp> +#include <boost/bind.hpp> +#include <algorithm> #include <Swiften/Parser/PayloadParsers/JingleParser.h> #include <Swiften/Jingle/JingleContentID.h> +#include <Swiften/Jingle/JingleSessionListener.h> #include <Swiften/Elements/JingleContentPayload.h> #include <Swiften/Queries/Request.h> #include <Swiften/Queries/GenericRequest.h> #include <Swiften/Base/Log.h> -#include "Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h" -#include "Swiften/FileTransfer/JingleTransport.h" +#include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h> namespace Swift { @@ -27,11 +29,11 @@ JingleSessionImpl::JingleSessionImpl(const JID& initiator, const JID& peerJID, c void JingleSessionImpl::handleIncomingAction(JinglePayload::ref action) { if (action->getAction() == JinglePayload::SessionTerminate) { - onSessionTerminateReceived(action->getReason()); + notifyListeners(&JingleSessionListener::handleSessionTerminateReceived, action->getReason()); return; } if (action->getAction() == JinglePayload::SessionInfo) { - onSessionInfoReceived(action); + notifyListeners(&JingleSessionListener::handleSessionInfoReceived, action); return; } @@ -45,19 +47,19 @@ void JingleSessionImpl::handleIncomingAction(JinglePayload::ref action) { JingleTransportPayload::ref transport = content->getTransports().empty() ? JingleTransportPayload::ref() : content->getTransports()[0]; switch(action->getAction()) { case JinglePayload::SessionAccept: - onSessionAcceptReceived(contentID, description, transport); + notifyListeners(&JingleSessionListener::handleSessionAcceptReceived, contentID, description, transport); return; case JinglePayload::TransportAccept: - onTransportAcceptReceived(contentID, transport); + notifyListeners(&JingleSessionListener::handleTransportAcceptReceived, contentID, transport); return; case JinglePayload::TransportInfo: - onTransportInfoReceived(contentID, transport); + notifyListeners(&JingleSessionListener::handleTransportInfoReceived, contentID, transport); return; case JinglePayload::TransportReject: - onTransportRejectReceived(contentID, transport); + notifyListeners(&JingleSessionListener::handleTransportRejectReceived, contentID, transport); return; case JinglePayload::TransportReplace: - onTransportReplaceReceived(contentID, transport); + notifyListeners(&JingleSessionListener::handleTransportReplaceReceived, contentID, transport); return; // following unused Jingle actions case JinglePayload::ContentAccept: @@ -76,7 +78,7 @@ void JingleSessionImpl::handleIncomingAction(JinglePayload::ref action) { case JinglePayload::UnknownAction: return; } - std::cerr << "Unhandled Jingle action!!! ACTION: " << action->getAction() << std::endl; + assert(false); } void JingleSessionImpl::sendInitiate(const JingleContentID& id, JingleDescription::ref description, JingleTransportPayload::ref transport) { @@ -136,7 +138,7 @@ void JingleSessionImpl::sendTransportAccept(const JingleContentID& id, JingleTra sendSetRequest(payload); } -void JingleSessionImpl::sendTransportInfo(const JingleContentID& id, JingleTransportPayload::ref transPayload) { +std::string JingleSessionImpl::sendTransportInfo(const JingleContentID& id, JingleTransportPayload::ref transPayload) { JinglePayload::ref payload = createPayload(); JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); @@ -146,7 +148,7 @@ void JingleSessionImpl::sendTransportInfo(const JingleContentID& id, JingleTrans payload->setAction(JinglePayload::TransportInfo); payload->addPayload(content); - sendSetRequest(payload); + return sendSetRequest(payload); } void JingleSessionImpl::sendTransportReject(const JingleContentID& /* id */, JingleTransportPayload::ref /* transPayload */) { @@ -167,9 +169,13 @@ void JingleSessionImpl::sendTransportReplace(const JingleContentID& id, JingleTr } -void JingleSessionImpl::sendSetRequest(JinglePayload::ref payload) { - boost::shared_ptr<GenericRequest<JinglePayload> > request = boost::make_shared<GenericRequest<JinglePayload> >(IQ::Set, peerJID, payload, iqRouter); - request->send(); +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(); } @@ -180,6 +186,15 @@ JinglePayload::ref JingleSessionImpl::createPayload() const { 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); +} } diff --git a/Swiften/Jingle/JingleSessionImpl.h b/Swiften/Jingle/JingleSessionImpl.h index 3c1559a..b7f4a55 100644 --- a/Swiften/Jingle/JingleSessionImpl.h +++ b/Swiften/Jingle/JingleSessionImpl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,11 +7,14 @@ #pragma once #include <boost/shared_ptr.hpp> +#include <map> #include <Swiften/Jingle/JingleSession.h> +#include <Swiften/Queries/GenericRequest.h> namespace Swift { class IQRouter; + class Request; class JingleSessionImpl : public JingleSession { friend class JingleResponder; @@ -24,19 +27,24 @@ namespace Swift { virtual void sendTerminate(JinglePayload::Reason::Type reason); virtual void sendInfo(boost::shared_ptr<Payload>); virtual void sendAccept(const JingleContentID&, JingleDescription::ref, JingleTransportPayload::ref); - virtual void sendTransportInfo(const JingleContentID&, 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); - void sendSetRequest(JinglePayload::ref payload); + 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; }; } diff --git a/Swiften/Jingle/JingleSessionListener.cpp b/Swiften/Jingle/JingleSessionListener.cpp new file mode 100644 index 0000000..75d3be9 --- /dev/null +++ b/Swiften/Jingle/JingleSessionListener.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Jingle/JingleSessionListener.h> + +using namespace Swift; + +JingleSessionListener::~JingleSessionListener() { +} diff --git a/Swiften/Jingle/JingleSessionListener.h b/Swiften/Jingle/JingleSessionListener.h new file mode 100644 index 0000000..e1270c4 --- /dev/null +++ b/Swiften/Jingle/JingleSessionListener.h @@ -0,0 +1,40 @@ +/* + * 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> +#include <Swiften/Elements/JinglePayload.h> + +namespace Swift { + class JingleContentID; + class JingleTransportPayload; + class JingleDescription; + + 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 handleTransportInfoAcknowledged(const std::string& id) = 0; + }; +} diff --git a/Swiften/Jingle/JingleSessionManager.cpp b/Swiften/Jingle/JingleSessionManager.cpp index 2e15fcd..f31ddb8 100644 --- a/Swiften/Jingle/JingleSessionManager.cpp +++ b/Swiften/Jingle/JingleSessionManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #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> diff --git a/Swiften/Jingle/SConscript b/Swiften/Jingle/SConscript index 5dcf293..546c1b2 100644 --- a/Swiften/Jingle/SConscript +++ b/Swiften/Jingle/SConscript @@ -2,6 +2,8 @@ Import("swiften_env") sources = [ "JingleSession.cpp", + "JingleSessionListener.cpp", + "AbstractJingleSessionListener.cpp", "JingleSessionImpl.cpp", "IncomingJingleSessionHandler.cpp", "JingleSessionManager.cpp", diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h index 6e79290..52d6654 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -9,6 +9,7 @@ #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; @@ -48,7 +49,7 @@ namespace Swift { } else { //std::cout << "Discovered service: name:" << name << " domain:" << domain << " type: " << type << std::endl; - DNSSDServiceID service(name, domain, type, interfaceIndex); + DNSSDServiceID service(name, domain, type, boost::numeric_cast<int>(interfaceIndex)); if (flags & kDNSServiceFlagsAdd) { eventLoop->postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this()); } diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h index d3c9488..1bec5f7 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h @@ -10,6 +10,7 @@ #include <Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/EventLoop/EventLoop.h> +#include <boost/numeric/conversion/cast.hpp> namespace Swift { class BonjourQuerier; @@ -18,8 +19,8 @@ namespace Swift { 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, port, - txtRecord.size(), vecptr(txtRecord), + &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; @@ -41,7 +42,7 @@ namespace Swift { void updateServiceInfo(const ByteArray& txtRecord) { boost::lock_guard<boost::mutex> lock(sdRefMutex); - DNSServiceUpdateRecord(sdRef, NULL, 0, txtRecord.size(), vecptr(txtRecord), 0); + DNSServiceUpdateRecord(sdRef, NULL, 0, boost::numeric_cast<unsigned short>(txtRecord.size()), vecptr(txtRecord), 0); } private: diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h index 9fdd3d5..59d1af5 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -13,6 +13,7 @@ #include <Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h> #include <Swiften/EventLoop/EventLoop.h> #include <Swiften/Network/HostAddress.h> +#include <boost/numeric/conversion/cast.hpp> #include <netinet/in.h> @@ -23,7 +24,7 @@ namespace Swift { public: BonjourResolveHostnameQuery(const std::string& hostname, int interfaceIndex, boost::shared_ptr<BonjourQuerier> querier, EventLoop* eventLoop) : BonjourQuery(querier, eventLoop) { DNSServiceErrorType result = DNSServiceGetAddrInfo( - &sdRef, 0, interfaceIndex, kDNSServiceProtocol_IPv4, + &sdRef, 0, boost::numeric_cast<unsigned int>(interfaceIndex), kDNSServiceProtocol_IPv4, hostname.c_str(), &BonjourResolveHostnameQuery::handleHostnameResolvedStatic, this); if (result != kDNSServiceErr_NoError) { diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h index 1fb050c..2eeac64 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -19,7 +19,7 @@ namespace Swift { public: BonjourResolveServiceQuery(const DNSSDServiceID& service, boost::shared_ptr<BonjourQuerier> querier, EventLoop* eventLoop) : BonjourQuery(querier, eventLoop) { DNSServiceErrorType result = DNSServiceResolve( - &sdRef, 0, service.getNetworkInterfaceID(), + &sdRef, 0, boost::numeric_cast<unsigned int>(service.getNetworkInterfaceID()), service.getName().c_str(), service.getType().c_str(), service.getDomain().c_str(), &BonjourResolveServiceQuery::handleServiceResolvedStatic, this); diff --git a/Swiften/LinkLocal/LinkLocalServiceInfo.cpp b/Swiften/LinkLocal/LinkLocalServiceInfo.cpp index 516d303..7e18315 100644 --- a/Swiften/LinkLocal/LinkLocalServiceInfo.cpp +++ b/Swiften/LinkLocal/LinkLocalServiceInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #include <Swiften/LinkLocal/LinkLocalServiceInfo.h> #include <boost/lexical_cast.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/Concat.h> @@ -49,7 +50,7 @@ ByteArray LinkLocalServiceInfo::toTXTRecord() const { ByteArray LinkLocalServiceInfo::getEncoded(const std::string& s) { ByteArray sizeByte; sizeByte.resize(1); - sizeByte[0] = s.size(); + sizeByte[0] = boost::numeric_cast<unsigned char>(s.size()); return concat(sizeByte, createByteArray(s)); } @@ -109,11 +110,11 @@ std::pair<std::string,std::string> LinkLocalServiceInfo::readEntry(const ByteArr inKey = false; } else { - key += record[i]; + key += static_cast<char>(record[i]); } } else { - value += record[i]; + value += static_cast<char>(record[i]); } ++i; } diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp index a52f552..f85cf8d 100644 --- a/Swiften/MUC/MUC.cpp +++ b/Swiften/MUC/MUC.cpp @@ -29,7 +29,7 @@ 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) { +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)); } @@ -58,6 +58,10 @@ void MUC::joinWithContextSince(const std::string &nick, const boost::posix_time: internalJoin(nick); } +std::map<std::string, MUCOccupant> MUC::getOccupants() const { + return occupants; +} + void MUC::internalJoin(const std::string &nick) { //TODO: history request joinComplete_ = false; @@ -97,6 +101,7 @@ void MUC::handleUserLeft(LeavingType type) { occupants.clear(); joinComplete_ = false; joinSucceeded_ = false; + isUnlocked_ = false; presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence); } @@ -170,8 +175,9 @@ void MUC::handleIncomingPresence(Presence::ref presence) { std::map<std::string,MUCOccupant>::iterator i = occupants.find(nick); if (i != occupants.end()) { //TODO: part type - onOccupantLeft(i->second, type, ""); + MUCOccupant occupant = i->second; occupants.erase(i); + onOccupantLeft(occupant, type, ""); } } } @@ -200,6 +206,7 @@ void MUC::handleIncomingPresence(Presence::ref presence) { 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. */ @@ -212,6 +219,7 @@ void MUC::handleIncomingPresence(Presence::ref presence) { 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()) { @@ -233,6 +241,10 @@ void MUC::handleIncomingPresence(Presence::ref presence) { } } } + if (!isLocked && !isUnlocked_ && (presence->getFrom() == ownMUCJID)) { + isUnlocked_ = true; + onUnlocked(); + } } } @@ -243,6 +255,8 @@ void MUC::handleCreationConfigResponse(MUCOwnerPayload::ref /*unused*/, ErrorPay onJoinFailed(error); } else { onJoinComplete(getOwnNick()); /* Previously, this wasn't needed here, as the presence duplication bug caused an emit elsewhere. */ + isUnlocked_ = true; + onUnlocked(); } } @@ -386,13 +400,15 @@ void MUC::destroyRoom() { request->send(); } -void MUC::invitePerson(const JID& person, const std::string& reason) { +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); } diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h index 85f4564..6a0ab75 100644 --- a/Swiften/MUC/MUC.h +++ b/Swiften/MUC/MUC.h @@ -45,11 +45,20 @@ namespace Swift { return ownMUCJID.toBare(); } + /** + * 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_; + } + 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 */ @@ -67,7 +76,7 @@ namespace Swift { void cancelConfigureRoom(); void destroyRoom(); /** Send an invite for the person to join the MUC */ - void invitePerson(const JID& person, const std::string& reason = ""); + 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); @@ -85,6 +94,7 @@ namespace Swift { 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; */ @@ -121,6 +131,7 @@ namespace Swift { boost::posix_time::ptime joinSince_; bool createAsReservedIfNew; bool unlocking; + bool isUnlocked_; boost::optional<std::string> password; }; } diff --git a/Swiften/Network/BOSHConnection.cpp b/Swiften/Network/BOSHConnection.cpp index 377373d..23772eb 100644 --- a/Swiften/Network/BOSHConnection.cpp +++ b/Swiften/Network/BOSHConnection.cpp @@ -110,7 +110,7 @@ std::pair<SafeByteArray, size_t> BOSHConnection::createHTTPRequest(const SafeByt header << ":" << *boshURL.getPort(); } header << "\r\n" - /*<< "Accept-Encoding: deflate\r\n"*/ + // << "Accept-Encoding: deflate\r\n" << "Content-Type: text/xml; charset=utf-8\r\n" << "Content-Length: " << size << "\r\n\r\n"; @@ -156,7 +156,7 @@ void BOSHConnection::startStream(const std::string& to, unsigned long long rid) << " rid='" << rid << "'" << " ver='1.6'" << " wait='60'" /* FIXME: we probably want this configurable*/ - /*<< " ack='0'" FIXME: support acks */ + // << " ack='0'" FIXME: support acks << " xml:lang='en'" << " xmlns:xmpp='urn:xmpp:bosh'" << " xmpp:version='1.0'" @@ -170,7 +170,7 @@ void BOSHConnection::startStream(const std::string& to, unsigned long long rid) header << ":" << *boshURL_.getPort(); } header << "\r\n" - /*<< "Accept-Encoding: deflate\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; @@ -208,7 +208,7 @@ void BOSHConnection::handleDataRead(boost::shared_ptr<SafeByteArray> data) { waitingForStartResponse_ = false; sid_ = parser.getBody()->attributes.getAttribute("sid"); std::string requestsString = parser.getBody()->attributes.getAttribute("requests"); - int requests = 2; + size_t requests = 2; if (!requestsString.empty()) { try { requests = boost::lexical_cast<size_t>(requestsString); diff --git a/Swiften/Network/BOSHConnectionPool.cpp b/Swiften/Network/BOSHConnectionPool.cpp index e535deb..4517ffb 100644 --- a/Swiften/Network/BOSHConnectionPool.cpp +++ b/Swiften/Network/BOSHConnectionPool.cpp @@ -210,14 +210,14 @@ void BOSHConnectionPool::handleHTTPError(const std::string& /*errorCode*/) { handleSessionTerminated(boost::make_shared<BOSHError>(BOSHError::UndefinedCondition)); } -void BOSHConnectionPool::handleConnectionDisconnected(bool error, BOSHConnection::ref connection) { +void BOSHConnectionPool::handleConnectionDisconnected(bool/* error*/, BOSHConnection::ref connection) { destroyConnection(connection); if (pendingTerminate && sid.empty() && connections.empty()) { handleSessionTerminated(BOSHError::ref()); } - else if (false && error) { - handleSessionTerminated(boost::make_shared<BOSHError>(BOSHError::UndefinedCondition)); - } + //else if (error) { + // handleSessionTerminated(boost::make_shared<BOSHError>(BOSHError::UndefinedCondition)); + //} else { /* We might have just freed up a connection slot to send with */ tryToSendQueuedData(); diff --git a/Swiften/Network/BoostConnection.cpp b/Swiften/Network/BoostConnection.cpp index 1d4bd32..5137c3c 100644 --- a/Swiften/Network/BoostConnection.cpp +++ b/Swiften/Network/BoostConnection.cpp @@ -14,6 +14,7 @@ #include <boost/asio/placeholders.hpp> #include <boost/asio/write.hpp> #include <boost/smart_ptr/make_shared.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/Log.h> #include <Swiften/Base/Algorithm.h> @@ -63,7 +64,7 @@ void BoostConnection::listen() { void BoostConnection::connect(const HostAddressPort& addressPort) { boost::asio::ip::tcp::endpoint endpoint( - boost::asio::ip::address::from_string(addressPort.getAddress().toString()), addressPort.getPort()); + 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)); diff --git a/Swiften/Network/BoostConnectionServer.cpp b/Swiften/Network/BoostConnectionServer.cpp index eccffc6..c90b554 100644 --- a/Swiften/Network/BoostConnectionServer.cpp +++ b/Swiften/Network/BoostConnectionServer.cpp @@ -9,6 +9,8 @@ #include <boost/bind.hpp> #include <boost/system/system_error.hpp> #include <boost/asio/placeholders.hpp> +#include <boost/numeric/conversion/cast.hpp> +#include <boost/optional.hpp> #include <Swiften/EventLoop/EventLoop.h> @@ -21,28 +23,36 @@ BoostConnectionServer::BoostConnectionServer(const HostAddress &address, int por } void BoostConnectionServer::start() { + 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(), port_)); + 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(), port_)); + 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) { - eventLoop->postEvent(boost::bind(boost::ref(onStopped), Conflict), shared_from_this()); + return Conflict; } else { - eventLoop->postEvent(boost::bind(boost::ref(onStopped), UnknownError), shared_from_this()); + return UnknownError; } } + return boost::optional<Error>(); } diff --git a/Swiften/Network/BoostConnectionServer.h b/Swiften/Network/BoostConnectionServer.h index 66af2a4..3ad0450 100644 --- a/Swiften/Network/BoostConnectionServer.h +++ b/Swiften/Network/BoostConnectionServer.h @@ -16,17 +16,13 @@ #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; - enum Error { - Conflict, - UnknownError - }; - static ref create(int port, boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) { return ref(new BoostConnectionServer(port, ioService, eventLoop)); } @@ -35,6 +31,7 @@ namespace Swift { 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(); diff --git a/Swiften/Network/BoostNetworkFactories.cpp b/Swiften/Network/BoostNetworkFactories.cpp index 488e519..72e826a 100644 --- a/Swiften/Network/BoostNetworkFactories.cpp +++ b/Swiften/Network/BoostNetworkFactories.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,38 +7,60 @@ #include <Swiften/Network/BoostNetworkFactories.h> #include <Swiften/Network/BoostTimerFactory.h> #include <Swiften/Network/BoostConnectionFactory.h> -#include <Swiften/Network/PlatformDomainNameResolver.h> + #include <Swiften/Network/BoostConnectionServerFactory.h> #include <Swiften/Network/PlatformNATTraversalWorker.h> #include <Swiften/Parser/PlatformXMLParserFactory.h> #include <Swiften/Network/NullNATTraverser.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> + +#ifdef USE_UNBOUND +#include <Swiften/Network/UnboundDomainNameResolver.h> +#else +#include <Swiften/Network/PlatformDomainNameResolver.h> +#endif namespace Swift { BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop) : eventLoop(eventLoop){ timerFactory = new BoostTimerFactory(ioServiceThread.getIOService(), eventLoop); connectionFactory = new BoostConnectionFactory(ioServiceThread.getIOService(), eventLoop); - domainNameResolver = new PlatformDomainNameResolver(eventLoop); connectionServerFactory = new BoostConnectionServerFactory(ioServiceThread.getIOService(), eventLoop); #ifdef SWIFT_EXPERIMENTAL_FT natTraverser = new PlatformNATTraversalWorker(eventLoop); #else natTraverser = new NullNATTraverser(eventLoop); #endif + 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); +#else + domainNameResolver = new PlatformDomainNameResolver(idnConverter, eventLoop); +#endif + cryptoProvider = PlatformCryptoProvider::create(); } BoostNetworkFactories::~BoostNetworkFactories() { + delete cryptoProvider; + delete domainNameResolver; + delete idnConverter; delete proxyProvider; delete tlsFactories; delete xmlParserFactory; + delete networkEnvironment; delete natTraverser; delete connectionServerFactory; - delete domainNameResolver; delete connectionFactory; delete timerFactory; } diff --git a/Swiften/Network/BoostNetworkFactories.h b/Swiften/Network/BoostNetworkFactories.h index 1968acd..9c3bab1 100644 --- a/Swiften/Network/BoostNetworkFactories.h +++ b/Swiften/Network/BoostNetworkFactories.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #pragma once #include <Swiften/Base/API.h> +#include <Swiften/Base/Override.h> #include <Swiften/Network/NetworkFactories.h> #include <Swiften/Network/BoostIOServiceThread.h> @@ -20,11 +21,11 @@ namespace Swift { BoostNetworkFactories(EventLoop* eventLoop); ~BoostNetworkFactories(); - virtual TimerFactory* getTimerFactory() const { + virtual TimerFactory* getTimerFactory() const SWIFTEN_OVERRIDE { return timerFactory; } - virtual ConnectionFactory* getConnectionFactory() const { + virtual ConnectionFactory* getConnectionFactory() const SWIFTEN_OVERRIDE { return connectionFactory; } @@ -32,32 +33,44 @@ namespace Swift { return &ioServiceThread; } - DomainNameResolver* getDomainNameResolver() const { + DomainNameResolver* getDomainNameResolver() const SWIFTEN_OVERRIDE { return domainNameResolver; } - ConnectionServerFactory* getConnectionServerFactory() const { + ConnectionServerFactory* getConnectionServerFactory() const SWIFTEN_OVERRIDE { return connectionServerFactory; } - NATTraverser* getNATTraverser() const { + NetworkEnvironment* getNetworkEnvironment() const SWIFTEN_OVERRIDE { + return networkEnvironment; + } + + NATTraverser* getNATTraverser() const SWIFTEN_OVERRIDE { return natTraverser; } - virtual XMLParserFactory* getXMLParserFactory() const { + virtual XMLParserFactory* getXMLParserFactory() const SWIFTEN_OVERRIDE { return xmlParserFactory; } - virtual TLSContextFactory* getTLSContextFactory() const; + virtual TLSContextFactory* getTLSContextFactory() const SWIFTEN_OVERRIDE; - virtual ProxyProvider* getProxyProvider() const { + virtual ProxyProvider* getProxyProvider() const SWIFTEN_OVERRIDE { return proxyProvider; } - virtual EventLoop* getEventLoop() const { + 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; @@ -65,9 +78,12 @@ namespace Swift { DomainNameResolver* domainNameResolver; ConnectionServerFactory* connectionServerFactory; NATTraverser* natTraverser; + NetworkEnvironment* networkEnvironment; XMLParserFactory* xmlParserFactory; PlatformTLSFactories* tlsFactories; ProxyProvider* proxyProvider; EventLoop* eventLoop; + IDNConverter* idnConverter; + CryptoProvider* cryptoProvider; }; } diff --git a/Swiften/Network/ChainedConnector.h b/Swiften/Network/ChainedConnector.h index 4110522..03462bc 100644 --- a/Swiften/Network/ChainedConnector.h +++ b/Swiften/Network/ChainedConnector.h @@ -49,4 +49,4 @@ namespace Swift { boost::shared_ptr<Connector> currentConnector; boost::shared_ptr<Error> lastError; }; -}; +} diff --git a/Swiften/Network/ConnectionServer.h b/Swiften/Network/ConnectionServer.h index e644d90..2e09348 100644 --- a/Swiften/Network/ConnectionServer.h +++ b/Swiften/Network/ConnectionServer.h @@ -12,14 +12,22 @@ #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 + }; + virtual ~ConnectionServer(); virtual HostAddressPort getAddressPort() const = 0; + virtual boost::optional<Error> tryStart() = 0; // FIXME: This should become the new start + virtual void start() = 0; virtual void stop() = 0; diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp index 5ab3b92..a0155cf 100644 --- a/Swiften/Network/Connector.cpp +++ b/Swiften/Network/Connector.cpp @@ -183,4 +183,4 @@ void Connector::handleTimeout() { handleConnectionConnectFinished(true); } -}; +} diff --git a/Swiften/Network/Connector.h b/Swiften/Network/Connector.h index 26a98b8..49ac271 100644 --- a/Swiften/Network/Connector.h +++ b/Swiften/Network/Connector.h @@ -71,4 +71,4 @@ namespace Swift { boost::shared_ptr<Connection> currentConnection; bool foundSomeDNS; }; -}; +} diff --git a/Swiften/Network/DomainNameServiceQuery.cpp b/Swiften/Network/DomainNameServiceQuery.cpp index da1e1ab..5e87295 100644 --- a/Swiften/Network/DomainNameServiceQuery.cpp +++ b/Swiften/Network/DomainNameServiceQuery.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -13,8 +13,12 @@ #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> using namespace Swift; +namespace lambda = boost::lambda; namespace { struct ResultPriorityComparator { @@ -22,14 +26,6 @@ namespace { return a.priority < b.priority; } }; - - struct GetWeight { - GetWeight() {} - - int operator()(const DomainNameServiceQuery::Result& result) { - return result.weight + 1 /* easy hack to account for '0' weights getting at least some weight */; - } - }; } namespace Swift { @@ -39,19 +35,24 @@ DomainNameServiceQuery::~DomainNameServiceQuery() { void DomainNameServiceQuery::sortResults(std::vector<DomainNameServiceQuery::Result>& queries, RandomGenerator& generator) { ResultPriorityComparator comparator; - std::sort(queries.begin(), queries.end(), 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), GetWeight()); - for (size_t j = 0; j < weights.size() - 1; ++j) { + 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)); + std::partial_sum( + weights.begin() + j, + weights.end(), + std::back_inserter(cumulativeWeights)); int randomNumber = generator.generateRandomInteger(cumulativeWeights.back()); - int selectedIndex = std::lower_bound(cumulativeWeights.begin(), cumulativeWeights.end(), randomNumber) - cumulativeWeights.begin(); + 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]); } diff --git a/Swiften/Network/HostAddress.cpp b/Swiften/Network/HostAddress.cpp index f00581f..ff5c1c4 100644 --- a/Swiften/Network/HostAddress.cpp +++ b/Swiften/Network/HostAddress.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -15,6 +15,9 @@ #include <Swiften/Base/foreach.h> #include <string> +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()); + namespace Swift { HostAddress::HostAddress() { @@ -28,18 +31,18 @@ HostAddress::HostAddress(const std::string& address) { } } -HostAddress::HostAddress(const unsigned char* address, int length) { +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 (int i = 0; i < length; ++i) { + 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 (int i = 0; i < length; ++i) { + for (size_t i = 0; i < length; ++i) { data[i] = address[i]; } address_ = boost::asio::ip::address(boost::asio::ip::address_v6(data)); @@ -61,4 +64,8 @@ boost::asio::ip::address HostAddress::getRawAddress() const { return address_; } +bool HostAddress::isLocalhost() const { + return address_ == localhost4 || address_ == localhost6; +} + } diff --git a/Swiften/Network/HostAddress.h b/Swiften/Network/HostAddress.h index 621aa5d..c62239b 100644 --- a/Swiften/Network/HostAddress.h +++ b/Swiften/Network/HostAddress.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -15,7 +15,7 @@ namespace Swift { public: HostAddress(); HostAddress(const std::string&); - HostAddress(const unsigned char* address, int length); + HostAddress(const unsigned char* address, size_t length); HostAddress(const boost::asio::ip::address& address); std::string toString() const; @@ -26,6 +26,7 @@ namespace Swift { } bool isValid() const; + bool isLocalhost() const; private: boost::asio::ip::address address_; diff --git a/Swiften/Network/MacOSXProxyProvider.cpp b/Swiften/Network/MacOSXProxyProvider.cpp index 00fb478..3456c73 100644 --- a/Swiften/Network/MacOSXProxyProvider.cpp +++ b/Swiften/Network/MacOSXProxyProvider.cpp @@ -4,18 +4,27 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #include <Swiften/Base/Platform.h> #include <Swiften/Network/MacOSXProxyProvider.h> #include <stdio.h> #include <stdlib.h> #include <iostream> +#include <boost/numeric/conversion/cast.hpp> #include <utility> #ifndef SWIFTEN_PLATFORM_IPHONE #include <SystemConfiguration/SystemConfiguration.h> #endif +#pragma clang diagnostic ignored "-Wdisabled-macro-expansion" + using namespace Swift; #ifndef SWIFTEN_PLATFORM_IPHONE @@ -27,6 +36,7 @@ static HostAddressPort getFromDictionary(CFDictionaryRef dict, CFStringRef enabl const int i = 0; CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i); CFComparisonResult result = CFNumberCompare(numberValue, zero, NULL); + CFRelease(zero); if(result != kCFCompareEqualTo) { int port = 0; @@ -44,7 +54,7 @@ static HostAddressPort getFromDictionary(CFDictionaryRef dict, CFStringRef enabl // 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(length); + 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; @@ -75,6 +85,7 @@ HostAddressPort MacOSXProxyProvider::getHTTPConnectProxy() const { CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL); if(proxies != NULL) { result = getFromDictionary(proxies, kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort); + CFRelease(proxies); } #endif return result; @@ -86,6 +97,7 @@ HostAddressPort MacOSXProxyProvider::getSOCKS5Proxy() const { CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL); if(proxies != NULL) { result = getFromDictionary(proxies, kSCPropNetProxiesSOCKSEnable, kSCPropNetProxiesSOCKSProxy, kSCPropNetProxiesSOCKSPort); + CFRelease(proxies); } #endif return result; diff --git a/Swiften/Network/MiniUPnPInterface.cpp b/Swiften/Network/MiniUPnPInterface.cpp index c729371..bfa989f 100644 --- a/Swiften/Network/MiniUPnPInterface.cpp +++ b/Swiften/Network/MiniUPnPInterface.cpp @@ -72,7 +72,16 @@ boost::optional<NATPortMapping> MiniUPnPInterface::addPortForward(int actualLoca 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.getPublicPort() == NATPortMapping::TCP ? "TCP" : "UDP", 0, leaseSeconds.c_str()); + 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; } diff --git a/Swiften/Network/NATPMPInterface.cpp b/Swiften/Network/NATPMPInterface.cpp index 220e3e9..c7a41ff 100644 --- a/Swiften/Network/NATPMPInterface.cpp +++ b/Swiften/Network/NATPMPInterface.cpp @@ -7,6 +7,7 @@ #include <Swiften/Network/NATPMPInterface.h> #include <boost/smart_ptr/make_shared.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/Log.h> @@ -63,9 +64,14 @@ boost::optional<HostAddress> NATPMPInterface::getPublicIP() { 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, mapping.getLeaseInSeconds(), mapping.getPublicPort(), mapping.getLocalPort()) < 0) { - SWIFT_LOG(debug) << "Failed to send NAT-PMP port forwarding request!" << std::endl; - return boost::optional<NATPortMapping>(); + 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; @@ -81,7 +87,7 @@ boost::optional<NATPortMapping> NATPMPInterface::addPortForward(int localPort, i } while(r == NATPMP_TRYAGAIN); if (r == 0) { - NATPortMapping result(response.pnu.newportmapping.privateport, response.pnu.newportmapping.mappedpublicport, NATPortMapping::TCP, response.pnu.newportmapping.lifetime); + NATPortMapping result(response.pnu.newportmapping.privateport, response.pnu.newportmapping.mappedpublicport, NATPortMapping::TCP, boost::numeric_cast<int>(response.pnu.newportmapping.lifetime)); return result; } else { @@ -91,7 +97,7 @@ boost::optional<NATPortMapping> NATPMPInterface::addPortForward(int localPort, i } bool NATPMPInterface::removePortForward(const NATPortMapping& mapping) { - if (sendnewportmappingrequest(&p->natpmp, mapping.getProtocol() == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, 0, 0, mapping.getLocalPort()) < 0) { + 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; } diff --git a/Swiften/Network/NATPortMapping.h b/Swiften/Network/NATPortMapping.h index db14500..0f6bd95 100644 --- a/Swiften/Network/NATPortMapping.h +++ b/Swiften/Network/NATPortMapping.h @@ -13,10 +13,11 @@ namespace Swift { public: enum Protocol { TCP, - UDP, + UDP }; - NATPortMapping(int localPort, int publicPort, Protocol protocol = TCP, int leaseInSeconds = 60 * 60 * 24) : publicPort(publicPort), localPort(localPort), protocol(protocol), leaseInSeconds(leaseInSeconds) { + NATPortMapping(int localPort, int publicPort, Protocol protocol = TCP, int leaseInSeconds = 60 * 60 * 24) : + publicPort(publicPort), localPort(localPort), protocol(protocol), leaseInSeconds(leaseInSeconds) { } diff --git a/Swiften/Network/NATTraversalForwardPortRequest.h b/Swiften/Network/NATTraversalForwardPortRequest.h index 35b23c4..48f85ea 100644 --- a/Swiften/Network/NATTraversalForwardPortRequest.h +++ b/Swiften/Network/NATTraversalForwardPortRequest.h @@ -16,7 +16,8 @@ namespace Swift { public: virtual ~NATTraversalForwardPortRequest(); - virtual void run() = 0; + virtual void start() = 0; + virtual void stop() = 0; boost::signal<void (boost::optional<NATPortMapping>)> onResult; }; diff --git a/Swiften/Network/NATTraversalGetPublicIPRequest.h b/Swiften/Network/NATTraversalGetPublicIPRequest.h index db1f005..1270db3 100644 --- a/Swiften/Network/NATTraversalGetPublicIPRequest.h +++ b/Swiften/Network/NATTraversalGetPublicIPRequest.h @@ -14,7 +14,8 @@ namespace Swift { public: virtual ~NATTraversalGetPublicIPRequest(); - virtual void run() = 0; + virtual void start() = 0; + virtual void stop() = 0; boost::signal<void (boost::optional<HostAddress>)> onResult; }; diff --git a/Swiften/Network/NATTraversalRemovePortForwardingRequest.h b/Swiften/Network/NATTraversalRemovePortForwardingRequest.h index cf349b1..210cbcb 100644 --- a/Swiften/Network/NATTraversalRemovePortForwardingRequest.h +++ b/Swiften/Network/NATTraversalRemovePortForwardingRequest.h @@ -15,7 +15,7 @@ namespace Swift { struct PortMapping { enum Protocol { TCP, - UDP, + UDP }; unsigned int publicPort; @@ -27,7 +27,8 @@ namespace Swift { public: virtual ~NATTraversalRemovePortForwardingRequest(); - virtual void run() = 0; + virtual void start() = 0; + virtual void stop() = 0; boost::signal<void (boost::optional<bool> /* failure */)> onResult; }; diff --git a/Swiften/Network/NetworkFactories.h b/Swiften/Network/NetworkFactories.h index c8009a6..dd8e216 100644 --- a/Swiften/Network/NetworkFactories.h +++ b/Swiften/Network/NetworkFactories.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -17,6 +17,9 @@ namespace Swift { class CertificateFactory; class ProxyProvider; class EventLoop; + class IDNConverter; + class NetworkEnvironment; + class CryptoProvider; /** * An interface collecting network factories. @@ -30,9 +33,12 @@ namespace Swift { 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/NullNATTraverser.cpp b/Swiften/Network/NullNATTraverser.cpp index 8cb35cd..43fcd08 100644 --- a/Swiften/Network/NullNATTraverser.cpp +++ b/Swiften/Network/NullNATTraverser.cpp @@ -21,10 +21,13 @@ class NullNATTraversalGetPublicIPRequest : public NATTraversalGetPublicIPRequest NullNATTraversalGetPublicIPRequest(EventLoop* eventLoop) : eventLoop(eventLoop) { } - virtual void run() { + virtual void start() { eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<HostAddress>())); } + virtual void stop() { + } + private: EventLoop* eventLoop; }; @@ -34,10 +37,13 @@ class NullNATTraversalForwardPortRequest : public NATTraversalForwardPortRequest NullNATTraversalForwardPortRequest(EventLoop* eventLoop) : eventLoop(eventLoop) { } - virtual void run() { + virtual void start() { eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<NATPortMapping>())); } + virtual void stop() { + } + private: EventLoop* eventLoop; }; @@ -47,10 +53,13 @@ class NullNATTraversalRemovePortForwardingRequest : public NATTraversalRemovePor NullNATTraversalRemovePortForwardingRequest(EventLoop* eventLoop) : eventLoop(eventLoop) { } - virtual void run() { + virtual void start() { eventLoop->postEvent(boost::bind(boost::ref(onResult), boost::optional<bool>(true))); } + virtual void stop() { + } + private: EventLoop* eventLoop; }; diff --git a/Swiften/Network/PlatformDomainNameResolver.cpp b/Swiften/Network/PlatformDomainNameResolver.cpp index 63f7404..677f1d5 100644 --- a/Swiften/Network/PlatformDomainNameResolver.cpp +++ b/Swiften/Network/PlatformDomainNameResolver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -16,7 +16,7 @@ #include <algorithm> #include <string> -#include <Swiften/IDN/IDNA.h> +#include <Swiften/IDN/IDNConverter.h> #include <Swiften/Network/HostAddress.h> #include <Swiften/EventLoop/EventLoop.h> #include <Swiften/Network/HostAddressPort.h> @@ -27,7 +27,7 @@ using namespace Swift; namespace Swift { -PlatformDomainNameResolver::PlatformDomainNameResolver(EventLoop* eventLoop) : eventLoop(eventLoop), stopRequested(false) { +PlatformDomainNameResolver::PlatformDomainNameResolver(IDNConverter* idnConverter, EventLoop* eventLoop) : idnConverter(idnConverter), eventLoop(eventLoop), stopRequested(false) { thread = new boost::thread(boost::bind(&PlatformDomainNameResolver::run, this)); } @@ -39,11 +39,11 @@ PlatformDomainNameResolver::~PlatformDomainNameResolver() { } boost::shared_ptr<DomainNameServiceQuery> PlatformDomainNameResolver::createServiceQuery(const std::string& name) { - return boost::shared_ptr<DomainNameServiceQuery>(new PlatformDomainNameServiceQuery(IDNA::getEncoded(name), eventLoop, this)); + return boost::shared_ptr<DomainNameServiceQuery>(new PlatformDomainNameServiceQuery(idnConverter->getIDNAEncoded(name), eventLoop, this)); } boost::shared_ptr<DomainNameAddressQuery> PlatformDomainNameResolver::createAddressQuery(const std::string& name) { - return boost::shared_ptr<DomainNameAddressQuery>(new PlatformDomainNameAddressQuery(IDNA::getEncoded(name), eventLoop, this)); + return boost::shared_ptr<DomainNameAddressQuery>(new PlatformDomainNameAddressQuery(idnConverter->getIDNAEncoded(name), eventLoop, this)); } void PlatformDomainNameResolver::run() { diff --git a/Swiften/Network/PlatformDomainNameResolver.h b/Swiften/Network/PlatformDomainNameResolver.h index 0617d9e..25d87cf 100644 --- a/Swiften/Network/PlatformDomainNameResolver.h +++ b/Swiften/Network/PlatformDomainNameResolver.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -18,12 +18,12 @@ #include <Swiften/Network/DomainNameAddressQuery.h> namespace Swift { - + class IDNConverter; class EventLoop; class SWIFTEN_API PlatformDomainNameResolver : public DomainNameResolver { public: - PlatformDomainNameResolver(EventLoop* eventLoop); + PlatformDomainNameResolver(IDNConverter* idnConverter, EventLoop* eventLoop); ~PlatformDomainNameResolver(); virtual DomainNameServiceQuery::ref createServiceQuery(const std::string& name); @@ -36,6 +36,7 @@ namespace Swift { private: friend class PlatformDomainNameServiceQuery; friend class PlatformDomainNameAddressQuery; + IDNConverter* idnConverter; EventLoop* eventLoop; bool stopRequested; boost::thread* thread; diff --git a/Swiften/Network/PlatformDomainNameServiceQuery.cpp b/Swiften/Network/PlatformDomainNameServiceQuery.cpp index b0579a7..5788d2f 100644 --- a/Swiften/Network/PlatformDomainNameServiceQuery.cpp +++ b/Swiften/Network/PlatformDomainNameServiceQuery.cpp @@ -12,6 +12,7 @@ #include <Swiften/Base/Platform.h> #include <stdlib.h> +#include <boost/numeric/conversion/cast.hpp> #ifdef SWIFTEN_PLATFORM_WINDOWS #undef UNICODE #include <windows.h> @@ -121,7 +122,7 @@ void PlatformDomainNameServiceQuery::runBlocking() { emitError(); return; } - record.priority = ns_get16(currentEntry); + record.priority = boost::numeric_cast<int>(ns_get16(currentEntry)); currentEntry += 2; // Weight @@ -129,7 +130,7 @@ void PlatformDomainNameServiceQuery::runBlocking() { emitError(); return; } - record.weight = ns_get16(currentEntry); + record.weight = boost::numeric_cast<int>(ns_get16(currentEntry)); currentEntry += 2; // Port @@ -137,7 +138,7 @@ void PlatformDomainNameServiceQuery::runBlocking() { emitError(); return; } - record.port = ns_get16(currentEntry); + record.port = boost::numeric_cast<int>(ns_get16(currentEntry)); currentEntry += 2; // Hostname diff --git a/Swiften/Network/PlatformDomainNameServiceQuery.h b/Swiften/Network/PlatformDomainNameServiceQuery.h index 3372517..310e639 100644 --- a/Swiften/Network/PlatformDomainNameServiceQuery.h +++ b/Swiften/Network/PlatformDomainNameServiceQuery.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ diff --git a/Swiften/Network/PlatformNATTraversalWorker.cpp b/Swiften/Network/PlatformNATTraversalWorker.cpp index c962b3b..133b006 100644 --- a/Swiften/Network/PlatformNATTraversalWorker.cpp +++ b/Swiften/Network/PlatformNATTraversalWorker.cpp @@ -8,13 +8,18 @@ #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/Network/NATTraversalGetPublicIPRequest.h> #include <Swiften/Network/NATTraversalForwardPortRequest.h> #include <Swiften/Network/NATTraversalRemovePortForwardingRequest.h> +#ifdef HAVE_LIBNATPMP #include <Swiften/Network/NATPMPInterface.h> +#endif +#ifdef HAVE_LIBMINIUPNPC #include <Swiften/Network/MiniUPnPInterface.h> +#endif namespace Swift { @@ -49,10 +54,14 @@ class PlatformNATTraversalGetPublicIPRequest : public NATTraversalGetPublicIPReq PlatformNATTraversalGetPublicIPRequest(PlatformNATTraversalWorker* worker) : PlatformNATTraversalRequest(worker) { } - virtual void run() { + virtual void start() { doRun(); } + virtual void stop() { + // TODO + } + virtual void runBlocking() { onResult(getNATTraversalInterface()->getPublicIP()); } @@ -63,12 +72,16 @@ class PlatformNATTraversalForwardPortRequest : public NATTraversalForwardPortReq PlatformNATTraversalForwardPortRequest(PlatformNATTraversalWorker* worker, unsigned int localIP, unsigned int publicIP) : PlatformNATTraversalRequest(worker), localIP(localIP), publicIP(publicIP) { } - virtual void run() { + virtual void start() { doRun(); } + virtual void stop() { + // TODO + } + virtual void runBlocking() { - onResult(getNATTraversalInterface()->addPortForward(localIP, publicIP)); + onResult(getNATTraversalInterface()->addPortForward(boost::numeric_cast<int>(localIP), boost::numeric_cast<int>(publicIP))); } private: @@ -81,10 +94,14 @@ class PlatformNATTraversalRemovePortForwardingRequest : public NATTraversalRemov PlatformNATTraversalRemovePortForwardingRequest(PlatformNATTraversalWorker* worker, const NATPortMapping& mapping) : PlatformNATTraversalRequest(worker), mapping(mapping) { } - virtual void run() { + virtual void start() { doRun(); } + virtual void stop() { + // TODO + } + virtual void runBlocking() { onResult(getNATTraversalInterface()->removePortForward(mapping)); } @@ -95,7 +112,8 @@ class PlatformNATTraversalRemovePortForwardingRequest : public NATTraversalRemov PlatformNATTraversalWorker::PlatformNATTraversalWorker(EventLoop* eventLoop) : eventLoop(eventLoop), stopRequested(false), natPMPSupported(boost::logic::indeterminate), natPMPInterface(NULL), miniUPnPSupported(boost::logic::indeterminate), miniUPnPInterface(NULL) { nullNATTraversalInterface = new NullNATTraversalInterface(); - thread = new boost::thread(boost::bind(&PlatformNATTraversalWorker::run, this)); + // 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() { @@ -103,12 +121,17 @@ PlatformNATTraversalWorker::~PlatformNATTraversalWorker() { addRequestToQueue(boost::shared_ptr<PlatformNATTraversalRequest>()); thread->join(); delete thread; +#ifdef HAVE_LIBNATPMP delete natPMPInterface; +#endif +#ifdef HAVE_LIBMINIUPNPC delete miniUPnPInterface; +#endif delete nullNATTraversalInterface; } NATTraversalInterface* PlatformNATTraversalWorker::getNATTraversalInterface() const { +#ifdef HAVE_LIBMINIUPNPC if (boost::logic::indeterminate(miniUPnPSupported)) { miniUPnPInterface = new MiniUPnPInterface(); miniUPnPSupported = miniUPnPInterface->isAvailable(); @@ -116,8 +139,9 @@ NATTraversalInterface* PlatformNATTraversalWorker::getNATTraversalInterface() co if (miniUPnPSupported) { return miniUPnPInterface; } +#endif - +#ifdef HAVE_LIBNATPMP if (boost::logic::indeterminate(natPMPSupported)) { natPMPInterface = new NATPMPInterface(); natPMPSupported = natPMPInterface->isAvailable(); @@ -125,6 +149,7 @@ NATTraversalInterface* PlatformNATTraversalWorker::getNATTraversalInterface() co if (natPMPSupported) { return natPMPInterface; } +#endif return nullNATTraversalInterface; } @@ -142,7 +167,7 @@ boost::shared_ptr<NATTraversalRemovePortForwardingRequest> PlatformNATTraversalW return boost::make_shared<PlatformNATTraversalRemovePortForwardingRequest>(this, mapping); } -void PlatformNATTraversalWorker::run() { +void PlatformNATTraversalWorker::start() { while (!stopRequested) { PlatformNATTraversalRequest::ref request; { @@ -161,6 +186,10 @@ void PlatformNATTraversalWorker::run() { } } +void PlatformNATTraversalWorker::stop() { + // TODO +} + void PlatformNATTraversalWorker::addRequestToQueue(PlatformNATTraversalRequest::ref request) { { boost::lock_guard<boost::mutex> lock(queueMutex); diff --git a/Swiften/Network/PlatformNATTraversalWorker.h b/Swiften/Network/PlatformNATTraversalWorker.h index 8060e31..6148705 100644 --- a/Swiften/Network/PlatformNATTraversalWorker.h +++ b/Swiften/Network/PlatformNATTraversalWorker.h @@ -43,7 +43,8 @@ namespace Swift { private: NATTraversalInterface* getNATTraversalInterface() const; void addRequestToQueue(boost::shared_ptr<PlatformNATTraversalRequest>); - void run(); + void start(); + void stop(); private: EventLoop* eventLoop; diff --git a/Swiften/Network/ProxyProvider.h b/Swiften/Network/ProxyProvider.h index 0b63d51..9a1ccee 100644 --- a/Swiften/Network/ProxyProvider.h +++ b/Swiften/Network/ProxyProvider.h @@ -7,7 +7,6 @@ #pragma once #include <map> -#include <Swiften/Base/Log.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Base/String.h> diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript index b742bfe..ea0fb62 100644 --- a/Swiften/Network/SConscript +++ b/Swiften/Network/SConscript @@ -2,6 +2,10 @@ Import("swiften_env") myenv = swiften_env.Clone() +if myenv.get("unbound", False) : + myenv.MergeFlags(myenv.get("UNBOUND_FLAGS", {})) + myenv.MergeFlags(myenv.get("LDNS_FLAGS", {})) + sourceList = [ "ProxiedConnection.cpp", "HTTPConnectProxiedConnection.cpp", @@ -30,9 +34,6 @@ sourceList = [ "DomainNameResolver.cpp", "DomainNameAddressQuery.cpp", "DomainNameServiceQuery.cpp", - "PlatformDomainNameResolver.cpp", - "PlatformDomainNameServiceQuery.cpp", - "PlatformDomainNameAddressQuery.cpp", "StaticDomainNameResolver.cpp", "HostAddress.cpp", "HostAddressPort.cpp", @@ -53,8 +54,16 @@ sourceList = [ "NATTraversalRemovePortForwardingRequest.cpp", "NATTraversalInterface.cpp", ] - -if myenv["PLATFORM"] == "darwin" : + +if myenv.get("unbound", False) : + myenv.Append(CPPDEFINES = "USE_UNBOUND") + sourceList.append("UnboundDomainNameResolver.cpp") +else : + 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" ] @@ -72,20 +81,24 @@ else : objects = myenv.SwiftenObject(sourceList) -if myenv["experimental"] : +if myenv["experimental"] : # LibNATPMP classes - natpmp_env = myenv.Clone() - natpmp_env.Append(CPPDEFINES = natpmp_env["LIBNATPMP_FLAGS"].get("INTERNAL_CPPDEFINES", [])) - objects += natpmp_env.SwiftenObject([ - "NATPMPInterface.cpp", - ]) + 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 - upnp_env = myenv.Clone() - upnp_env.Append(CPPDEFINES = upnp_env["LIBMINIUPNPC_FLAGS"].get("INTERNAL_CPPDEFINES", [])) - objects += upnp_env.SwiftenObject([ - "MiniUPnPInterface.cpp", - ]) + 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", ]) diff --git a/Swiften/Network/SOCKS5ProxiedConnection.cpp b/Swiften/Network/SOCKS5ProxiedConnection.cpp index bf7a056..a9243d6 100644 --- a/Swiften/Network/SOCKS5ProxiedConnection.cpp +++ b/Swiften/Network/SOCKS5ProxiedConnection.cpp @@ -65,7 +65,7 @@ void SOCKS5ProxiedConnection::handleProxyInitializeData(boost::shared_ptr<SafeBy else { uc = rawAddress.to_v6().to_bytes()[s]; // the address. } - socksConnect.push_back(static_cast<char>(uc)); + socksConnect.push_back(uc); } socksConnect.push_back(static_cast<unsigned char> ((getServer().getPort() >> 8) & 0xFF)); // highbyte of the port. diff --git a/Swiften/Network/SOCKS5ProxiedConnection.h b/Swiften/Network/SOCKS5ProxiedConnection.h index 61092e0..7906879 100644 --- a/Swiften/Network/SOCKS5ProxiedConnection.h +++ b/Swiften/Network/SOCKS5ProxiedConnection.h @@ -30,7 +30,7 @@ namespace Swift { private: enum { ProxyAuthenticating = 0, - ProxyConnecting, + ProxyConnecting } proxyState_; }; } diff --git a/Swiften/Network/TLSConnection.h b/Swiften/Network/TLSConnection.h index a798393..60f73ea 100644 --- a/Swiften/Network/TLSConnection.h +++ b/Swiften/Network/TLSConnection.h @@ -24,7 +24,7 @@ namespace Swift { TLSConnection(Connection::ref connection, TLSContextFactory* tlsFactory); virtual ~TLSConnection(); - virtual void listen() {assert(false);}; + virtual void listen() {assert(false);} virtual void connect(const HostAddressPort& address); virtual void disconnect(); virtual void write(const SafeByteArray& data); diff --git a/Swiften/Network/UnboundDomainNameResolver.cpp b/Swiften/Network/UnboundDomainNameResolver.cpp new file mode 100755 index 0000000..d986385 --- /dev/null +++ b/Swiften/Network/UnboundDomainNameResolver.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "UnboundDomainNameResolver.h" + +#include <vector> + +#include <boost/bind.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/enable_shared_from_this.hpp> + +#include <Swiften/Base/Log.h> +#include <Swiften/EventLoop/EventLoop.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; +}; + +struct UnboundWrapperHelper { + UnboundWrapperHelper(UnboundDomainNameResolver* resolver, boost::shared_ptr<UnboundQuery> query) : resolver(resolver), query(query) {} + UnboundDomainNameResolver* resolver; + boost::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 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; +}; + +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>(); + + ub_ctx_async(ubContext, true); + + 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; + } + + ubDescriptior.assign(ub_fd(ubContext)); + + 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); + } +} + +void UnboundDomainNameResolver::unbound_callback(boost::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; +} + +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)); +} + +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; + } + } +} + +boost::shared_ptr<DomainNameServiceQuery> UnboundDomainNameResolver::createServiceQuery(const std::string& name) { + return boost::make_shared<UnboundDomainNameServiceQuery>(this, ubContext, name); +} + +boost::shared_ptr<DomainNameAddressQuery> UnboundDomainNameResolver::createAddressQuery(const std::string& name) { + return boost::make_shared<UnboundDomainNameAddressQuery>(this, ubContext, name); +} + +} diff --git a/Swiften/Network/UnboundDomainNameResolver.h b/Swiften/Network/UnboundDomainNameResolver.h new file mode 100755 index 0000000..0db8a66 --- /dev/null +++ b/Swiften/Network/UnboundDomainNameResolver.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Network/DomainNameResolver.h> +#include <Swiften/Network/Timer.h> +#include <Swiften/EventLoop/EventOwner.h> + +#include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/asio.hpp> + +struct ub_ctx; +struct ub_result; + +namespace Swift { + class EventLoop; + class TimerFactory; + + 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(); + + virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& name); + virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name); + + 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); + + 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; + }; + +} diff --git a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp index 23f1a3c..8a63fcb 100644 --- a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp +++ b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp @@ -170,7 +170,7 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture { void testConnectionCount_ThreeWritesTwoReads() { boost::shared_ptr<MockConnection> c0; boost::shared_ptr<MockConnection> c1; - long rid = initialRID; + unsigned long long rid = initialRID; PoolRef testling = createTestling(); CPPUNIT_ASSERT_EQUAL(st(1), connectionFactory->connections.size()); @@ -461,7 +461,7 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture { std::string port; std::string sid; std::string initial; - long initialRID; + unsigned long long initialRID; int sessionStarted; int sessionTerminated; diff --git a/Swiften/Network/UnixNetworkEnvironment.cpp b/Swiften/Network/UnixNetworkEnvironment.cpp index 52c5cbe..e1fdc88 100644 --- a/Swiften/Network/UnixNetworkEnvironment.cpp +++ b/Swiften/Network/UnixNetworkEnvironment.cpp @@ -14,7 +14,10 @@ #include <sys/socket.h> #include <arpa/inet.h> #include <net/if.h> + +#ifndef __ANDROID__ #include <ifaddrs.h> +#endif #include <Swiften/Base/boost_bsignals.h> #include <Swiften/Network/HostAddress.h> @@ -24,7 +27,7 @@ namespace Swift { std::vector<NetworkInterface> UnixNetworkEnvironment::getNetworkInterfaces() const { std::map<std::string, NetworkInterface> interfaces; - +#ifndef __ANDROID__ ifaddrs* addrs = 0; int ret = getifaddrs(&addrs); if (ret != 0) { @@ -42,14 +45,14 @@ std::vector<NetworkInterface> UnixNetworkEnvironment::getNetworkInterfaces() con sockaddr_in6* sa = reinterpret_cast<sockaddr_in6*>(a->ifa_addr); address = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin6_addr)), 16); } - if (address) { + 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); diff --git a/Swiften/Network/WindowsNetworkEnvironment.cpp b/Swiften/Network/WindowsNetworkEnvironment.cpp index 20f559d..e2d1966 100644 --- a/Swiften/Network/WindowsNetworkEnvironment.cpp +++ b/Swiften/Network/WindowsNetworkEnvironment.cpp @@ -50,7 +50,7 @@ std::vector<NetworkInterface> WindowsNetworkEnvironment::getNetworkInterfaces() sockaddr_in6* sa = reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr); hostAddress = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin6_addr)), 16); } - if (hostAddress) { + 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); } diff --git a/Swiften/Parser/AttributeMap.cpp b/Swiften/Parser/AttributeMap.cpp index 1aeaf99..d508157 100644 --- a/Swiften/Parser/AttributeMap.cpp +++ b/Swiften/Parser/AttributeMap.cpp @@ -8,27 +8,18 @@ #include <algorithm> #include <boost/optional.hpp> +#include <boost/lambda/lambda.hpp> +#include <boost/lambda/bind.hpp> using namespace Swift; - -namespace { - struct AttributeIs { - AttributeIs(const Attribute& attribute) : attribute(attribute) { - } - - bool operator()(const AttributeMap::Entry& o) const { - return o.getAttribute() == attribute; - } - - Attribute attribute; - }; -} +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(), AttributeIs(Attribute(attribute, ns))); + 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 ""; } @@ -38,7 +29,8 @@ std::string AttributeMap::getAttribute(const std::string& attribute, const std:: } bool AttributeMap::getBoolAttribute(const std::string& attribute, bool defaultValue) const { - AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, ""))); + 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; } @@ -48,7 +40,8 @@ bool AttributeMap::getBoolAttribute(const std::string& attribute, bool defaultVa } boost::optional<std::string> AttributeMap::getAttributeValue(const std::string& attribute) const { - AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, ""))); + 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>(); } diff --git a/Swiften/Parser/BOSHBodyExtractor.cpp b/Swiften/Parser/BOSHBodyExtractor.cpp index eeebe8a..715a448 100644 --- a/Swiften/Parser/BOSHBodyExtractor.cpp +++ b/Swiften/Parser/BOSHBodyExtractor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2011-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #include <Swiften/Parser/BOSHBodyExtractor.h> #include <boost/shared_ptr.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Parser/XMLParserClient.h> #include <Swiften/Parser/XMLParser.h> @@ -33,7 +34,7 @@ class BOSHBodyParserClient : public XMLParserClient { BOSHBodyExtractor* bodyExtractor; }; -inline bool isWhitespace(char c) { +inline bool isWhitespace(unsigned char c) { return c == ' ' || c == '\n' || c == '\t' || c == '\r'; } @@ -117,13 +118,17 @@ BOSHBodyExtractor::BOSHBodyExtractor(XMLParserFactory* parserFactory, const Byte body = BOSHBody(); if (!endElementSeen) { - body->content = std::string(reinterpret_cast<const char*>(vecptr(data) + std::distance(data.begin(), i)), std::distance(i, j.base())); + 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)), std::distance(data.begin(), i)))) { + 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>(); diff --git a/Swiften/Parser/EnumParser.h b/Swiften/Parser/EnumParser.h new file mode 100644 index 0000000..d7bdbbc --- /dev/null +++ b/Swiften/Parser/EnumParser.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> +#include <map> +#include <cassert> +#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; + }; +} diff --git a/Swiften/Parser/ExpatParser.cpp b/Swiften/Parser/ExpatParser.cpp index 8222ae0..8b7bf82 100644 --- a/Swiften/Parser/ExpatParser.cpp +++ b/Swiften/Parser/ExpatParser.cpp @@ -9,10 +9,13 @@ #include <iostream> #include <string> #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 Swift { static const char NAMESPACE_SEPARATOR = '\x01'; @@ -52,7 +55,8 @@ static void handleEndElement(void* parser, const XML_Char* name) { } static void handleCharacterData(void* parser, const XML_Char* data, int len) { - static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(data, 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) { @@ -77,7 +81,7 @@ ExpatParser::~ExpatParser() { } bool ExpatParser::parse(const std::string& data) { - bool success = XML_Parse(p->parser_, data.c_str(), data.size(), false) == XML_STATUS_OK; + 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; }*/ diff --git a/Swiften/Parser/GenericPayloadParserFactory2.h b/Swiften/Parser/GenericPayloadParserFactory2.h new file mode 100644 index 0000000..f24b64e --- /dev/null +++ b/Swiften/Parser/GenericPayloadParserFactory2.h @@ -0,0 +1,39 @@ +/* + * 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 <Swiften/Parser/PayloadParserFactory.h> +#include <string> + +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_; + }; +} diff --git a/Swiften/Parser/LibXMLParser.cpp b/Swiften/Parser/LibXMLParser.cpp index caba716..e4938e1 100644 --- a/Swiften/Parser/LibXMLParser.cpp +++ b/Swiften/Parser/LibXMLParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #include <Swiften/Parser/LibXMLParser.h> #include <iostream> +#include <boost/numeric/conversion/cast.hpp> #include <cassert> #include <cstring> #include <libxml/parser.h> @@ -32,7 +33,11 @@ static void handleStartElement(void* parser, const xmlChar* name, const xmlChar* 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]), attributes[i+4]-attributes[i+3])); + 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); } @@ -42,7 +47,7 @@ static void handleEndElement(void *parser, const xmlChar* name, const xmlChar*, } static void handleCharacterData(void* parser, const xmlChar* data, int len) { - static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(reinterpret_cast<const char*>(data), len)); + static_cast<XMLParser*>(parser)->getClient()->handleCharacterData(std::string(reinterpret_cast<const char*>(data), boost::numeric_cast<size_t>(len))); } static void handleError(void*, const char* /*m*/, ... ) { @@ -86,7 +91,7 @@ LibXMLParser::~LibXMLParser() { } bool LibXMLParser::parse(const std::string& data) { - if (xmlParseChunk(p->context_, data.c_str(), data.size(), false) == XML_ERR_OK) { + if (xmlParseChunk(p->context_, data.c_str(), boost::numeric_cast<int>(data.size()), false) == XML_ERR_OK) { return true; } xmlError* error = xmlCtxtGetLastError(p->context_); diff --git a/Swiften/Parser/PayloadParsers/BlockParser.h b/Swiften/Parser/PayloadParsers/BlockParser.h index cd727ad..6ee47a2 100644 --- a/Swiften/Parser/PayloadParsers/BlockParser.h +++ b/Swiften/Parser/PayloadParsers/BlockParser.h @@ -7,13 +7,14 @@ #pragma once #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>() { + BlockParser() : GenericPayloadParser<BLOCK_ELEMENT>(), level(0) { } virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { diff --git a/Swiften/Parser/PayloadParsers/BytestreamsParser.h b/Swiften/Parser/PayloadParsers/BytestreamsParser.h index 4785913..5c151c2 100644 --- a/Swiften/Parser/PayloadParsers/BytestreamsParser.h +++ b/Swiften/Parser/PayloadParsers/BytestreamsParser.h @@ -24,7 +24,7 @@ namespace Swift { private: enum Level { TopLevel = 0, - PayloadLevel = 1, + PayloadLevel = 1 }; int level; }; diff --git a/Swiften/Parser/PayloadParsers/FormParser.cpp b/Swiften/Parser/PayloadParsers/FormParser.cpp index 2df0a85..7c29189 100644 --- a/Swiften/Parser/PayloadParsers/FormParser.cpp +++ b/Swiften/Parser/PayloadParsers/FormParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -10,7 +10,7 @@ namespace Swift { -FormParser::FormParser() : level_(TopLevel), parsingItem_(false), parsingReported_(false) { +FormParser::FormParser() : level_(TopLevel), parsingItem_(false), parsingReported_(false), parsingOption_(false) { } void FormParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { @@ -36,67 +36,62 @@ void FormParser::handleStartElement(const std::string& element, const std::strin else if (element == "instructions") { currentText_.clear(); } - else if (element == "field") { - std::string type; - FormField::ref correspondingReportedField; - if (!parsingItem_) { - type = attributes.getAttribute("type"); - } else { - foreach(FormField::ref field, getPayloadInternal()->getReportedFields()) { - if (field->getName() == attributes.getAttribute("var")) { - correspondingReportedField = field; - break; - } - } - } - if (type == "boolean" || boost::dynamic_pointer_cast<BooleanFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = BooleanFormFieldParseHelper::create(); - } - else if (type == "fixed" || boost::dynamic_pointer_cast<FixedFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = FixedFormFieldParseHelper::create(); + 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; } - else if (type == "hidden" || boost::dynamic_pointer_cast<HiddenFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = HiddenFormFieldParseHelper::create(); + if (type == "fixed") { + fieldType = FormField::FixedType; } - else if (type == "jid-multi" || boost::dynamic_pointer_cast<JIDMultiFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = JIDMultiFormFieldParseHelper::create(); + if (type == "hidden") { + fieldType = FormField::HiddenType; } - else if (type == "jid-single" || boost::dynamic_pointer_cast<JIDSingleFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = JIDSingleFormFieldParseHelper::create(); + if (type == "list-single") { + fieldType = FormField::ListSingleType; } - else if (type == "list-multi" || boost::dynamic_pointer_cast<ListMultiFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = ListMultiFormFieldParseHelper::create(); + if (type == "text-multi") { + fieldType = FormField::TextMultiType; } - else if (type == "list-single" || boost::dynamic_pointer_cast<ListSingleFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = ListSingleFormFieldParseHelper::create(); + if (type == "text-private") { + fieldType = FormField::TextPrivateType; } - else if (type == "text-multi" || boost::dynamic_pointer_cast<TextMultiFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = TextMultiFormFieldParseHelper::create(); + if (type == "text-single") { + fieldType = FormField::TextSingleType; } - else if (type == "text-private" || boost::dynamic_pointer_cast<TextPrivateFormField>(correspondingReportedField)) { - currentFieldParseHelper_ = TextPrivateFormFieldParseHelper::create(); + if (type == "jid-single") { + fieldType = FormField::JIDSingleType; } - else /*if (type == "text-single") || undefined */ { - currentFieldParseHelper_ = TextSingleFormFieldParseHelper::create(); + if (type == "jid-multi") { + fieldType = FormField::JIDMultiType; } - if (currentFieldParseHelper_) { - currentFieldParseHelper_->getField()->setName(attributes.getAttribute("var")); - currentFieldParseHelper_->getField()->setLabel(attributes.getAttribute("label")); + if (type == "list-multi") { + fieldType = FormField::ListMultiType; } + currentField_->setType(fieldType); + currentField_->setName(attributes.getAttribute("var")); + currentField_->setLabel(attributes.getAttribute("label")); } - else if (element == "reported") { - parsingReported_ = true; - level_ = PayloadLevel - 1; - } - else if (element == "item") { - parsingItem_ = true; - level_ = PayloadLevel - 1; - } - } - else if (level_ == FieldLevel && currentFieldParseHelper_) { - currentText_.clear(); - if (element == "option") { - currentOptionLabel_ = attributes.getAttribute("label"); + else if (element == "value") { + currentText_.clear(); } } ++level_; @@ -123,42 +118,48 @@ void FormParser::handleEndElement(const std::string& element, const std::string& getPayloadInternal()->setInstructions(currentInstructions + "\n" + currentText_); } } - else if (element == "field") { - if (currentFieldParseHelper_) { - if (parsingReported_) { - getPayloadInternal()->addReportedField(currentFieldParseHelper_->getField()); - } else if (parsingItem_) { - currentFields_.push_back(currentFieldParseHelper_->getField()); - } else { - getPayloadInternal()->addField(currentFieldParseHelper_->getField()); - } - currentFieldParseHelper_.reset(); - } + else if (element == "reported") { + parsingReported_ = false; + } + else if (element == "item") { + parsingItem_ = false; + getPayloadInternal()->addItem(currentFields_); + currentFields_.clear(); } } - else if (level_ == FieldLevel && currentFieldParseHelper_) { + else if (currentField_) { if (element == "required") { - currentFieldParseHelper_->getField()->setRequired(true); + currentField_->setRequired(true); } else if (element == "desc") { - currentFieldParseHelper_->getField()->setDescription(currentText_); + currentField_->setDescription(currentText_); } else if (element == "option") { - currentFieldParseHelper_->getField()->addOption(FormField::Option(currentOptionLabel_, currentText_)); + currentField_->addOption(FormField::Option(currentOptionLabel_, currentOptionValue_)); + parsingOption_ = false; } else if (element == "value") { - currentFieldParseHelper_->addValue(currentText_); + if (parsingOption_) { + currentOptionValue_ = currentText_; + } + else { + currentField_->addValue(currentText_); + } } } - if (element == "reported") { - parsingReported_ = false; - level_++; - } - else if (element == "item") { - parsingItem_ = false; - level_++; - getPayloadInternal()->addItem(currentFields_); - currentFields_.clear(); + 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(); + } } } diff --git a/Swiften/Parser/PayloadParsers/FormParser.h b/Swiften/Parser/PayloadParsers/FormParser.h index a3e2524..0b23a81 100644 --- a/Swiften/Parser/PayloadParsers/FormParser.h +++ b/Swiften/Parser/PayloadParsers/FormParser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -18,86 +18,6 @@ namespace Swift { virtual void handleEndElement(const std::string& element, const std::string&); virtual void handleCharacterData(const std::string& data); - private: - class FieldParseHelper { - public: - virtual ~FieldParseHelper() {} - virtual void addValue(const std::string&) = 0; - virtual boost::shared_ptr<FormField> getField() const { - return field; - } - protected: - boost::shared_ptr<FormField> field; - }; - class BoolFieldParseHelper : public FieldParseHelper { - virtual void addValue(const std::string& s) { - boost::dynamic_pointer_cast< GenericFormField<bool> >(getField())->setValue(s == "1" || s == "true"); - getField()->addRawValue(s); - } - }; - class StringFieldParseHelper : public FieldParseHelper { - virtual void addValue(const std::string& s) { - boost::shared_ptr<GenericFormField<std::string> > field = boost::dynamic_pointer_cast< GenericFormField<std::string> >(getField()); - if (field->getValue().empty()) { - field->setValue(s); - } - else { - field->setValue(field->getValue() + "\n" + s); - } - getField()->addRawValue(s); - } - }; - class JIDFieldParseHelper : public FieldParseHelper { - virtual void addValue(const std::string& s) { - getField()->addRawValue(s); - boost::dynamic_pointer_cast< GenericFormField<JID> >(getField())->setValue(JID(s)); - } - }; - class StringListFieldParseHelper : public FieldParseHelper { - virtual void addValue(const std::string& s) { - // FIXME: Inefficient, but too much hassle to do efficiently - boost::shared_ptr<GenericFormField< std::vector<std::string> > > field = boost::dynamic_pointer_cast< GenericFormField<std::vector<std::string > > >(getField()); - std::vector<std::string> l = field->getValue(); - l.push_back(s); - field->setValue(l); - getField()->addRawValue(s); - } - }; - class JIDListFieldParseHelper : public FieldParseHelper { - virtual void addValue(const std::string& s) { - // FIXME: Inefficient, but too much hassle to do efficiently - boost::shared_ptr< GenericFormField< std::vector<JID> > > field = boost::dynamic_pointer_cast< GenericFormField<std::vector<JID > > >(getField()); - std::vector<JID> l = field->getValue(); - l.push_back(JID(s)); - field->setValue(l); - getField()->addRawValue(s); - } - }; - -#define SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(name, baseParser) \ - class name##FormFieldParseHelper : public baseParser##FieldParseHelper { \ - public: \ - typedef boost::shared_ptr<name##FormFieldParseHelper> ref; \ - static ref create() { \ - return ref(new name##FormFieldParseHelper()); \ - } \ - private: \ - name##FormFieldParseHelper() : baseParser##FieldParseHelper() { \ - field = name##FormField::create(); \ - } \ - }; - - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Boolean, Bool); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Fixed, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Hidden, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(ListSingle, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(TextMulti, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(TextPrivate, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(TextSingle, String); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(JIDSingle, JID); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(JIDMulti, JIDList); - SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(ListMulti, StringList); - enum Level { TopLevel = 0, PayloadLevel = 1, @@ -106,9 +26,11 @@ namespace Swift { int level_; std::string currentText_; std::string currentOptionLabel_; - boost::shared_ptr<FieldParseHelper> currentFieldParseHelper_; + std::string currentOptionValue_; bool parsingItem_; bool parsingReported_; + bool parsingOption_; + FormField::ref currentField_; std::vector<FormField::ref> currentFields_; }; } diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index a40e8f6..3ec5a7a 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -10,6 +10,8 @@ #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> @@ -67,6 +69,12 @@ #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/UserLocationParser.h> using namespace boost; @@ -126,8 +134,14 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() { 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>()); foreach(shared_ptr<PayloadParserFactory> factory, factories_) { addFactory(factory.get()); diff --git a/Swiften/Parser/PayloadParsers/IBBParser.h b/Swiften/Parser/PayloadParsers/IBBParser.h index d899475..59011b4 100644 --- a/Swiften/Parser/PayloadParsers/IBBParser.h +++ b/Swiften/Parser/PayloadParsers/IBBParser.h @@ -23,7 +23,7 @@ namespace Swift { private: enum Level { - TopLevel = 0, + TopLevel = 0 }; int level; std::string currentText; diff --git a/Swiften/Parser/PayloadParsers/IdleParser.cpp b/Swiften/Parser/PayloadParsers/IdleParser.cpp new file mode 100644 index 0000000..51aa34b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/IdleParser.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swiften/Parser/PayloadParsers/IdleParser.h> + +#include <Swiften/Base/DateTime.h> + +namespace Swift { + +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_; +} + +void IdleParser::handleEndElement(const std::string&, const std::string&) { + --level_; +} + +void IdleParser::handleCharacterData(const std::string&) { + +} + +} diff --git a/Swiften/Parser/PayloadParsers/IdleParser.h b/Swiften/Parser/PayloadParsers/IdleParser.h new file mode 100644 index 0000000..38001b2 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/IdleParser.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Elements/Idle.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + class 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); + + private: + int level_; + }; +} diff --git a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h index ae8d36c..1f85c85 100644 --- a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h @@ -27,7 +27,7 @@ namespace Swift { private: enum Level { TopLevel = 0, - PayloadLevel = 1, + PayloadLevel = 1 }; int level; FormParserFactory* formParserFactory; diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h index 93560c6..7ea22b4 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h @@ -26,7 +26,7 @@ class JingleFileTransferDescriptionParser : public GenericPayloadParser<JingleFi enum CurrentParseElement { UnknownElement, RequestElement, - OfferElement, + OfferElement }; PayloadParserFactoryCollection* factories; diff --git a/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp b/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp index a3dfd12..d140368 100644 --- a/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + #include <boost/lexical_cast.hpp> #include <boost/optional.hpp> @@ -18,9 +24,12 @@ namespace Swift { void JingleIBBTransportMethodPayloadParser::handleStartElement(const std::string&, const std::string&, const AttributeMap& attributes) { try { - getPayloadInternal()->setBlockSize(boost::lexical_cast<int>(attributes.getAttributeValue("block-size").get_value_or("0"))); - } catch (boost::bad_lexical_cast &) { - getPayloadInternal()->setBlockSize(0); + 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; diff --git a/Swiften/Parser/PayloadParsers/JingleParser.h b/Swiften/Parser/PayloadParsers/JingleParser.h index 188ead9..c7bd58c 100644 --- a/Swiften/Parser/PayloadParsers/JingleParser.h +++ b/Swiften/Parser/PayloadParsers/JingleParser.h @@ -29,5 +29,5 @@ class JingleParser : public GenericPayloadParser<JinglePayload> { boost::shared_ptr<PayloadParser> currentPayloadParser; }; -}; +} diff --git a/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.cpp index fa95af7..c1cf33d 100644 --- a/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/MUCInvitationPayloadParser.cpp @@ -17,6 +17,7 @@ void MUCInvitationPayloadParser::handleTree(ParserElement::ref root) { 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); } } diff --git a/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.cpp b/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.cpp new file mode 100644 index 0000000..05fa119 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + +using namespace Swift; + +PubSubAffiliationParser::PubSubAffiliationParser(PayloadParserFactoryCollection* parsers) : parsers(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; +} + +void PubSubAffiliationParser::handleEndElement(const std::string& element, const std::string& ns) { + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } +} + +void PubSubAffiliationParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.h b/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.h new file mode 100644 index 0000000..43c619d --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubAffiliationParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubAffiliationParser : public GenericPayloadParser<PubSubAffiliation> { + public: + PubSubAffiliationParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubAffiliationParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.cpp new file mode 100644 index 0000000..b75e339 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubAffiliationParser.h> + +using namespace Swift; + +PubSubAffiliationsParser::PubSubAffiliationsParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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; +} + +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(); + } + } +} + +void PubSubAffiliationsParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.h b/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.h new file mode 100644 index 0000000..646e7a8 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubAffiliationsParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubAffiliationsParser : public GenericPayloadParser<PubSubAffiliations> { + public: + PubSubAffiliationsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubAffiliationsParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubConfigureParser.cpp b/Swiften/Parser/PayloadParsers/PubSubConfigureParser.cpp new file mode 100644 index 0000000..773c1c7 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubConfigureParser.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +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(); + } + } +} + +void PubSubConfigureParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubConfigureParser.h b/Swiften/Parser/PayloadParsers/PubSubConfigureParser.h new file mode 100644 index 0000000..8300140 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubConfigureParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubConfigureParser : public GenericPayloadParser<PubSubConfigure> { + public: + PubSubConfigureParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubConfigureParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubCreateParser.cpp b/Swiften/Parser/PayloadParsers/PubSubCreateParser.cpp new file mode 100644 index 0000000..47f35c9 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubCreateParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +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(); + } + } +} + +void PubSubCreateParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubCreateParser.h b/Swiften/Parser/PayloadParsers/PubSubCreateParser.h new file mode 100644 index 0000000..865b8ec --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubCreateParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubCreateParser : public GenericPayloadParser<PubSubCreate> { + public: + PubSubCreateParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubCreateParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubDefaultParser.cpp b/Swiften/Parser/PayloadParsers/PubSubDefaultParser.cpp new file mode 100644 index 0000000..7a370cd --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubDefaultParser.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + +using namespace Swift; + +PubSubDefaultParser::PubSubDefaultParser(PayloadParserFactoryCollection* parsers) : parsers(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; +} + +void PubSubDefaultParser::handleEndElement(const std::string& element, const std::string& ns) { + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } +} + +void PubSubDefaultParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubDefaultParser.h b/Swiften/Parser/PayloadParsers/PubSubDefaultParser.h new file mode 100644 index 0000000..7bd8d66 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubDefaultParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubDefaultParser : public GenericPayloadParser<PubSubDefault> { + public: + PubSubDefaultParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubDefaultParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubErrorParser.cpp b/Swiften/Parser/PayloadParsers/PubSubErrorParser.cpp new file mode 100644 index 0000000..9752cd2 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubErrorParser.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/PubSubErrorParser.h> + +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"); +} + +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; +} + +void PubSubErrorParser::handleEndElement(const std::string&, const std::string&) { + --level; +} + +void PubSubErrorParser::handleCharacterData(const std::string&) { +} diff --git a/Swiften/Parser/PayloadParsers/PubSubErrorParser.h b/Swiften/Parser/PayloadParsers/PubSubErrorParser.h new file mode 100644 index 0000000..eb7dcfe --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubErrorParser.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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> + +namespace Swift { + class PayloadParserFactoryCollection; + class PayloadParser; + + class SWIFTEN_API PubSubErrorParser : public GenericPayloadParser<PubSubError> { + public: + PubSubErrorParser(); + virtual ~PubSubErrorParser(); + + 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; + + 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 new file mode 100644 index 0000000..10dfd63 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h> + +using namespace Swift; + +PubSubErrorParserFactory::~PubSubErrorParserFactory() { +} diff --git a/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h b/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h new file mode 100644 index 0000000..e2386da --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/PubSubErrorParser.h> + +namespace Swift { + class 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 PayloadParser* createPayloadParser() { + return new PubSubErrorParser(); + } + }; +} + + diff --git a/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.cpp new file mode 100644 index 0000000..f187be8 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +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(); + } + } +} + +void PubSubEventAssociateParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.h b/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.h new file mode 100644 index 0000000..000edf2 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventAssociateParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventAssociateParser : public GenericPayloadParser<PubSubEventAssociate> { + public: + PubSubEventAssociateParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventAssociateParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.cpp new file mode 100644 index 0000000..08b9c65 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubEventAssociateParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.h> + +using namespace Swift; + +PubSubEventCollectionParser::PubSubEventCollectionParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 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 && 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); + } + + 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(); + } + } +} + +void PubSubEventCollectionParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.h b/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.h new file mode 100644 index 0000000..aad97d2 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventCollectionParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventCollectionParser : public GenericPayloadParser<PubSubEventCollection> { + public: + PubSubEventCollectionParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventCollectionParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.cpp new file mode 100644 index 0000000..f905299 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +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(); + } + } +} + +void PubSubEventConfigurationParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.h b/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.h new file mode 100644 index 0000000..7189460 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventConfigurationParser : public GenericPayloadParser<PubSubEventConfiguration> { + public: + PubSubEventConfigurationParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventConfigurationParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.cpp new file mode 100644 index 0000000..03c7423 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubEventRedirectParser.h> + +using namespace Swift; + +PubSubEventDeleteParser::PubSubEventDeleteParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 1) { + if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#event") { + currentPayloadParser = boost::make_shared<PubSubEventRedirectParser>(parsers); + } + } + + 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); + } + + if (level == 1) { + if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#event") { + getPayloadInternal()->setRedirects(boost::dynamic_pointer_cast<PubSubEventRedirect>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } +} + +void PubSubEventDeleteParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.h b/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.h new file mode 100644 index 0000000..36f8e0b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventDeleteParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventDeleteParser : public GenericPayloadParser<PubSubEventDelete> { + public: + PubSubEventDeleteParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventDeleteParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.cpp new file mode 100644 index 0000000..287ac35 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +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(); + } + } +} + +void PubSubEventDisassociateParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.h b/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.h new file mode 100644 index 0000000..9015100 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventDisassociateParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventDisassociateParser : public GenericPayloadParser<PubSubEventDisassociate> { + public: + PubSubEventDisassociateParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventDisassociateParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventItemParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventItemParser.cpp new file mode 100644 index 0000000..8903545 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventItemParser.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubEventItemParser::PubSubEventItemParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 1) { + if (PayloadParserFactory* factory = parsers->getPayloadParserFactory(element, ns, attributes)) { + currentPayloadParser.reset(factory->createPayloadParser()); + } + } + + 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); + } + + if (level == 1) { + getPayloadInternal()->addData(currentPayloadParser->getPayload()); + currentPayloadParser.reset(); + } + } +} + +void PubSubEventItemParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventItemParser.h b/Swiften/Parser/PayloadParsers/PubSubEventItemParser.h new file mode 100644 index 0000000..6c16043 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventItemParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventItemParser : public GenericPayloadParser<PubSubEventItem> { + public: + PubSubEventItemParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventItemParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.cpp new file mode 100644 index 0000000..fa155e9 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubEventItemParser.h> + +using namespace Swift; + +PubSubEventItemsParser::PubSubEventItemsParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 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 && 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); + } + + 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(); + } + } +} + +void PubSubEventItemsParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.h b/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.h new file mode 100644 index 0000000..60ecb25 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventItemsParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventItemsParser : public GenericPayloadParser<PubSubEventItems> { + public: + PubSubEventItemsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventItemsParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventParser.cpp new file mode 100644 index 0000000..c4406a9 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventParser.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubEventCollectionParser.h> +#include <Swiften/Parser/PayloadParsers/PubSubEventConfigurationParser.h> + +using namespace Swift; + +PubSubEventParser::PubSubEventParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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; +} + +void PubSubEventParser::handleEndElement(const std::string& element, const std::string& 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(); + } + } +} + +void PubSubEventParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventParser.h b/Swiften/Parser/PayloadParsers/PubSubEventParser.h new file mode 100644 index 0000000..1042e75 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventParser : public GenericPayloadParser<PubSubEvent> { + public: + PubSubEventParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.cpp new file mode 100644 index 0000000..14d1e96 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +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(); + } + } +} + +void PubSubEventPurgeParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.h b/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.h new file mode 100644 index 0000000..740bff3 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventPurgeParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventPurgeParser : public GenericPayloadParser<PubSubEventPurge> { + public: + PubSubEventPurgeParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventPurgeParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.cpp new file mode 100644 index 0000000..f053117 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +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(); + } + } +} + +void PubSubEventRedirectParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.h b/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.h new file mode 100644 index 0000000..33880ed --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventRedirectParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventRedirectParser : public GenericPayloadParser<PubSubEventRedirect> { + public: + PubSubEventRedirectParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventRedirectParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.cpp new file mode 100644 index 0000000..da3dea3 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubEventRetractParser::PubSubEventRetractParser(PayloadParserFactoryCollection* parsers) : parsers(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; +} + +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(); + } + } +} + +void PubSubEventRetractParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.h b/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.h new file mode 100644 index 0000000..115bb7a --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventRetractParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventRetractParser : public GenericPayloadParser<PubSubEventRetract> { + public: + PubSubEventRetractParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventRetractParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.cpp b/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.cpp new file mode 100644 index 0000000..3367202 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + +using namespace Swift; + +PubSubEventSubscriptionParser::PubSubEventSubscriptionParser(PayloadParserFactoryCollection* parsers) : parsers(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 >= 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); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } +} + +void PubSubEventSubscriptionParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.h b/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.h new file mode 100644 index 0000000..1469920 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubEventSubscriptionParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubEventSubscriptionParser : public GenericPayloadParser<PubSubEventSubscription> { + public: + PubSubEventSubscriptionParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubEventSubscriptionParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubItemParser.cpp b/Swiften/Parser/PayloadParsers/PubSubItemParser.cpp new file mode 100644 index 0000000..2e7d01a --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubItemParser.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubItemParser::PubSubItemParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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; +} + +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(); + } + } +} + +void PubSubItemParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubItemParser.h b/Swiften/Parser/PayloadParsers/PubSubItemParser.h new file mode 100644 index 0000000..4f02211 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubItemParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubItemParser : public GenericPayloadParser<PubSubItem> { + public: + PubSubItemParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubItemParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubItemsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubItemsParser.cpp new file mode 100644 index 0000000..615f05d --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubItemsParser.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParsers/PubSubItemParser.h> + +using namespace Swift; + +PubSubItemsParser::PubSubItemsParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = boost::make_shared<PubSubItemParser>(parsers); + } + } + + 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); + } + + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->addItem(boost::dynamic_pointer_cast<PubSubItem>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } +} + +void PubSubItemsParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubItemsParser.h b/Swiften/Parser/PayloadParsers/PubSubItemsParser.h new file mode 100644 index 0000000..895863f --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubItemsParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubItemsParser : public GenericPayloadParser<PubSubItems> { + public: + PubSubItemsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubItemsParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOptionsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOptionsParser.cpp new file mode 100644 index 0000000..3bf4998 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOptionsParser.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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 == 1) { + if (element == "x" && ns == "jabber:x:data") { + currentPayloadParser = boost::make_shared<FormParser>(); + } + } + + 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); + } + + if (level == 1) { + if (element == "x" && ns == "jabber:x:data") { + getPayloadInternal()->setData(boost::dynamic_pointer_cast<Form>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } +} + +void PubSubOptionsParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOptionsParser.h b/Swiften/Parser/PayloadParsers/PubSubOptionsParser.h new file mode 100644 index 0000000..3c8754b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOptionsParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOptionsParser : public GenericPayloadParser<PubSubOptions> { + public: + PubSubOptionsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOptionsParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.cpp new file mode 100644 index 0000000..a648862 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + +using namespace Swift; + +PubSubOwnerAffiliationParser::PubSubOwnerAffiliationParser(PayloadParserFactoryCollection* parsers) : parsers(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; +} + +void PubSubOwnerAffiliationParser::handleEndElement(const std::string& element, const std::string& ns) { + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } +} + +void PubSubOwnerAffiliationParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.h new file mode 100644 index 0000000..ae54b5f --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOwnerAffiliationParser : public GenericPayloadParser<PubSubOwnerAffiliation> { + public: + PubSubOwnerAffiliationParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerAffiliationParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.cpp new file mode 100644 index 0000000..b824279 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubOwnerAffiliationParser.h> + +using namespace Swift; + +PubSubOwnerAffiliationsParser::PubSubOwnerAffiliationsParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 1) { + if (element == "affiliation" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = boost::make_shared<PubSubOwnerAffiliationParser>(parsers); + } + } + + 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); + } + + if (level == 1) { + if (element == "affiliation" && ns == "http://jabber.org/protocol/pubsub#owner") { + getPayloadInternal()->addAffiliation(boost::dynamic_pointer_cast<PubSubOwnerAffiliation>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } +} + +void PubSubOwnerAffiliationsParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.h new file mode 100644 index 0000000..755d58c --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerAffiliationsParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOwnerAffiliationsParser : public GenericPayloadParser<PubSubOwnerAffiliations> { + public: + PubSubOwnerAffiliationsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerAffiliationsParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.cpp new file mode 100644 index 0000000..43d262f --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +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(); + } + } +} + +void PubSubOwnerConfigureParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.h new file mode 100644 index 0000000..f9a8553 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerConfigureParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOwnerConfigureParser : public GenericPayloadParser<PubSubOwnerConfigure> { + public: + PubSubOwnerConfigureParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerConfigureParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.cpp new file mode 100644 index 0000000..4c284bf --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +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(); + } + } +} + +void PubSubOwnerDefaultParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.h new file mode 100644 index 0000000..5207bc5 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerDefaultParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOwnerDefaultParser : public GenericPayloadParser<PubSubOwnerDefault> { + public: + PubSubOwnerDefaultParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerDefaultParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.cpp new file mode 100644 index 0000000..a2b7a9d --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubOwnerRedirectParser.h> + +using namespace Swift; + +PubSubOwnerDeleteParser::PubSubOwnerDeleteParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 1) { + if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = boost::make_shared<PubSubOwnerRedirectParser>(parsers); + } + } + + 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); + } + + if (level == 1) { + if (element == "redirect" && ns == "http://jabber.org/protocol/pubsub#owner") { + getPayloadInternal()->setRedirect(boost::dynamic_pointer_cast<PubSubOwnerRedirect>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } +} + +void PubSubOwnerDeleteParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.h new file mode 100644 index 0000000..c171ab8 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerDeleteParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOwnerDeleteParser : public GenericPayloadParser<PubSubOwnerDelete> { + public: + PubSubOwnerDeleteParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerDeleteParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.cpp new file mode 100644 index 0000000..5262997 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/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> + +using namespace Swift; + +PubSubOwnerPubSubParser::PubSubOwnerPubSubParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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; +} + +void PubSubOwnerPubSubParser::handleEndElement(const std::string& element, const std::string& 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(); + } + } +} + +void PubSubOwnerPubSubParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.h new file mode 100644 index 0000000..25fee8a --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerPubSubParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOwnerPubSubParser : public GenericPayloadParser<PubSubOwnerPubSub> { + public: + PubSubOwnerPubSubParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerPubSubParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.cpp new file mode 100644 index 0000000..ebea0a7 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubOwnerPurgeParser::PubSubOwnerPurgeParser(PayloadParserFactoryCollection* parsers) : parsers(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; +} + +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(); + } + } +} + +void PubSubOwnerPurgeParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.h new file mode 100644 index 0000000..0b85d3d --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerPurgeParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOwnerPurgeParser : public GenericPayloadParser<PubSubOwnerPurge> { + public: + PubSubOwnerPurgeParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerPurgeParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.cpp new file mode 100644 index 0000000..bc54e86 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +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(); + } + } +} + +void PubSubOwnerRedirectParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.h new file mode 100644 index 0000000..9a97d74 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerRedirectParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOwnerRedirectParser : public GenericPayloadParser<PubSubOwnerRedirect> { + public: + PubSubOwnerRedirectParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerRedirectParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.cpp new file mode 100644 index 0000000..7c91526 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + +using namespace Swift; + +PubSubOwnerSubscriptionParser::PubSubOwnerSubscriptionParser(PayloadParserFactoryCollection* parsers) : parsers(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; +} + +void PubSubOwnerSubscriptionParser::handleEndElement(const std::string& element, const std::string& ns) { + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } +} + +void PubSubOwnerSubscriptionParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.h new file mode 100644 index 0000000..8ef8d5b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOwnerSubscriptionParser : public GenericPayloadParser<PubSubOwnerSubscription> { + public: + PubSubOwnerSubscriptionParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerSubscriptionParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.cpp new file mode 100644 index 0000000..ebe90d8 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubOwnerSubscriptionParser.h> + +using namespace Swift; + +PubSubOwnerSubscriptionsParser::PubSubOwnerSubscriptionsParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 1) { + if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub#owner") { + currentPayloadParser = boost::make_shared<PubSubOwnerSubscriptionParser>(parsers); + } + } + + 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); + } + + if (level == 1) { + if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub#owner") { + getPayloadInternal()->addSubscription(boost::dynamic_pointer_cast<PubSubOwnerSubscription>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } +} + +void PubSubOwnerSubscriptionsParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.h b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.h new file mode 100644 index 0000000..a5459a9 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubOwnerSubscriptionsParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubOwnerSubscriptionsParser : public GenericPayloadParser<PubSubOwnerSubscriptions> { + public: + PubSubOwnerSubscriptionsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubOwnerSubscriptionsParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubParser.cpp b/Swiften/Parser/PayloadParsers/PubSubParser.cpp new file mode 100644 index 0000000..5b1462b --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubParser.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/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/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/PubSubSubscriptionsParser.h> + +using namespace Swift; + +PubSubParser::PubSubParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 && 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); + } + + 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 == 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); + } + } + } + } +} + +void PubSubParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubParser.h b/Swiften/Parser/PayloadParsers/PubSubParser.h new file mode 100644 index 0000000..0618361 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubParser.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubParser : public GenericPayloadParser<PubSub> { + public: + PubSubParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + boost::shared_ptr<PubSubConfigure> configurePayload; + boost::shared_ptr<PubSubOptions> optionsPayload; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubPublishParser.cpp b/Swiften/Parser/PayloadParsers/PubSubPublishParser.cpp new file mode 100644 index 0000000..ca358c3 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubPublishParser.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubItemParser.h> + +using namespace Swift; + +PubSubPublishParser::PubSubPublishParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = boost::make_shared<PubSubItemParser>(parsers); + } + } + + 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); + } + + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->addItem(boost::dynamic_pointer_cast<PubSubItem>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } +} + +void PubSubPublishParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubPublishParser.h b/Swiften/Parser/PayloadParsers/PubSubPublishParser.h new file mode 100644 index 0000000..3d64e9d --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubPublishParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubPublishParser : public GenericPayloadParser<PubSubPublish> { + public: + PubSubPublishParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubPublishParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubRetractParser.cpp b/Swiften/Parser/PayloadParsers/PubSubRetractParser.cpp new file mode 100644 index 0000000..f4a42d0 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubRetractParser.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubItemParser.h> + +using namespace Swift; + +PubSubRetractParser::PubSubRetractParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = boost::make_shared<PubSubItemParser>(parsers); + } + } + + 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); + } + + if (level == 1) { + if (element == "item" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->addItem(boost::dynamic_pointer_cast<PubSubItem>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } +} + +void PubSubRetractParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubRetractParser.h b/Swiften/Parser/PayloadParsers/PubSubRetractParser.h new file mode 100644 index 0000000..2b5e633 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubRetractParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubRetractParser : public GenericPayloadParser<PubSubRetract> { + public: + PubSubRetractParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubRetractParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.cpp new file mode 100644 index 0000000..caed681 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +void PubSubSubscribeOptionsParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { + + + + + 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(); + } + } +} + +void PubSubSubscribeOptionsParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.h b/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.h new file mode 100644 index 0000000..c9ac1ca --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubSubscribeOptionsParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubSubscribeOptionsParser : public GenericPayloadParser<PubSubSubscribeOptions> { + public: + PubSubSubscribeOptionsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubSubscribeOptionsParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.cpp b/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.cpp new file mode 100644 index 0000000..093c2c4 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +void PubSubSubscribeParser::handleEndElement(const std::string& element, const std::string& ns) { + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } +} + +void PubSubSubscribeParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.h b/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.h new file mode 100644 index 0000000..f0ad09d --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubSubscribeParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubSubscribeParser : public GenericPayloadParser<PubSubSubscribe> { + public: + PubSubSubscribeParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubSubscribeParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.cpp b/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.cpp new file mode 100644 index 0000000..be06ec8 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubSubscribeOptionsParser.h> + +using namespace Swift; + +PubSubSubscriptionParser::PubSubSubscriptionParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 1) { + if (element == "subscribe-options" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = boost::make_shared<PubSubSubscribeOptionsParser>(parsers); + } + } + + 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); + } + + if (level == 1) { + if (element == "subscribe-options" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->setOptions(boost::dynamic_pointer_cast<PubSubSubscribeOptions>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } +} + +void PubSubSubscriptionParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h b/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h new file mode 100644 index 0000000..49290c2 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubSubscriptionParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubSubscriptionParser : public GenericPayloadParser<PubSubSubscription> { + public: + PubSubSubscriptionParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubSubscriptionParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.cpp b/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.cpp new file mode 100644 index 0000000..3ac3ca0 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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/PayloadParsers/PubSubSubscriptionParser.h> + +using namespace Swift; + +PubSubSubscriptionsParser::PubSubSubscriptionsParser(PayloadParserFactoryCollection* parsers) : parsers(parsers), level(0) { +} + +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 == 1) { + if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub") { + currentPayloadParser = boost::make_shared<PubSubSubscriptionParser>(parsers); + } + } + + 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); + } + + if (level == 1) { + if (element == "subscription" && ns == "http://jabber.org/protocol/pubsub") { + getPayloadInternal()->addSubscription(boost::dynamic_pointer_cast<PubSubSubscription>(currentPayloadParser->getPayload())); + } + currentPayloadParser.reset(); + } + } +} + +void PubSubSubscriptionsParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.h b/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.h new file mode 100644 index 0000000..b08db93 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubSubscriptionsParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubSubscriptionsParser : public GenericPayloadParser<PubSubSubscriptions> { + public: + PubSubSubscriptionsParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubSubscriptionsParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.cpp b/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.cpp new file mode 100644 index 0000000..53b4fae --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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() { +} + +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; +} + +void PubSubUnsubscribeParser::handleEndElement(const std::string& element, const std::string& ns) { + --level; + if (currentPayloadParser) { + if (level >= 1) { + currentPayloadParser->handleEndElement(element, ns); + } + + if (level == 1) { + + currentPayloadParser.reset(); + } + } +} + +void PubSubUnsubscribeParser::handleCharacterData(const std::string& data) { + if (level > 1 && currentPayloadParser) { + currentPayloadParser->handleCharacterData(data); + } +} diff --git a/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.h b/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.h new file mode 100644 index 0000000..a9e5ed0 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/PubSubUnsubscribeParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#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 SWIFTEN_API PubSubUnsubscribeParser : public GenericPayloadParser<PubSubUnsubscribe> { + public: + PubSubUnsubscribeParser(PayloadParserFactoryCollection* parsers); + virtual ~PubSubUnsubscribeParser(); + + 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; + + private: + PayloadParserFactoryCollection* parsers; + int level; + boost::shared_ptr<PayloadParser> currentPayloadParser; + }; +} diff --git a/Swiften/Parser/PayloadParsers/SearchPayloadParser.h b/Swiften/Parser/PayloadParsers/SearchPayloadParser.h index 006e0d9..d456eb8 100644 --- a/Swiften/Parser/PayloadParsers/SearchPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/SearchPayloadParser.h @@ -28,7 +28,7 @@ namespace Swift { enum Level { TopLevel = 0, PayloadLevel = 1, - ItemLevel = 2, + ItemLevel = 2 }; int level; FormParserFactory* formParserFactory; diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp index 0a13844..cc69348 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp +++ b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp @@ -35,7 +35,7 @@ void StreamInitiationFileInfoParser::handleStartElement(const std::string& eleme } else { parseDescription = false; if (element == "range") { - int offset = 0; + 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 &) { diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp index fd3d019..ff0a061 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp +++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -40,7 +40,7 @@ void StreamInitiationParser::handleStartElement(const std::string& element, cons currentFile = StreamInitiationFileInfo(); currentFile.setName(attributes.getAttribute("name")); try { - currentFile.setSize(boost::lexical_cast<int>(attributes.getAttribute("size"))); + currentFile.setSize(boost::lexical_cast<unsigned long long>(attributes.getAttribute("size"))); } catch (boost::bad_lexical_cast&) { } @@ -96,8 +96,8 @@ void StreamInitiationParser::handleEndElement(const std::string& element, const } } else if (form->getType() == Form::SubmitType) { - if (field->getRawValues().size() > 0) { - getPayloadInternal()->setRequestedMethod(field->getRawValues()[0]); + if (!field->getValues().empty()) { + getPayloadInternal()->setRequestedMethod(field->getValues()[0]); } } } diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.h b/Swiften/Parser/PayloadParsers/StreamInitiationParser.h index c2ffd07..f7350cd 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.h +++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.h @@ -29,7 +29,7 @@ namespace Swift { TopLevel = 0, PayloadLevel = 1, FileOrFeatureLevel = 2, - FormOrDescriptionLevel = 3, + FormOrDescriptionLevel = 3 }; int level; FormParserFactory* formParserFactory; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/BlockParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/BlockParserTest.cpp new file mode 100644 index 0000000..ddd3a88 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/BlockParserTest.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Parser/PayloadParsers/BlockParser.h> +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> + +#include <Swiften/Elements/BlockPayload.h> +#include <Swiften/Elements/UnblockPayload.h> +#include <Swiften/Elements/BlockListPayload.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_REGISTRATION(BlockParserTest); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp index c36fbeb..bc8f1bc 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/FormParserTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -54,13 +54,13 @@ class FormParserTest : public CppUnit::TestFixture { "</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>" + "<value>news</value>" + "<value>search</value>" "</field>" "<field label=\"Maximum number of subscribers\" type=\"list-single\" var=\"maxsubs\">" "<value>20</value>" @@ -84,37 +84,35 @@ class FormParserTest : public CppUnit::TestFixture { 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"), boost::dynamic_pointer_cast<HiddenFormField>(payload->getFields()[0])->getValue()); + 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"), boost::dynamic_pointer_cast<FixedFormField>(payload->getFields()[1])->getValue()); + 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"), boost::dynamic_pointer_cast<TextMultiFormField>(payload->getFields()[3])->getValue()); + CPPUNIT_ASSERT_EQUAL(std::string("This is a bot.\nA quite good one actually"), payload->getFields()[3]->getTextMultiValue()); - CPPUNIT_ASSERT_EQUAL(true, boost::dynamic_pointer_cast<BooleanFormField>(payload->getFields()[4])->getValue()); + CPPUNIT_ASSERT_EQUAL(true, payload->getFields()[4]->getBoolValue()); CPPUNIT_ASSERT(payload->getFields()[4]->getRequired()); - CPPUNIT_ASSERT_EQUAL(std::string("1"), boost::dynamic_pointer_cast<BooleanFormField>(payload->getFields()[4])->getRawValues()[0]); - - CPPUNIT_ASSERT_EQUAL(std::string("news"), boost::dynamic_pointer_cast<ListMultiFormField>(payload->getFields()[6])->getValue()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("news"), payload->getFields()[6]->getRawValues()[0]); - CPPUNIT_ASSERT_EQUAL(std::string("search"), boost::dynamic_pointer_cast<ListMultiFormField>(payload->getFields()[6])->getValue()[1]); - CPPUNIT_ASSERT_EQUAL(std::string("search"), payload->getFields()[6]->getRawValues()[1]); + 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"), boost::dynamic_pointer_cast<ListSingleFormField>(payload->getFields()[7])->getValue()); + CPPUNIT_ASSERT_EQUAL(std::string("20"), payload->getFields()[7]->getValues()[0]); - CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com"), boost::dynamic_pointer_cast<JIDMultiFormField>(payload->getFields()[8])->getValue()[0]); - CPPUNIT_ASSERT_EQUAL(JID("baz@fum.org"), boost::dynamic_pointer_cast<JIDMultiFormField>(payload->getFields()[8])->getValue()[1]); + 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"), boost::dynamic_pointer_cast<TextSingleFormField>(payload->getFields()[9])->getValue()); + CPPUNIT_ASSERT_EQUAL(std::string("foo"), payload->getFields()[9]->getValues()[0]); } void testParse_FormItems() { @@ -157,29 +155,28 @@ class FormParserTest : public CppUnit::TestFixture { Form::FormItem item = items[0]; CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); - CPPUNIT_ASSERT_EQUAL(std::string("Benvolio"), item[0]->getRawValues()[0]); + 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]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); - JIDSingleFormField::ref jidField = boost::dynamic_pointer_cast<JIDSingleFormField>(item[2]); - CPPUNIT_ASSERT(jidField); - CPPUNIT_ASSERT_EQUAL(JID("benvolio@montague.net"), jidField->getValue()); + 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]->getRawValues()[0]); + 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]->getRawValues()[0]); + 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]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("Montague"), item[1]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("last"), item[1]->getName()); - jidField = boost::dynamic_pointer_cast<JIDSingleFormField>(item[2]); + jidField = item[2]; CPPUNIT_ASSERT(jidField); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), jidField->getValue()); + 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]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); } }; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/IdleParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/IdleParserTest.cpp new file mode 100644 index 0000000..74da474 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UnitTest/IdleParserTest.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/Idle.h> +#include <Swiften/Base/DateTime.h> + +using namespace Swift; + +class IdleParserTest : public CppUnit::TestFixture { + 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" + )); + + 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/JingleParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp index 8719a5d..8c8601a 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp @@ -121,7 +121,7 @@ class JingleParserTest : public CppUnit::TestFixture { JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); CPPUNIT_ASSERT(transportPaylod); - CPPUNIT_ASSERT_EQUAL(4096, transportPaylod->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(4096U, *transportPaylod->getBlockSize()); CPPUNIT_ASSERT_EQUAL(std::string("ch3d9s71"), transportPaylod->getSessionID()); } @@ -158,7 +158,7 @@ class JingleParserTest : public CppUnit::TestFixture { JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); CPPUNIT_ASSERT(transportPaylod); - CPPUNIT_ASSERT_EQUAL(2048, transportPaylod->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(2048U, *transportPaylod->getBlockSize()); CPPUNIT_ASSERT_EQUAL(std::string("ch3d9s71"), transportPaylod->getSessionID()); } @@ -191,7 +191,7 @@ class JingleParserTest : public CppUnit::TestFixture { JingleIBBTransportPayload::ref transportPaylod = payload->getTransport<JingleIBBTransportPayload>(); CPPUNIT_ASSERT(transportPaylod); - CPPUNIT_ASSERT_EQUAL(2048, transportPaylod->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(2048U, *transportPaylod->getBlockSize()); CPPUNIT_ASSERT_EQUAL(std::string("bt8a71h6"), transportPaylod->getSessionID()); } @@ -468,7 +468,7 @@ class JingleParserTest : public CppUnit::TestFixture { StreamInitiationFileInfo file = content->getDescription<JingleFileTransferDescription>()->getRequests()[0]; CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), file.getHash()); - CPPUNIT_ASSERT_EQUAL(static_cast<boost::uintmax_t>(270336), file.getRangeOffset()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned long long>(270336), file.getRangeOffset()); CPPUNIT_ASSERT_EQUAL(true, file.getSupportsRangeRequests()); } diff --git a/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h b/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h index 213cd06..b328670 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h +++ b/Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h @@ -1,13 +1,11 @@ /* - * Copyright (c) 2010 Remko Tronçon + * 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 <cppunit/extensions/HelperMacros.h> - #include <Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h> #include <Swiften/Parser/XMLParser.h> #include <Swiften/Parser/XMLParserClient.h> @@ -32,9 +30,9 @@ namespace Swift { virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { if (level == 0) { - CPPUNIT_ASSERT(!payloadParser.get()); + assert(!payloadParser.get()); PayloadParserFactory* payloadParserFactory = factories.getPayloadParserFactory(element, ns, attributes); - CPPUNIT_ASSERT(payloadParserFactory); + assert(payloadParserFactory); payloadParser.reset(payloadParserFactory->createPayloadParser()); } payloadParser->handleStartElement(element, ns, attributes); diff --git a/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp index ef48ced..59ea3ff 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/SearchPayloadParserTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -155,25 +155,25 @@ class SearchPayloadParserTest : public CppUnit::TestFixture { Form::FormItem item = items[0]; CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), item.size()); - CPPUNIT_ASSERT_EQUAL(std::string("Benvolio"), item[0]->getRawValues()[0]); + 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]->getRawValues()[0]); + 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]->getRawValues()[0]); + 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]->getRawValues()[0]); + 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]->getRawValues()[0]); + 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]->getRawValues()[0]); + 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]->getRawValues()[0]); + 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]->getRawValues()[0]); + CPPUNIT_ASSERT_EQUAL(std::string("male"), item[3]->getValues()[0]); CPPUNIT_ASSERT_EQUAL(std::string("x-gender"), item[3]->getName()); } }; diff --git a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp index f1e6635..6436e90 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp @@ -7,6 +7,8 @@ #include <Swiften/Base/ByteArray.h> #include <QA/Checker/IO.h> +#include <boost/date_time/posix_time/posix_time.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -19,6 +21,7 @@ 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(); @@ -48,8 +51,36 @@ class VCardParserTest : public CppUnit::TestFixture { "<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>1234</BDAY>" + "<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>")); @@ -62,7 +93,7 @@ class VCardParserTest : public CppUnit::TestFixture { 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(std::string("<BDAY xmlns=\"vcard-temp\">1234</BDAY><MAILER xmlns=\"vcard-temp\">mutt</MAILER>"), payload->getUnknownContent()); + 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); @@ -76,6 +107,45 @@ class VCardParserTest : public CppUnit::TestFixture { 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() { @@ -97,6 +167,30 @@ class VCardParserTest : public CppUnit::TestFixture { 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; diff --git a/Swiften/Parser/PayloadParsers/UserLocationParser.cpp b/Swiften/Parser/PayloadParsers/UserLocationParser.cpp new file mode 100644 index 0000000..d3aac69 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UserLocationParser.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/UserLocationParser.h> + +#include <boost/lexical_cast.hpp> + +#include <Swiften/Base/DateTime.h> + +using namespace Swift; + +UserLocationParser::UserLocationParser() : level(0) { +} + +UserLocationParser::~UserLocationParser() { +} + +void UserLocationParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { + 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&) { + } + } +} + +void UserLocationParser::handleCharacterData(const std::string& data) { + currentText += data; +} diff --git a/Swiften/Parser/PayloadParsers/UserLocationParser.h b/Swiften/Parser/PayloadParsers/UserLocationParser.h new file mode 100644 index 0000000..eb6e668 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UserLocationParser.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <string> + +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Parser/GenericPayloadParser.h> +#include <Swiften/Elements/UserLocation.h> + +namespace Swift { + class SWIFTEN_API UserLocationParser : public GenericPayloadParser<UserLocation> { + public: + UserLocationParser(); + virtual ~UserLocationParser(); + + 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; + + private: + int level; + std::string currentText; + }; +} diff --git a/Swiften/Parser/PayloadParsers/VCardParser.cpp b/Swiften/Parser/PayloadParsers/VCardParser.cpp index 553d26a..0028411 100644 --- a/Swiften/Parser/PayloadParsers/VCardParser.cpp +++ b/Swiften/Parser/PayloadParsers/VCardParser.cpp @@ -6,6 +6,7 @@ #include <Swiften/Parser/PayloadParsers/VCardParser.h> #include <Swiften/Base/foreach.h> +#include <Swiften/Base/DateTime.h> #include <Swiften/StringCodecs/Base64.h> #include <Swiften/Parser/SerializingParser.h> @@ -20,6 +21,18 @@ void VCardParser::handleStartElement(const std::string& element, const std::stri 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(); @@ -68,6 +81,8 @@ void VCardParser::handleEndElement(const std::string& element, const std::string 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") { @@ -90,9 +105,160 @@ void VCardParser::handleEndElement(const std::string& element, const std::string else if (elementHierarchy == "/vCard/EMAIL/PREF") { currentEMailAddress_.isPreferred = true; } - else if (elementHierarchy == "/vCard/EMAIL") { + 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()); } diff --git a/Swiften/Parser/PayloadParsers/VCardParser.h b/Swiften/Parser/PayloadParsers/VCardParser.h index b1c47a3..f10d639 100644 --- a/Swiften/Parser/PayloadParsers/VCardParser.h +++ b/Swiften/Parser/PayloadParsers/VCardParser.h @@ -28,6 +28,10 @@ namespace Swift { 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/WhiteboardParser.cpp b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp index 09d8de9..a480813 100644 --- a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp +++ b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp @@ -83,8 +83,8 @@ namespace Swift { std::string pathData = attributes.getAttributeValue("d").get_value_or(""); std::vector<std::pair<int, int> > points; if (pathData[0] == 'M') { - unsigned int pos = 1; - unsigned int npos; + size_t pos = 1; + size_t npos; int x, y; if (pathData[pos] == ' ') { pos++; @@ -163,8 +163,8 @@ namespace Swift { std::string pointsData = attributes.getAttributeValue("points").get_value_or(""); std::vector<std::pair<int, int> > points; - unsigned int pos = 0; - unsigned int npos; + size_t pos = 0; + size_t npos; int x, y; try { while (pos < pointsData.size()) { diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 64e9eb9..0a6972e 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -69,10 +69,13 @@ sources = [ "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", diff --git a/Swiften/Parser/Tree/ParserElement.cpp b/Swiften/Parser/Tree/ParserElement.cpp index 9d9b9b6..e5f8bc8 100644 --- a/Swiften/Parser/Tree/ParserElement.cpp +++ b/Swiften/Parser/Tree/ParserElement.cpp @@ -9,8 +9,12 @@ #include <Swiften/Parser/Tree/NullParserElement.h> #include <iostream> +#include <boost/lambda/lambda.hpp> +#include <boost/lambda/bind.hpp> -namespace Swift{ +namespace lambda = boost::lambda; + +namespace Swift { ParserElement::ParserElement(const std::string& name, const std::string& xmlns, const AttributeMap& attributes) : name_(name), xmlns_(xmlns), attributes_(attributes) { } @@ -28,19 +32,10 @@ void ParserElement::appendCharacterData(const std::string& data) { text_ += data; } -struct DoesntMatch { - public: - DoesntMatch(const std::string& tagName, const std::string& ns) : tagName(tagName), ns(ns) {} - bool operator()(ParserElement::ref element) { return element->getName() != tagName || element->getNamespace() != ns; } - private: - std::string tagName; - std::string ns; -}; - - 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), DoesntMatch(name, xmlns)); + 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; } diff --git a/Swiften/Parser/UnitTest/EnumParserTest.cpp b/Swiften/Parser/UnitTest/EnumParserTest.cpp new file mode 100644 index 0000000..44a30c0 --- /dev/null +++ b/Swiften/Parser/UnitTest/EnumParserTest.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Parser/EnumParser.h> + +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_REGISTRATION(EnumParserTest); diff --git a/Swiften/PubSub/PubSubManager.cpp b/Swiften/PubSub/PubSubManager.cpp new file mode 100644 index 0000000..8899b1e --- /dev/null +++ b/Swiften/PubSub/PubSubManager.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/PubSub/PubSubManager.h> + +using namespace Swift; + +PubSubManager::~PubSubManager() { +} diff --git a/Swiften/PubSub/PubSubManager.h b/Swiften/PubSub/PubSubManager.h new file mode 100644 index 0000000..2f3c84d --- /dev/null +++ b/Swiften/PubSub/PubSubManager.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.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/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/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/PubSubOwnerPurge.h> +#include <Swiften/Elements/PubSubOwnerSubscriptions.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/PubSubEventPayload.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; + +namespace Swift { + class JID; + + class SWIFTEN_API PubSubManager { + public: + virtual ~PubSubManager(); + + SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE( + SWIFTEN_PUBSUBMANAGER_DECLARE_CREATE_REQUEST) + + boost::signal<void (const JID&, const boost::shared_ptr<PubSubEventPayload>)> onEvent; + }; +} diff --git a/Swiften/PubSub/PubSubManagerImpl.cpp b/Swiften/PubSub/PubSubManagerImpl.cpp new file mode 100644 index 0000000..38b02aa --- /dev/null +++ b/Swiften/PubSub/PubSubManagerImpl.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/PubSub/PubSubManagerImpl.h> + +#include <boost/bind.hpp> + +#include <Swiften/Client/StanzaChannel.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/PubSubEvent.h> + +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->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()); + } +} diff --git a/Swiften/PubSub/PubSubManagerImpl.h b/Swiften/PubSub/PubSubManagerImpl.h new file mode 100644 index 0000000..ba363ef --- /dev/null +++ b/Swiften/PubSub/PubSubManagerImpl.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/smart_ptr/make_shared.hpp> + +#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); \ + } + +namespace Swift { + class JID; + class StanzaChannel; + class Message; + + class SWIFTEN_API PubSubManagerImpl : public PubSubManager { + public: + PubSubManagerImpl(StanzaChannel* stanzaChannel, IQRouter* router); + virtual ~PubSubManagerImpl(); + + SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE( + SWIFTEN_PUBSUBMANAGERIMPL_DECLARE_CREATE_REQUEST) + + private: + void handleMessageRecevied(boost::shared_ptr<Message>); + + private: + StanzaChannel* stanzaChannel; + IQRouter* router; + }; +} diff --git a/Swiften/PubSub/PubSubUtil.h b/Swiften/PubSub/PubSubUtil.h new file mode 100644 index 0000000..3342659 --- /dev/null +++ b/Swiften/PubSub/PubSubUtil.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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) + diff --git a/Swiften/QA/ClientTest/ClientTest.cpp b/Swiften/QA/ClientTest/ClientTest.cpp index 397921a..e88e5ac 100644 --- a/Swiften/QA/ClientTest/ClientTest.cpp +++ b/Swiften/QA/ClientTest/ClientTest.cpp @@ -18,19 +18,19 @@ using namespace Swift; -SimpleEventLoop eventLoop; -BoostNetworkFactories networkFactories(&eventLoop); +static SimpleEventLoop eventLoop; +static BoostNetworkFactories networkFactories(&eventLoop); -Client* client = 0; -bool rosterReceived = false; +static Client* client = 0; +static bool rosterReceived = false; enum TestStage { FirstConnect, Reconnect }; -TestStage stage; -ClientOptions options; +static TestStage stage; +static ClientOptions options; -void handleDisconnected(boost::optional<ClientError> e) { +static void handleDisconnected(boost::optional<ClientError> e) { std::cout << "Disconnected: " << e << std::endl; if (stage == FirstConnect) { stage = Reconnect; @@ -41,13 +41,13 @@ void handleDisconnected(boost::optional<ClientError> e) { } } -void handleRosterReceived(boost::shared_ptr<Payload>) { +static void handleRosterReceived(boost::shared_ptr<Payload>) { rosterReceived = true; std::cout << "Disconnecting" << std::endl; client->disconnect(); } -void handleConnected() { +static void handleConnected() { std::cout << "Connected" << std::endl; rosterReceived = false; GetRosterRequest::ref rosterRequest = GetRosterRequest::create(client->getIQRouter()); diff --git a/Swiften/QA/NetworkTest/BoostConnectionTest.cpp b/Swiften/QA/NetworkTest/BoostConnectionTest.cpp index 335f2d2..53faff7 100644 --- a/Swiften/QA/NetworkTest/BoostConnectionTest.cpp +++ b/Swiften/QA/NetworkTest/BoostConnectionTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -18,7 +18,7 @@ #include <Swiften/Network/BoostIOServiceThread.h> #include <Swiften/EventLoop/DummyEventLoop.h> -const unsigned char* address = reinterpret_cast<const unsigned char*>("\x41\x63\xde\x89"); +static const unsigned char* address = reinterpret_cast<const unsigned char*>("\x4A\x32\x3e\x31"); using namespace Swift; @@ -70,7 +70,7 @@ class BoostConnectionTest : public CppUnit::TestFixture { 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("65.99.222.137"), 5222)); + testling->connect(HostAddressPort(HostAddress("74.50.62.49"), 5222)); while (receivedData.empty()) { Swift::sleep(10); eventLoop_->processEvents(); @@ -97,7 +97,7 @@ class BoostConnectionTest : public CppUnit::TestFixture { 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("65.99.222.137"), 5222)); + testling->connect(HostAddressPort(HostAddress("74.50.62.49"), 5222)); while (!connectFinished) { boostIOService->run_one(); eventLoop_->processEvents(); diff --git a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp index 7cb9ed3..bc4f1a3 100644 --- a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp +++ b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp @@ -9,14 +9,22 @@ #include <boost/bind.hpp> #include <algorithm> - #include <Swiften/Base/sleep.h> #include <string> #include <Swiften/Base/ByteArray.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; @@ -30,23 +38,34 @@ class DomainNameResolverTest : public CppUnit::TestFixture { 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); +#endif CPPUNIT_TEST(testResolveAddress_Localhost); CPPUNIT_TEST(testResolveAddress_Parallel); +#ifndef USE_UNBOUND CPPUNIT_TEST(testResolveService); +#endif CPPUNIT_TEST(testResolveService_Error); CPPUNIT_TEST_SUITE_END(); public: void setUp() { + ioServiceThread = new BoostIOServiceThread(); eventLoop = new DummyEventLoop(); - resolver = new PlatformDomainNameResolver(eventLoop); +#ifdef USE_UNBOUND + resolver = new UnboundDomainNameResolver(ioServiceThread->getIOService(), eventLoop); +#else + idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); + resolver = new PlatformDomainNameResolver(idnConverter.get(), eventLoop); +#endif resultsAvailable = false; } void tearDown() { + delete ioServiceThread; delete resolver; delete eventLoop; } @@ -208,13 +227,16 @@ class DomainNameResolverTest : public CppUnit::TestFixture { } 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; - PlatformDomainNameResolver* resolver; + DomainNameResolver* resolver; }; CPPUNIT_TEST_SUITE_REGISTRATION(DomainNameResolverTest); diff --git a/Swiften/QA/NetworkTest/SConscript b/Swiften/QA/NetworkTest/SConscript index e1dea26..b090165 100644 --- a/Swiften/QA/NetworkTest/SConscript +++ b/Swiften/QA/NetworkTest/SConscript @@ -11,6 +11,9 @@ if env["TEST"] : myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) + if env.get("unbound", False) : + myenv.Append(CPPDEFINES = ["USE_UNBOUND"]) + tester = myenv.Program("NetworkTest", [ "BoostConnectionServerTest.cpp", "BoostConnectionTest.cpp", diff --git a/Swiften/QA/ScriptedTests/MultipleClients.lua b/Swiften/QA/ScriptedTests/MultipleClients.lua index ce51481..ddc7c44 100644 --- a/Swiften/QA/ScriptedTests/MultipleClients.lua +++ b/Swiften/QA/ScriptedTests/MultipleClients.lua @@ -1,5 +1,5 @@ -- --- Copyright (c) 2010 Remko Tronçon +-- Copyright (c) 2010-2013 Remko Tronçon -- Licensed under the GNU General Public License v3. -- See Documentation/Licenses/GPLv3.txt for more information. -- @@ -16,17 +16,17 @@ for i = 1, num_clients do client = sluift.new_client(jid, os.getenv("SWIFT_CLIENTTEST_PASS")) client:set_options({compress = false}) client:async_connect() - table.insert(clients, client) + clients[#clients+1] = client end print("Waiting for clients to be connected") -for i, client in ipairs(clients) do +for _, client in ipairs(clients) do client:wait_connected() client:send_presence("Hello") end print("Disconnecting clients") -for i, client in ipairs(clients) do +for _, client in ipairs(clients) do client:disconnect() end diff --git a/Swiften/QA/ScriptedTests/PubSub.lua b/Swiften/QA/ScriptedTests/PubSub.lua new file mode 100644 index 0000000..43cce14 --- /dev/null +++ b/Swiften/QA/ScriptedTests/PubSub.lua @@ -0,0 +1,340 @@ + --[[ + Copyright (c) 2013 Remko Tronçon + Licensed under the GNU General Public License. + See the COPYING file for more information. +--]] + +require 'sluift' + +sluift.debug = os.getenv("SLUIFT_DEBUG") + +local publisher +local publisher_jid = os.getenv("SLUIFT_JID") +local pubsub_jid = os.getenv("SLUIFT_PUBSUB_SERVICE") or sluift.jid.to_bare(publisher_jid) +local pubsub +local node_id = os.getenv("SLUIFT_PUBSUB_NODE") or "http://swift.im/Swiften/QA/PubSub" +local node + +local subscriber +local subscriber_jid = os.getenv("SLUIFT_JID2") +local subscriber_pubsub +local subscriber_node + +local publish_item = {id = 'item_id', data = {{ _type = 'software_version', name = 'MyTest', os = 'Lua' }} } +local publish_item2 = {id = 'item_id2', data = {{ _type = 'software_version', name = 'MyTest2', os = 'Lua' }} } +local publish_item3 = {id = 'item_id3', data = {{ _type = 'software_version', name = 'MyTest3', os = 'Lua' }} } + +-------------------------------------------------------------------------------- +-- Helper methods +-------------------------------------------------------------------------------- + +function purge_pubsub_events(client) + client:for_each_pubsub_event({timeout = 2000}, function() end) +end + +-------------------------------------------------------------------------------- +-- 5. Entity use cases +-------------------------------------------------------------------------------- +function test_entity_use_cases() + node:delete() + + -- 5.2 List nodes + assert(node:create()) + local nodes = assert(pubsub:list_nodes()).items + local found_item = false + for _, node in ipairs(nodes) do + if node.node == node_id then found_item = true end + end + assert(found_item) + assert(node:delete()) + + + -- 5.5 Discover items of node + assert(node:create()) + assert(node:publish {items = {publish_item}}) + local items = assert(node:list_items()).items + assert(#items == 1) + assert(items[1].name == 'item_id') + assert(node:delete()) + + -- 5.6 Subscriptions + assert(node:create()) + assert(subscriber_node:subscribe({ jid = subscriber_jid })) + 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 + --print(pubsub:get_affiliations()) -- Freezes Isode + --print(node:get_affiliations()) -- Freezes isode +end + +-------------------------------------------------------------------------------- +-- 6. Subscriber use cases +-------------------------------------------------------------------------------- + +function test_subscriber_use_cases() + node:delete() + + -- 6.1 Subscribe to a node + assert(node:create()) + local subscription = assert(subscriber_node:subscribe({ jid = subscriber_jid })) + -- TODO: Test subscription id etc. Doesn't work with M-link atm + -- TODO: Test pending subscription + -- TODO: Test configuration required + assert(node:delete()) + + -- 6.2 Unsubscribe from a node + assert(node:create()) + assert(subscriber_node:subscribe({ jid = subscriber_jid })) + assert(subscriber_node:unsubscribe({ jid = subscriber_jid })) + assert(node:delete()) + + -- 6.3 Configure subscription options + -- TODO: Not supported by M-Link? Finish it later + --assert(node:create()) + --assert(subscriber_node:subscribe({ jid = subscriber_jid })) + --local options = assert(subscriber_node:get_subscription_options({ jid = subscriber_jid })) + --print(options) + --assert(node:delete()) + + -- 6.4 Request default subscription configuration options + -- TODO: Not supported by M-Link? Finish it later + --local options = assert(subscriber_pubsub:get_default_subscription_options()) + --print(options) + --local options = assert(subscriber_node:get_default_subscription_options()) + --print(options) + + -- 6.5 Retrieve items of a node + assert(node:create()) + assert(node:set_configuration{configuration = {['pubsub#max_items'] = '10'}}) + assert(node:publish{item = publish_item}) + assert(node:publish{item = publish_item2}) + local items = assert(subscriber_node:get_items()) + assert(#items == 2) + assert(items[1].id == 'item_id') + assert(items[1].data[1].name == 'MyTest') + assert(items[2].id == 'item_id2') + assert(items[2].data[1].name == 'MyTest2') + assert(node:delete()) + + -- 6.5.7 Requesting most recent items + assert(node:create()) + assert(node:set_configuration{configuration = {['pubsub#max_items'] = '10'}}) + assert(node:publish{item = publish_item}) + assert(node:publish{item = publish_item2}) + assert(node:publish{item = publish_item3}) + local items = assert(subscriber_node:get_items{maximum_items = 2}) + assert(#items == 2) + assert(items[1].id == 'item_id2') + assert(items[1].data[1].name == 'MyTest2') + assert(items[2].id == 'item_id3') + assert(items[2].data[1].name == 'MyTest3') + assert(node:delete()) + + -- 6.5.8 requesting specific item + assert(node:create()) + assert(node:set_configuration{configuration = {['pubsub#max_items'] = '10'}}) + assert(node:publish{item = publish_item}) + assert(node:publish{item = publish_item2}) + local items = assert(subscriber_node:get_item{id = 'item_id2'}) + assert(#items == 1) + assert(items[1].id == 'item_id2') + assert(items[1].data[1].name == 'MyTest2') + assert(node:delete()) +end + +-------------------------------------------------------------------------------- +-- 7. Publisher use cases +-------------------------------------------------------------------------------- + +function test_publisher_use_cases() + node:delete() + + -- 7.1 Publish item to a node + assert(node:create()) + assert(subscriber_node:subscribe({ jid = subscriber_jid })) + purge_pubsub_events(subscriber) + assert(node:publish {items = {publish_item}}) + local event = assert(subscriber:get_next_event { type = 'pubsub' }) + assert(event.from == publisher_jid) + assert(event._type == 'pubsub_event_items') + assert(event.items[1].id == publish_item.id) + assert(event.items[1].data[1].os == publish_item.data[1].os) + assert(event.item.os == publish_item.data[1].os) + assert(node:delete()) + + -- 7.2 Delete item from a node + assert(node:create()) + assert(subscriber_node:subscribe({ jid = subscriber_jid })) + assert(node:publish {items = {publish_item}}) + assert(node:retract { id = 'item_id', notify = true }) + assert(node:delete()) + + -- 7.2.2.1 Delete and notify + assert(node:create()) + assert(subscriber_node:subscribe({ jid = subscriber_jid })) + assert(node:publish {items = {publish_item}}) + purge_pubsub_events(subscriber) + assert(node:retract { id = 'item_id', notify = true }) + local event = assert(subscriber:get_next_event { type = 'pubsub' }) + assert(event._type == 'pubsub_event_items') + assert(event.retracts[1].id == 'item_id') + assert(node:delete()) + + -- Publish an unknown element type + atom = [[ + <entry xmlns='http://www.w3.org/2005/Atom'> + <title>Down the Rabbit Hole</title> + <summary> + Alice was beginning to get very tired of sitting by her sister on the + bank and of having nothing to do: once or twice she had peeped into the + book her sister was reading, but it had no pictures or conversations in + it, "and what is the use of a book," thought Alice, "without pictures + or conversations?' + </summary> + <link rel='alternate' type='text/html' + href='http://www.gutenberg.org/files/11/11-h/11-h.htm#link2HCH0001'/> + <id>tag:gutenberg.org,2008:entry-1234</id> + <published>2008-06-25T18:30:02Z</published> + <updated>2008-06-25T18:30:02Z</updated> + </entry> + ]] + assert(node:create()) + assert(subscriber_node:subscribe({ jid = subscriber_jid })) + purge_pubsub_events(subscriber) + assert(node:publish { item = atom }) + local event_item = assert(subscriber:get_next_event { type = 'pubsub' }).item + assert(event_item._type == 'dom') + assert(event_item.ns == 'http://www.w3.org/2005/Atom') + assert(event_item.tag == 'entry') + assert(node:delete()) +end + +-------------------------------------------------------------------------------- +-- 8 Owner Use Cases +-------------------------------------------------------------------------------- + +function test_owner_use_cases() + node:delete() + + -- 8.1 Create a node + -- Create node with default config + assert(node:create()) + configuration = assert(node:get_configuration())['data'] + assert(node:delete()) + + -- Create node with custom config + print("Creating with configuration") + assert(node:create { configuration = { ['pubsub#access_model'] = 'whitelist' } }) + configuration = assert(node:get_configuration())['data'] + assert(configuration['pubsub#access_model']['value'] == 'whitelist') + assert(node:delete()) + + -- 8.2 Configure node + -- Set configuration + assert(node:create()) + assert(node:set_configuration {configuration = {['pubsub#access_model'] = 'whitelist'}}) + configuration = assert(node:get_configuration())['data'] + assert(configuration['pubsub#access_model']['value'] == 'whitelist') + assert(node:delete()) + + -- Untested: 8.2.5.3 Success With Notifications + + -- 8.3 Request Default Node Configuration Options + configuration = assert(pubsub:get_default_configuration())['data'] + assert(configuration['pubsub#access_model'] ~= nil) + + -- 8.4 Delete node + -- Without redirection (see above) + -- With redirection + assert(node:create()) + assert(subscriber_node:subscribe({ jid = subscriber_jid })) + purge_pubsub_events(subscriber) + assert(node:delete {redirect = 'foo@bar.com'}) + -- FIXME: M-Link doesn't send out an event. Test this later. + --local event = assert(subscriber:get_next_event { type = 'pubsub' }) + --print(event) + --assert(event._type == 'pubsub_event_items') + --assert(event.retracts[1].id == 'item_id') + + -- 8.5 Purge node items + assert(node:create()) + assert(subscriber_node:subscribe({ jid = subscriber_jid })) + -- Publishing multiple items doesn't seem to work in M-Link + --assert(node:publish {items = { publish_item, publish_item2 }}) + assert(node:publish {items = {publish_item} }) + assert(node:publish {items = {publish_item2} }) + purge_pubsub_events(subscriber) + if node:purge() then + -- Hasn't worked yet. Add more to this test later (including notifications) + else + print("Warning: Purge not supported. Skipping test") + end + assert(node:delete()) + + -- 8.6 Manage subscription requests + -- TODO + + -- 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() + connect_options = {} + + -- Set up publisher & subscriber + publisher = sluift.new_client(publisher_jid, os.getenv("SLUIFT_PASS")) + assert(publisher:connect(connect_options)) + subscriber = sluift.new_client(subscriber_jid, os.getenv("SLUIFT_PASS2")) + assert(subscriber:connect(connect_options)) + + pubsub = publisher:pubsub(pubsub_jid) + node = pubsub:node(node_id) + + subscriber_pubsub = subscriber:pubsub(pubsub_jid) + subscriber_node = subscriber_pubsub:node(node_id) + + -- The tests + test_entity_use_cases() + test_subscriber_use_cases() + test_publisher_use_cases() + test_owner_use_cases() +end + +success, err = pcall(run_tests) + +if subscriber then subscriber:disconnect() end +if publisher then publisher:disconnect() end + +if not success then + print(err) + os.exit(-1) +end diff --git a/Swiften/QA/ScriptedTests/SendMessage.lua b/Swiften/QA/ScriptedTests/SendMessage.lua index 8c54d00..9623ef4 100644 --- a/Swiften/QA/ScriptedTests/SendMessage.lua +++ b/Swiften/QA/ScriptedTests/SendMessage.lua @@ -1,5 +1,5 @@ -- --- Copyright (c) 2010 Remko Tronçon +-- Copyright (c) 2010-2013 Remko Tronçon -- Licensed under the GNU General Public License v3. -- See Documentation/Licenses/GPLv3.txt for more information. -- @@ -23,22 +23,22 @@ client2:send_presence("I'm here") print "Checking version of client 2 from client 1" client2:set_version({name = "Sluift Test", version = "1.0"}) -client2_version = client1:get_version(client2_jid) +client2_version = client1:get_software_version {to=client2_jid} assert(client2_version["name"] == "Sluift Test") assert(client2_version["version"] == "1.0") print "Sending message from client 1 to client 2" client1:send_message(client2_jid, "Hello") -received_message = client2:for_event(function(event) - if event["type"] == "message" and event["from"] == client1_jid then - return event["body"] - end - end, 10000) +received_message = client2:for_each_message({timeout = 1000}, function(message) + if message["from"] == client1_jid then + return message["body"] + end +end) assert(received_message == "Hello") print "Retrieving the roster" roster = client1:get_roster() -tprint(roster) +sluift.tprint(roster) client1:disconnect() client2:disconnect() diff --git a/Swiften/QA/StorageTest/VCardFileStorageTest.cpp b/Swiften/QA/StorageTest/VCardFileStorageTest.cpp index 7667176..4145696 100644 --- a/Swiften/QA/StorageTest/VCardFileStorageTest.cpp +++ b/Swiften/QA/StorageTest/VCardFileStorageTest.cpp @@ -49,7 +49,7 @@ class VCardFileStorageTest : public CppUnit::TestFixture { boost::filesystem::path vcardFile(vcardsPath / "alice@wonderland.lit%2fTeaRoom.xml"); CPPUNIT_ASSERT(boost::filesystem::exists(vcardFile)); ByteArray data; - data.readFromFile(vcardFile.string()); + data.readFromFile(vcardFile); CPPUNIT_ASSERT(boost::starts_with(data.toString(), "<vCard xmlns=\"vcard-temp\">")); } diff --git a/Swiften/QA/TLSTest/CertificateTest.cpp b/Swiften/QA/TLSTest/CertificateTest.cpp index 6932881..2fa4c04 100644 --- a/Swiften/QA/TLSTest/CertificateTest.cpp +++ b/Swiften/QA/TLSTest/CertificateTest.cpp @@ -32,7 +32,7 @@ class CertificateTest : public CppUnit::TestFixture { public: void setUp() { pathProvider = new PlatformApplicationPathProvider("FileReadBytestreamTest"); - readByteArrayFromFile(certificateData, (pathProvider->getExecutableDir() / "jabber_org.crt").string()); + readByteArrayFromFile(certificateData, (pathProvider->getExecutableDir() / "jabber_org.crt")); certificateFactory = new CERTIFICATE_FACTORY(); } diff --git a/Swiften/Queries/GenericRequest.h b/Swiften/Queries/GenericRequest.h index 68c86c5..b1b7f8a 100644 --- a/Swiften/Queries/GenericRequest.h +++ b/Swiften/Queries/GenericRequest.h @@ -22,6 +22,9 @@ namespace Swift { template<typename PAYLOAD_TYPE> class GenericRequest : public Request { public: + typedef boost::shared_ptr<GenericRequest<PAYLOAD_TYPE> > ref; + + public: /** * Create a request suitable for client use. * @param type Iq type - Get or Set. @@ -61,7 +64,7 @@ namespace Swift { onResponse(boost::dynamic_pointer_cast<PAYLOAD_TYPE>(payload), error); } - protected: + public: boost::shared_ptr<PAYLOAD_TYPE> getPayloadGeneric() const { return boost::dynamic_pointer_cast<PAYLOAD_TYPE>(getPayload()); } diff --git a/Swiften/Queries/PubSubRequest.h b/Swiften/Queries/PubSubRequest.h new file mode 100644 index 0000000..55bf9e3 --- /dev/null +++ b/Swiften/Queries/PubSubRequest.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Queries/Request.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/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/PubSubOwnerPurge.h> +#include <Swiften/Elements/PubSubOwnerSubscriptions.h> + +namespace Swift { + 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; \ + }; + + 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; + + 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); + } + + 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); + } + + 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); + } + + public: + boost::signal<void (boost::shared_ptr<ResponseType>, ErrorPayload::ref)> onResponse; + }; +} diff --git a/Swiften/Queries/Request.cpp b/Swiften/Queries/Request.cpp index 422f36c..40c8f60 100644 --- a/Swiften/Queries/Request.cpp +++ b/Swiften/Queries/Request.cpp @@ -23,7 +23,7 @@ Request::Request(IQ::Type type, const JID& sender, const JID& receiver, boost::s Request::Request(IQ::Type type, const JID& sender, const JID& receiver, IQRouter* router) : router_(router), type_(type), sender_(sender), receiver_(receiver), sent_(false) { } -void Request::send() { +std::string Request::send() { assert(payload_); assert(!sent_); sent_ = true; @@ -43,6 +43,7 @@ void Request::send() { } router_->sendIQ(iq); + return id_; } bool Request::handleIQ(boost::shared_ptr<IQ> iq) { diff --git a/Swiften/Queries/Request.h b/Swiften/Queries/Request.h index 5e3a4b8..f17cc11 100644 --- a/Swiften/Queries/Request.h +++ b/Swiften/Queries/Request.h @@ -24,12 +24,21 @@ namespace Swift { */ class SWIFTEN_API Request : public IQHandler, public boost::enable_shared_from_this<Request> { public: - void send(); + 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 diff --git a/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp b/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp index 249a538..74cdb85 100644 --- a/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp +++ b/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -8,18 +8,14 @@ #include <cassert> -#include <Swiften/StringCodecs/MD5.h> #include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Base/Concat.h> #include <Swiften/Base/Algorithm.h> +#include <Swiften/Crypto/CryptoProvider.h> namespace Swift { -DIGESTMD5ClientAuthenticator::DIGESTMD5ClientAuthenticator(const std::string& host, const std::string& nonce) : ClientAuthenticator("DIGEST-MD5"), step(Initial), host(host), cnonce(nonce) { -} - -bool DIGESTMD5ClientAuthenticator::canBeUsed() { - return MD5::isAllowedForCrypto(); +DIGESTMD5ClientAuthenticator::DIGESTMD5ClientAuthenticator(const std::string& host, const std::string& nonce, CryptoProvider* crypto) : ClientAuthenticator("DIGEST-MD5"), step(Initial), host(host), cnonce(nonce), crypto(crypto) { } boost::optional<SafeByteArray> DIGESTMD5ClientAuthenticator::getResponse() const { @@ -37,7 +33,7 @@ boost::optional<SafeByteArray> DIGESTMD5ClientAuthenticator::getResponse() const // Compute the response value ByteArray A1 = concat( - MD5::getHash( + 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()) { @@ -45,10 +41,10 @@ boost::optional<SafeByteArray> DIGESTMD5ClientAuthenticator::getResponse() const } ByteArray A2 = createByteArray("AUTHENTICATE:" + digestURI); - std::string responseValue = Hexify::hexify(MD5::getHash(createByteArray( - Hexify::hexify(MD5::getHash(A1)) + ":" + std::string responseValue = Hexify::hexify(crypto->getMD5Hash(createByteArray( + Hexify::hexify(crypto->getMD5Hash(A1)) + ":" + *challenge.getValue("nonce") + ":" + nc + ":" + cnonce + ":" + qop + ":" - + Hexify::hexify(MD5::getHash(A2))))); + + Hexify::hexify(crypto->getMD5Hash(A2))))); DIGESTMD5Properties response; diff --git a/Swiften/SASL/DIGESTMD5ClientAuthenticator.h b/Swiften/SASL/DIGESTMD5ClientAuthenticator.h index 01cdde9..d141401 100644 --- a/Swiften/SASL/DIGESTMD5ClientAuthenticator.h +++ b/Swiften/SASL/DIGESTMD5ClientAuthenticator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -16,22 +16,24 @@ #include <Swiften/Base/SafeByteArray.h> namespace Swift { + class CryptoProvider; + class SWIFTEN_API DIGESTMD5ClientAuthenticator : public ClientAuthenticator { public: - DIGESTMD5ClientAuthenticator(const std::string& host, const std::string& nonce); + 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> >&); - static bool canBeUsed(); private: enum Step { Initial, Response, - Final, + 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 6d406e0..23a3476 100644 --- a/Swiften/SASL/DIGESTMD5Properties.cpp +++ b/Swiften/SASL/DIGESTMD5Properties.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -48,13 +48,13 @@ DIGESTMD5Properties DIGESTMD5Properties::parse(const ByteArray& data) { ByteArray currentKey; ByteArray currentValue; for (size_t i = 0; i < data.size(); ++i) { - char c = data[i]; + char c = static_cast<char>(data[i]); if (inKey) { if (c == '=') { inKey = false; } else { - currentKey.push_back(c); + currentKey.push_back(static_cast<unsigned char>(c)); } } else { @@ -71,7 +71,7 @@ DIGESTMD5Properties DIGESTMD5Properties::parse(const ByteArray& data) { currentValue = ByteArray(); } else { - currentValue.push_back(c); + currentValue.push_back(static_cast<unsigned char>(c)); } } } diff --git a/Swiften/SASL/PLAINMessage.cpp b/Swiften/SASL/PLAINMessage.cpp index 20ffea7..c43b446 100644 --- a/Swiften/SASL/PLAINMessage.cpp +++ b/Swiften/SASL/PLAINMessage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -15,7 +15,7 @@ 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 += value[i]; + authzid += static_cast<char>(value[i]); ++i; } if (i == value.size()) { @@ -23,7 +23,7 @@ PLAINMessage::PLAINMessage(const SafeByteArray& value) { } ++i; while (i < value.size() && value[i] != '\0') { - authcid += value[i]; + authcid += static_cast<char>(value[i]); ++i; } if (i == value.size()) { diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp index 98460b1..44fef76 100644 --- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp +++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp @@ -10,11 +10,10 @@ #include <map> #include <boost/lexical_cast.hpp> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/StringCodecs/Base64.h> -#include <Swiften/StringCodecs/HMAC_SHA1.h> #include <Swiften/StringCodecs/PBKDF2.h> -#include <Swiften/IDN/StringPrep.h> +#include <Swiften/IDN/IDNConverter.h> #include <Swiften/Base/Concat.h> namespace Swift { @@ -36,7 +35,7 @@ static std::string escape(const std::string& s) { } -SCRAMSHA1ClientAuthenticator::SCRAMSHA1ClientAuthenticator(const std::string& nonce, bool useChannelBinding) : ClientAuthenticator(useChannelBinding ? "SCRAM-SHA-1-PLUS" : "SCRAM-SHA-1"), step(Initial), clientnonce(nonce), useChannelBinding(useChannelBinding) { +SCRAMSHA1ClientAuthenticator::SCRAMSHA1ClientAuthenticator(const std::string& nonce, bool useChannelBinding, IDNConverter* idnConverter, CryptoProvider* crypto) : ClientAuthenticator(useChannelBinding ? "SCRAM-SHA-1-PLUS" : "SCRAM-SHA-1"), step(Initial), clientnonce(nonce), useChannelBinding(useChannelBinding), idnConverter(idnConverter), crypto(crypto) { } boost::optional<SafeByteArray> SCRAMSHA1ClientAuthenticator::getResponse() const { @@ -44,9 +43,9 @@ boost::optional<SafeByteArray> SCRAMSHA1ClientAuthenticator::getResponse() const return createSafeByteArray(concat(getGS2Header(), getInitialBareClientMessage())); } else if (step == Proof) { - ByteArray clientKey = HMAC_SHA1()(saltedPassword, createByteArray("Client Key")); - ByteArray storedKey = SHA1::getHash(clientKey); - ByteArray clientSignature = HMAC_SHA1()(createSafeByteArray(storedKey), authMessage); + 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]; @@ -96,13 +95,13 @@ bool SCRAMSHA1ClientAuthenticator::setChallenge(const boost::optional<ByteArray> // Compute all the values needed for the server signature try { - saltedPassword = PBKDF2::encode<HMAC_SHA1>(StringPrep::getPrepared(getPassword(), StringPrep::SASLPrep), salt, iterations); + saltedPassword = PBKDF2::encode(idnConverter->getStringPrepared(getPassword(), IDNConverter::SASLPrep), salt, iterations, crypto); } catch (const std::exception&) { } authMessage = concat(getInitialBareClientMessage(), createByteArray(","), initialServerMessage, createByteArray(","), getFinalMessageWithoutProof()); - ByteArray serverKey = HMAC_SHA1()(saltedPassword, createByteArray("Server Key")); - serverSignature = HMAC_SHA1()(serverKey, authMessage); + ByteArray serverKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Server Key")); + serverSignature = crypto->getHMACSHA1(serverKey, authMessage); step = Proof; return true; @@ -131,7 +130,7 @@ std::map<char, std::string> SCRAMSHA1ClientAuthenticator::parseMap(const std::st i++; } else if (s[i] == ',') { - result[static_cast<size_t>(key)] = value; + result[key] = value; value = ""; expectKey = true; } @@ -148,7 +147,7 @@ std::map<char, std::string> SCRAMSHA1ClientAuthenticator::parseMap(const std::st ByteArray SCRAMSHA1ClientAuthenticator::getInitialBareClientMessage() const { std::string authenticationID; try { - authenticationID = StringPrep::getPrepared(getAuthenticationID(), StringPrep::SASLPrep); + authenticationID = idnConverter->getStringPrepared(getAuthenticationID(), IDNConverter::SASLPrep); } catch (const std::exception&) { } diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h index ace69b0..b713f9f 100644 --- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h +++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -15,9 +15,12 @@ #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 = false); + SCRAMSHA1ClientAuthenticator(const std::string& nonce, bool useChannelBinding, IDNConverter*, CryptoProvider*); void setTLSChannelBindingData(const ByteArray& channelBindingData); @@ -44,6 +47,8 @@ namespace Swift { ByteArray saltedPassword; ByteArray serverSignature; bool useChannelBinding; + IDNConverter* idnConverter; + CryptoProvider* crypto; boost::optional<ByteArray> tlsChannelBindingData; }; } diff --git a/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp b/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp index 38bab15..94bcd0a 100644 --- a/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp +++ b/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -12,6 +12,9 @@ #include <Swiften/SASL/DIGESTMD5ClientAuthenticator.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> + using namespace Swift; class DIGESTMD5ClientAuthenticatorTest : public CppUnit::TestFixture { @@ -23,14 +26,18 @@ class DIGESTMD5ClientAuthenticatorTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_END(); public: + void setUp() { + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } + void testGetInitialResponse() { - DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh"); + DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get()); CPPUNIT_ASSERT(!testling.getResponse()); } void testGetResponse() { - DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh"); + DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); testling.setChallenge(createByteArray( @@ -44,7 +51,7 @@ class DIGESTMD5ClientAuthenticatorTest : public CppUnit::TestFixture { } void testGetResponse_WithAuthorizationID() { - DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh"); + DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), "myauthzid"); testling.setChallenge(createByteArray( @@ -56,6 +63,9 @@ class DIGESTMD5ClientAuthenticatorTest : public CppUnit::TestFixture { 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_REGISTRATION(DIGESTMD5ClientAuthenticatorTest); diff --git a/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp b/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp index f0ca01c..3341ad8 100644 --- a/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp +++ b/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,6 +11,10 @@ #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> using namespace Swift; @@ -39,10 +43,12 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { public: void setUp() { + idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); } void testGetInitialResponse() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH"); + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); SafeByteArray response = *testling.getResponse(); @@ -51,7 +57,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testGetInitialResponse_UsernameHasSpecialChars() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH"); + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); testling.setCredentials(",us=,er=", createSafeByteArray("pass"), ""); SafeByteArray response = *testling.getResponse(); @@ -60,7 +66,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testGetInitialResponse_WithAuthorizationID() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH"); + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), "auth"); SafeByteArray response = *testling.getResponse(); @@ -69,7 +75,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testGetInitialResponse_WithAuthorizationIDWithSpecialChars() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH"); + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), "a=u,th"); SafeByteArray response = *testling.getResponse(); @@ -78,7 +84,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testGetInitialResponse_WithoutChannelBindingWithTLSChannelBindingData() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false); + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get()); testling.setTLSChannelBindingData(createByteArray("xyza")); testling.setCredentials("user", createSafeByteArray("pass"), ""); @@ -88,7 +94,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testGetInitialResponse_WithChannelBindingWithTLSChannelBindingData() { - SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", true); + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", true, idnConverter.get(), crypto.get()); testling.setTLSChannelBindingData(createByteArray("xyza")); testling.setCredentials("user", createSafeByteArray("pass"), ""); @@ -98,7 +104,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testGetFinalResponse() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); @@ -108,7 +114,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testGetFinalResponse_WithoutChannelBindingWithTLSChannelBindingData() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", false); + 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")); @@ -119,7 +125,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testGetFinalResponse_WithChannelBindingWithTLSChannelBindingData() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh", true); + 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")); @@ -130,7 +136,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testSetFinalChallenge() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); @@ -140,7 +146,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testSetChallenge() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); @@ -149,7 +155,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testSetChallenge_InvalidClientNonce() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); bool result = testling.setChallenge(createByteArray("r=abcdefgiABCDEFGH,s=MTIzNDU2NzgK,i=4096")); @@ -158,7 +164,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testSetChallenge_OnlyClientNonce() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); bool result = testling.setChallenge(createByteArray("r=abcdefgh,s=MTIzNDU2NzgK,i=4096")); @@ -167,7 +173,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testSetChallenge_InvalidIterations() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=bla")); @@ -176,7 +182,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testSetChallenge_MissingIterations() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK")); @@ -185,7 +191,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testSetChallenge_ZeroIterations() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=0")); @@ -194,7 +200,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testSetChallenge_NegativeIterations() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get()); testling.setCredentials("user", createSafeByteArray("pass"), ""); bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=-1")); @@ -203,7 +209,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testSetFinalChallenge_InvalidChallenge() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + 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=")); @@ -212,13 +218,16 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { } void testGetResponseAfterFinalChallenge() { - SCRAMSHA1ClientAuthenticator testling("abcdefgh"); + 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()); } + + boost::shared_ptr<IDNConverter> idnConverter; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(SCRAMSHA1ClientAuthenticatorTest); diff --git a/Swiften/SConscript b/Swiften/SConscript index 2111d26..a8daac5 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -6,7 +6,7 @@ Import("env") # Flags ################################################################################ -swiften_dep_modules = ["BOOST", "GCONF", "ICU", "LIBIDN", "ZLIB", "OPENSSL", "LIBXML", "EXPAT", "AVAHI", "LIBMINIUPNPC", "LIBNATPMP", "SQLITE", "SQLITE_ASYNC"] +swiften_dep_modules = ["BOOST", "GCONF", "ICU", "LIBIDN", "ZLIB", "LDNS", "UNBOUND", "OPENSSL", "LIBXML", "EXPAT", "AVAHI", "LIBMINIUPNPC", "LIBNATPMP", "SQLITE"] external_swiften_dep_modules = ["BOOST"] if env["SCONS_STAGE"] == "flags" : @@ -65,7 +65,6 @@ if env["SCONS_STAGE"] == "flags" : 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", []), @@ -121,17 +120,23 @@ if env["SCONS_STAGE"] == "build" : "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", @@ -140,6 +145,8 @@ if env["SCONS_STAGE"] == "build" : "MUC/MUCManager.cpp", "MUC/MUCRegistry.cpp", "MUC/MUCBookmarkManager.cpp", + "PubSub/PubSubManager.cpp", + "PubSub/PubSubManagerImpl.cpp", "Queries/IQChannel.cpp", "Queries/IQHandler.cpp", "Queries/IQRouter.cpp", @@ -206,6 +213,7 @@ if env["SCONS_STAGE"] == "build" : "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", @@ -220,8 +228,6 @@ if env["SCONS_STAGE"] == "build" : "Session/BasicSessionStream.cpp", "Session/BOSHSessionStream.cpp", "StringCodecs/Base64.cpp", - "StringCodecs/SHA256.cpp", - "StringCodecs/MD5.cpp", "StringCodecs/Hexify.cpp", "Whiteboard/WhiteboardResponder.cpp", "Whiteboard/WhiteboardSession.cpp", @@ -233,6 +239,28 @@ if env["SCONS_STAGE"] == "build" : "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", + + "PubSubError", + ] + for element in elements : + sources += [ + "Elements/" + element + ".cpp", + "Serializer/PayloadSerializers/" + element + "Serializer.cpp", + "Parser/PayloadParsers/" + element + "Parser.cpp", + ] SConscript(dirs = [ "Avatars", @@ -240,6 +268,7 @@ if env["SCONS_STAGE"] == "build" : "IDN", "SASL", "TLS", + "Crypto", "EventLoop", "Parser", "JID", @@ -266,11 +295,6 @@ if env["SCONS_STAGE"] == "build" : ]) myenv = swiften_env.Clone() - if myenv["PLATFORM"] == "win32": - sources.append("StringCodecs/SHA1_Windows.cpp") - else: - sources.append("StringCodecs/SHA1.cpp") - if myenv["PLATFORM"] != "darwin" and myenv["PLATFORM"] != "win32" and myenv.get("HAVE_GCONF", 0) : env.MergeFlags(env["GCONF_FLAGS"]) @@ -279,7 +303,7 @@ if env["SCONS_STAGE"] == "build" : myenv.Append(LINKFLAGS = ["-Wl,-soname,libSwiften.so.$SWIFTEN_VERSION_MAJOR"]) myenv["SHLIBSUFFIX"] = "" elif myenv["PLATFORM"] == "darwin" : - myenv.Append(LINKFLAGS = ["-Wl,-install_name,libSwiften.so.$SWIFTEN_VERSION_MAJOR", "-Wl,-compatibility_version,${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}", "-Wl,-current_version,${SWIFTEN_VERSION_MAJOR}.${SWIFTEN_VERSION_MINOR}"]) + 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 = [ @@ -313,10 +337,12 @@ if env["SCONS_STAGE"] == "build" : 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"), @@ -346,6 +372,7 @@ if env["SCONS_STAGE"] == "build" : 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"), @@ -374,8 +401,10 @@ if env["SCONS_STAGE"] == "build" : 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"), @@ -399,6 +428,7 @@ if env["SCONS_STAGE"] == "build" : 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"), @@ -423,6 +453,7 @@ if env["SCONS_STAGE"] == "build" : 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"), @@ -435,11 +466,7 @@ if env["SCONS_STAGE"] == "build" : File("StreamStack/UnitTest/StreamStackTest.cpp"), File("StreamStack/UnitTest/XMPPLayerTest.cpp"), File("StringCodecs/UnitTest/Base64Test.cpp"), - File("StringCodecs/UnitTest/SHA1Test.cpp"), - File("StringCodecs/UnitTest/SHA256Test.cpp"), - File("StringCodecs/UnitTest/MD5Test.cpp"), File("StringCodecs/UnitTest/HexifyTest.cpp"), - File("StringCodecs/UnitTest/HMACTest.cpp"), File("StringCodecs/UnitTest/PBKDF2Test.cpp"), File("TLS/UnitTest/ServerIdentityVerifierTest.cpp"), File("TLS/UnitTest/CertificateTest.cpp"), @@ -474,7 +501,7 @@ if env["SCONS_STAGE"] == "build" : 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" : + 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 diff --git a/Swiften/Serializer/PayloadSerializers/BlockSerializer.h b/Swiften/Serializer/PayloadSerializers/BlockSerializer.h index 345463c..fc628c2 100644 --- a/Swiften/Serializer/PayloadSerializers/BlockSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/BlockSerializer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -8,9 +8,9 @@ #include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/JID/JID.h> #include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Base/foreach.h> namespace Swift { template<typename BLOCK_ELEMENT> @@ -19,11 +19,13 @@ namespace Swift { BlockSerializer(std::string tag) : GenericPayloadSerializer<BLOCK_ELEMENT>(), tag(tag) { } - virtual std::string serializePayload(boost::shared_ptr<BLOCK_ELEMENT> payload) const { + virtual std::string serializePayload(boost::shared_ptr<BLOCK_ELEMENT> payload) const { XMLElement element(tag, "urn:xmpp:blocking"); - foreach (const JID& jid, payload->getItems()) { + 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", jid); + item->setAttribute("jid", *i); + element.addNode(item); } return element.serialize(); } diff --git a/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp index ee468bb..d23cad7 100644 --- a/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/ChatStateSerializer.cpp @@ -19,7 +19,6 @@ std::string ChatStateSerializer::serializePayload(boost::shared_ptr<ChatState> c case ChatState::Paused: result += "paused"; break; case ChatState::Inactive: result += "inactive"; break; case ChatState::Gone: result += "gone"; break; - default: result += "gone"; break; } result += " xmlns=\"http://jabber.org/protocol/chatstates\"/>"; return result; diff --git a/Swiften/Serializer/PayloadSerializers/ErrorSerializer.cpp b/Swiften/Serializer/PayloadSerializers/ErrorSerializer.cpp index fa6a566..954b885 100644 --- a/Swiften/Serializer/PayloadSerializers/ErrorSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/ErrorSerializer.cpp @@ -20,7 +20,7 @@ std::string ErrorSerializer::serializePayload(boost::shared_ptr<ErrorPayload> er case ErrorPayload::Modify: result += "modify"; break; case ErrorPayload::Auth: result += "auth"; break; case ErrorPayload::Wait: result += "wait"; break; - default: result += "cancel"; break; + case ErrorPayload::Cancel: result += "cancel"; break; } result += "\">"; @@ -47,7 +47,7 @@ std::string ErrorSerializer::serializePayload(boost::shared_ptr<ErrorPayload> er case ErrorPayload::ServiceUnavailable: conditionElement = "service-unavailable"; break; case ErrorPayload::SubscriptionRequired: conditionElement = "subscription-required"; break; case ErrorPayload::UnexpectedRequest: conditionElement = "unexpected-request"; break; - default: conditionElement = "undefined-condition"; break; + case ErrorPayload::UndefinedCondition: conditionElement = "undefined-condition"; break; } result += "<" + conditionElement + " xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>"; diff --git a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp index ba658e3..cf0f4ea 100644 --- a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -37,6 +37,10 @@ FormSerializer::FormSerializer() : GenericPayloadSerializer<Form>() { } 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()) { @@ -92,66 +96,27 @@ boost::shared_ptr<XMLElement> FormSerializer::fieldToXML(boost::shared_ptr<FormF // Set the value and type std::string fieldType; - if (boost::dynamic_pointer_cast<BooleanFormField>(field)) { - fieldType = "boolean"; - boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); - valueElement->addNode(XMLTextNode::create(boost::dynamic_pointer_cast<BooleanFormField>(field)->getValue() ? "1" : "0")); - fieldElement->addNode(valueElement); - } - else if (boost::dynamic_pointer_cast<FixedFormField>(field)) { - fieldType = "fixed"; - serializeValueAsString<FixedFormField>(field, fieldElement); - } - else if (boost::dynamic_pointer_cast<HiddenFormField>(field)) { - fieldType = "hidden"; - serializeValueAsString<HiddenFormField>(field, fieldElement); - } - else if (boost::dynamic_pointer_cast<ListSingleFormField>(field)) { - fieldType = "list-single"; - serializeValueAsString<ListSingleFormField>(field, fieldElement); - } - else if (boost::dynamic_pointer_cast<TextPrivateFormField>(field)) { - fieldType = "text-private"; - serializeValueAsString<TextPrivateFormField>(field, fieldElement); - } - else if (boost::dynamic_pointer_cast<TextSingleFormField>(field)) { - fieldType = "text-single"; - serializeValueAsString<TextSingleFormField>(field, fieldElement); - } - else if (boost::dynamic_pointer_cast<JIDMultiFormField>(field)) { - fieldType = "jid-multi"; - std::vector<JID> jids = boost::dynamic_pointer_cast<JIDMultiFormField>(field)->getValue(); - foreach(const JID& jid, jids) { - boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); - valueElement->addNode(XMLTextNode::create(jid.toString())); - fieldElement->addNode(valueElement); - } - } - else if (boost::dynamic_pointer_cast<JIDSingleFormField>(field)) { - fieldType = "jid-single"; - boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); - valueElement->addNode(XMLTextNode::create(boost::dynamic_pointer_cast<JIDSingleFormField>(field)->getValue().toString())); - if ( boost::dynamic_pointer_cast<JIDSingleFormField>(field)->getValue().isValid()) fieldElement->addNode(valueElement); - } - else if (boost::dynamic_pointer_cast<ListMultiFormField>(field)) { - fieldType = "list-multi"; - std::vector<std::string> lines = boost::dynamic_pointer_cast<ListMultiFormField>(field)->getValue(); - foreach(const std::string& line, lines) { - boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); - valueElement->addNode(XMLTextNode::create(line)); - fieldElement->addNode(valueElement); - } - } - else if (boost::dynamic_pointer_cast<TextMultiFormField>(field)) { - fieldType = "text-multi"; - multiLineify(boost::dynamic_pointer_cast<TextMultiFormField>(field)->getValue(), "value", fieldElement); - } - else { - assert(false); + 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")); diff --git a/Swiften/Serializer/PayloadSerializers/FormSerializer.h b/Swiften/Serializer/PayloadSerializers/FormSerializer.h index bb31c97..f0f365c 100644 --- a/Swiften/Serializer/PayloadSerializers/FormSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/FormSerializer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp index b4822cd..a57a74e 100644 --- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp +++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -51,6 +51,12 @@ #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> @@ -110,6 +116,8 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() { 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()); @@ -122,6 +130,11 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() { 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()); foreach(PayloadSerializer* serializer, serializers_) { addSerializer(serializer); diff --git a/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp b/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp index e78cdb4..c83b293 100644 --- a/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp @@ -8,6 +8,7 @@ #include <boost/shared_ptr.hpp> #include <boost/smart_ptr/make_shared.hpp> +#include <cassert> #include <boost/lexical_cast.hpp> #include <Swiften/Base/foreach.h> @@ -48,6 +49,7 @@ std::string IBBSerializer::serializePayload(boost::shared_ptr<IBB> ibb) const { return ibbElement.serialize(); } } + assert(false); return ""; } diff --git a/Swiften/Serializer/PayloadSerializers/IdleSerializer.h b/Swiften/Serializer/PayloadSerializers/IdleSerializer.h new file mode 100644 index 0000000..45f9da4 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/IdleSerializer.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2013 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/Idle.h> +#include <Swiften/Base/DateTime.h> + +namespace Swift { + class 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()) + "'/>"; + } + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp index 48da742..0e21812 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/JingleContentPayloadSerializer.cpp @@ -20,8 +20,6 @@ #include <Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h> #include <Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h> -#include "Swiften/FileTransfer/JingleTransport.h" - namespace Swift { JingleContentPayloadSerializer::JingleContentPayloadSerializer() { diff --git a/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp index 029a5b4..61e093f 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.cpp @@ -22,7 +22,9 @@ JingleIBBTransportPayloadSerializer::JingleIBBTransportPayloadSerializer() { std::string JingleIBBTransportPayloadSerializer::serializePayload(boost::shared_ptr<JingleIBBTransportPayload> payload) const { XMLElement payloadXML("transport", "urn:xmpp:jingle:transports:ibb:1"); - payloadXML.setAttribute("block-size", boost::lexical_cast<std::string>(payload->getBlockSize())); + if (payload->getBlockSize()) { + payloadXML.setAttribute("block-size", boost::lexical_cast<std::string>(*payload->getBlockSize())); + } payloadXML.setAttribute("sid", payload->getSessionID()); return payloadXML.serialize(); diff --git a/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp index 24e30e6..26df08c 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/MUCInvitationPayloadSerializer.cpp @@ -37,6 +37,9 @@ std::string MUCInvitationPayloadSerializer::serializePayload(boost::shared_ptr<M 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(); } diff --git a/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h index 2b5ffcc..2f2623f 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h @@ -23,7 +23,6 @@ namespace Swift { case MUCOccupant::Member: result = "member"; break; case MUCOccupant::Outcast: result = "outcast"; break; case MUCOccupant::NoAffiliation: result = "none"; break; - default: assert(false); } return result; } @@ -35,7 +34,6 @@ namespace Swift { case MUCOccupant::NoRole: result = "none"; break; case MUCOccupant::Participant: result = "participant"; break; case MUCOccupant::Visitor: result = "visitor"; break; - default: assert(false); } return result; diff --git a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.cpp new file mode 100644 index 0000000..d5d5ead --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> + + +using namespace Swift; + +PubSubAffiliationSerializer::PubSubAffiliationSerializer(PayloadSerializerCollection* serializers) : serializers(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::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 ""; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.h new file mode 100644 index 0000000..f6722c8 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubAffiliation.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubAffiliationSerializer : public GenericPayloadSerializer<PubSubAffiliation> { + public: + PubSubAffiliationSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubAffiliationSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubAffiliation>) const SWIFTEN_OVERRIDE; + + private: + static std::string serializeType(PubSubAffiliation::Type); + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.cpp new file mode 100644 index 0000000..25a0786 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubAffiliationSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubAffiliationsSerializer::PubSubAffiliationsSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.h new file mode 100644 index 0000000..ba3c591 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubAffiliations.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubAffiliationsSerializer : public GenericPayloadSerializer<PubSubAffiliations> { + public: + PubSubAffiliationsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubAffiliationsSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubAffiliations>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.cpp new file mode 100644 index 0000000..86a1ae8 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubConfigureSerializer::PubSubConfigureSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h new file mode 100644 index 0000000..093fd35 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubConfigure.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.cpp new file mode 100644 index 0000000..73b2703 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubCreateSerializer::PubSubCreateSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.h new file mode 100644 index 0000000..29c2393 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubCreateSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubCreate.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.cpp new file mode 100644 index 0000000..d395c80 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubDefaultSerializer::PubSubDefaultSerializer(PayloadSerializerCollection* serializers) : serializers(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::serializeType(PubSubDefault::Type value) { + 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 new file mode 100644 index 0000000..e7b8a6f --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubDefaultSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubDefault.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubDefaultSerializer : public GenericPayloadSerializer<PubSubDefault> { + public: + PubSubDefaultSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubDefaultSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubDefault>) const SWIFTEN_OVERRIDE; + + private: + static std::string serializeType(PubSubDefault::Type); + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.cpp new file mode 100644 index 0000000..a25b71e --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h> +#include <Swiften/Serializer/XML/XMLElement.h> + +#include <Swiften/Serializer/PayloadSerializerCollection.h> + +using namespace Swift; + +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::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 ""; +} + +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 ""; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h new file mode 100644 index 0000000..3ee09ce --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubErrorSerializer.h @@ -0,0 +1,28 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubError.h> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubErrorSerializer : public GenericPayloadSerializer<PubSubError> { + public: + PubSubErrorSerializer(); + virtual ~PubSubErrorSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubError>) const SWIFTEN_OVERRIDE; + + 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 new file mode 100644 index 0000000..1baf7e4 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubEventAssociateSerializer::PubSubEventAssociateSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.h new file mode 100644 index 0000000..60cf9c7 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventAssociate.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.cpp new file mode 100644 index 0000000..b44acaa --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventAssociateSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubEventCollectionSerializer::PubSubEventCollectionSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.h new file mode 100644 index 0000000..ac5e7c4 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventCollection.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubEventCollectionSerializer : public GenericPayloadSerializer<PubSubEventCollection> { + public: + PubSubEventCollectionSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventCollectionSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubEventCollection>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.cpp new file mode 100644 index 0000000..f478e4f --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubEventConfigurationSerializer::PubSubEventConfigurationSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.h new file mode 100644 index 0000000..6a73496 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventConfigurationSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventConfiguration.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.cpp new file mode 100644 index 0000000..b45adb8 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubEventDeleteSerializer::PubSubEventDeleteSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.h new file mode 100644 index 0000000..10de3c3 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventDelete.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubEventDeleteSerializer : public GenericPayloadSerializer<PubSubEventDelete> { + public: + PubSubEventDeleteSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventDeleteSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubEventDelete>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.cpp new file mode 100644 index 0000000..60cc562 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubEventDisassociateSerializer::PubSubEventDisassociateSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.h new file mode 100644 index 0000000..c7187c7 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventDisassociateSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventDisassociate.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.cpp new file mode 100644 index 0000000..2b8b08e --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubEventItemSerializer::PubSubEventItemSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.h new file mode 100644 index 0000000..93fa5b0 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventItem.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubEventItemSerializer : public GenericPayloadSerializer<PubSubEventItem> { + public: + PubSubEventItemSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventItemSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubEventItem>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.cpp new file mode 100644 index 0000000..099aa4b --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventItemSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubEventItemsSerializer::PubSubEventItemsSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.h new file mode 100644 index 0000000..6e60ee4 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventItems.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubEventItemsSerializer : public GenericPayloadSerializer<PubSubEventItems> { + public: + PubSubEventItemsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventItemsSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubEventItems>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.cpp new file mode 100644 index 0000000..1387848 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubEventPurgeSerializer::PubSubEventPurgeSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.h new file mode 100644 index 0000000..ab2d1d8 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventPurgeSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventPurge.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.cpp new file mode 100644 index 0000000..7134e58 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubEventRedirectSerializer::PubSubEventRedirectSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.h new file mode 100644 index 0000000..751ff19 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventRedirectSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventRedirect.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.cpp new file mode 100644 index 0000000..17d1a0f --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubEventRetractSerializer::PubSubEventRetractSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h new file mode 100644 index 0000000..0d73ec8 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventRetractSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventRetract.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.cpp new file mode 100644 index 0000000..da813cd --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializers/PubSubEventCollectionSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventDeleteSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubEventItemsSerializer.h> +#include <Swiften/Base/foreach.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() { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.h new file mode 100644 index 0000000..85b5b90 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventSerializer.h @@ -0,0 +1,33 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEvent.h> +#include <boost/shared_ptr.hpp> +#include <vector> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubEventSerializer : public GenericPayloadSerializer<PubSubEvent> { + public: + PubSubEventSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubEvent>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + std::vector< boost::shared_ptr<PayloadSerializer> > pubsubSerializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.cpp new file mode 100644 index 0000000..9b0a334 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + +using namespace Swift; + +PubSubEventSubscriptionSerializer::PubSubEventSubscriptionSerializer(PayloadSerializerCollection* serializers) : serializers(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::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 ""; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.h new file mode 100644 index 0000000..3b613bd --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubEventSubscriptionSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubEventSubscription.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubEventSubscriptionSerializer : public GenericPayloadSerializer<PubSubEventSubscription> { + public: + PubSubEventSubscriptionSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubEventSubscriptionSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubEventSubscription>) const SWIFTEN_OVERRIDE; + + private: + static std::string serializeSubscriptionType(PubSubEventSubscription::SubscriptionType); + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.cpp new file mode 100644 index 0000000..5a82b42 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubItemSerializer::PubSubItemSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h new file mode 100644 index 0000000..56f186d --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubItem.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubItemSerializer : public GenericPayloadSerializer<PubSubItem> { + public: + PubSubItemSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubItemSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubItem>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.cpp new file mode 100644 index 0000000..6bffa6a --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <boost/lexical_cast.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubItemsSerializer::PubSubItemsSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.h new file mode 100644 index 0000000..050e156 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubItemsSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubItems.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubItemsSerializer : public GenericPayloadSerializer<PubSubItems> { + public: + PubSubItemsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubItemsSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubItems>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.cpp new file mode 100644 index 0000000..db983b9 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubOptionsSerializer::PubSubOptionsSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h new file mode 100644 index 0000000..258f1f2 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOptions.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.cpp new file mode 100644 index 0000000..3699b8e --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> + + +using namespace Swift; + +PubSubOwnerAffiliationSerializer::PubSubOwnerAffiliationSerializer(PayloadSerializerCollection* serializers) : serializers(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::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 ""; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.h new file mode 100644 index 0000000..acea723 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOwnerAffiliation.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubOwnerAffiliationSerializer : public GenericPayloadSerializer<PubSubOwnerAffiliation> { + public: + PubSubOwnerAffiliationSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerAffiliationSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerAffiliation>) const SWIFTEN_OVERRIDE; + + private: + static std::string serializeType(PubSubOwnerAffiliation::Type); + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.cpp new file mode 100644 index 0000000..c393bfb --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubOwnerAffiliationsSerializer::PubSubOwnerAffiliationsSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.h new file mode 100644 index 0000000..3d20042 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerAffiliationsSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOwnerAffiliations.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubOwnerAffiliationsSerializer : public GenericPayloadSerializer<PubSubOwnerAffiliations> { + public: + PubSubOwnerAffiliationsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerAffiliationsSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerAffiliations>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.cpp new file mode 100644 index 0000000..154a370 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubOwnerConfigureSerializer::PubSubOwnerConfigureSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.h new file mode 100644 index 0000000..41f2a9d --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerConfigureSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOwnerConfigure.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.cpp new file mode 100644 index 0000000..7ce2e71 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializers/FormSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubOwnerDefaultSerializer::PubSubOwnerDefaultSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.h new file mode 100644 index 0000000..02aefe8 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDefaultSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOwnerDefault.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.cpp new file mode 100644 index 0000000..010645c --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubOwnerDeleteSerializer::PubSubOwnerDeleteSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.h new file mode 100644 index 0000000..d537a4f --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOwnerDelete.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubOwnerDeleteSerializer : public GenericPayloadSerializer<PubSubOwnerDelete> { + public: + PubSubOwnerDeleteSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerDeleteSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerDelete>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.cpp new file mode 100644 index 0000000..de7d5a5 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializers/PubSubOwnerDeleteSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.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() { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h new file mode 100644 index 0000000..9f5732b --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h @@ -0,0 +1,33 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOwnerPubSub.h> +#include <boost/shared_ptr.hpp> +#include <vector> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubOwnerPubSubSerializer : public GenericPayloadSerializer<PubSubOwnerPubSub> { + public: + PubSubOwnerPubSubSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerPubSubSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerPubSub>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + std::vector< boost::shared_ptr<PayloadSerializer> > pubsubSerializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.cpp new file mode 100644 index 0000000..591cdf9 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubOwnerPurgeSerializer::PubSubOwnerPurgeSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.h new file mode 100644 index 0000000..51a086f --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerPurgeSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOwnerPurge.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.cpp new file mode 100644 index 0000000..ea7d721 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubOwnerRedirectSerializer::PubSubOwnerRedirectSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.h new file mode 100644 index 0000000..e5d5af5 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerRedirectSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOwnerRedirect.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.cpp new file mode 100644 index 0000000..91bc00b --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> + + +using namespace Swift; + +PubSubOwnerSubscriptionSerializer::PubSubOwnerSubscriptionSerializer(PayloadSerializerCollection* serializers) : serializers(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::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 ""; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.h new file mode 100644 index 0000000..4cecca7 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOwnerSubscription.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubOwnerSubscriptionSerializer : public GenericPayloadSerializer<PubSubOwnerSubscription> { + public: + PubSubOwnerSubscriptionSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerSubscriptionSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerSubscription>) const SWIFTEN_OVERRIDE; + + private: + static std::string serializeSubscriptionType(PubSubOwnerSubscription::SubscriptionType); + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.cpp new file mode 100644 index 0000000..c265662 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionSerializer.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubOwnerSubscriptionsSerializer::PubSubOwnerSubscriptionsSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.h new file mode 100644 index 0000000..d77bc99 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubOwnerSubscriptionsSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubOwnerSubscriptions.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubOwnerSubscriptionsSerializer : public GenericPayloadSerializer<PubSubOwnerSubscriptions> { + public: + PubSubOwnerSubscriptionsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubOwnerSubscriptionsSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubOwnerSubscriptions>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.cpp new file mode 100644 index 0000000..5a150e0 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubPublishSerializer::PubSubPublishSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.h new file mode 100644 index 0000000..9d53141 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubPublishSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubPublish.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubPublishSerializer : public GenericPayloadSerializer<PubSubPublish> { + public: + PubSubPublishSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubPublishSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubPublish>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.cpp new file mode 100644 index 0000000..3f1434b --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubRetractSerializer::PubSubRetractSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.h new file mode 100644 index 0000000..47a01af --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubRetractSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubRetract.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubRetractSerializer : public GenericPayloadSerializer<PubSubRetract> { + public: + PubSubRetractSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubRetractSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubRetract>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubSerializer.cpp new file mode 100644 index 0000000..0e61331 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubSerializer.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubConfigureSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubAffiliationsSerializer.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/PubSubRetractSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubOptionsSerializer.h> +#include <Swiften/Base/foreach.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)); +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubSerializer.h new file mode 100644 index 0000000..7665800 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubSerializer.h @@ -0,0 +1,29 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSub.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubSerializer : public GenericPayloadSerializer<PubSub> { + public: + PubSubSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSub>) const SWIFTEN_OVERRIDE; + + private: + std::vector< boost::shared_ptr<PayloadSerializer> > pubsubSerializers; + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.cpp new file mode 100644 index 0000000..7a55228 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + +using namespace Swift; + +PubSubSubscribeOptionsSerializer::PubSubSubscribeOptionsSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.h new file mode 100644 index 0000000..6ffaac7 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubSubscribeOptions.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.cpp new file mode 100644 index 0000000..83a73af --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubSubscribeSerializer::PubSubSubscribeSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.h new file mode 100644 index 0000000..b730a4d --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscribeSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubSubscribe.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.cpp new file mode 100644 index 0000000..8a54afa --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubSubscribeOptionsSerializer.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubSubscriptionSerializer::PubSubSubscriptionSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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::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 ""; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h new file mode 100644 index 0000000..d03bb69 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubSubscription.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubSubscriptionSerializer : public GenericPayloadSerializer<PubSubSubscription> { + public: + PubSubSubscriptionSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubSubscriptionSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubSubscription>) const SWIFTEN_OVERRIDE; + + private: + static std::string serializeSubscriptionType(PubSubSubscription::SubscriptionType); + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.cpp new file mode 100644 index 0000000..74f1123 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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 <Swiften/Serializer/PayloadSerializerCollection.h> +#include <Swiften/Serializer/PayloadSerializers/PubSubSubscriptionSerializer.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> + +using namespace Swift; + +PubSubSubscriptionsSerializer::PubSubSubscriptionsSerializer(PayloadSerializerCollection* serializers) : serializers(serializers) { +} + +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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.h new file mode 100644 index 0000000..2b5d8fa --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionsSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubSubscriptions.h> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API PubSubSubscriptionsSerializer : public GenericPayloadSerializer<PubSubSubscriptions> { + public: + PubSubSubscriptionsSerializer(PayloadSerializerCollection* serializers); + virtual ~PubSubSubscriptionsSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<PubSubSubscriptions>) const SWIFTEN_OVERRIDE; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.cpp new file mode 100644 index 0000000..e0d6cd3 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * 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> + + +using namespace Swift; + +PubSubUnsubscribeSerializer::PubSubUnsubscribeSerializer(PayloadSerializerCollection* serializers) : serializers(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(); +} + + diff --git a/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.h b/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.h new file mode 100644 index 0000000..b4f6f62 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/PubSubUnsubscribeSerializer.h @@ -0,0 +1,31 @@ +/* + * 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/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/PubSubUnsubscribe.h> +#include <boost/shared_ptr.hpp> + +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; + + private: + + + private: + PayloadSerializerCollection* serializers; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp index 030b024..973ced9 100644 --- a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -52,7 +52,7 @@ std::string StreamInitiationSerializer::serializePayload(boost::shared_ptr<Strea boost::shared_ptr<XMLElement> featureElement(new XMLElement("feature", FEATURE_NEG_NS)); if (streamInitiation->getProvidedMethods().size() > 0) { Form::ref form(new Form(Form::FormType)); - ListSingleFormField::ref field = ListSingleFormField::create(); + 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)); @@ -62,7 +62,8 @@ std::string StreamInitiationSerializer::serializePayload(boost::shared_ptr<Strea } else if (!streamInitiation->getRequestedMethod().empty()) { Form::ref form(new Form(Form::SubmitType)); - ListSingleFormField::ref field = ListSingleFormField::create(streamInitiation->getRequestedMethod()); + 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))); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/BlockSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/BlockSerializerTest.cpp new file mode 100644 index 0000000..7772381 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/BlockSerializerTest.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Swiften/Serializer/PayloadSerializers/BlockSerializer.h> +#include <Swiften/Elements/BlockListPayload.h> +#include <Swiften/Elements/BlockPayload.h> +#include <Swiften/Elements/UnblockPayload.h> +#include <Swiften/JID/JID.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_REGISTRATION(BlockSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp index 4608522..e4ce2c8 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp @@ -1,11 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Serializer/PayloadSerializers/FormSerializer.h> using namespace Swift; @@ -36,37 +37,37 @@ class FormSerializerTest : public CppUnit::TestFixture { FormSerializer testling; boost::shared_ptr<Form> form(new Form(Form::FormType)); - FormField::ref field = HiddenFormField::create("jabber:bot"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:bot"); field->setName("FORM_TYPE"); form->addField(field); - form->addField(FixedFormField::create("Section 1: Bot Info")); + form->addField(boost::make_shared<FormField>(FormField::FixedType, "Section 1: Bot Info")); - field = TextSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::TextSingleType); field->setName("botname"); field->setLabel("The name of your bot"); form->addField(field); - field = TextMultiFormField::create("This is a bot.\nA quite good one actually"); + 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 = BooleanFormField::create(true); + field = boost::make_shared<FormField>(FormField::BooleanType, "1"); field->setName("public"); field->setLabel("Public bot?"); field->setRequired(true); form->addField(field); - field = TextPrivateFormField::create(); + field = boost::make_shared<FormField>(FormField::TextPrivateType); field->setName("password"); field->setLabel("Password for special access"); form->addField(field); - std::vector<std::string> values; - values.push_back("news"); - values.push_back("search"); - field = ListMultiFormField::create(values); + 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")); @@ -76,7 +77,7 @@ class FormSerializerTest : public CppUnit::TestFixture { field->addOption(FormField::Option("Search", "search")); form->addField(field); - field = ListSingleFormField::create("20"); + field = boost::make_shared<FormField>(FormField::ListSingleType, "20"); field->setName("maxsubs"); field->setLabel("Maximum number of subscribers"); field->addOption(FormField::Option("10", "10")); @@ -88,9 +89,9 @@ class FormSerializerTest : public CppUnit::TestFixture { form->addField(field); std::vector<JID> jids; - jids.push_back(JID("foo@bar.com")); - jids.push_back(JID("baz@fum.org")); - field = JIDMultiFormField::create(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!"); @@ -140,62 +141,62 @@ class FormSerializerTest : public CppUnit::TestFixture { boost::shared_ptr<Form> form(new Form(Form::ResultType)); - FormField::ref field = HiddenFormField::create("jabber:iq:search"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:iq:search"); field->setName("FORM_TYPE"); form->addField(field); // reported fields - field = TextSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::TextSingleType); field->setName("first"); field->setLabel("Given Name"); form->addReportedField(field); - field = TextSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::TextSingleType); field->setName("last"); field->setLabel("Family Name"); form->addReportedField(field); - field = JIDSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::JIDSingleType); field->setName("jid"); field->setLabel("Jabber ID"); form->addReportedField(field); - field = ListSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::ListSingleType); field->setName("x-gender"); field->setLabel("Gender"); form->addReportedField(field); Form::FormItem firstItem; - field = TextSingleFormField::create("Benvolio"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Benvolio"); field->setName("first"); firstItem.push_back(field); - field = TextSingleFormField::create("Montague"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); field->setName("last"); firstItem.push_back(field); - field = JIDSingleFormField::create(JID("benvolio@montague.net")); + field = boost::make_shared<FormField>(FormField::JIDSingleType, JID("benvolio@montague.net")); field->setName("jid"); firstItem.push_back(field); - field = ListSingleFormField::create("male"); + field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); field->setName("x-gender"); firstItem.push_back(field); Form::FormItem secondItem; - field = TextSingleFormField::create("Romeo"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Romeo"); field->setName("first"); secondItem.push_back(field); - field = TextSingleFormField::create("Montague"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); field->setName("last"); secondItem.push_back(field); - field = JIDSingleFormField::create(JID("romeo@montague.net")); + field = boost::make_shared<FormField>(FormField::JIDSingleType, JID("romeo@montague.net")); field->setName("jid"); secondItem.push_back(field); - field = ListSingleFormField::create("male"); + field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); field->setName("x-gender"); secondItem.push_back(field); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/IdleSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/IdleSerializerTest.cpp new file mode 100644 index 0000000..9700869 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/IdleSerializerTest.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <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(); + + public: + IdleSerializerTest() {} + + void testSerialize() { + IdleSerializer testling; + Idle::ref idle = boost::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_TEST_SUITE_REGISTRATION(IdleSerializerTest); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp index df43e69..7cbce35 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp @@ -1,11 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h> @@ -38,7 +39,7 @@ class InBandRegistrationPayloadSerializerTest : public CppUnit::TestFixture { boost::shared_ptr<Form> form(new Form(Form::FormType)); form->setTitle("Contest Registration"); - FormField::ref field = HiddenFormField::create("jabber:iq:register"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:iq:register"); field->setName("FORM_TYPE"); form->addField(field); registration->setForm(form); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp index 42bff72..29e20c9 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/SearchPayloadSerializerTest.cpp @@ -1,11 +1,12 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Serializer/PayloadSerializers/SearchPayloadSerializer.h> @@ -78,62 +79,62 @@ class SearchPayloadSerializerTest : public CppUnit::TestFixture { SearchPayload::ref payload(new SearchPayload()); boost::shared_ptr<Form> form(new Form(Form::ResultType)); - FormField::ref field = HiddenFormField::create("jabber:iq:search"); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "jabber:iq:search"); field->setName("FORM_TYPE"); form->addField(field); // reported fields - field = TextSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::TextSingleType); field->setName("first"); field->setLabel("Given Name"); form->addReportedField(field); - field = TextSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::TextSingleType); field->setName("last"); field->setLabel("Family Name"); form->addReportedField(field); - field = JIDSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::JIDSingleType); field->setName("jid"); field->setLabel("Jabber ID"); form->addReportedField(field); - field = ListSingleFormField::create(); + field = boost::make_shared<FormField>(FormField::ListSingleType); field->setName("x-gender"); field->setLabel("Gender"); form->addReportedField(field); Form::FormItem firstItem; - field = TextSingleFormField::create("Benvolio"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Benvolio"); field->setName("first"); firstItem.push_back(field); - field = TextSingleFormField::create("Montague"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); field->setName("last"); firstItem.push_back(field); - field = TextSingleFormField::create("benvolio@montague.net"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "benvolio@montague.net"); field->setName("jid"); firstItem.push_back(field); - field = ListSingleFormField::create("male"); + field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); field->setName("x-gender"); firstItem.push_back(field); Form::FormItem secondItem; - field = TextSingleFormField::create("Romeo"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Romeo"); field->setName("first"); secondItem.push_back(field); - field = TextSingleFormField::create("Montague"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Montague"); field->setName("last"); secondItem.push_back(field); - field = TextSingleFormField::create("romeo@montague.net"); + field = boost::make_shared<FormField>(FormField::TextSingleType, "romeo@montague.net"); field->setName("jid"); secondItem.push_back(field); - field = ListSingleFormField::create("male"); + field = boost::make_shared<FormField>(FormField::ListSingleType, "male"); field->setName("x-gender"); secondItem.push_back(field); diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp index 3ac1d77..01c8e77 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp @@ -31,14 +31,15 @@ class VCardSerializerTest : public CppUnit::TestFixture vcard->setNickname("DreamGirl"); vcard->setPhoto(createByteArray("abcdef")); vcard->setPhotoType("image/png"); - vcard->addUnknownContent("<BDAY>1234</BDAY><MAILER>mutt</MAILER>"); + vcard->setBirthday(boost::posix_time::ptime(boost::gregorian::date(1865, 5, 4))); + vcard->addUnknownContent("<MAILER>mutt</MAILER>"); - VCard::EMailAddress address1; - address1.address = "alice@wonderland.lit"; - address1.isHome = true; - address1.isPreferred = true; - address1.isInternet = true; - vcard->addEMailAddress(address1); + 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"; @@ -46,6 +47,41 @@ class VCardSerializerTest : public CppUnit::TestFixture 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>" @@ -73,7 +109,35 @@ class VCardSerializerTest : public CppUnit::TestFixture "<TYPE>image/png</TYPE>" "<BINVAL>YWJjZGVm</BINVAL>" "</PHOTO>" - "<BDAY>1234</BDAY>" + "<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>"; diff --git a/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp new file mode 100644 index 0000000..e257654 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h> + +#include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/lexical_cast.hpp> + +#include <Swiften/Base/foreach.h> +#include <Swiften/Base/DateTime.h> +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { + +UserLocationSerializer::UserLocationSerializer() { +} + +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(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h b/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h new file mode 100644 index 0000000..28a5fe8 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/UserLocation.h> + +namespace Swift { + class UserLocationSerializer : public GenericPayloadSerializer<UserLocation> { + public: + UserLocationSerializer(); + + virtual std::string serializePayload(boost::shared_ptr<UserLocation>) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp b/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp index 1512c6c..22d59b4 100644 --- a/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp @@ -13,6 +13,7 @@ #include <Swiften/Serializer/XML/XMLTextNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> #include <Swiften/StringCodecs/Base64.h> +#include <Swiften/Base/DateTime.h> #include <Swiften/Base/foreach.h> namespace Swift { @@ -23,49 +24,33 @@ VCardSerializer::VCardSerializer() : GenericPayloadSerializer<VCard>() { std::string VCardSerializer::serializePayload(boost::shared_ptr<VCard> vcard) const { XMLElement queryElement("vCard", "vcard-temp"); if (!vcard->getVersion().empty()) { - boost::shared_ptr<XMLElement> versionElement(new XMLElement("VERSION")); - versionElement->addNode(boost::make_shared<XMLTextNode>(vcard->getVersion())); - queryElement.addNode(versionElement); + queryElement.addNode(boost::make_shared<XMLElement>("VERSION", "", vcard->getVersion())); } if (!vcard->getFullName().empty()) { - boost::shared_ptr<XMLElement> fullNameElement(new XMLElement("FN")); - fullNameElement->addNode(boost::make_shared<XMLTextNode>(vcard->getFullName())); - queryElement.addNode(fullNameElement); + 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()) { - boost::shared_ptr<XMLElement> familyNameElement(new XMLElement("FAMILY")); - familyNameElement->addNode(boost::make_shared<XMLTextNode>(vcard->getFamilyName())); - nameElement->addNode(familyNameElement); + nameElement->addNode(boost::make_shared<XMLElement>("FAMILY", "", vcard->getFamilyName())); } if (!vcard->getGivenName().empty()) { - boost::shared_ptr<XMLElement> givenNameElement(new XMLElement("GIVEN")); - givenNameElement->addNode(boost::make_shared<XMLTextNode>(vcard->getGivenName())); - nameElement->addNode(givenNameElement); + nameElement->addNode(boost::make_shared<XMLElement>("GIVEN", "", vcard->getGivenName())); } if (!vcard->getMiddleName().empty()) { - boost::shared_ptr<XMLElement> middleNameElement(new XMLElement("MIDDLE")); - middleNameElement->addNode(boost::make_shared<XMLTextNode>(vcard->getMiddleName())); - nameElement->addNode(middleNameElement); + nameElement->addNode(boost::make_shared<XMLElement>("MIDDLE", "", vcard->getMiddleName())); } if (!vcard->getPrefix().empty()) { - boost::shared_ptr<XMLElement> prefixElement(new XMLElement("PREFIX")); - prefixElement->addNode(boost::make_shared<XMLTextNode>(vcard->getPrefix())); - nameElement->addNode(prefixElement); + nameElement->addNode(boost::make_shared<XMLElement>("PREFIX", "", vcard->getPrefix())); } if (!vcard->getSuffix().empty()) { - boost::shared_ptr<XMLElement> suffixElement(new XMLElement("SUFFIX")); - suffixElement->addNode(boost::make_shared<XMLTextNode>(vcard->getSuffix())); - nameElement->addNode(suffixElement); + 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")); - boost::shared_ptr<XMLElement> userIDElement(new XMLElement("USERID")); - userIDElement->addNode(boost::make_shared<XMLTextNode>(emailAddress.address)); - emailElement->addNode(userIDElement); + emailElement->addNode(boost::make_shared<XMLElement>("USERID", "", emailAddress.address)); if (emailAddress.isHome) { emailElement->addNode(boost::make_shared<XMLElement>("HOME")); } @@ -84,24 +69,179 @@ std::string VCardSerializer::serializePayload(boost::shared_ptr<VCard> vcard) c queryElement.addNode(emailElement); } if (!vcard->getNickname().empty()) { - boost::shared_ptr<XMLElement> nickElement(new XMLElement("NICKNAME")); - nickElement->addNode(boost::make_shared<XMLTextNode>(vcard->getNickname())); - queryElement.addNode(nickElement); + 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()) { - XMLElement::ref typeElement(new XMLElement("TYPE")); - typeElement->addNode(XMLTextNode::ref(new XMLTextNode(vcard->getPhotoType()))); - photoElement->addNode(typeElement); + photoElement->addNode(boost::make_shared<XMLElement>("TYPE", "", vcard->getPhotoType())); } if (!vcard->getPhoto().empty()) { - XMLElement::ref binvalElement(new XMLElement("BINVAL")); - binvalElement->addNode(XMLTextNode::ref(new XMLTextNode(Base64::encode(vcard->getPhoto())))); - photoElement->addNode(binvalElement); + 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())); } diff --git a/Swiften/Serializer/XML/XMLElement.cpp b/Swiften/Serializer/XML/XMLElement.cpp index d39ec39..42b602a 100644 --- a/Swiften/Serializer/XML/XMLElement.cpp +++ b/Swiften/Serializer/XML/XMLElement.cpp @@ -52,7 +52,9 @@ void XMLElement::setAttribute(const std::string& attribute, const std::string& v } void XMLElement::addNode(boost::shared_ptr<XMLNode> node) { - childNodes_.push_back(node); + if (node) { + childNodes_.push_back(node); + } } } diff --git a/Swiften/Session/BOSHSessionStream.cpp b/Swiften/Session/BOSHSessionStream.cpp index 479e415..62261d0 100644 --- a/Swiften/Session/BOSHSessionStream.cpp +++ b/Swiften/Session/BOSHSessionStream.cpp @@ -46,7 +46,7 @@ BOSHSessionStream::BOSHSessionStream( boost::mt19937 random; boost::uniform_int<unsigned long long> dist(0, (1LL<<53) - 1); - random.seed(time(NULL)); + 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); @@ -212,4 +212,4 @@ void BOSHSessionStream::handlePoolBOSHDataWritten(const SafeByteArray& data) { onDataWritten(data); } -}; +} diff --git a/Swiften/Session/BasicSessionStream.cpp b/Swiften/Session/BasicSessionStream.cpp index cd6d0e6..2bd8d66 100644 --- a/Swiften/Session/BasicSessionStream.cpp +++ b/Swiften/Session/BasicSessionStream.cpp @@ -207,4 +207,4 @@ void BasicSessionStream::handleDataWritten(const SafeByteArray& data) { onDataWritten(data); } -}; +} diff --git a/Swiften/Session/SessionStream.cpp b/Swiften/Session/SessionStream.cpp index 0d73b63..7378680 100644 --- a/Swiften/Session/SessionStream.cpp +++ b/Swiften/Session/SessionStream.cpp @@ -11,4 +11,4 @@ namespace Swift { SessionStream::~SessionStream() { } -}; +} diff --git a/Swiften/StringCodecs/Base64.cpp b/Swiften/StringCodecs/Base64.cpp index e4eaa4e..e1d70a0 100644 --- a/Swiften/StringCodecs/Base64.cpp +++ b/Swiften/StringCodecs/Base64.cpp @@ -1,129 +1,101 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ -#include <boost/numeric/conversion/cast.hpp> - -#include <algorithm> - #include <Swiften/StringCodecs/Base64.h> -#include <Swiften/Base/Algorithm.h> -namespace Swift { +#pragma clang diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wold-style-cast" +using namespace Swift; namespace { - template<typename TargetType, typename SourceType> - TargetType base64Encode(const SourceType& s) { - int i; - int len = s.size(); - char tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - int a, b, c; - - TargetType p; - p.resize((len+2)/3*4); - int at = 0; - for( i = 0; i < len; i += 3 ) { - a = ((unsigned char) (s[i]) & 3) << 4; - if(i + 1 < len) { - a += (unsigned char) (s[i + 1]) >> 4; - b = ((unsigned char) (s[i + 1]) & 0xF) << 2; - if(i + 2 < len) { - b += (unsigned char) (s[i + 2]) >> 6; - c = (unsigned char) (s[i + 2]) & 0x3F; - } - else - c = 64; - } - else { - b = c = 64; - } + 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 + }; - p[at++] = tbl[(unsigned char) (s[i]) >> 2]; - p[at++] = tbl[a]; - p[at++] = tbl[b]; - p[at++] = tbl[c]; + 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 p; + return result; } } -std::string Base64::encode(const ByteArray &s) { - return base64Encode<std::string, ByteArray>(s); + +std::string Base64::encode(const ByteArray& s) { + return encodeDetail<std::string>(s); } -SafeByteArray Base64::encode(const SafeByteArray &s) { - return base64Encode<SafeByteArray, SafeByteArray>(s); +SafeByteArray Base64::encode(const SafeByteArray& s) { + return encodeDetail<SafeByteArray>(s); } ByteArray Base64::decode(const std::string& input) { - std::string inputWithoutNewlines(input); - erase(inputWithoutNewlines, '\n'); - - const std::string& s = inputWithoutNewlines; - ByteArray p; - - // -1 specifies invalid - // 64 specifies eof - // everything else specifies data - - char tbl[] = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, - 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,64,-1,-1, - -1, 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,-1,-1,-1,-1,-1, - -1,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,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - }; + ByteArray result; - // this should be a multiple of 4 - int len = s.size(); - - if(len % 4) { - return p; + if (input.size() % 4) { + return ByteArray(); } - - p.resize(len / 4 * 3); - - int i; - int at = 0; - - int a, b, c, d; - c = d = 0; - - for( i = 0; i < len; i += 4 ) { - a = tbl[boost::numeric_cast<int>(s[i])]; - b = tbl[boost::numeric_cast<int>(s[i + 1])]; - c = tbl[boost::numeric_cast<int>(s[i + 2])]; - d = tbl[boost::numeric_cast<int>(s[i + 3])]; - if((a == 64 || b == 64) || (a < 0 || b < 0 || c < 0 || d < 0)) { - p.resize(0); - return p; + 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); } - p[at++] = ((a & 0x3F) << 2) | ((b >> 4) & 0x03); - p[at++] = ((b & 0x0F) << 4) | ((c >> 2) & 0x0F); - p[at++] = ((c & 0x03) << 6) | ((d >> 0) & 0x3F); } - - if(c & 64) - p.resize(at - 2); - else if(d & 64) - p.resize(at - 1); - - return p; -} - + return result; } diff --git a/Swiften/StringCodecs/HMAC.h b/Swiften/StringCodecs/HMAC.h deleted file mode 100644 index 72d3bab..0000000 --- a/Swiften/StringCodecs/HMAC.h +++ /dev/null @@ -1,67 +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 <Swiften/Base/SafeByteArray.h> -#include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/Algorithm.h> -#include <cassert> - -namespace Swift { - namespace HMAC_Detail { - template<typename KeyType> struct KeyWrapper; - template<> struct KeyWrapper<ByteArray> { - ByteArray wrap(const ByteArray& hash) const { - return hash; - } - }; - template<> struct KeyWrapper<SafeByteArray> { - SafeByteArray wrap(const ByteArray& hash) const { - return createSafeByteArray(hash); - } - }; - - template<typename Hash, typename KeyType, int BlockSize> - static ByteArray getHMAC(const KeyType& key, const ByteArray& data) { - Hash hash; - - // Create the padded key - KeyType paddedKey(key.size() <= BlockSize ? key : KeyWrapper<KeyType>().wrap(hash(key))); - paddedKey.resize(BlockSize, 0x0); - - // Create the first value - KeyType x(paddedKey); - for (unsigned int i = 0; i < x.size(); ++i) { - x[i] ^= 0x36; - } - append(x, data); - - // Create the second value - KeyType y(paddedKey); - for (unsigned int i = 0; i < y.size(); ++i) { - y[i] ^= 0x5c; - } - append(y, hash(x)); - - return hash(y); - } - }; - - template<typename Hash, int BlockSize> - class HMAC { - private: - - public: - ByteArray operator()(const ByteArray& key, const ByteArray& data) const { - return HMAC_Detail::getHMAC<Hash,ByteArray,BlockSize>(key, data); - } - - ByteArray operator()(const SafeByteArray& key, const ByteArray& data) const { - return HMAC_Detail::getHMAC<Hash,SafeByteArray,BlockSize>(key, data); - } - }; -} diff --git a/Swiften/StringCodecs/HMAC_SHA1.h b/Swiften/StringCodecs/HMAC_SHA1.h deleted file mode 100644 index 8f403c6..0000000 --- a/Swiften/StringCodecs/HMAC_SHA1.h +++ /dev/null @@ -1,14 +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 <Swiften/StringCodecs/HMAC.h> -#include <Swiften/StringCodecs/SHA1.h> - -namespace Swift { - typedef HMAC<SHA1, 64> HMAC_SHA1; -} diff --git a/Swiften/StringCodecs/HMAC_SHA256.h b/Swiften/StringCodecs/HMAC_SHA256.h deleted file mode 100644 index 2d856cb..0000000 --- a/Swiften/StringCodecs/HMAC_SHA256.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include <Swiften/StringCodecs/HMAC.h> -#include <Swiften/StringCodecs/SHA256.h> - -namespace Swift { - typedef HMAC<SHA256, 64> HMAC_SHA256; -} diff --git a/Swiften/StringCodecs/Hexify.cpp b/Swiften/StringCodecs/Hexify.cpp index 668079b..ed2b2a3 100644 --- a/Swiften/StringCodecs/Hexify.cpp +++ b/Swiften/StringCodecs/Hexify.cpp @@ -13,6 +13,8 @@ #include <string> #include <Swiften/Base/ByteArray.h> +#pragma clang diagnostic ignored "-Wconversion" + namespace Swift { std::string Hexify::hexify(unsigned char byte) { @@ -31,20 +33,39 @@ std::string Hexify::hexify(const ByteArray& data) { return std::string(result.str()); } -ByteArray Hexify::unhexify(const std::string& hexstring) { - if (hexstring.size() % 2) { + +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 +}; + +ByteArray Hexify::unhexify(const std::string& in) { + if (in.size() % 2) { return ByteArray(); } - ByteArray result = ByteArray(hexstring.size() / 2); - for (size_t pos = 0; pos < hexstring.size() - 1; pos += 2) { - char c; - c = hexstring[pos]; - int a = (c>='0'&&c<='9') ? c-'0' : (c>='A'&&c<='Z') ? c-'A' + 10 : (c>='a'&&c<='z') ? c-'a' + 10 : -1; - c = hexstring[pos+1]; - int b = (c>='0'&&c<='9') ? c-'0' : (c>='A'&&c<='Z') ? c-'A' + 10 : (c>='a'&&c<='z') ? c-'a' + 10 : -1; - if (a == -1 || b == -1) return ByteArray(); // fail - result[pos/2] = (a<<4) | b; + 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/MD5.cpp b/Swiften/StringCodecs/MD5.cpp deleted file mode 100644 index bd03314..0000000 --- a/Swiften/StringCodecs/MD5.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -/* - * This implementation is shamelessly copied from L. Peter Deutsch's - * implementation, and altered to use our own defines and datastructures. - * Original license below. - *//* - Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - */ - -#pragma GCC diagnostic ignored "-Wold-style-cast" - -#include <Swiften/StringCodecs/MD5.h> - -#include <cassert> -#include <string.h> - -#include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/Platform.h> - -#ifdef SWIFTEN_PLATFORM_WIN32 -#include <Swiften/Base/WindowsRegistry.h> -#endif - -namespace Swift { - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; - -#define T_MASK ((md5_word_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - - -static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) { - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; -#ifdef SWIFTEN_LITTLE_ENDIAN - /* Define storage for little-endian or both types of CPUs. */ - md5_word_t xbuf[16]; - const md5_word_t *X; -#else - /* Define storage only for big-endian CPUs. */ - md5_word_t X[16]; -#endif - - { -#ifdef SWIFTEN_LITTLE_ENDIAN - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const md5_byte_t *)0) & 3)) { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } -#else - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const md5_byte_t *xp = data; - int i; - - for (i = 0; i < 16; ++i, xp += 4) - X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } -#endif - } - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) -{ - static const md5_byte_t pad[64] = { - 0x80, 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, 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 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} - -namespace { - template<typename SourceType> - ByteArray getMD5Hash(const SourceType& data) { - ByteArray digest; - digest.resize(16); - - md5_state_t state; - md5_init(&state); - md5_append(&state, reinterpret_cast<const md5_byte_t*>(vecptr(data)), data.size()); - md5_finish(&state, reinterpret_cast<md5_byte_t*>(vecptr(digest))); - - return digest; - } -} - -MD5::MD5() { - state = new md5_state_t; - md5_init(state); -} - -MD5::~MD5() { - delete state; -} - -MD5& MD5::update(const std::vector<unsigned char>& input) { - md5_append(state, reinterpret_cast<const md5_byte_t*>(vecptr(input)), input.size()); - return *this; -} - -std::vector<unsigned char> MD5::getHash() { - ByteArray digest; - digest.resize(16); - md5_finish(state, reinterpret_cast<md5_byte_t*>(vecptr(digest))); - return digest; -} - -ByteArray MD5::getHash(const ByteArray& data) { - return getMD5Hash(data); -} - -ByteArray MD5::getHash(const SafeByteArray& data) { - return getMD5Hash(data); -} - -bool MD5::isAllowedForCrypto() { -#ifdef SWIFTEN_PLATFORM_WIN32 - return !WindowsRegistry::isFIPSEnabled(); -#else - return true; -#endif -} - -} diff --git a/Swiften/StringCodecs/MD5.h b/Swiften/StringCodecs/MD5.h deleted file mode 100644 index 48d62af..0000000 --- a/Swiften/StringCodecs/MD5.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2010-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/ByteArray.h> -#include <Swiften/Base/SafeByteArray.h> - -namespace Swift { - struct md5_state_s; - - class SWIFTEN_API MD5 { - public: - MD5(); - ~MD5(); - - MD5& update(const std::vector<unsigned char>& data); - std::vector<unsigned char> getHash(); - - static ByteArray getHash(const ByteArray& data); - static ByteArray getHash(const SafeByteArray& data); - static bool isAllowedForCrypto(); - - private: - md5_state_s* state; - }; -} diff --git a/Swiften/StringCodecs/PBKDF2.h b/Swiften/StringCodecs/PBKDF2.h index 0c04145..ae0bb17 100644 --- a/Swiften/StringCodecs/PBKDF2.h +++ b/Swiften/StringCodecs/PBKDF2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -8,18 +8,17 @@ #include <Swiften/Base/SafeByteArray.h> #include <Swiften/Base/Concat.h> +#include <Swiften/Crypto/CryptoProvider.h> namespace Swift { class PBKDF2 { public: - template<typename PRF> - static ByteArray encode(const SafeByteArray& password, const ByteArray& salt, int iterations) { - PRF prf; - ByteArray u = prf(password, concat(salt, createByteArray("\0\0\0\1", 4))); + 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 = prf(password, u); + u = crypto->getHMACSHA1(password, u); for (unsigned int j = 0; j < u.size(); ++j) { result[j] ^= u[j]; } diff --git a/Swiften/StringCodecs/SHA1.cpp b/Swiften/StringCodecs/SHA1.cpp deleted file mode 100644 index e4081f4..0000000 --- a/Swiften/StringCodecs/SHA1.cpp +++ /dev/null @@ -1,224 +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/StringCodecs/SHA1.h> - -#include <Swiften/Base/Platform.h> - -#pragma GCC diagnostic ignored "-Wold-style-cast" - -using namespace Swift; - -/* -SHA-1 in C -By Steve Reid <steve@edmweb.com> -100% Public Domain - -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ - -/* #define LITTLE_ENDIAN * This should be #define'd if true. */ -/* #define SHA1HANDSOFF * Copies data before messing with it. */ - -#include <stdio.h> -#include <string.h> - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ -#ifdef SWIFTEN_LITTLE_ENDIAN -#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ - |(rol(block->l[i],8)&0x00FF00FF)) -#else -#define blk0(i) block->l[i] -#endif -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -/* Hash a single 512-bit block. This is the core of the algorithm. */ - -void SHA1::Transform(boost::uint32_t state[5], boost::uint8_t buffer[64]) -{ -boost::uint32_t a, b, c, d, e; -typedef union { - boost::uint8_t c[64]; - boost::uint32_t l[16]; -} CHAR64LONG16; -CHAR64LONG16* block; -#ifdef SHA1HANDSOFF -static boost::uint8_t workspace[64]; - block = (CHAR64LONG16*)workspace; - memcpy(block, buffer, 64); -#else - block = reinterpret_cast<CHAR64LONG16*>(buffer); -#endif - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; -} - - -/* SHA1Init - Initialize new context */ - -void SHA1::Init(SHA1::CTX* context) -{ - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* Run your data through this. */ - -void SHA1::Update(SHA1::CTX* context, boost::uint8_t* data, unsigned int len) -{ -unsigned int i, j; - - j = (context->count[0] >> 3) & 63; - if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; - context->count[1] += (len >> 29); - if ((j + len) > 63) { - memcpy(&context->buffer[j], data, (i = 64-j)); - Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) { - Transform(context->state, &data[i]); - } - j = 0; - } - else i = 0; - memcpy(&context->buffer[j], &data[i], len - i); -} - - -/* Add padding and return the message digest. */ - -void SHA1::Final(boost::uint8_t digest[20], SHA1::CTX* context) -{ -boost::uint32_t i, j; -boost::uint8_t finalcount[8]; - - for (i = 0; i < 8; i++) { - finalcount[i] = (boost::uint8_t) ((context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - Update(context, (boost::uint8_t *)("\200"), 1); - while ((context->count[0] & 504) != 448) { - Update(context, (boost::uint8_t *)("\0"), 1); - } - Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ - for (i = 0; i < 20; i++) { - digest[i] = (boost::uint8_t) - ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } - /* Wipe variables */ - i = j = 0; - memset(context->buffer, 0, 64); - memset(context->state, 0, 20); - memset(context->count, 0, 8); - memset(&finalcount, 0, 8); -#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ - Transform(context->state, context->buffer); -#endif -} - -// ----------------------------------------------------------------------------- - -namespace Swift { - -SHA1::SHA1() { - Init(&context); -} - -SHA1& SHA1::update(const std::vector<unsigned char>& input) { - std::vector<unsigned char> inputCopy(input); - Update(&context, (boost::uint8_t*) vecptr(inputCopy), inputCopy.size()); - return *this; -} - -std::vector<unsigned char> SHA1::getHash() const { - std::vector<unsigned char> digest; - digest.resize(20); - CTX contextCopy(context); - Final((boost::uint8_t*) vecptr(digest), &contextCopy); - return digest; -} - -template<typename Container> -ByteArray SHA1::getHashInternal(const Container& input) { - CTX context; - Init(&context); - - Container inputCopy(input); - Update(&context, (boost::uint8_t*) vecptr(inputCopy), inputCopy.size()); - - ByteArray digest; - digest.resize(20); - Final((boost::uint8_t*) vecptr(digest), &context); - - return digest; -} - -ByteArray SHA1::getHash(const ByteArray& input) { - return getHashInternal(input); -} - -ByteArray SHA1::getHash(const SafeByteArray& input) { - return getHashInternal(input); -} - - -} diff --git a/Swiften/StringCodecs/SHA1.h b/Swiften/StringCodecs/SHA1.h deleted file mode 100644 index 30e757c..0000000 --- a/Swiften/StringCodecs/SHA1.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2010-2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#ifdef SWIFTEN_PLATFORM_WIN32 -#include "SHA1_Windows.h" -#else - -#include <vector> -#include <boost/cstdint.hpp> - -#include <Swiften/Base/API.h> -#include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/SafeByteArray.h> - -namespace Swift { - class SWIFTEN_API SHA1 { - public: - SHA1(); - - SHA1& update(const std::vector<unsigned char>& data); - std::vector<unsigned char> getHash() const; - - /** - * Equivalent of: - * SHA1().update(data),getHash(), but slightly more efficient and - * convenient. - */ - static ByteArray getHash(const ByteArray& data); - static ByteArray getHash(const SafeByteArray& data); - - ByteArray operator()(const SafeByteArray& data) { - return getHash(data); - } - - ByteArray operator()(const ByteArray& data) { - return getHash(data); - } - - private: - typedef struct { - boost::uint32_t state[5]; - boost::uint32_t count[2]; - boost::uint8_t buffer[64]; - } CTX; - static void Init(CTX* context); - static void Transform(boost::uint32_t state[5], boost::uint8_t buffer[64]); - static void Update(CTX* context, boost::uint8_t* data, unsigned int len); - static void Final(boost::uint8_t digest[20], CTX* context); - - template<typename Container> static ByteArray getHashInternal(const Container& input); - - private: - CTX context; - }; -} - -#endif diff --git a/Swiften/StringCodecs/SHA256.cpp b/Swiften/StringCodecs/SHA256.cpp deleted file mode 100644 index f92e7af..0000000 --- a/Swiften/StringCodecs/SHA256.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/StringCodecs/SHA256.h> - -#include <cassert> -#include <algorithm> -#include <string.h> - -#pragma GCC diagnostic ignored "-Wold-style-cast" - -using namespace Swift; - -// Copied & adapted from LibTomCrypt, by Tom St Denis, tomstdenis@gmail.com, http://libtom.org -// Substituted some macros by the platform-independent (slower) variants - -#include <stdlib.h> - -#define CRYPT_OK 0 -#define CRYPT_INVALID_ARG -1 -#define LTC_ARGCHK assert - -#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) -#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) - -#define LOAD32H(x, y) \ - { x = ((unsigned long)((y)[0] & 255)<<24) | \ - ((unsigned long)((y)[1] & 255)<<16) | \ - ((unsigned long)((y)[2] & 255)<<8) | \ - ((unsigned long)((y)[3] & 255)); } - -#define STORE32H(x, y) \ - { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ - (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } - -#define STORE64H(x, y) \ - { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ - (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ - (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ - (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } - -/* a simple macro for making hash "process" functions */ -#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ -int func_name (State * md, const unsigned char *in, unsigned int inlen) \ -{ \ - unsigned long n; \ - int err; \ - LTC_ARGCHK(md != NULL); \ - LTC_ARGCHK(in != NULL || inlen == 0); \ - if (md-> curlen > sizeof(md->buf)) { \ - return CRYPT_INVALID_ARG; \ - } \ - while (inlen > 0) { \ - if (md->curlen == 0 && inlen >= block_size) { \ - if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \ - return err; \ - } \ - md-> length += block_size * 8; \ - in += block_size; \ - inlen -= block_size; \ - } else { \ - n = std::min(inlen, (block_size - md-> curlen)); \ - memcpy(md-> buf + md-> curlen, in, (size_t)n); \ - md-> curlen += n; \ - in += n; \ - inlen -= n; \ - if (md-> curlen == block_size) { \ - if ((err = compress_name (md, md-> buf)) != CRYPT_OK) { \ - return err; \ - } \ - md-> length += 8*block_size; \ - md-> curlen = 0; \ - } \ - } \ - } \ - return CRYPT_OK; \ -} - -#ifdef LTC_SMALL_CODE -/* the K array */ -static const boost::uint32_t K[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, - 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, - 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, - 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, - 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, - 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, - 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, - 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, - 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, - 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; -#endif - -/* Various logical functions */ -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) RORc((x),(n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) - -#ifdef LTC_CLEAN_STACK -int SHA256::_compress(State * md, unsigned char *buf) -#else -int SHA256::compress(State * md, unsigned char *buf) -#endif -{ - boost::uint32_t S[8], W[64], t0, t1; -#ifdef LTC_SMALL_CODE - boost::uint32_t t; -#endif - int i; - - /* copy state into S */ - for (i = 0; i < 8; i++) { - S[i] = md->state[i]; - } - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) { - LOAD32H(W[i], buf + (4*i)); - } - - /* fill W[16..63] */ - for (i = 16; i < 64; i++) { - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - } - - /* Compress */ -#ifdef LTC_SMALL_CODE -#define RND(a,b,c,d,e,f,g,h,i) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - for (i = 0; i < 64; ++i) { - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); - t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; - S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; - } -#else -#define RND(a,b,c,d,e,f,g,h,i,ki) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); - -#undef RND - -#endif - - /* feedback */ - for (i = 0; i < 8; i++) { - md->state[i] = md->state[i] + S[i]; - } - return CRYPT_OK; -} - -#ifdef LTC_CLEAN_STACK -int SHA256::compress(State * md, unsigned char *buf) -{ - int err; - err = SHA256::_compress(md, buf); - burn_stack(sizeof(boost::uint32_t) * 74); - return err; -} -#endif - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return CRYPT_OK if successful -*/ -int SHA256::init(State * md) -{ - LTC_ARGCHK(md != NULL); - - md->curlen = 0; - md->length = 0; - md->state[0] = 0x6A09E667UL; - md->state[1] = 0xBB67AE85UL; - md->state[2] = 0x3C6EF372UL; - md->state[3] = 0xA54FF53AUL; - md->state[4] = 0x510E527FUL; - md->state[5] = 0x9B05688CUL; - md->state[6] = 0x1F83D9ABUL; - md->state[7] = 0x5BE0CD19UL; - return CRYPT_OK; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -HASH_PROCESS(SHA256::process, SHA256::compress, sha256, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (32 bytes) - @return CRYPT_OK if successful -*/ -int SHA256::done(State * md, unsigned char *out) -{ - int i; - - LTC_ARGCHK(md != NULL); - LTC_ARGCHK(out != NULL); - - if (md->curlen >= sizeof(md->buf)) { - return CRYPT_INVALID_ARG; - } - - - /* increase the length of the message */ - md->length += md->curlen * 8; - - /* append the '1' bit */ - md->buf[md->curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->curlen > 56) { - while (md->curlen < 64) { - md->buf[md->curlen++] = (unsigned char)0; - } - SHA256::compress(md, md->buf); - md->curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->curlen < 56) { - md->buf[md->curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64H(md->length, md->buf+56); - SHA256::compress(md, md->buf); - - /* copy output */ - for (i = 0; i < 8; i++) { - STORE32H(md->state[i], out+(4*i)); - } -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(State)); -#endif - return CRYPT_OK; -} - -// End copied code - -namespace Swift { - -SHA256::SHA256() { - init(&state); -} - -SHA256& SHA256::update(const std::vector<unsigned char>& input) { - std::vector<unsigned char> inputCopy(input); - process(&state, (boost::uint8_t*) vecptr(inputCopy), inputCopy.size()); - return *this; -} - -std::vector<unsigned char> SHA256::getHash() const { - std::vector<unsigned char> digest; - digest.resize(256/8); - State contextCopy(state); - done(&contextCopy, (boost::uint8_t*) vecptr(digest)); - return digest; -} - -template<typename Container> -ByteArray SHA256::getHashInternal(const Container& input) { - State context; - init(&context); - - Container inputCopy(input); - process(&context, (boost::uint8_t*) vecptr(inputCopy), inputCopy.size()); - - ByteArray digest; - digest.resize(256/8); - done(&context, (boost::uint8_t*) vecptr(digest)); - - return digest; -} - -ByteArray SHA256::getHash(const ByteArray& input) { - return getHashInternal(input); -} - -ByteArray SHA256::getHash(const SafeByteArray& input) { - return getHashInternal(input); -} - -} diff --git a/Swiften/StringCodecs/SHA256.h b/Swiften/StringCodecs/SHA256.h deleted file mode 100644 index fe60f2e..0000000 --- a/Swiften/StringCodecs/SHA256.h +++ /dev/null @@ -1,57 +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 <vector> -#include <boost/cstdint.hpp> - -#include <Swiften/Base/API.h> -#include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/SafeByteArray.h> - -namespace Swift { - class SWIFTEN_API SHA256 { - public: - SHA256(); - - SHA256& update(const std::vector<unsigned char>& data); - std::vector<unsigned char> getHash() const; - - /** - * Equivalent of: - * SHA256().update(data),getHash(), but slightly more efficient and - * convenient. - */ - static ByteArray getHash(const ByteArray& data); - static ByteArray getHash(const SafeByteArray& data); - - ByteArray operator()(const SafeByteArray& data) { - return getHash(data); - } - - ByteArray operator()(const ByteArray& data) { - return getHash(data); - } - - private: - struct State { - boost::uint64_t length; - boost::uint32_t state[8], curlen; - unsigned char buf[64]; - }; - - static int init(State *md); - static int process(State * md, const unsigned char *in, unsigned int inlen); - static int compress(State *md, unsigned char *buf); - static int done(State * md, unsigned char *out); - - template<typename Container> static ByteArray getHashInternal(const Container& input); - - private: - State state; - }; -} diff --git a/Swiften/StringCodecs/UnitTest/Base64Test.cpp b/Swiften/StringCodecs/UnitTest/Base64Test.cpp index f6a424b..4005047 100644 --- a/Swiften/StringCodecs/UnitTest/Base64Test.cpp +++ b/Swiften/StringCodecs/UnitTest/Base64Test.cpp @@ -16,22 +16,41 @@ using namespace Swift; class Base64Test : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(Base64Test); - CPPUNIT_TEST(testEncode); - CPPUNIT_TEST(testEncode_NonAscii); + CPPUNIT_TEST(testEncodeDecodeAllChars); + CPPUNIT_TEST(testEncodeDecodeOneBytePadding); + CPPUNIT_TEST(testEncodeDecodeTwoBytesPadding); CPPUNIT_TEST(testEncode_NoData); - CPPUNIT_TEST(testDecode); CPPUNIT_TEST(testDecode_NoData); CPPUNIT_TEST_SUITE_END(); public: - void testEncode() { - std::string result(Base64::encode(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"))); - CPPUNIT_ASSERT_EQUAL(std::string("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejEyMzQ1Njc4OTA="), result); + 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 testEncode_NonAscii() { - std::string result(Base64::encode(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"))); - CPPUNIT_ASSERT_EQUAL(std::string("QgayPKawpkPSDYmwT/WM94uAlu0="), 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() { @@ -39,11 +58,6 @@ class Base64Test : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(std::string(""), result); } - void testDecode() { - ByteArray result(Base64::decode("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejEyMzQ1Njc4OTA=")); - CPPUNIT_ASSERT_EQUAL(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"), result); - } - void testDecode_NoData() { ByteArray result(Base64::decode("")); CPPUNIT_ASSERT_EQUAL(ByteArray(), result); diff --git a/Swiften/StringCodecs/UnitTest/HMACTest.cpp b/Swiften/StringCodecs/UnitTest/HMACTest.cpp deleted file mode 100644 index 50b1330..0000000 --- a/Swiften/StringCodecs/UnitTest/HMACTest.cpp +++ /dev/null @@ -1,49 +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/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/HMAC_SHA1.h> -#include <Swiften/StringCodecs/HMAC_SHA256.h> - -using namespace Swift; - -class HMACTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(HMACTest); - CPPUNIT_TEST(testGetResult); - CPPUNIT_TEST(testGetResult_KeyLongerThanBlockSize); - CPPUNIT_TEST(testGetResult_RFC4231_1); - CPPUNIT_TEST(testGetResult_RFC4231_7); - CPPUNIT_TEST_SUITE_END(); - - public: - void testGetResult() { - ByteArray result(HMAC_SHA1()(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 testGetResult_KeyLongerThanBlockSize() { - ByteArray result(HMAC_SHA1()(createSafeByteArray("---------|---------|---------|---------|---------|----------|---------|"), createByteArray("foobar"))); - CPPUNIT_ASSERT_EQUAL(createByteArray("\xd6""n""\x8f""P|1""\xd3"",""\x6"" ""\xb9\xe3""gg""\x8e\xcf"" ]+""\xa"), result); - } - - void testGetResult_RFC4231_1() { - ByteArray result(HMAC_SHA256()(createSafeByteArray("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20), createByteArray("Hi There"))); - CPPUNIT_ASSERT_EQUAL(createByteArray("\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7", 32), result); - } - - void testGetResult_RFC4231_7() { - ByteArray result(HMAC_SHA256()(createSafeByteArray("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131), createByteArray("This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."))); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2", 32), result); - } -}; - -CPPUNIT_TEST_SUITE_REGISTRATION(HMACTest); diff --git a/Swiften/StringCodecs/UnitTest/MD5Test.cpp b/Swiften/StringCodecs/UnitTest/MD5Test.cpp deleted file mode 100644 index c62c46a..0000000 --- a/Swiften/StringCodecs/UnitTest/MD5Test.cpp +++ /dev/null @@ -1,49 +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/Base/ByteArray.h> -#include <QA/Checker/IO.h> - -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> - -#include <Swiften/StringCodecs/MD5.h> -#include <Swiften/Base/ByteArray.h> - -using namespace Swift; - -class MD5Test : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(MD5Test); - CPPUNIT_TEST(testGetHash_Empty); - CPPUNIT_TEST(testGetHash_Alphabet); - CPPUNIT_TEST(testIncrementalTest); - CPPUNIT_TEST_SUITE_END(); - - public: - void testGetHash_Empty() { - ByteArray result(MD5::getHash(createByteArray(""))); - - CPPUNIT_ASSERT_EQUAL(createByteArray("\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e", 16), result); - } - - void testGetHash_Alphabet() { - ByteArray result(MD5::getHash(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 testIncrementalTest() { - MD5 testling; - 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); - } -}; - -CPPUNIT_TEST_SUITE_REGISTRATION(MD5Test); diff --git a/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp b/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp index 608ca62..1172679 100644 --- a/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp +++ b/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -12,7 +12,8 @@ #include <Swiften/Base/ByteArray.h> #include <Swiften/StringCodecs/PBKDF2.h> -#include <Swiften/StringCodecs/HMAC_SHA1.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> using namespace Swift; @@ -24,23 +25,30 @@ class PBKDF2Test : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_END(); public: + void setUp() { + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } + void testGetResult_I1() { - ByteArray result(PBKDF2::encode<HMAC_SHA1 >(createSafeByteArray("password"), createByteArray("salt"), 1)); + 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); } void testGetResult_I2() { - ByteArray result(PBKDF2::encode<HMAC_SHA1 >(createSafeByteArray("password"), createByteArray("salt"), 2)); + 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); } void testGetResult_I4096() { - ByteArray result(PBKDF2::encode<HMAC_SHA1 >(createSafeByteArray("password"), createByteArray("salt"), 4096)); + 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); } + + private: + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(PBKDF2Test); diff --git a/Swiften/StringCodecs/UnitTest/SHA1Test.cpp b/Swiften/StringCodecs/UnitTest/SHA1Test.cpp deleted file mode 100644 index cb1a6f4..0000000 --- a/Swiften/StringCodecs/UnitTest/SHA1Test.cpp +++ /dev/null @@ -1,93 +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/Base/ByteArray.h> -#include <QA/Checker/IO.h> - -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> - -#include <Swiften/StringCodecs/SHA1.h> - -using namespace Swift; - -class SHA1Test : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SHA1Test); - CPPUNIT_TEST(testGetHash); - CPPUNIT_TEST(testGetHash_TwoUpdates); - //CPPUNIT_TEST(testGetHash_TwoGetHash); - CPPUNIT_TEST(testGetHash_NoData); - //CPPUNIT_TEST(testGetHash_InterleavedUpdate); - CPPUNIT_TEST(testGetHashStatic); - CPPUNIT_TEST(testGetHashStatic_Twice); - CPPUNIT_TEST(testGetHashStatic_NoData); - CPPUNIT_TEST_SUITE_END(); - - public: - void testGetHash() { - SHA1 sha; - 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 testGetHash_TwoUpdates() { - SHA1 sha; - 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 testGetHash_TwoGetHash() { - SHA1 sha; - 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<")); - - sha.getHash(); - - 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 testGetHash_InterleavedUpdate() { - SHA1 sha; - - sha.update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<")); - sha.getHash(); - 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 testGetHash_NoData() { - SHA1 sha; - 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 testGetHashStatic() { - ByteArray result(SHA1::getHash(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 testGetHashStatic_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<")); - SHA1::getHash(input); - ByteArray result(SHA1::getHash(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 testGetHashStatic_NoData() { - ByteArray result(SHA1::getHash(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); - } -}; - -CPPUNIT_TEST_SUITE_REGISTRATION(SHA1Test); diff --git a/Swiften/StringCodecs/UnitTest/SHA256Test.cpp b/Swiften/StringCodecs/UnitTest/SHA256Test.cpp deleted file mode 100644 index 5bcdd11..0000000 --- a/Swiften/StringCodecs/UnitTest/SHA256Test.cpp +++ /dev/null @@ -1,41 +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/Base/ByteArray.h> -#include <QA/Checker/IO.h> - -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> - -#include <Swiften/StringCodecs/SHA256.h> - -using namespace Swift; - -class SHA256Test : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SHA256Test); - CPPUNIT_TEST(testGetHashStatic_Empty); - CPPUNIT_TEST(testGetHashStatic_Small); - CPPUNIT_TEST(testGetHashStatic_Large); - CPPUNIT_TEST_SUITE_END(); - - public: - void testGetHashStatic_Empty() { - ByteArray result(SHA256::getHash(createByteArray(""))); - CPPUNIT_ASSERT_EQUAL(createByteArray("\xe3\xb0\xc4" "B" "\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99" "o" "\xb9" "$'" "\xae" "A" "\xe4" "d" "\x9b\x93" "L" "\xa4\x95\x99\x1b" "xR" "\xb8" "U", 32), result); - } - - void testGetHashStatic_Small() { - ByteArray result(SHA256::getHash(createByteArray("abc"))); - CPPUNIT_ASSERT_EQUAL(createByteArray("\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad", 32), result); - } - - void testGetHashStatic_Large() { - ByteArray result(SHA256::getHash(createByteArray("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1", 32), result); - } -}; - -CPPUNIT_TEST_SUITE_REGISTRATION(SHA256Test); diff --git a/Swiften/TLS/Certificate.cpp b/Swiften/TLS/Certificate.cpp index a796463..ec268c8 100644 --- a/Swiften/TLS/Certificate.cpp +++ b/Swiften/TLS/Certificate.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -8,7 +8,7 @@ #include <sstream> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/StringCodecs/Hexify.h> namespace Swift { @@ -19,8 +19,8 @@ const char* Certificate::ID_ON_DNSSRV_OID = "1.3.6.1.5.5.7.8.7"; Certificate::~Certificate() { } -std::string Certificate::getSHA1Fingerprint() const { - ByteArray hash = SHA1::getHash(toDER()); +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) { diff --git a/Swiften/TLS/Certificate.h b/Swiften/TLS/Certificate.h index 9aec86c..f558c12 100644 --- a/Swiften/TLS/Certificate.h +++ b/Swiften/TLS/Certificate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -13,6 +13,8 @@ #include <Swiften/Base/ByteArray.h> namespace Swift { + class CryptoProvider; + class SWIFTEN_API Certificate { public: typedef boost::shared_ptr<Certificate> ref; @@ -32,7 +34,7 @@ namespace Swift { virtual ByteArray toDER() const = 0; - virtual std::string getSHA1Fingerprint() const; + static std::string getSHA1Fingerprint(Certificate::ref, CryptoProvider* crypto); protected: static const char* ID_ON_XMPPADDR_OID; diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp b/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp index 76b8bb9..d654787 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -13,6 +13,9 @@ #include <openssl/x509v3.h> #pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wcast-align" +#pragma clang diagnostic ignored "-Wsign-conversion" namespace Swift { @@ -55,7 +58,7 @@ void OpenSSLCertificate::parse() { // Subject name ByteArray subjectNameData; subjectNameData.resize(256); - X509_NAME_oneline(X509_get_subject_name(cert.get()), reinterpret_cast<char*>(vecptr(subjectNameData)), subjectNameData.size()); + 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 diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp index e8a9019..77f780f 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -25,13 +25,17 @@ #include <Swiften/TLS/PKCS12Certificate.h> #pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#pragma clang diagnostic ignored "-Wcast-align" +#pragma clang diagnostic ignored "-Wsign-conversion" namespace Swift { static const int MAX_FINISHED_SIZE = 4096; static const int SSL_READ_BUFFERSIZE = 8192; -void freeX509Stack(STACK_OF(X509)* stack) { +static void freeX509Stack(STACK_OF(X509)* stack) { sk_X509_free(stack); } diff --git a/Swiften/TLS/PKCS12Certificate.h b/Swiften/TLS/PKCS12Certificate.h index 2f70456..2d4c2e5 100644 --- a/Swiften/TLS/PKCS12Certificate.h +++ b/Swiften/TLS/PKCS12Certificate.h @@ -8,13 +8,14 @@ #include <Swiften/Base/SafeByteArray.h> #include <Swiften/TLS/CertificateWithKey.h> +#include <boost/filesystem/path.hpp> namespace Swift { class PKCS12Certificate : public Swift::CertificateWithKey { public: PKCS12Certificate() {} - PKCS12Certificate(const std::string& filename, const SafeByteArray& password) : password_(password) { + PKCS12Certificate(const boost::filesystem::path& filename, const SafeByteArray& password) : password_(password) { readByteArrayFromFile(data_, filename); } diff --git a/Swiften/TLS/ServerIdentityVerifier.cpp b/Swiften/TLS/ServerIdentityVerifier.cpp index a908ad0..02459b9 100644 --- a/Swiften/TLS/ServerIdentityVerifier.cpp +++ b/Swiften/TLS/ServerIdentityVerifier.cpp @@ -9,18 +9,21 @@ #include <boost/algorithm/string.hpp> #include <Swiften/Base/foreach.h> -#include <Swiften/IDN/IDNA.h> +#include <Swiften/IDN/IDNConverter.h> namespace Swift { -ServerIdentityVerifier::ServerIdentityVerifier(const JID& jid) { +ServerIdentityVerifier::ServerIdentityVerifier(const JID& jid, IDNConverter* idnConverter) { domain = jid.getDomain(); - encodedDomain = IDNA::getEncoded(domain); + encodedDomain = idnConverter->getIDNAEncoded(domain); } bool ServerIdentityVerifier::certificateVerifies(Certificate::ref certificate) { bool hasSAN = false; + if (certificate == NULL) { + return false; + } // DNS names std::vector<std::string> dnsNames = certificate->getDNSNames(); foreach (const std::string& dnsName, dnsNames) { @@ -67,8 +70,8 @@ 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; - int dotIndex = matchDomain.find('.'); - if (dotIndex >= 0) { + size_t dotIndex = matchDomain.find('.'); + if (dotIndex != matchDomain.npos) { matchDomain = matchDomain.substr(dotIndex + 1, matchDomain.npos); } return matchString == matchDomain; diff --git a/Swiften/TLS/ServerIdentityVerifier.h b/Swiften/TLS/ServerIdentityVerifier.h index 730ee74..4167ce8 100644 --- a/Swiften/TLS/ServerIdentityVerifier.h +++ b/Swiften/TLS/ServerIdentityVerifier.h @@ -14,9 +14,11 @@ #include <Swiften/TLS/Certificate.h> namespace Swift { + class IDNConverter; + class SWIFTEN_API ServerIdentityVerifier { public: - ServerIdentityVerifier(const JID& jid); + ServerIdentityVerifier(const JID& jid, IDNConverter* idnConverter); bool certificateVerifies(Certificate::ref); diff --git a/Swiften/TLS/UnitTest/CertificateTest.cpp b/Swiften/TLS/UnitTest/CertificateTest.cpp index 5df5639..3352118 100644 --- a/Swiften/TLS/UnitTest/CertificateTest.cpp +++ b/Swiften/TLS/UnitTest/CertificateTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -12,6 +12,8 @@ #include <Swiften/TLS/Certificate.h> #include <Swiften/TLS/SimpleCertificate.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Crypto/PlatformCryptoProvider.h> using namespace Swift; @@ -25,7 +27,7 @@ class CertificateTest : public CppUnit::TestFixture { SimpleCertificate::ref testling = boost::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"), testling->getSHA1Fingerprint()); + 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())); } }; diff --git a/Swiften/TLS/UnitTest/ServerIdentityVerifierTest.cpp b/Swiften/TLS/UnitTest/ServerIdentityVerifierTest.cpp index bd68c84..e974eb7 100644 --- a/Swiften/TLS/UnitTest/ServerIdentityVerifierTest.cpp +++ b/Swiften/TLS/UnitTest/ServerIdentityVerifierTest.cpp @@ -12,6 +12,8 @@ #include <Swiften/TLS/ServerIdentityVerifier.h> #include <Swiften/TLS/SimpleCertificate.h> +#include <Swiften/IDN/IDNConverter.h> +#include <Swiften/IDN/PlatformIDNConverter.h> using namespace Swift; @@ -36,8 +38,12 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE_END(); public: + void setUp() { + idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); + } + void testCertificateVerifies_WithoutMatchingDNSName() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addDNSName("foo.com"); @@ -45,7 +51,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingDNSName() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addDNSName("bar.com"); @@ -53,7 +59,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithSecondMatchingDNSName() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addDNSName("foo.com"); certificate->addDNSName("bar.com"); @@ -62,7 +68,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingInternationalDNSName() { - ServerIdentityVerifier testling(JID("foo@tron\xc3\xa7on.com/baz")); + ServerIdentityVerifier testling(JID("foo@tron\xc3\xa7on.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addDNSName("xn--tronon-zua.com"); @@ -70,7 +76,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingDNSNameWithWildcard() { - ServerIdentityVerifier testling(JID("foo@im.bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@im.bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addDNSName("*.bar.com"); @@ -78,7 +84,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingDNSNameWithWildcardMatchingNoComponents() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addDNSName("*.bar.com"); @@ -86,7 +92,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithDNSNameWithWildcardMatchingTwoComponents() { - ServerIdentityVerifier testling(JID("foo@xmpp.im.bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@xmpp.im.bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addDNSName("*.bar.com"); @@ -94,7 +100,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingSRVNameWithoutService() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addSRVName("bar.com"); @@ -102,7 +108,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingSRVNameWithService() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addSRVName("_xmpp-client.bar.com"); @@ -110,7 +116,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingSRVNameWithServiceAndWildcard() { - ServerIdentityVerifier testling(JID("foo@im.bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@im.bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addSRVName("_xmpp-client.*.bar.com"); @@ -118,7 +124,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingSRVNameWithDifferentService() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addSRVName("_xmpp-server.bar.com"); @@ -126,7 +132,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingXmppAddr() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addXMPPAddress("bar.com"); @@ -134,7 +140,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingXmppAddrWithWildcard() { - ServerIdentityVerifier testling(JID("foo@im.bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@im.bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addXMPPAddress("*.bar.com"); @@ -142,7 +148,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingInternationalXmppAddr() { - ServerIdentityVerifier testling(JID("foo@tron\xc3\xa7.com/baz")); + ServerIdentityVerifier testling(JID("foo@tron\xc3\xa7.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addXMPPAddress("tron\xc3\xa7.com"); @@ -150,7 +156,7 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingCNWithoutSAN() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz")); + ServerIdentityVerifier testling(JID("foo@bar.com/baz"), idnConverter.get()); SimpleCertificate::ref certificate(new SimpleCertificate()); certificate->addCommonName("bar.com"); @@ -158,13 +164,15 @@ class ServerIdentityVerifierTest : public CppUnit::TestFixture { } void testCertificateVerifies_WithMatchingCNWithSAN() { - ServerIdentityVerifier testling(JID("foo@bar.com/baz")); + 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)); } + + boost::shared_ptr<IDNConverter> idnConverter; }; CPPUNIT_TEST_SUITE_REGISTRATION(ServerIdentityVerifierTest); diff --git a/Swiften/VCards/UnitTest/VCardManagerTest.cpp b/Swiften/VCards/UnitTest/VCardManagerTest.cpp index eecec7b..9f1c8bb 100644 --- a/Swiften/VCards/UnitTest/VCardManagerTest.cpp +++ b/Swiften/VCards/UnitTest/VCardManagerTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -16,6 +16,8 @@ #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; @@ -36,9 +38,10 @@ class VCardManagerTest : public CppUnit::TestFixture { 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(); + vcardStorage = new VCardMemoryStorage(crypto.get()); } void tearDown() { @@ -201,6 +204,7 @@ class VCardManagerTest : public CppUnit::TestFixture { VCardMemoryStorage* vcardStorage; std::vector< std::pair<JID, VCard::ref> > changes; std::vector<VCard::ref> ownChanges; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(VCardManagerTest); diff --git a/Swiften/VCards/VCardMemoryStorage.h b/Swiften/VCards/VCardMemoryStorage.h index ade9c89..86ae1b2 100644 --- a/Swiften/VCards/VCardMemoryStorage.h +++ b/Swiften/VCards/VCardMemoryStorage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -15,7 +15,7 @@ namespace Swift { class VCardMemoryStorage : public VCardStorage { public: - VCardMemoryStorage() {} + VCardMemoryStorage(CryptoProvider* crypto) : VCardStorage(crypto) {} virtual VCard::ref getVCard(const JID& jid) const { VCardMap::const_iterator i = vcards.find(jid); diff --git a/Swiften/VCards/VCardStorage.cpp b/Swiften/VCards/VCardStorage.cpp index 900f1e5..fefea83 100644 --- a/Swiften/VCards/VCardStorage.cpp +++ b/Swiften/VCards/VCardStorage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,17 +7,20 @@ #include <Swiften/VCards/VCardStorage.h> #include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/Crypto/CryptoProvider.h> namespace Swift { +VCardStorage::VCardStorage(CryptoProvider* crypto) : crypto(crypto) { +} + VCardStorage::~VCardStorage() { } std::string VCardStorage::getPhotoHash(const JID& jid) const { VCard::ref vCard = getVCard(jid); if (vCard && !vCard->getPhoto().empty()) { - return Hexify::hexify(SHA1::getHash(vCard->getPhoto())); + return Hexify::hexify(crypto->getSHA1Hash(vCard->getPhoto())); } else { return ""; diff --git a/Swiften/VCards/VCardStorage.h b/Swiften/VCards/VCardStorage.h index 5fba915..924204c 100644 --- a/Swiften/VCards/VCardStorage.h +++ b/Swiften/VCards/VCardStorage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -14,14 +14,19 @@ namespace Swift { class JID; + class CryptoProvider; 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 std::string getPhotoHash(const JID&) const; + + private: + CryptoProvider* crypto; }; } |