From 1ece98b08f07909cbcd8c6d174902a41e388ca02 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Wed, 15 Dec 2004 10:00:49 +0000 Subject: [PATCH] Working on 'maildir' implementation. --- src/messaging/maildirFolder.cpp | 254 +++++++++---------------------- src/messaging/maildirFolder.hpp | 1 + src/messaging/maildirMessage.cpp | 16 +- src/messaging/maildirMessage.hpp | 2 + 4 files changed, 82 insertions(+), 191 deletions(-) diff --git a/src/messaging/maildirFolder.cpp b/src/messaging/maildirFolder.cpp index d19210e5..c5c1054a 100644 --- a/src/messaging/maildirFolder.cpp +++ b/src/messaging/maildirFolder.cpp @@ -490,202 +490,22 @@ void maildirFolder::rename(const folder::path& newPath) void maildirFolder::deleteMessage(const int num) { - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - if (m_messageInfos[num].type == messageInfos::TYPE_DELETED) - return; - - // Mark message as deleted - try - { - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); - - const utility::file::path::component path = m_messageInfos[num].path; - utility::auto_ptr file = fsf->create(curDirPath / path); - - 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) - { - // Ignore (not important) - } - - // Update local flags - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if ((*it)->getNumber() == num && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags |= message::FLAG_DELETED; - } - } - - // Notify message flags changed - std::vector nums; - nums.push_back(num); - - events::messageChangedEvent event(this, events::messageChangedEvent::TYPE_FLAGS, nums); - - notifyMessageChanged(event); + // Mark messages as deleted + setMessageFlags(num, num, message::FLAG_MODE_ADD, message::FLAG_DELETED); } void maildirFolder::deleteMessages(const int from, const int to) { - if (from < 1 || (to < from && to != -1)) - throw exceptions::invalid_argument(); - - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - const int to2 = (to == -1) ? m_messageCount : to; - const int count = to - from + 1; - // Mark messages as deleted - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); - - for (int i = from ; i <= to2 ; ++i) - { - if (m_messageInfos[i].type != messageInfos::TYPE_DELETED) - { - try - { - const utility::file::path::component path = m_messageInfos[i].path; - utility::auto_ptr file = fsf->create(curDirPath / path); - - 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) - { - // Ignore (not important) - } - } - } - - // Update local flags - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if ((*it)->getNumber() >= from && (*it)->getNumber() <= to2 && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags |= message::FLAG_DELETED; - } - } - - // Notify message flags changed - std::vector nums; - nums.resize(count); - - for (int i = from, j = 0 ; i <= to2 ; ++i, ++j) - nums[j] = i; - - events::messageChangedEvent event(this, events::messageChangedEvent::TYPE_FLAGS, nums); - - notifyMessageChanged(event); + setMessageFlags(from, to, message::FLAG_MODE_ADD, message::FLAG_DELETED); } void maildirFolder::deleteMessages(const std::vector & nums) { - if (nums.empty()) - throw exceptions::invalid_argument(); - - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - // Sort the list of message numbers - std::vector list; - - list.resize(nums.size()); - std::copy(nums.begin(), nums.end(), list.begin()); - - std::sort(list.begin(), list.end()); - // Mark messages as deleted - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); - - for (std::vector ::const_iterator it = - list.begin() ; it != list.end() ; ++it) - { - const int num = *it; - - if (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); - - 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) - { - // Ignore (not important) - } - } - } - - // Update local flags - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(list.begin(), list.end(), (*it)->getNumber())) - { - if ((*it)->m_flags != message::FLAG_UNDEFINED) - (*it)->m_flags |= message::FLAG_DELETED; - } - } - - // Notify message flags changed - events::messageChangedEvent event(this, events::messageChangedEvent::TYPE_FLAGS, list); - - notifyMessageChanged(event); + setMessageFlags(nums, message::FLAG_MODE_ADD, message::FLAG_DELETED); } @@ -859,7 +679,7 @@ void maildirFolder::setMessageFlagsImpl for (std::vector ::const_iterator it = nums.begin() ; it != nums.end() ; ++it) { - const int num = *it; + const int num = *it - 1; try { @@ -971,6 +791,8 @@ void maildirFolder::status(int& count, int& unseen) if ((*it)->getFullPath() == m_path) { (*it)->m_messageCount = count; + (*it)->m_unreadMessageCount = unseen; + (*it)->notifyMessageCount(event); (*it)->scanFolder(); @@ -982,7 +804,67 @@ void maildirFolder::status(int& count, int& unseen) void maildirFolder::expunge() { - // TODO + if (!m_store) + throw exceptions::illegal_state("Store disconnected"); + else if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + else if (m_mode == MODE_READ_ONLY) + throw exceptions::illegal_state("Folder is read-only"); + + utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); + + utility::file::path curDirPath = maildirUtils::getFolderFSPath + (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); + + std::vector nums; + int unreadCount = 0; + + for (int num = 1 ; num <= m_messageCount ; ++num) + { + messageInfos& infos = m_messageInfos[num - 1]; + + if (infos.type == messageInfos::TYPE_DELETED) + { + nums.push_back(num); + + for (std::vector ::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) + { + if ((*it)->m_num == num) + (*it)->m_expunged = true; + else if ((*it)->m_num > num) + (*it)->m_num--; + } + + if (maildirUtils::extractFlags(infos.path) & message::FLAG_SEEN) + ++unreadCount; + + // Delete file from file system + try + { + utility::auto_ptr file = fsf->create(curDirPath / infos.path); + file->remove(); + } + catch (exceptions::filesystem_exception& e) + { + // Ignore (not important) + } + } + } + + if (!nums.empty()) + { + for (int i = nums.size() - 1 ; i >= 0 ; --i) + m_messageInfos.erase(m_messageInfos.begin() + i); + } + + // Notify message expunged + events::messageCountEvent event(this, events::messageCountEvent::TYPE_REMOVED, nums); + + m_messageCount -= nums.size(); + m_unreadMessageCount -= unreadCount; + + notifyMessageCount(event); } diff --git a/src/messaging/maildirFolder.hpp b/src/messaging/maildirFolder.hpp index 9ece8f45..b7ce92fc 100644 --- a/src/messaging/maildirFolder.hpp +++ b/src/messaging/maildirFolder.hpp @@ -126,6 +126,7 @@ private: void onClose(); + void deleteMessagesImpl(const std::vector & nums); void setMessageFlagsImpl(const std::vector & nums, const int flags, const int mode); diff --git a/src/messaging/maildirMessage.cpp b/src/messaging/maildirMessage.cpp index 4d561f25..12ac8cdf 100644 --- a/src/messaging/maildirMessage.cpp +++ b/src/messaging/maildirMessage.cpp @@ -30,7 +30,8 @@ namespace messaging { maildirMessage::maildirMessage(maildirFolder* folder, const int num) - : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED) + : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED), + m_expunged(false) { m_folder->registerMessage(this); } @@ -57,7 +58,7 @@ const int maildirMessage::getNumber() const const message::uid maildirMessage::getUniqueId() const { - // TODO + return (m_uid); } @@ -72,7 +73,7 @@ const int maildirMessage::getSize() const const bool maildirMessage::isExpunged() const { - // TODO + return (m_expunged); } @@ -105,7 +106,10 @@ const int maildirMessage::getFlags() const void maildirMessage::setFlags(const int flags, const int mode) { - // TODO + if (!m_folder) + throw exceptions::folder_not_found(); + + m_folder->setMessageFlags(m_num, m_num, flags, mode); } @@ -144,7 +148,6 @@ void maildirMessage::fetch(maildirFolder* folder, const int options) TODO: FETCH_STRUCTURE TODO: FETCH_CONTENT_INFO TODO: FETCH_FULL_HEADER - TODO: FETCH_UID */ if (options & folder::FETCH_FLAGS) @@ -152,6 +155,9 @@ void maildirMessage::fetch(maildirFolder* folder, const int options) if (options & folder::FETCH_SIZE) m_size = file->length(); + + if (options & folder::FETCH_UID) + m_uid = maildirUtils::extractId(path.getLastComponent()).getBuffer(); } diff --git a/src/messaging/maildirMessage.hpp b/src/messaging/maildirMessage.hpp index 74a1a7b3..0b543bc2 100644 --- a/src/messaging/maildirMessage.hpp +++ b/src/messaging/maildirMessage.hpp @@ -81,6 +81,8 @@ private: int m_num; int m_size; int m_flags; + bool m_expunged; + uid m_uid; };