diff options
Diffstat (limited to 'Swiften/Avatars')
-rw-r--r-- | Swiften/Avatars/AvatarFileStorage.cpp | 26 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarFileStorage.h | 24 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarManager.cpp | 65 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarManager.h | 39 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarStorage.cpp | 8 | ||||
-rw-r--r-- | Swiften/Avatars/AvatarStorage.h | 18 | ||||
-rw-r--r-- | Swiften/Avatars/Makefile.inc | 6 | ||||
-rw-r--r-- | Swiften/Avatars/UnitTest/Makefile.inc | 0 |
8 files changed, 186 insertions, 0 deletions
diff --git a/Swiften/Avatars/AvatarFileStorage.cpp b/Swiften/Avatars/AvatarFileStorage.cpp new file mode 100644 index 0000000..1348018 --- /dev/null +++ b/Swiften/Avatars/AvatarFileStorage.cpp @@ -0,0 +1,26 @@ +#include "Swiften/Avatars/AvatarFileStorage.h" + +#include <iostream> +#include <boost/filesystem/fstream.hpp> + +namespace Swift { + +AvatarFileStorage::AvatarFileStorage(const boost::filesystem::path& path) : path_(path) { + boost::filesystem::create_directory(path_); +} + +bool AvatarFileStorage::hasAvatar(const String& hash) const { + return boost::filesystem::exists(getAvatarPath(hash)); +} + +void AvatarFileStorage::addAvatar(const String& hash, const ByteArray& avatar) { + boost::filesystem::ofstream file(getAvatarPath(hash), boost::filesystem::ofstream::binary|boost::filesystem::ofstream::out); + file.write(avatar.getData(), avatar.getSize()); + file.close(); +} + +boost::filesystem::path AvatarFileStorage::getAvatarPath(const String& hash) const { + return path_ / hash.getUTF8String(); +} + +} diff --git a/Swiften/Avatars/AvatarFileStorage.h b/Swiften/Avatars/AvatarFileStorage.h new file mode 100644 index 0000000..1afa703 --- /dev/null +++ b/Swiften/Avatars/AvatarFileStorage.h @@ -0,0 +1,24 @@ +#pragma once + +#include <map> +#include <boost/filesystem.hpp> + +#include "Swiften/Base/String.h" +#include "Swiften/Base/ByteArray.h" +#include "Swiften/Avatars/AvatarStorage.h" + +namespace Swift { + class AvatarFileStorage : public AvatarStorage { + public: + AvatarFileStorage(const boost::filesystem::path& path); + + virtual bool hasAvatar(const String& hash) const; + virtual void addAvatar(const String& hash, const ByteArray& avatar); + + virtual boost::filesystem::path getAvatarPath(const String& hash) const; + + private: + boost::filesystem::path path_; + }; + +} diff --git a/Swiften/Avatars/AvatarManager.cpp b/Swiften/Avatars/AvatarManager.cpp new file mode 100644 index 0000000..f0b04b9 --- /dev/null +++ b/Swiften/Avatars/AvatarManager.cpp @@ -0,0 +1,65 @@ +#include "Swiften/Avatars/AvatarManager.h" + +#include <boost/bind.hpp> + +#include "Swiften/Client/StanzaChannel.h" +#include "Swiften/Elements/VCardUpdate.h" +#include "Swiften/Queries/Requests/GetVCardRequest.h" +#include "Swiften/StringCodecs/SHA1.h" +#include "Swiften/Avatars/AvatarStorage.h" + +namespace Swift { + +AvatarManager::AvatarManager(StanzaChannel* stanzaChannel, IQRouter* iqRouter, AvatarStorage* avatarStorage) : stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), avatarStorage_(avatarStorage) { + stanzaChannel->onPresenceReceived.connect(boost::bind(&AvatarManager::handlePresenceReceived, this, _1)); +} + +void AvatarManager::handlePresenceReceived(boost::shared_ptr<Presence> presence) { + boost::shared_ptr<VCardUpdate> update = presence->getPayload<VCardUpdate>(); + if (!update) { + return; + } + JID from = presence->getFrom().toBare(); + 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(); + } + else { + onAvatarChanged(from, hash); + } + } +} + +void AvatarManager::handleVCardReceived(JID from, boost::shared_ptr<VCard> vCard, const boost::optional<Error>& error) { + if (error) { + // FIXME: What to do here? + return; + } + String hash = SHA1::getHexHash(vCard->getPhoto()); + avatarStorage_->addAvatar(hash, vCard->getPhoto()); + onAvatarChanged(from, hash); +} + +String AvatarManager::getAvatarHash(const JID& jid) const { + std::map<JID, String>::const_iterator i = avatarHashes_.find(jid.toBare()); + if (i != avatarHashes_.end()) { + return i->second; + } + else { + return ""; + } +} + +boost::filesystem::path AvatarManager::getAvatarPath(const JID& jid) const { + String hash = getAvatarHash(jid); + if (!hash.isEmpty()) { + return avatarStorage_->getAvatarPath(hash); + } + return boost::filesystem::path(); +} + +} diff --git a/Swiften/Avatars/AvatarManager.h b/Swiften/Avatars/AvatarManager.h new file mode 100644 index 0000000..0085405 --- /dev/null +++ b/Swiften/Avatars/AvatarManager.h @@ -0,0 +1,39 @@ +#pragma once + +#include <boost/filesystem.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/optional.hpp> +#include <boost/signal.hpp> +#include <map> + +#include "Swiften/JID/JID.h" +#include "Swiften/Elements/Presence.h" +#include "Swiften/Elements/VCard.h" +#include "Swiften/Elements/Error.h" + +namespace Swift { + class AvatarStorage; + class StanzaChannel; + class IQRouter; + + class AvatarManager { + public: + AvatarManager(StanzaChannel*, IQRouter*, AvatarStorage*); + + String getAvatarHash(const JID&) const; + boost::filesystem::path getAvatarPath(const JID&) const; + + public: + boost::signal<void (const JID&, const String&)> onAvatarChanged; + + private: + void handlePresenceReceived(boost::shared_ptr<Presence>); + void handleVCardReceived(JID from, boost::shared_ptr<VCard>, const boost::optional<Error>&); + + private: + StanzaChannel* stanzaChannel_; + IQRouter* iqRouter_; + AvatarStorage* avatarStorage_; + std::map<JID, String> avatarHashes_; + }; +} diff --git a/Swiften/Avatars/AvatarStorage.cpp b/Swiften/Avatars/AvatarStorage.cpp new file mode 100644 index 0000000..4c98314 --- /dev/null +++ b/Swiften/Avatars/AvatarStorage.cpp @@ -0,0 +1,8 @@ +#include "Swiften/Avatars/AvatarStorage.h" + +namespace Swift { + +AvatarStorage::~AvatarStorage() { +} + +} diff --git a/Swiften/Avatars/AvatarStorage.h b/Swiften/Avatars/AvatarStorage.h new file mode 100644 index 0000000..b5c0f32 --- /dev/null +++ b/Swiften/Avatars/AvatarStorage.h @@ -0,0 +1,18 @@ +#pragma once + +#include <boost/filesystem.hpp> + +namespace Swift { + class String; + class ByteArray; + + class AvatarStorage { + public: + virtual ~AvatarStorage(); + + virtual bool hasAvatar(const String& hash) const = 0; + virtual void addAvatar(const String& hash, const ByteArray& avatar) = 0; + virtual boost::filesystem::path getAvatarPath(const String& hash) const = 0; + }; + +} diff --git a/Swiften/Avatars/Makefile.inc b/Swiften/Avatars/Makefile.inc new file mode 100644 index 0000000..4887a49 --- /dev/null +++ b/Swiften/Avatars/Makefile.inc @@ -0,0 +1,6 @@ +SWIFTEN_SOURCES += \ + Swiften/Avatars/AvatarManager.cpp \ + Swiften/Avatars/AvatarStorage.cpp \ + Swiften/Avatars/AvatarFileStorage.cpp + +include Swiften/Avatars/UnitTest/Makefile.inc diff --git a/Swiften/Avatars/UnitTest/Makefile.inc b/Swiften/Avatars/UnitTest/Makefile.inc new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Swiften/Avatars/UnitTest/Makefile.inc |