diff options
Diffstat (limited to 'Swift/Controllers')
23 files changed, 522 insertions, 16 deletions
| diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index efe4de4..d94094b 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -18,8 +18,7 @@  #include <Swift/Controllers/UIInterfaces/UIFactory.h>  #include "Swiften/Network/TimerFactory.h"  #include "Swift/Controllers/BuildVersion.h" -#include "Swift/Controllers/StoragesFactory.h" -#include "Swiften/Client/Storages.h" +#include "Swift/Controllers/Storages/StoragesFactory.h"  #include "Swiften/VCards/VCardManager.h"  #include "Swift/Controllers/Chat/UserSearchController.h"  #include "Swift/Controllers/Chat/ChatsManager.h" @@ -59,8 +58,8 @@  #include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"  #include "Swift/Controllers/UIEvents/ToggleNotificationsUIEvent.h"  #include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h" -#include "Swift/Controllers/CertificateStorageFactory.h" -#include "Swift/Controllers/CertificateStorageTrustChecker.h" +#include "Swift/Controllers/Storages/CertificateStorageFactory.h" +#include "Swift/Controllers/Storages/CertificateStorageTrustChecker.h"  #include "Swiften/Network/NetworkFactories.h"  #include <Swift/Controllers/ProfileController.h>  #include <Swift/Controllers/ContactEditController.h> diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript index bd18a3e..5b55892 100644 --- a/Swift/Controllers/SConscript +++ b/Swift/Controllers/SConscript @@ -50,9 +50,14 @@ if env["SCONS_STAGE"] == "build" :  			"UIInterfaces/XMLConsoleWidget.cpp",  			"UIInterfaces/ChatListWindow.cpp",  			"PreviousStatusStore.cpp", -			"CertificateStorageFactory.cpp", -			"CertificateStorage.cpp", -			"CertificateFileStorage.cpp", +			"Storages/CertificateStorageFactory.cpp", +			"Storages/CertificateStorage.cpp", +			"Storages/CertificateFileStorage.cpp", +			"Storages/AvatarFileStorage.cpp", +			"Storages/FileStorages.cpp", +			"Storages/RosterFileStorage.cpp", +			"Storages/CapsFileStorage.cpp", +			"Storages/VCardFileStorage.cpp",  			"StatusUtil.cpp",  			"Translator.cpp",  			"XMPPURIController.cpp", diff --git a/Swift/Controllers/Storages/AvatarFileStorage.cpp b/Swift/Controllers/Storages/AvatarFileStorage.cpp new file mode 100644 index 0000000..288f6fd --- /dev/null +++ b/Swift/Controllers/Storages/AvatarFileStorage.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swift/Controllers/Storages/AvatarFileStorage.h> + +#include <iostream> +#include <boost/filesystem/fstream.hpp> +#include <boost/filesystem.hpp> + +#include <Swiften/Base/foreach.h> +#include <Swiften/Base/String.h> +#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/StringCodecs/Hexify.h> + +namespace Swift { + +AvatarFileStorage::AvatarFileStorage(const boost::filesystem::path& avatarsDir, const boost::filesystem::path& avatarsFile) : avatarsDir(avatarsDir), avatarsFile(avatarsFile) { +	if (boost::filesystem::exists(avatarsFile)) { +		try { +			boost::filesystem::ifstream file(avatarsFile); +			std::string line; +			if (file.is_open()) { +				while (!file.eof()) { +					getline(file, line); +					std::pair<std::string, std::string> r = String::getSplittedAtFirst(line, ' '); +					JID jid(r.second); +					if (jid.isValid()) { +						jidAvatars.insert(std::make_pair(jid, r.first)); +					} +					else if (!r.first.empty() || !r.second.empty()) { +						std::cerr << "Invalid entry in avatars file: " << r.second << std::endl; +					} +				} +			} +		} +		catch (...) { +			std::cerr << "Error reading avatars file" << std::endl; +		} +	} +} + +bool AvatarFileStorage::hasAvatar(const std::string& hash) const {  +	return boost::filesystem::exists(getAvatarPath(hash)); +} + +void AvatarFileStorage::addAvatar(const std::string& hash, const ByteArray& avatar) { +	assert(Hexify::hexify(SHA1::getHash(avatar)) == hash); + +	boost::filesystem::path avatarPath = getAvatarPath(hash); +	if (!boost::filesystem::exists(avatarPath.parent_path())) { +		try { +			boost::filesystem::create_directories(avatarPath.parent_path()); +		} +		catch (const boost::filesystem::filesystem_error& e) { +			std::cerr << "ERROR: " << e.what() << std::endl; +		} +	} +	boost::filesystem::ofstream file(avatarPath, boost::filesystem::ofstream::binary|boost::filesystem::ofstream::out); +	file.write(reinterpret_cast<const char*>(avatar.getData()), static_cast<std::streamsize>(avatar.getSize())); +	file.close(); +} + +boost::filesystem::path AvatarFileStorage::getAvatarPath(const std::string& hash) const { +	return avatarsDir / hash; +} + +ByteArray AvatarFileStorage::getAvatar(const std::string& hash) const { +	ByteArray data; +	data.readFromFile(getAvatarPath(hash).string()); +	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() { +	try { +		boost::filesystem::ofstream file(avatarsFile); +		for (JIDAvatarMap::const_iterator i = jidAvatars.begin(); i != jidAvatars.end(); ++i) { +			file << i->second << " " << i->first.toString() << std::endl; +		} +		file.close(); +	} +	catch (...) { +		std::cerr << "Error writing avatars file" << std::endl; +	} +} + +} diff --git a/Swift/Controllers/Storages/AvatarFileStorage.h b/Swift/Controllers/Storages/AvatarFileStorage.h new file mode 100644 index 0000000..b7e73f5 --- /dev/null +++ b/Swift/Controllers/Storages/AvatarFileStorage.h @@ -0,0 +1,41 @@ +/* + * 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 <map> +#include <string> +#include <boost/filesystem/path.hpp> + +#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& avatarsDir, const boost::filesystem::path& avatarsFile); + +			virtual bool hasAvatar(const std::string& hash) const; +			virtual void addAvatar(const std::string& hash, const ByteArray& avatar); +			virtual ByteArray getAvatar(const std::string& hash) const; + +			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 avatarsDir; +			boost::filesystem::path avatarsFile; +			typedef std::map<JID, std::string> JIDAvatarMap; +			JIDAvatarMap jidAvatars; +	}; + +} diff --git a/Swift/Controllers/Storages/CapsFileStorage.cpp b/Swift/Controllers/Storages/CapsFileStorage.cpp new file mode 100644 index 0000000..b7593fd --- /dev/null +++ b/Swift/Controllers/Storages/CapsFileStorage.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swift/Controllers/Storages/CapsFileStorage.h" + +#include <Swiften/Entity/GenericPayloadPersister.h> +#include "Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.h" +#include "Swiften/Parser/PayloadParsers/DiscoInfoParser.h" +#include "Swiften/StringCodecs/Hexify.h" +#include "Swiften/StringCodecs/Base64.h" + +using namespace Swift; + +typedef GenericPayloadPersister<DiscoInfo, DiscoInfoParser, DiscoInfoSerializer> DiscoInfoPersister; + +CapsFileStorage::CapsFileStorage(const boost::filesystem::path& path) : path(path) { +} + +DiscoInfo::ref CapsFileStorage::getDiscoInfo(const std::string& hash) const { +	return DiscoInfoPersister().loadPayloadGeneric(getCapsPath(hash)); +} + +void CapsFileStorage::setDiscoInfo(const std::string& hash, DiscoInfo::ref discoInfo) { +	DiscoInfo::ref bareDiscoInfo(new DiscoInfo(*discoInfo.get())); +	bareDiscoInfo->setNode(""); +	DiscoInfoPersister().savePayload(bareDiscoInfo, getCapsPath(hash)); +} + +boost::filesystem::path CapsFileStorage::getCapsPath(const std::string& hash) const { +	return path / (Hexify::hexify(Base64::decode(hash)) + ".xml"); +} diff --git a/Swift/Controllers/Storages/CapsFileStorage.h b/Swift/Controllers/Storages/CapsFileStorage.h new file mode 100644 index 0000000..b3757e0 --- /dev/null +++ b/Swift/Controllers/Storages/CapsFileStorage.h @@ -0,0 +1,28 @@ +/* + * 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 <boost/filesystem/path.hpp> + +#include "Swiften/Disco/CapsStorage.h" +#include <string> + +namespace Swift { +	class CapsFileStorage : public CapsStorage { +		public: +			CapsFileStorage(const boost::filesystem::path& path); + +			virtual DiscoInfo::ref getDiscoInfo(const std::string& hash) const; +			virtual void setDiscoInfo(const std::string& hash, DiscoInfo::ref discoInfo); + +		private: +			boost::filesystem::path getCapsPath(const std::string& hash) const; + +		private: +			boost::filesystem::path path; +	}; +} diff --git a/Swift/Controllers/CertificateFileStorage.cpp b/Swift/Controllers/Storages/CertificateFileStorage.cpp index cf924ee..31af949 100644 --- a/Swift/Controllers/CertificateFileStorage.cpp +++ b/Swift/Controllers/Storages/CertificateFileStorage.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include <Swift/Controllers/CertificateFileStorage.h> +#include <Swift/Controllers/Storages/CertificateFileStorage.h>  #include <iostream>  #include <boost/filesystem/fstream.hpp> diff --git a/Swift/Controllers/CertificateFileStorage.h b/Swift/Controllers/Storages/CertificateFileStorage.h index 2b853ed..f7a60b9 100644 --- a/Swift/Controllers/CertificateFileStorage.h +++ b/Swift/Controllers/Storages/CertificateFileStorage.h @@ -8,7 +8,7 @@  #include <boost/filesystem.hpp> -#include "Swift/Controllers/CertificateStorage.h" +#include "Swift/Controllers/Storages/CertificateStorage.h"  namespace Swift {  	class CertificateFactory; diff --git a/Swift/Controllers/CertificateFileStorageFactory.h b/Swift/Controllers/Storages/CertificateFileStorageFactory.h index 7ed8287..b215165 100644 --- a/Swift/Controllers/CertificateFileStorageFactory.h +++ b/Swift/Controllers/Storages/CertificateFileStorageFactory.h @@ -6,8 +6,8 @@  #pragma once -#include <Swift/Controllers/CertificateStorageFactory.h> -#include <Swift/Controllers/CertificateFileStorage.h> +#include <Swift/Controllers/Storages/CertificateStorageFactory.h> +#include <Swift/Controllers/Storages/CertificateFileStorage.h>  namespace Swift {  	class CertificateFactory; diff --git a/Swift/Controllers/CertificateStorage.cpp b/Swift/Controllers/Storages/CertificateStorage.cpp index 343fccd..ee942c0 100644 --- a/Swift/Controllers/CertificateStorage.cpp +++ b/Swift/Controllers/Storages/CertificateStorage.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swift/Controllers/CertificateStorage.h" +#include "Swift/Controllers/Storages/CertificateStorage.h"  namespace Swift { diff --git a/Swift/Controllers/CertificateStorage.h b/Swift/Controllers/Storages/CertificateStorage.h index f8c6fb5..f8c6fb5 100644 --- a/Swift/Controllers/CertificateStorage.h +++ b/Swift/Controllers/Storages/CertificateStorage.h diff --git a/Swift/Controllers/CertificateStorageFactory.cpp b/Swift/Controllers/Storages/CertificateStorageFactory.cpp index 613a8c3..ba0179a 100644 --- a/Swift/Controllers/CertificateStorageFactory.cpp +++ b/Swift/Controllers/Storages/CertificateStorageFactory.cpp @@ -4,7 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include <Swift/Controllers/CertificateStorageFactory.h> +#include <Swift/Controllers/Storages/CertificateStorageFactory.h>  namespace Swift { diff --git a/Swift/Controllers/CertificateStorageFactory.h b/Swift/Controllers/Storages/CertificateStorageFactory.h index 5b85757..5b85757 100644 --- a/Swift/Controllers/CertificateStorageFactory.h +++ b/Swift/Controllers/Storages/CertificateStorageFactory.h diff --git a/Swift/Controllers/CertificateStorageTrustChecker.h b/Swift/Controllers/Storages/CertificateStorageTrustChecker.h index f33287c..40838dd 100644 --- a/Swift/Controllers/CertificateStorageTrustChecker.h +++ b/Swift/Controllers/Storages/CertificateStorageTrustChecker.h @@ -7,7 +7,7 @@  #pragma once  #include <Swiften/TLS/CertificateTrustChecker.h> -#include <Swift/Controllers/CertificateStorage.h> +#include <Swift/Controllers/Storages/CertificateStorage.h>  namespace Swift {  	/** diff --git a/Swift/Controllers/Storages/FileStorages.cpp b/Swift/Controllers/Storages/FileStorages.cpp new file mode 100644 index 0000000..6447099 --- /dev/null +++ b/Swift/Controllers/Storages/FileStorages.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swift/Controllers/Storages/FileStorages.h" +#include "Swift/Controllers/Storages/VCardFileStorage.h" +#include "Swift/Controllers/Storages/AvatarFileStorage.h" +#include "Swift/Controllers/Storages/CapsFileStorage.h" +#include "Swift/Controllers/Storages/RosterFileStorage.h" + +namespace Swift { + +FileStorages::FileStorages(const boost::filesystem::path& baseDir, const JID& jid) { +	std::string profile = jid.toBare(); +	vcardStorage = new VCardFileStorage(baseDir / profile / "vcards"); +	capsStorage = new CapsFileStorage(baseDir / "caps"); +	avatarStorage = new AvatarFileStorage(baseDir / "avatars", baseDir / profile / "avatars"); +	rosterStorage = new RosterFileStorage(baseDir / profile / "roster.xml"); +} + +FileStorages::~FileStorages() { +	delete rosterStorage; +	delete avatarStorage; +	delete capsStorage; +	delete vcardStorage; +} + +VCardStorage* FileStorages::getVCardStorage() const { +	return vcardStorage; +} + +CapsStorage* FileStorages::getCapsStorage() const { +	return capsStorage; +} + +AvatarStorage* FileStorages::getAvatarStorage() const { +	return avatarStorage; +} + +RosterStorage* FileStorages::getRosterStorage() const { +	return rosterStorage; +} + +} diff --git a/Swift/Controllers/Storages/FileStorages.h b/Swift/Controllers/Storages/FileStorages.h new file mode 100644 index 0000000..28df314 --- /dev/null +++ b/Swift/Controllers/Storages/FileStorages.h @@ -0,0 +1,53 @@ +/* + * 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 <boost/filesystem/path.hpp> + +#include "Swiften/Client/Storages.h" + +namespace Swift { +	class VCardFileStorage; +	class AvatarFileStorage; +	class CapsFileStorage; +	class RosterFileStorage; +	class JID; + +	/** +	 * A storages implementation that stores all controller data on disk. +	 */ +	class FileStorages : public Storages { +		public: +			/** +			 * Creates the storages interface. +			 * +			 * All data will be stored relative to a base directory, and +			 * for some controllers, in a subdirectory for the given profile. +			 * The data is stored in the following places: +			 * - Avatars: <basedir>/avatars +			 * - VCards: <basedir>/<profile>/vcards +			 * - Entity capabilities: <basedir>/caps +			 * +			 * \param baseDir the base dir to store data relative to +			 * \param jid the subdir in which profile-specific data will be stored.  +			 *   The bare JID will be used as the subdir name. +			 */ +			FileStorages(const boost::filesystem::path& baseDir, const JID& jid); +			~FileStorages(); + +			virtual VCardStorage* getVCardStorage() const; +			virtual AvatarStorage* getAvatarStorage() const; +			virtual CapsStorage* getCapsStorage() const; +			virtual RosterStorage* getRosterStorage() const; + +		private: +			VCardFileStorage* vcardStorage; +			AvatarFileStorage* avatarStorage; +			CapsFileStorage* capsStorage; +			RosterFileStorage* rosterStorage; +	}; +} diff --git a/Swift/Controllers/FileStoragesFactory.h b/Swift/Controllers/Storages/FileStoragesFactory.h index bd7cdfb..75c65b7 100644 --- a/Swift/Controllers/FileStoragesFactory.h +++ b/Swift/Controllers/Storages/FileStoragesFactory.h @@ -6,7 +6,7 @@  #pragma once -#include "Swift/Controllers/StoragesFactory.h" +#include "Swift/Controllers/Storages/StoragesFactory.h"  #include "Swiften/Client/FileStorages.h"  namespace Swift { diff --git a/Swift/Controllers/MemoryStoragesFactory.h b/Swift/Controllers/Storages/MemoryStoragesFactory.h index 8408e10..6648bcd 100644 --- a/Swift/Controllers/MemoryStoragesFactory.h +++ b/Swift/Controllers/Storages/MemoryStoragesFactory.h @@ -6,7 +6,7 @@  #pragma once -#include "Swift/Controllers/StoragesFactory.h" +#include "Swift/Controllers/Storages/StoragesFactory.h"  #include "Swiften/Client/MemoryStorages.h"  namespace Swift { diff --git a/Swift/Controllers/Storages/RosterFileStorage.cpp b/Swift/Controllers/Storages/RosterFileStorage.cpp new file mode 100644 index 0000000..73e582f --- /dev/null +++ b/Swift/Controllers/Storages/RosterFileStorage.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swift/Controllers/Storages/RosterFileStorage.h> + +#include <Swiften/Entity/GenericPayloadPersister.h> +#include <Swiften/Serializer/PayloadSerializers/RosterSerializer.h> +#include <Swiften/Parser/PayloadParsers/RosterParser.h> + +using namespace Swift; + +typedef GenericPayloadPersister<RosterPayload, RosterParser, RosterSerializer> RosterPersister; + +RosterFileStorage::RosterFileStorage(const boost::filesystem::path& path) : path(path) { +} + +boost::shared_ptr<RosterPayload> RosterFileStorage::getRoster() const { +	return RosterPersister().loadPayloadGeneric(path); +} + +void RosterFileStorage::setRoster(boost::shared_ptr<RosterPayload> roster) { +	RosterPersister().savePayload(roster, path); +} diff --git a/Swift/Controllers/Storages/RosterFileStorage.h b/Swift/Controllers/Storages/RosterFileStorage.h new file mode 100644 index 0000000..cb00969 --- /dev/null +++ b/Swift/Controllers/Storages/RosterFileStorage.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/filesystem/path.hpp> + +#include <Swiften/Roster/RosterStorage.h> + +namespace Swift { +	class RosterFileStorage : public RosterStorage { +		public: +			RosterFileStorage(const boost::filesystem::path& path); + +			virtual boost::shared_ptr<RosterPayload> getRoster() const; +			virtual void setRoster(boost::shared_ptr<RosterPayload>); + +		private: +			boost::filesystem::path path; +	}; +} diff --git a/Swift/Controllers/StoragesFactory.h b/Swift/Controllers/Storages/StoragesFactory.h index 441a4e9..441a4e9 100644 --- a/Swift/Controllers/StoragesFactory.h +++ b/Swift/Controllers/Storages/StoragesFactory.h diff --git a/Swift/Controllers/Storages/VCardFileStorage.cpp b/Swift/Controllers/Storages/VCardFileStorage.cpp new file mode 100644 index 0000000..4933d0c --- /dev/null +++ b/Swift/Controllers/Storages/VCardFileStorage.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swift/Controllers/Storages/VCardFileStorage.h" + +#include <boost/filesystem/fstream.hpp> +#include <boost/filesystem.hpp> +#include <iostream> + +#include <Swiften/Entity/GenericPayloadPersister.h> +#include <Swiften/Base/String.h> +#include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/Base/foreach.h> +#include "Swiften/JID/JID.h" +#include "Swiften/Elements/VCard.h" +#include "Swiften/Serializer/PayloadSerializers/VCardSerializer.h" +#include "Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h" +#include "Swiften/Parser/PayloadParsers/VCardParser.h" + +using namespace Swift; + +typedef GenericPayloadPersister<VCard, VCardParser, VCardSerializer> VCardPersister; + +VCardFileStorage::VCardFileStorage(boost::filesystem::path dir) : vcardsPath(dir) { +	cacheFile = vcardsPath / "phashes"; +	if (boost::filesystem::exists(cacheFile)) { +		try { +			boost::filesystem::ifstream file(cacheFile); +			std::string line; +			if (file.is_open()) { +				while (!file.eof()) { +					getline(file, line); +					std::pair<std::string, std::string> r = String::getSplittedAtFirst(line, ' '); +					JID jid(r.second); +					if (jid.isValid()) { +						photoHashes.insert(std::make_pair(jid, r.first)); +					} +					else if (!r.first.empty() || !r.second.empty()) { +						std::cerr << "Invalid entry in phashes file" << std::endl; +					} +				} +			} +		} +		catch (...) { +			std::cerr << "Error reading phashes file" << std::endl; +		} +	} +} + +boost::shared_ptr<VCard> VCardFileStorage::getVCard(const JID& jid) const { +	return VCardPersister().loadPayloadGeneric(getVCardPath(jid)); +} + +void VCardFileStorage::setVCard(const JID& jid, VCard::ref v) { +	VCardPersister().savePayload(v, getVCardPath(jid)); +	getAndUpdatePhotoHash(jid, v); +} + +boost::filesystem::path VCardFileStorage::getVCardPath(const JID& jid) const { +	std::string file(jid.toString()); +	String::replaceAll(file, '/', "%2f"); +	return boost::filesystem::path(vcardsPath / (file + ".xml")); +} + +std::string VCardFileStorage::getPhotoHash(const JID& jid) const { +	PhotoHashMap::const_iterator i = photoHashes.find(jid); +	if (i != photoHashes.end()) { +		return i->second; +	} +	else { +		VCard::ref vCard = getVCard(jid); +		return getAndUpdatePhotoHash(jid, vCard); +	} +} + +std::string VCardFileStorage::getAndUpdatePhotoHash(const JID& jid, VCard::ref vCard) const { +	std::string hash; +	if (vCard && !vCard->getPhoto().isEmpty()) { +		hash = Hexify::hexify(SHA1::getHash(vCard->getPhoto())); +	} +	std::pair<PhotoHashMap::iterator, bool> r = photoHashes.insert(std::make_pair(jid, hash)); +	if (r.second) { +		savePhotoHashes(); +	} +	else if (r.first->second != hash) { +		r.first->second = hash; +		savePhotoHashes(); +	} +	return hash; +} + +void VCardFileStorage::savePhotoHashes() const { +	try { +		boost::filesystem::ofstream file(cacheFile); +		for (PhotoHashMap::const_iterator i = photoHashes.begin(); i != photoHashes.end(); ++i) { +			file << i->second << " " << i->first.toString() << std::endl; +		} +		file.close(); +	} +	catch (...) { +		std::cerr << "Error writing vcards file" << std::endl; +	} +} diff --git a/Swift/Controllers/Storages/VCardFileStorage.h b/Swift/Controllers/Storages/VCardFileStorage.h new file mode 100644 index 0000000..ba422f4 --- /dev/null +++ b/Swift/Controllers/Storages/VCardFileStorage.h @@ -0,0 +1,38 @@ +/* + * 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 <boost/shared_ptr.hpp> +#include <boost/filesystem/path.hpp> +#include <string> +#include <map> + +#include "Swiften/VCards/VCardStorage.h" + +namespace Swift { +	class VCardFileStorage : public VCardStorage { +		public: +			VCardFileStorage(boost::filesystem::path dir); + +			virtual VCard::ref getVCard(const JID& jid) const; +			virtual void setVCard(const JID& jid, VCard::ref v); + +			virtual std::string getPhotoHash(const JID&) const; + +		private: +			boost::filesystem::path getVCardPath(const JID&) const; + +			std::string getAndUpdatePhotoHash(const JID& jid, VCard::ref vcard) const; +			void savePhotoHashes() const; + +		private: +			boost::filesystem::path vcardsPath; +			boost::filesystem::path cacheFile; +			typedef std::map<JID, std::string> PhotoHashMap; +			mutable PhotoHashMap photoHashes; +	}; +} | 
 Swift
 Swift