diff options
author | Remko Tronçon <git@el-tramo.be> | 2009-06-22 17:38:29 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2009-06-22 17:39:06 (GMT) |
commit | e8360f0dd62ea651e94f681499faef58747f2ece (patch) | |
tree | 5eeb231a12a44c65baf648b0350387a6f25986af /Swiften | |
parent | 86e892137d512a11edde0aa7760fc1c15e598dad (diff) | |
download | swift-e8360f0dd62ea651e94f681499faef58747f2ece.zip swift-e8360f0dd62ea651e94f681499faef58747f2ece.tar.bz2 |
Support vCard-based avatars in MUCs.
Diffstat (limited to 'Swiften')
-rw-r--r-- | Swiften/Avatars/AvatarManager.cpp | 40 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarManager.h | 8 | ||||
-rw-r--r-- | Swiften/Avatars/UnitTest/AvatarManagerTest.cpp | 101 | ||||
-rw-r--r-- | Swiften/Avatars/UnitTest/Makefile.inc | 2 | ||||
-rw-r--r-- | Swiften/Client/DummyStanzaChannel.h | 34 | ||||
-rw-r--r-- | Swiften/MUC/MUCRegistry.cpp | 8 | ||||
-rw-r--r-- | Swiften/MUC/MUCRegistry.h | 12 | ||||
-rw-r--r-- | Swiften/MUC/Makefile.inc | 1 | ||||
-rw-r--r-- | Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp | 2 | ||||
-rw-r--r-- | Swiften/Queries/Requests/GetVCardRequest.h | 6 |
10 files changed, 194 insertions, 20 deletions
diff --git a/Swiften/Avatars/AvatarManager.cpp b/Swiften/Avatars/AvatarManager.cpp index f0b04b9..c15d002 100644 --- a/Swiften/Avatars/AvatarManager.cpp +++ b/Swiften/Avatars/AvatarManager.cpp @@ -7,10 +7,11 @@ #include "Swiften/Queries/Requests/GetVCardRequest.h" #include "Swiften/StringCodecs/SHA1.h" #include "Swiften/Avatars/AvatarStorage.h" +#include "Swiften/MUC/MUCRegistry.h" namespace Swift { -AvatarManager::AvatarManager(StanzaChannel* stanzaChannel, IQRouter* iqRouter, AvatarStorage* avatarStorage) : stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), avatarStorage_(avatarStorage) { +AvatarManager::AvatarManager(StanzaChannel* stanzaChannel, IQRouter* iqRouter, AvatarStorage* avatarStorage, MUCRegistry* mucRegistry) : stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), avatarStorage_(avatarStorage), mucRegistry_(mucRegistry) { stanzaChannel->onPresenceReceived.connect(boost::bind(&AvatarManager::handlePresenceReceived, this, _1)); } @@ -19,33 +20,42 @@ void AvatarManager::handlePresenceReceived(boost::shared_ptr<Presence> presence) if (!update) { return; } - JID from = presence->getFrom().toBare(); + JID from = getAvatarJID(presence->getFrom()); String& hash = avatarHashes_[from]; if (hash != update->getPhotoHash()) { - hash = update->getPhotoHash(); - if (!avatarStorage_->hasAvatar(hash)) { - boost::shared_ptr<GetVCardRequest> request(new GetVCardRequest(from, iqRouter_)); - request->onResponse.connect(boost::bind(&AvatarManager::handleVCardReceived, this, from, _1, _2)); - request->send(); + String newHash = update->getPhotoHash(); + if (avatarStorage_->hasAvatar(newHash)) { + setAvatarHash(from, newHash); } else { - onAvatarChanged(from, hash); + boost::shared_ptr<GetVCardRequest> request(new GetVCardRequest(from, iqRouter_)); + request->onResponse.connect(boost::bind(&AvatarManager::handleVCardReceived, this, from, newHash, _1, _2)); + request->send(); } } } -void AvatarManager::handleVCardReceived(JID from, boost::shared_ptr<VCard> vCard, const boost::optional<Error>& error) { +void AvatarManager::handleVCardReceived(const JID& from, const String& promisedHash, boost::shared_ptr<VCard> vCard, const boost::optional<Error>& error) { if (error) { // FIXME: What to do here? + std::cerr << "Warning: " << from << ": Could not get vCard" << std::endl; return; } - String hash = SHA1::getHexHash(vCard->getPhoto()); - avatarStorage_->addAvatar(hash, vCard->getPhoto()); + String realHash = SHA1::getHexHash(vCard->getPhoto()); + if (promisedHash != realHash) { + std::cerr << "Warning: " << from << ": Got different vCard photo hash (" << promisedHash << " != " << realHash << ")" << std::endl; + } + avatarStorage_->addAvatar(realHash, vCard->getPhoto()); + setAvatarHash(from, realHash); +} + +void AvatarManager::setAvatarHash(const JID& from, const String& hash) { + avatarHashes_[from] = hash; onAvatarChanged(from, hash); } String AvatarManager::getAvatarHash(const JID& jid) const { - std::map<JID, String>::const_iterator i = avatarHashes_.find(jid.toBare()); + std::map<JID, String>::const_iterator i = avatarHashes_.find(getAvatarJID(jid)); if (i != avatarHashes_.end()) { return i->second; } @@ -62,4 +72,10 @@ boost::filesystem::path AvatarManager::getAvatarPath(const JID& jid) const { return boost::filesystem::path(); } +JID AvatarManager::getAvatarJID(const JID& jid) const { + JID bareFrom = jid.toBare(); + return (mucRegistry_->isMUC(bareFrom) ? jid : bareFrom); +} + + } diff --git a/Swiften/Avatars/AvatarManager.h b/Swiften/Avatars/AvatarManager.h index 0085405..13c6cb7 100644 --- a/Swiften/Avatars/AvatarManager.h +++ b/Swiften/Avatars/AvatarManager.h @@ -12,13 +12,14 @@ #include "Swiften/Elements/Error.h" namespace Swift { + class MUCRegistry; class AvatarStorage; class StanzaChannel; class IQRouter; class AvatarManager { public: - AvatarManager(StanzaChannel*, IQRouter*, AvatarStorage*); + AvatarManager(StanzaChannel*, IQRouter*, AvatarStorage*, MUCRegistry*); String getAvatarHash(const JID&) const; boost::filesystem::path getAvatarPath(const JID&) const; @@ -28,12 +29,15 @@ namespace Swift { private: void handlePresenceReceived(boost::shared_ptr<Presence>); - void handleVCardReceived(JID from, boost::shared_ptr<VCard>, const boost::optional<Error>&); + void handleVCardReceived(const JID& from, const String& hash, boost::shared_ptr<VCard>, const boost::optional<Error>&); + void setAvatarHash(const JID& from, const String& hash); + JID getAvatarJID(const JID& o) const; private: StanzaChannel* stanzaChannel_; IQRouter* iqRouter_; AvatarStorage* avatarStorage_; + MUCRegistry* mucRegistry_; std::map<JID, String> avatarHashes_; }; } diff --git a/Swiften/Avatars/UnitTest/AvatarManagerTest.cpp b/Swiften/Avatars/UnitTest/AvatarManagerTest.cpp new file mode 100644 index 0000000..b8a6246 --- /dev/null +++ b/Swiften/Avatars/UnitTest/AvatarManagerTest.cpp @@ -0,0 +1,101 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Avatars/AvatarManager.h" +#include "Swiften/Avatars/AvatarStorage.h" +#include "Swiften/MUC/MUCRegistry.h" +#include "Swiften/Queries/IQRouter.h" +#include "Swiften/Client/DummyStanzaChannel.h" + +using namespace Swift; + +class AvatarManagerTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(AvatarManagerTest); + CPPUNIT_TEST(testUpdate_UpdateNewHash); + CPPUNIT_TEST(testUpdate_UpdateNewHashAlreadyHaveAvatar); + CPPUNIT_TEST(testUpdate_UpdateNewHashFromMUC); + CPPUNIT_TEST(testUpdate_UpdateSameHash); + CPPUNIT_TEST(testUpdate_UpdateNewHashSameThanOtherUser); + CPPUNIT_TEST(testReceiveVCard); + CPPUNIT_TEST(testGetAvatarPath); + CPPUNIT_TEST(testGetAvatarPathFromMUC); + CPPUNIT_TEST_SUITE_END(); + + public: + AvatarManagerTest() {} + + void setUp() { + stanzaChannel_ = new DummyStanzaChannel(); + iqRouter_ = new IQRouter(stanzaChannel_); + mucRegistry_ = new DummyMUCRegistry(); + avatarStorage_ = new DummyAvatarStorage(); + } + + void tearDown() { + delete avatarStorage_; + delete mucRegistry_; + delete iqRouter_; + delete stanzaChannel_; + } + + void testUpdateNewHash() { + std::auto_ptr<AvatarManager> testling = createManager(); + } + + void testUpdate_UpdateNewHash() { + std::auto_ptr<AvatarManager> testling = createManager(); + } + + void testUpdate_UpdateNewHashAlreadyHaveAvatar() { + std::auto_ptr<AvatarManager> testling = createManager(); + } + + void testUpdate_UpdateNewHashFromMUC() { + std::auto_ptr<AvatarManager> testling = createManager(); + } + + void testUpdate_UpdateSameHash() { + std::auto_ptr<AvatarManager> testling = createManager(); + } + + void testUpdate_UpdateNewHashSameThanOtherUser() { + std::auto_ptr<AvatarManager> testling = createManager(); + } + + void testReceiveVCard() { + std::auto_ptr<AvatarManager> testling = createManager(); + } + + void testGetAvatarPath() { + std::auto_ptr<AvatarManager> testling = createManager(); + } + + void testGetAvatarPathFromMUC() { + std::auto_ptr<AvatarManager> testling = createManager(); + } + + private: + std::auto_ptr<AvatarManager> createManager() { + return std::auto_ptr<AvatarManager>(new AvatarManager(stanzaChannel_, iqRouter_, avatarStorage_, mucRegistry_)); + } + + private: + struct DummyMUCRegistry : public MUCRegistry { + bool isMUC(const JID& jid) const { return std::find(mucs_.begin(), mucs_.end(), jid) != mucs_.end(); } + std::vector<JID> mucs_; + }; + struct DummyAvatarStorage : public AvatarStorage { + virtual bool hasAvatar(const String& hash) const { return avatars.find(hash) != avatars.end(); } + virtual void addAvatar(const String& hash, const ByteArray& avatar) { avatars[hash] = avatar; } + virtual boost::filesystem::path getAvatarPath(const String& hash) const { + return boost::filesystem::path("/avatars") / hash.getUTF8String(); + } + std::map<String, ByteArray> avatars; + }; + DummyStanzaChannel* stanzaChannel_; + IQRouter* iqRouter_; + DummyMUCRegistry* mucRegistry_; + DummyAvatarStorage* avatarStorage_; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(AvatarManagerTest); diff --git a/Swiften/Avatars/UnitTest/Makefile.inc b/Swiften/Avatars/UnitTest/Makefile.inc index e69de29..c089c02 100644 --- a/Swiften/Avatars/UnitTest/Makefile.inc +++ b/Swiften/Avatars/UnitTest/Makefile.inc @@ -0,0 +1,2 @@ +UNITTEST_SOURCES += \ + Swiften/Avatars/UnitTest/AvatarManagerTest.cpp diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h new file mode 100644 index 0000000..4b66a9d --- /dev/null +++ b/Swiften/Client/DummyStanzaChannel.h @@ -0,0 +1,34 @@ +#pragma once + +#include <vector> + +#include "Swiften/Client/StanzaChannel.h" + +namespace Swift { + class DummyStanzaChannel : public StanzaChannel { + public: + DummyStanzaChannel() {} + + virtual void sendStanza(boost::shared_ptr<Stanza> stanza) { + sentStanzas_.push_back(stanza); + } + + virtual void sendIQ(boost::shared_ptr<IQ> iq) { + sentStanzas_.push_back(iq); + } + + virtual void sendMessage(boost::shared_ptr<Message> message) { + sentStanzas_.push_back(message); + } + + virtual void sendPresence(boost::shared_ptr<Presence> presence) { + sentStanzas_.push_back(presence); + } + + virtual String getNewIQID() { + return "test-id"; + } + + std::vector<boost::shared_ptr<Stanza> > sentStanzas_; + }; +} diff --git a/Swiften/MUC/MUCRegistry.cpp b/Swiften/MUC/MUCRegistry.cpp new file mode 100644 index 0000000..95bab08 --- /dev/null +++ b/Swiften/MUC/MUCRegistry.cpp @@ -0,0 +1,8 @@ +#include "Swiften/MUC/MUCRegistry.h" + +namespace Swift { + +MUCRegistry::~MUCRegistry() { +} + +} diff --git a/Swiften/MUC/MUCRegistry.h b/Swiften/MUC/MUCRegistry.h new file mode 100644 index 0000000..a843abb --- /dev/null +++ b/Swiften/MUC/MUCRegistry.h @@ -0,0 +1,12 @@ +#pragma once + +namespace Swift { + class JID; + + class MUCRegistry { + public: + virtual ~MUCRegistry(); + + virtual bool isMUC(const JID&) const = 0; + }; +} diff --git a/Swiften/MUC/Makefile.inc b/Swiften/MUC/Makefile.inc index d97b9fa..dc47d97 100644 --- a/Swiften/MUC/Makefile.inc +++ b/Swiften/MUC/Makefile.inc @@ -1,3 +1,4 @@ SWIFTEN_SOURCES += \ + Swiften/MUC/MUCRegistry.cpp \ Swiften/MUC/MUC.cpp \ Swiften/MUC/MUCOccupant.cpp diff --git a/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp b/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp index 855f9b0..e195eb7 100644 --- a/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp +++ b/Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp @@ -5,7 +5,7 @@ namespace Swift { VCardUpdateParser::VCardUpdateParser() : level_(TopLevel) { } -void VCardUpdateParser::handleStartElement(const String& element, const String&, const AttributeMap& attributes) { +void VCardUpdateParser::handleStartElement(const String&, const String&, const AttributeMap&) { if (level_ == PayloadLevel) { currentText_ = ""; } diff --git a/Swiften/Queries/Requests/GetVCardRequest.h b/Swiften/Queries/Requests/GetVCardRequest.h index e403096..8fc6e17 100644 --- a/Swiften/Queries/Requests/GetVCardRequest.h +++ b/Swiften/Queries/Requests/GetVCardRequest.h @@ -1,16 +1,12 @@ #pragma once -#include <cassert> - #include "Swiften/Queries/GenericRequest.h" #include "Swiften/Elements/VCard.h" namespace Swift { class GetVCardRequest : public GenericRequest<VCard> { public: - GetVCardRequest(const JID& jid, IQRouter* router) : - GenericRequest<VCard>(IQ::Get, jid, boost::shared_ptr<Payload>(new VCard()), router) { - assert(jid.isBare()); + GetVCardRequest(const JID& jid, IQRouter* router) : GenericRequest<VCard>(IQ::Get, jid, boost::shared_ptr<Payload>(new VCard()), router) { } }; } |