summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2009-06-22 17:38:29 (GMT)
committerRemko Tronçon <git@el-tramo.be>2009-06-22 17:39:06 (GMT)
commite8360f0dd62ea651e94f681499faef58747f2ece (patch)
tree5eeb231a12a44c65baf648b0350387a6f25986af /Swiften
parent86e892137d512a11edde0aa7760fc1c15e598dad (diff)
downloadswift-e8360f0dd62ea651e94f681499faef58747f2ece.zip
swift-e8360f0dd62ea651e94f681499faef58747f2ece.tar.bz2
Support vCard-based avatars in MUCs.
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/Avatars/AvatarManager.cpp40
-rw-r--r--Swiften/Avatars/AvatarManager.h8
-rw-r--r--Swiften/Avatars/UnitTest/AvatarManagerTest.cpp101
-rw-r--r--Swiften/Avatars/UnitTest/Makefile.inc2
-rw-r--r--Swiften/Client/DummyStanzaChannel.h34
-rw-r--r--Swiften/MUC/MUCRegistry.cpp8
-rw-r--r--Swiften/MUC/MUCRegistry.h12
-rw-r--r--Swiften/MUC/Makefile.inc1
-rw-r--r--Swiften/Parser/PayloadParsers/VCardUpdateParser.cpp2
-rw-r--r--Swiften/Queries/Requests/GetVCardRequest.h6
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) {
}
};
}