From e4ed55e237ed3b10afe459e6e99afedb57aaa4e3 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Sat, 4 Dec 2004 20:25:48 +0000 Subject: [PATCH] Working on 'maildir' implementation. --- src/messaging/maildirFolder.cpp | 88 +++++++++++++++++++++++++------- src/messaging/maildirFolder.hpp | 2 + src/messaging/maildirMessage.cpp | 56 ++++++++++++++++++-- src/messaging/maildirMessage.hpp | 4 +- src/messaging/maildirUtils.cpp | 36 ++++++++++--- src/messaging/maildirUtils.hpp | 28 ++++++++++ 6 files changed, 184 insertions(+), 30 deletions(-) diff --git a/src/messaging/maildirFolder.cpp b/src/messaging/maildirFolder.cpp index 8ae6b72c..1a8adaa7 100644 --- a/src/messaging/maildirFolder.cpp +++ b/src/messaging/maildirFolder.cpp @@ -500,9 +500,7 @@ void maildirFolder::deleteMessage(const int num) if (m_messageInfos[num].type == messageInfos::TYPE_DELETED) return; - m_messageInfos[num].type = messageInfos::TYPE_DELETED; - - // Delete file from file system + // Mark message as deleted try { utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); @@ -510,10 +508,17 @@ void maildirFolder::deleteMessage(const int num) utility::file::path curDirPath = maildirUtils::getFolderFSPath (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); - utility::auto_ptr file = fsf->create - (curDirPath / m_messageInfos[num].path); + const utility::file::path::component path = m_messageInfos[num].path; + utility::auto_ptr file = fsf->create(curDirPath / path); - file->remove(); + const utility::file::path::component newPath = maildirUtils::buildFilename + (maildirUtils::extractId(path), + maildirUtils::extractFlags(path) | message::FLAG_DELETED); + + file->rename(curDirPath / newPath); + + m_messageInfos[num].type = messageInfos::TYPE_DELETED; + m_messageInfos[num].path = newPath; } catch (exceptions::filesystem_exception& e) { @@ -556,7 +561,7 @@ void maildirFolder::deleteMessages(const int from, const int to) const int to2 = (to == -1) ? m_messageCount : to; const int count = to - from + 1; - // Delete files from file system + // Mark messages as deleted utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); utility::file::path curDirPath = maildirUtils::getFolderFSPath @@ -566,14 +571,19 @@ void maildirFolder::deleteMessages(const int from, const int to) { if (m_messageInfos[i].type != messageInfos::TYPE_DELETED) { - m_messageInfos[i].type = messageInfos::TYPE_DELETED; - try { - utility::auto_ptr file = fsf->create - (curDirPath / m_messageInfos[i].path); + const utility::file::path::component path = m_messageInfos[i].path; + utility::auto_ptr file = fsf->create(curDirPath / path); - file->remove(); + const utility::file::path::component newPath = maildirUtils::buildFilename + (maildirUtils::extractId(path), + maildirUtils::extractFlags(path) | message::FLAG_DELETED); + + file->rename(curDirPath / newPath); + + m_messageInfos[i].type = messageInfos::TYPE_DELETED; + m_messageInfos[i].path = newPath; } catch (exceptions::filesystem_exception& e) { @@ -626,7 +636,7 @@ void maildirFolder::deleteMessages(const std::vector & nums) std::sort(list.begin(), list.end()); - // Delete files from file system + // Mark messages as deleted utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); utility::file::path curDirPath = maildirUtils::getFolderFSPath @@ -639,14 +649,20 @@ void maildirFolder::deleteMessages(const std::vector & nums) if (m_messageInfos[num].type != messageInfos::TYPE_DELETED) { - m_messageInfos[num].type = messageInfos::TYPE_DELETED; - try { + const utility::file::path::component path = m_messageInfos[num].path; utility::auto_ptr file = fsf->create (curDirPath / m_messageInfos[num].path); - file->remove(); + const utility::file::path::component newPath = maildirUtils::buildFilename + (maildirUtils::extractId(path), + maildirUtils::extractFlags(path) | message::FLAG_DELETED); + + file->rename(curDirPath / newPath); + + m_messageInfos[num].type = messageInfos::TYPE_DELETED; + m_messageInfos[num].path = newPath; } catch (exceptions::filesystem_exception& e) { @@ -655,7 +671,6 @@ void maildirFolder::deleteMessages(const std::vector & nums) } } - // Update local flags for (std::vector ::iterator it = m_messages.begin() ; it != m_messages.end() ; ++it) @@ -782,13 +797,39 @@ store* maildirFolder::getStore() void maildirFolder::fetchMessages(std::vector & msg, const int options, progressionListener* progress) { - // TODO + if (!m_store) + throw exceptions::illegal_state("Store disconnected"); + else if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + const int total = msg.size(); + int current = 0; + + if (progress) + progress->start(total); + + for (std::vector ::iterator it = msg.begin() ; + it != msg.end() ; ++it) + { + dynamic_cast (*it)->fetch(this, options); + + if (progress) + progress->progress(++current, total); + } + + if (progress) + progress->stop(total); } void maildirFolder::fetchMessage(message* msg, const int options) { - // TODO + if (!m_store) + throw exceptions::illegal_state("Store disconnected"); + else if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + dynamic_cast (msg)->fetch(this, options); } @@ -799,5 +840,14 @@ const int maildirFolder::getFetchCapabilities() const } +const utility::file::path maildirFolder::getMessageFSPath(const int number) +{ + utility::file::path curDirPath = maildirUtils::getFolderFSPath + (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); + + return (curDirPath / m_messageInfos[number].path); +} + + } // messaging } // vmime diff --git a/src/messaging/maildirFolder.hpp b/src/messaging/maildirFolder.hpp index 96883736..d22765e5 100644 --- a/src/messaging/maildirFolder.hpp +++ b/src/messaging/maildirFolder.hpp @@ -120,6 +120,8 @@ private: void registerMessage(maildirMessage* msg); void unregisterMessage(maildirMessage* msg); + const utility::file::path getMessageFSPath(const int number); + void onStoreDisconnected(); void onClose(); diff --git a/src/messaging/maildirMessage.cpp b/src/messaging/maildirMessage.cpp index 65d41447..4d561f25 100644 --- a/src/messaging/maildirMessage.cpp +++ b/src/messaging/maildirMessage.cpp @@ -19,6 +19,10 @@ #include "maildirMessage.hpp" #include "maildirFolder.hpp" +#include "maildirUtils.hpp" + +#include "../exception.hpp" +#include "../platformDependant.hpp" namespace vmime { @@ -26,7 +30,7 @@ namespace messaging { maildirMessage::maildirMessage(maildirFolder* folder, const int num) - : m_folder(folder), m_num(num) + : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED) { m_folder->registerMessage(this); } @@ -47,61 +51,107 @@ void maildirMessage::onFolderClosed() const int maildirMessage::getNumber() const { + return (m_num); } const message::uid maildirMessage::getUniqueId() const { + // TODO } const int maildirMessage::getSize() const { + if (m_size == -1) + throw exceptions::unfetched_object(); + + return (m_size); } const bool maildirMessage::isExpunged() const { + // TODO } const structure& maildirMessage::getStructure() const { + // TODO } structure& maildirMessage::getStructure() { + // TODO } const header& maildirMessage::getHeader() const { + // TODO } const int maildirMessage::getFlags() const { + if (m_flags == FLAG_UNDEFINED) + throw exceptions::unfetched_object(); + + return (m_flags); } void maildirMessage::setFlags(const int flags, const int mode) { + // TODO } -void maildirMessage::extract(utility::outputStream& os, progressionListener* progress, const int start, const int length) const +void maildirMessage::extract(utility::outputStream& os, + progressionListener* progress, const int start, const int length) const { + // TODO } -void maildirMessage::extractPart(const part& p, utility::outputStream& os, progressionListener* progress, const int start, const int length) const +void maildirMessage::extractPart(const part& p, utility::outputStream& os, + progressionListener* progress, const int start, const int length) const { + // TODO } void maildirMessage::fetchPartHeader(part& p) { + // TODO +} + + +void maildirMessage::fetch(maildirFolder* folder, const int options) +{ + if (m_folder != folder) + throw exceptions::folder_not_found(); + + utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); + + const utility::file::path path = folder->getMessageFSPath(m_num); + utility::auto_ptr file = fsf->create(path); + + /* + TODO: FETCH_ENVELOPE + TODO: FETCH_STRUCTURE + TODO: FETCH_CONTENT_INFO + TODO: FETCH_FULL_HEADER + TODO: FETCH_UID + */ + + if (options & folder::FETCH_FLAGS) + m_flags = maildirUtils::extractFlags(path.getLastComponent()); + + if (options & folder::FETCH_SIZE) + m_size = file->length(); } diff --git a/src/messaging/maildirMessage.hpp b/src/messaging/maildirMessage.hpp index 7d2cd0d6..74a1a7b3 100644 --- a/src/messaging/maildirMessage.hpp +++ b/src/messaging/maildirMessage.hpp @@ -69,7 +69,9 @@ public: void fetchPartHeader(part& p); -protected: +private: + + void fetch(maildirFolder* folder, const int options); void onFolderClosed(); diff --git a/src/messaging/maildirUtils.cpp b/src/messaging/maildirUtils.cpp index f6e16d8a..697f46c6 100644 --- a/src/messaging/maildirUtils.cpp +++ b/src/messaging/maildirUtils.cpp @@ -110,10 +110,11 @@ const int maildirUtils::extractFlags(const utility::file::path::component& comp) { switch (flagsString[i]) { - case 'S': case 's': flags |= message::FLAG_SEEN; break; case 'R': case 'r': flags |= message::FLAG_REPLIED; break; - - // TODO: more flags + case 'S': case 's': flags |= message::FLAG_SEEN; break; + case 'T': case 't': flags |= message::FLAG_DELETED; break; + case 'F': case 'f': flags |= message::FLAG_MARKED; break; + case 'P': case 'p': flags |= message::FLAG_PASSED; break; } } @@ -121,12 +122,33 @@ const int maildirUtils::extractFlags(const utility::file::path::component& comp) } -/* -const utility::file::component maildirUtils::changeFlags - (const utility::file::component& comp, const int flags) +const utility::file::path::component maildirUtils::buildFlags(const int flags) { + string str; + str.reserve(6); + + if (flags & message::FLAG_REPLIED) str += "R"; + if (flags & message::FLAG_SEEN) str += "S"; + if (flags & message::FLAG_DELETED) str += "T"; + if (flags & message::FLAG_MARKED) str += "F"; + if (flags & message::FLAG_PASSED) str += "P"; + + return (utility::file::path::component(str)); +} + + +const utility::file::path::component maildirUtils::buildFilename + (const utility::file::path::component& id, const int flags) +{ + return (buildFilename(id, buildFlags(flags))); +} + + +const utility::file::path::component maildirUtils::buildFilename + (const utility::file::path::component& id, const utility::file::path::component& flags) +{ + return (utility::path::component(id.getBuffer() + ":" + flags.getBuffer())); } -*/ diff --git a/src/messaging/maildirUtils.hpp b/src/messaging/maildirUtils.hpp index dddc735d..d65e5d3e 100644 --- a/src/messaging/maildirUtils.hpp +++ b/src/messaging/maildirUtils.hpp @@ -78,6 +78,7 @@ public: * a maildir sub-folder. The name of the directory should not start * with '.' to be listed as a sub-folder. * + * @param file reference to a file-system directory * @return true if the specified directory is a maildir sub-folder, * false otherwise */ @@ -87,6 +88,7 @@ public: * Eg: for the filename "1071577232.28549.m03s:2,RS", it will * return "1071577232.28549.m03s". * + * @param filename filename part * @return part of the filename that corresponds to the unique * identifier of the message */ @@ -96,10 +98,36 @@ public: * Eg: for the filename "1071577232.28549.m03s:2,RS", it will * return (message::FLAG_SEEN | message::FLAG_REPLIED). * + * @param comp filename part * @return message flags extracted from the specified filename */ static const int extractFlags(const utility::file::path::component& comp); + /** Return a string representing the specified message flags. + * Eg: for (message::FLAG_SEEN | message::FLAG_REPLIED), it will + * return "RS". + * + * @param flags set of flags + * @return message flags in a string representation + */ + static const utility::file::path::component buildFlags(const int flags); + + /** Build a filename with the specified id and flags. + * + * @param id id part of the filename + * @param flags flags part of the filename + * @return message filename + */ + static const utility::file::path::component buildFilename(const utility::file::path::component& id, const utility::file::path::component& flags); + + /** Build a filename with the specified id and flags. + * + * @param id id part of the filename + * @param flags set of flags + * @return message filename + */ + static const utility::file::path::component buildFilename(const utility::file::path::component& id, const int flags); + private: static const vmime::word TMP_DIR;