summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2011-03-11 20:22:35 (GMT)
committerRemko Tronçon <git@el-tramo.be>2011-03-11 22:22:04 (GMT)
commit59aa5d7e29ca142ae324ad97e6a5f0353d1a6b89 (patch)
treee450b95ff4c0ba7f770723402a2634773f1a0451 /Swiften
parent3ff52013d810f94b6095e93f550f58133e2df239 (diff)
downloadswift-59aa5d7e29ca142ae324ad97e6a5f0353d1a6b89.zip
swift-59aa5d7e29ca142ae324ad97e6a5f0353d1a6b89.tar.bz2
Store JID->Avatar mappings.
Resolves: #653
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/Avatars/AvatarFileStorage.cpp62
-rw-r--r--Swiften/Avatars/AvatarFileStorage.h16
-rw-r--r--Swiften/Avatars/AvatarManager.cpp2
-rw-r--r--Swiften/Avatars/AvatarManager.h4
-rw-r--r--Swiften/Avatars/AvatarManagerImpl.cpp15
-rw-r--r--Swiften/Avatars/AvatarManagerImpl.h20
-rw-r--r--Swiften/Avatars/AvatarMemoryStorage.h17
-rw-r--r--Swiften/Avatars/AvatarStorage.h6
-rw-r--r--Swiften/Avatars/CombinedAvatarProvider.cpp5
-rw-r--r--Swiften/Avatars/OfflineAvatarManager.cpp32
-rw-r--r--Swiften/Avatars/OfflineAvatarManager.h25
-rw-r--r--Swiften/Avatars/SConscript1
-rw-r--r--Swiften/Avatars/VCardUpdateAvatarManager.cpp3
-rw-r--r--Swiften/Base/Log.h3
-rw-r--r--Swiften/Client/FileStorages.cpp2
15 files changed, 185 insertions, 28 deletions
diff --git a/Swiften/Avatars/AvatarFileStorage.cpp b/Swiften/Avatars/AvatarFileStorage.cpp
index 046ac16..44a6a7f 100644
--- a/Swiften/Avatars/AvatarFileStorage.cpp
+++ b/Swiften/Avatars/AvatarFileStorage.cpp
@@ -4,14 +4,39 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/Avatars/AvatarFileStorage.h"
+#include <Swiften/Avatars/AvatarFileStorage.h>
#include <iostream>
#include <boost/filesystem/fstream.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+
+#include <Swiften/Base/foreach.h>
namespace Swift {
-AvatarFileStorage::AvatarFileStorage(const boost::filesystem::path& path) : path_(path) {
+AvatarFileStorage::AvatarFileStorage(const boost::filesystem::path& avatarsDir, const boost::filesystem::path& avatarsFile) : avatarsDir(avatarsDir), avatarsFile(avatarsFile) {
+ if (boost::filesystem::exists(avatarsFile)) {
+ boost::property_tree::ptree tree;
+ try {
+ boost::property_tree::xml_parser::read_xml(avatarsFile.string(), tree);
+ }
+ catch (const boost::property_tree::xml_parser::xml_parser_error& e) {
+ std::cerr << "Error reading avatars file: " << e.filename() << ":" << e.line() << ": " << e.message() << std::endl;
+ }
+ foreach(const boost::property_tree::ptree::value_type &v, tree.get_child("avatars")) {
+ try {
+ JID jid(v.second.get<std::string>("jid"));
+ std::string hash(v.second.get<std::string>("hash"));
+ if (jid.isValid()) {
+ jidAvatars.insert(std::make_pair(jid, hash));
+ }
+ }
+ catch (const boost::property_tree::ptree_error& e) {
+ std::cerr << "Invalid avatar value: " << e.what() << std::endl;
+ }
+ }
+ }
}
bool AvatarFileStorage::hasAvatar(const std::string& hash) const {
@@ -34,7 +59,7 @@ void AvatarFileStorage::addAvatar(const std::string& hash, const ByteArray& avat
}
boost::filesystem::path AvatarFileStorage::getAvatarPath(const std::string& hash) const {
- return path_ / hash;
+ return avatarsDir / hash;
}
ByteArray AvatarFileStorage::getAvatar(const std::string& hash) const {
@@ -43,5 +68,36 @@ ByteArray AvatarFileStorage::getAvatar(const std::string& hash) const {
return data;
}
+void AvatarFileStorage::setAvatarForJID(const JID& jid, const std::string& hash) {
+ std::pair<JIDAvatarMap::iterator, bool> r = jidAvatars.insert(std::make_pair(jid, hash));
+ if (r.second) {
+ saveJIDAvatars();
+ }
+ else if (r.first->second != hash) {
+ r.first->second = hash;
+ saveJIDAvatars();
+ }
+}
+
+std::string AvatarFileStorage::getAvatarForJID(const JID& jid) const {
+ JIDAvatarMap::const_iterator i = jidAvatars.find(jid);
+ return i == jidAvatars.end() ? "" : i->second;
+}
+
+void AvatarFileStorage::saveJIDAvatars() {
+ boost::property_tree::ptree tree;
+ for (JIDAvatarMap::const_iterator i = jidAvatars.begin(); i != jidAvatars.end(); ++i) {
+ boost::property_tree::ptree entry;
+ entry.put("jid", i->first.toString());
+ entry.put("hash", i->second);
+ tree.add_child("avatars.avatar", entry);
+ }
+ try {
+ boost::property_tree::xml_parser::write_xml(avatarsFile.string(), tree);
+ }
+ catch (const boost::property_tree::xml_parser::xml_parser_error& e) {
+ std::cerr << "Error writing avatars file: " << e.filename() << ": " << e.message() << std::endl;
+ }
+}
}
diff --git a/Swiften/Avatars/AvatarFileStorage.h b/Swiften/Avatars/AvatarFileStorage.h
index e803430..e736230 100644
--- a/Swiften/Avatars/AvatarFileStorage.h
+++ b/Swiften/Avatars/AvatarFileStorage.h
@@ -7,16 +7,17 @@
#pragma once
#include <map>
+#include <string>
#include <boost/filesystem.hpp>
-#include <string>
+#include <Swiften/JID/JID.h>
#include "Swiften/Base/ByteArray.h"
#include "Swiften/Avatars/AvatarStorage.h"
namespace Swift {
class AvatarFileStorage : public AvatarStorage {
public:
- AvatarFileStorage(const boost::filesystem::path& path);
+ AvatarFileStorage(const boost::filesystem::path& avatarsDir, const boost::filesystem::path& avatarsFile);
virtual bool hasAvatar(const std::string& hash) const;
virtual void addAvatar(const std::string& hash, const ByteArray& avatar);
@@ -24,8 +25,17 @@ namespace Swift {
virtual boost::filesystem::path getAvatarPath(const std::string& hash) const;
+ virtual void setAvatarForJID(const JID& jid, const std::string& hash);
+ virtual std::string getAvatarForJID(const JID& jid) const;
+
+ private:
+ void saveJIDAvatars();
+
private:
- boost::filesystem::path path_;
+ boost::filesystem::path avatarsDir;
+ boost::filesystem::path avatarsFile;
+ typedef std::map<JID, std::string> JIDAvatarMap;
+ JIDAvatarMap jidAvatars;
};
}
diff --git a/Swiften/Avatars/AvatarManager.cpp b/Swiften/Avatars/AvatarManager.cpp
index a2b7200..ce7d372 100644
--- a/Swiften/Avatars/AvatarManager.cpp
+++ b/Swiften/Avatars/AvatarManager.cpp
@@ -4,7 +4,7 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swiften/Avatars/AvatarManager.h"
+#include <Swiften/Avatars/AvatarManager.h>
namespace Swift {
diff --git a/Swiften/Avatars/AvatarManager.h b/Swiften/Avatars/AvatarManager.h
index d40c3c0..e1af451 100644
--- a/Swiften/Avatars/AvatarManager.h
+++ b/Swiften/Avatars/AvatarManager.h
@@ -8,8 +8,8 @@
#include <boost/filesystem.hpp>
-#include "Swiften/Base/boost_bsignals.h"
-#include "Swiften/Base/ByteArray.h"
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Base/ByteArray.h>
namespace Swift {
class JID;
diff --git a/Swiften/Avatars/AvatarManagerImpl.cpp b/Swiften/Avatars/AvatarManagerImpl.cpp
index 6b77f8d..509ff47 100644
--- a/Swiften/Avatars/AvatarManagerImpl.cpp
+++ b/Swiften/Avatars/AvatarManagerImpl.cpp
@@ -11,6 +11,7 @@
#include "Swiften/Avatars/VCardUpdateAvatarManager.h"
#include "Swiften/Avatars/VCardAvatarManager.h"
#include "Swiften/Avatars/AvatarStorage.h"
+#include <Swiften/Avatars/OfflineAvatarManager.h>
#include "Swiften/Base/ByteArray.h"
namespace Swift {
@@ -22,10 +23,17 @@ AvatarManagerImpl::AvatarManagerImpl(VCardManager* vcardManager, StanzaChannel*
vcardAvatarManager = new VCardAvatarManager(vcardManager, avatarStorage, mucRegistry);
combinedAvatarProvider.addProvider(vcardAvatarManager);
- combinedAvatarProvider.onAvatarChanged.connect(boost::ref(onAvatarChanged));
+ offlineAvatarManager = new OfflineAvatarManager(avatarStorage);
+ combinedAvatarProvider.addProvider(offlineAvatarManager);
+
+ combinedAvatarProvider.onAvatarChanged.connect(boost::bind(&AvatarManagerImpl::handleCombinedAvatarChanged, this, _1));
}
AvatarManagerImpl::~AvatarManagerImpl() {
+ combinedAvatarProvider.onAvatarChanged.disconnect(boost::bind(&AvatarManagerImpl::handleCombinedAvatarChanged, this, _1));
+
+ combinedAvatarProvider.removeProvider(offlineAvatarManager);
+ delete offlineAvatarManager;
combinedAvatarProvider.removeProvider(vcardAvatarManager);
delete vcardAvatarManager;
combinedAvatarProvider.removeProvider(vcardUpdateAvatarManager);
@@ -48,4 +56,9 @@ ByteArray AvatarManagerImpl::getAvatar(const JID& jid) const {
return ByteArray();
}
+void AvatarManagerImpl::handleCombinedAvatarChanged(const JID& jid) {
+ offlineAvatarManager->setAvatar(jid, combinedAvatarProvider.getAvatarHash(jid));
+ onAvatarChanged(jid);
+}
+
}
diff --git a/Swiften/Avatars/AvatarManagerImpl.h b/Swiften/Avatars/AvatarManagerImpl.h
index a28d490..c2b8956 100644
--- a/Swiften/Avatars/AvatarManagerImpl.h
+++ b/Swiften/Avatars/AvatarManagerImpl.h
@@ -6,18 +6,8 @@
#pragma once
-#include <boost/filesystem.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/optional.hpp>
-#include <map>
-
-#include "Swiften/Avatars/AvatarManager.h"
-#include "Swiften/Base/boost_bsignals.h"
-#include "Swiften/JID/JID.h"
-#include "Swiften/Elements/Presence.h"
-#include "Swiften/Elements/VCard.h"
-#include "Swiften/Elements/ErrorPayload.h"
-#include "Swiften/Avatars/CombinedAvatarProvider.h"
+#include <Swiften/Avatars/AvatarManager.h>
+#include <Swiften/Avatars/CombinedAvatarProvider.h>
namespace Swift {
class MUCRegistry;
@@ -26,6 +16,7 @@ namespace Swift {
class VCardManager;
class VCardUpdateAvatarManager;
class VCardAvatarManager;
+ class OfflineAvatarManager;
class AvatarManagerImpl : public AvatarManager {
public:
@@ -36,9 +27,14 @@ namespace Swift {
virtual ByteArray getAvatar(const JID&) const;
private:
+ void handleCombinedAvatarChanged(const JID& jid);
+
+
+ private:
CombinedAvatarProvider combinedAvatarProvider;
AvatarStorage* avatarStorage;
VCardUpdateAvatarManager* vcardUpdateAvatarManager;
VCardAvatarManager* vcardAvatarManager;
+ OfflineAvatarManager* offlineAvatarManager;
};
}
diff --git a/Swiften/Avatars/AvatarMemoryStorage.h b/Swiften/Avatars/AvatarMemoryStorage.h
index 3fa770a..095b144 100644
--- a/Swiften/Avatars/AvatarMemoryStorage.h
+++ b/Swiften/Avatars/AvatarMemoryStorage.h
@@ -7,10 +7,11 @@
#pragma once
#include <map>
-
#include <string>
-#include "Swiften/Base/ByteArray.h"
-#include "Swiften/Avatars/AvatarStorage.h"
+
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/Avatars/AvatarStorage.h>
+#include <Swiften/JID/JID.h>
namespace Swift {
class AvatarMemoryStorage : public AvatarStorage {
@@ -26,7 +27,17 @@ namespace Swift {
return boost::filesystem::path("/avatars") / hash;
}
+ virtual void setAvatarForJID(const JID& jid, const std::string& hash) {
+ jidAvatars[jid] = hash;
+ }
+
+ virtual std::string getAvatarForJID(const JID& jid) const {
+ std::map<JID, std::string>::const_iterator i = jidAvatars.find(jid);
+ return i == jidAvatars.end() ? "" : i->second;
+ }
+
private:
std::map<std::string, ByteArray> avatars;
+ std::map<JID, std::string> jidAvatars;
};
}
diff --git a/Swiften/Avatars/AvatarStorage.h b/Swiften/Avatars/AvatarStorage.h
index 826a648..48fc885 100644
--- a/Swiften/Avatars/AvatarStorage.h
+++ b/Swiften/Avatars/AvatarStorage.h
@@ -7,9 +7,10 @@
#pragma once
#include <boost/filesystem.hpp>
+#include <string>
namespace Swift {
-
+ class JID;
class ByteArray;
class AvatarStorage {
@@ -20,6 +21,9 @@ namespace Swift {
virtual void addAvatar(const std::string& hash, const ByteArray& avatar) = 0;
virtual ByteArray getAvatar(const std::string& hash) const = 0;
virtual boost::filesystem::path getAvatarPath(const std::string& hash) const = 0;
+
+ virtual void setAvatarForJID(const JID& jid, const std::string& hash) = 0;
+ virtual std::string getAvatarForJID(const JID& jid) const = 0;
};
}
diff --git a/Swiften/Avatars/CombinedAvatarProvider.cpp b/Swiften/Avatars/CombinedAvatarProvider.cpp
index 6ac31e3..ae0fde3 100644
--- a/Swiften/Avatars/CombinedAvatarProvider.cpp
+++ b/Swiften/Avatars/CombinedAvatarProvider.cpp
@@ -9,15 +9,20 @@
#include <algorithm>
#include <boost/bind.hpp>
+#include <Swiften/Base/Log.h>
+
namespace Swift {
std::string CombinedAvatarProvider::getAvatarHash(const JID& jid) const {
+ SWIFT_LOG(debug) << "JID: " << jid << std::endl;
for (size_t i = 0; i < providers.size(); ++i) {
std::string hash = providers[i]->getAvatarHash(jid);
+ SWIFT_LOG(debug) << "Provider " << providers[i] << ": " << hash << std::endl;
if (!hash.empty()) {
return hash;
}
}
+ SWIFT_LOG(debug) << "No hash found" << std::endl;
return std::string();
}
diff --git a/Swiften/Avatars/OfflineAvatarManager.cpp b/Swiften/Avatars/OfflineAvatarManager.cpp
new file mode 100644
index 0000000..02c6a35
--- /dev/null
+++ b/Swiften/Avatars/OfflineAvatarManager.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Avatars/OfflineAvatarManager.h>
+
+#include <boost/bind.hpp>
+
+#include <Swiften/Avatars/AvatarStorage.h>
+
+namespace Swift {
+
+OfflineAvatarManager::OfflineAvatarManager(AvatarStorage* avatarStorage) : avatarStorage(avatarStorage) {
+}
+
+OfflineAvatarManager::~OfflineAvatarManager() {
+}
+
+std::string OfflineAvatarManager::getAvatarHash(const JID& jid) const {
+ return avatarStorage->getAvatarForJID(jid);
+}
+
+void OfflineAvatarManager::setAvatar(const JID& jid, const std::string& hash) {
+ if (getAvatarHash(jid) != hash) {
+ avatarStorage->setAvatarForJID(jid, hash);
+ onAvatarChanged(jid);
+ }
+}
+
+}
diff --git a/Swiften/Avatars/OfflineAvatarManager.h b/Swiften/Avatars/OfflineAvatarManager.h
new file mode 100644
index 0000000..2098990
--- /dev/null
+++ b/Swiften/Avatars/OfflineAvatarManager.h
@@ -0,0 +1,25 @@
+/*
+ * 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/Avatars/AvatarProvider.h>
+
+namespace Swift {
+ class AvatarStorage;
+
+ class OfflineAvatarManager : public AvatarProvider {
+ public:
+ OfflineAvatarManager(AvatarStorage*);
+ ~OfflineAvatarManager();
+
+ virtual std::string getAvatarHash(const JID&) const;
+ void setAvatar(const JID&, const std::string& hash);
+
+ private:
+ AvatarStorage* avatarStorage;
+ };
+}
diff --git a/Swiften/Avatars/SConscript b/Swiften/Avatars/SConscript
index 7922a51..acf2592 100644
--- a/Swiften/Avatars/SConscript
+++ b/Swiften/Avatars/SConscript
@@ -4,6 +4,7 @@ objects = swiften_env.StaticObject([
"AvatarFileStorage.cpp",
"VCardUpdateAvatarManager.cpp",
"VCardAvatarManager.cpp",
+ "OfflineAvatarManager.cpp",
"AvatarManager.cpp",
"AvatarManagerImpl.cpp",
"AvatarStorage.cpp",
diff --git a/Swiften/Avatars/VCardUpdateAvatarManager.cpp b/Swiften/Avatars/VCardUpdateAvatarManager.cpp
index 08d026b..ea074cc 100644
--- a/Swiften/Avatars/VCardUpdateAvatarManager.cpp
+++ b/Swiften/Avatars/VCardUpdateAvatarManager.cpp
@@ -16,6 +16,7 @@
#include "Swiften/Avatars/AvatarStorage.h"
#include "Swiften/MUC/MUCRegistry.h"
#include "Swiften/VCards/VCardManager.h"
+#include <Swiften/Base/Log.h>
namespace Swift {
@@ -34,6 +35,7 @@ void VCardUpdateAvatarManager::handlePresenceReceived(boost::shared_ptr<Presence
if (getAvatarHash(from) == update->getPhotoHash()) {
return;
}
+ SWIFT_LOG(debug) << "Updated hash: " << from << " -> " << update->getPhotoHash() << std::endl;
if (avatarStorage_->hasAvatar(update->getPhotoHash())) {
setAvatarHash(from, update->getPhotoHash());
}
@@ -61,6 +63,7 @@ void VCardUpdateAvatarManager::handleVCardChanged(const JID& from, VCard::ref vC
}
void VCardUpdateAvatarManager::setAvatarHash(const JID& from, const std::string& hash) {
+ SWIFT_LOG(debug) << "Updating hash: " << from << " -> " << hash << std::endl;
avatarHashes_[from] = hash;
onAvatarChanged(from);
}
diff --git a/Swiften/Base/Log.h b/Swiften/Base/Log.h
index 5296860..5e13a20 100644
--- a/Swiften/Base/Log.h
+++ b/Swiften/Base/Log.h
@@ -6,7 +6,8 @@
#pragma once
-#include "Swiften/Base/Platform.h"
+#include <iostream>
+
namespace Swift {
extern bool logging;
}
diff --git a/Swiften/Client/FileStorages.cpp b/Swiften/Client/FileStorages.cpp
index ad8b130..54a109d 100644
--- a/Swiften/Client/FileStorages.cpp
+++ b/Swiften/Client/FileStorages.cpp
@@ -15,7 +15,7 @@ FileStorages::FileStorages(const boost::filesystem::path& baseDir, const JID& ji
std::string profile = jid.toBare();
vcardStorage = new VCardFileStorage(baseDir / profile / "vcards");
capsStorage = new CapsFileStorage(baseDir / "caps");
- avatarStorage = new AvatarFileStorage(baseDir / "avatars");
+ avatarStorage = new AvatarFileStorage(baseDir / "avatars", baseDir / profile / "avatars.xml");
}
FileStorages::~FileStorages() {