diff options
author | Remko Tronçon <git@el-tramo.be> | 2011-03-11 20:22:35 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2011-03-11 22:22:04 (GMT) |
commit | 59aa5d7e29ca142ae324ad97e6a5f0353d1a6b89 (patch) | |
tree | e450b95ff4c0ba7f770723402a2634773f1a0451 /Swiften/Avatars | |
parent | 3ff52013d810f94b6095e93f550f58133e2df239 (diff) | |
download | swift-59aa5d7e29ca142ae324ad97e6a5f0353d1a6b89.zip swift-59aa5d7e29ca142ae324ad97e6a5f0353d1a6b89.tar.bz2 |
Store JID->Avatar mappings.
Resolves: #653
Diffstat (limited to 'Swiften/Avatars')
-rw-r--r-- | Swiften/Avatars/AvatarFileStorage.cpp | 62 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarFileStorage.h | 16 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarManager.cpp | 2 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarManager.h | 4 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarManagerImpl.cpp | 15 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarManagerImpl.h | 20 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarMemoryStorage.h | 17 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarStorage.h | 6 | ||||
-rw-r--r-- | Swiften/Avatars/CombinedAvatarProvider.cpp | 5 | ||||
-rw-r--r-- | Swiften/Avatars/OfflineAvatarManager.cpp | 32 | ||||
-rw-r--r-- | Swiften/Avatars/OfflineAvatarManager.h | 25 | ||||
-rw-r--r-- | Swiften/Avatars/SConscript | 1 | ||||
-rw-r--r-- | Swiften/Avatars/VCardUpdateAvatarManager.cpp | 3 |
13 files changed, 182 insertions, 26 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); } |