summaryrefslogtreecommitdiffstats
path: root/Swift
diff options
context:
space:
mode:
Diffstat (limited to 'Swift')
-rw-r--r--Swift/Controllers/MainController.cpp7
-rw-r--r--Swift/Controllers/SConscript11
-rw-r--r--Swift/Controllers/Storages/AvatarFileStorage.cpp105
-rw-r--r--Swift/Controllers/Storages/AvatarFileStorage.h41
-rw-r--r--Swift/Controllers/Storages/CapsFileStorage.cpp34
-rw-r--r--Swift/Controllers/Storages/CapsFileStorage.h28
-rw-r--r--Swift/Controllers/Storages/CertificateFileStorage.cpp (renamed from Swift/Controllers/CertificateFileStorage.cpp)2
-rw-r--r--Swift/Controllers/Storages/CertificateFileStorage.h (renamed from Swift/Controllers/CertificateFileStorage.h)2
-rw-r--r--Swift/Controllers/Storages/CertificateFileStorageFactory.h (renamed from Swift/Controllers/CertificateFileStorageFactory.h)4
-rw-r--r--Swift/Controllers/Storages/CertificateStorage.cpp (renamed from Swift/Controllers/CertificateStorage.cpp)2
-rw-r--r--Swift/Controllers/Storages/CertificateStorage.h (renamed from Swift/Controllers/CertificateStorage.h)0
-rw-r--r--Swift/Controllers/Storages/CertificateStorageFactory.cpp (renamed from Swift/Controllers/CertificateStorageFactory.cpp)2
-rw-r--r--Swift/Controllers/Storages/CertificateStorageFactory.h (renamed from Swift/Controllers/CertificateStorageFactory.h)0
-rw-r--r--Swift/Controllers/Storages/CertificateStorageTrustChecker.h (renamed from Swift/Controllers/CertificateStorageTrustChecker.h)2
-rw-r--r--Swift/Controllers/Storages/FileStorages.cpp46
-rw-r--r--Swift/Controllers/Storages/FileStorages.h53
-rw-r--r--Swift/Controllers/Storages/FileStoragesFactory.h (renamed from Swift/Controllers/FileStoragesFactory.h)2
-rw-r--r--Swift/Controllers/Storages/MemoryStoragesFactory.h (renamed from Swift/Controllers/MemoryStoragesFactory.h)2
-rw-r--r--Swift/Controllers/Storages/RosterFileStorage.cpp26
-rw-r--r--Swift/Controllers/Storages/RosterFileStorage.h24
-rw-r--r--Swift/Controllers/Storages/StoragesFactory.h (renamed from Swift/Controllers/StoragesFactory.h)0
-rw-r--r--Swift/Controllers/Storages/VCardFileStorage.cpp107
-rw-r--r--Swift/Controllers/Storages/VCardFileStorage.h38
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;
+ };
+}