diff --git a/src/exception.cpp b/src/exception.cpp index 7dd40992..92ce1a30 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -466,6 +466,18 @@ exception* folder_not_found::clone() const { return new folder_not_found(*this); const char* folder_not_found::name() const throw() { return "folder_not_found"; } +// +// folder_already_open +// + +folder_already_open::~folder_already_open() throw() {} +folder_already_open::folder_already_open(const exception& other) + : net_exception("Folder is already open in the same session.", other) {} + +exception* folder_already_open::clone() const { return new folder_already_open(*this); } +const char* folder_already_open::name() const throw() { return "folder_already_open"; } + + // // message_not_found // diff --git a/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp index 3c54bce8..4f88287d 100644 --- a/src/net/imap/IMAPFolder.cpp +++ b/src/net/imap/IMAPFolder.cpp @@ -55,7 +55,7 @@ namespace imap { IMAPFolder::IMAPFolder(const folder::path& path, ref store, const int type, const int flags) : m_store(store), m_connection(store->connection()), m_path(path), m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), m_mode(-1), - m_open(false), m_type(type), m_flags(flags), m_messageCount(0), m_uidValidity(0) + m_open(false), m_type(type), m_flags(flags) { store->registerFolder(this); @@ -150,6 +150,14 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) if (!store) throw exceptions::illegal_state("Store disconnected"); + // Ensure this folder is not already open in the same session + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) + { + if ((*it) != this && (*it)->getFullPath() == m_path) + throw exceptions::folder_already_open(); + } + // Open a connection for this folder ref connection = vmime::create (store, store->getAuthenticator()); @@ -218,11 +226,6 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) { switch (code->type()) { - case IMAPParser::resp_text_code::UIDVALIDITY: - - m_uidValidity = static_cast (code->nz_number()->value()); - break; - case IMAPParser::resp_text_code::NOMODSEQ: connection->disableMODSEQ(); @@ -251,16 +254,6 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) break; } - case IMAPParser::mailbox_data::EXISTS: - { - m_messageCount = responseData->mailbox_data()->number()->value(); - break; - } - case IMAPParser::mailbox_data::RECENT: - { - // TODO - break; - } } } @@ -328,7 +321,7 @@ void IMAPFolder::close(const bool expunge) m_open = false; m_mode = -1; - m_uidValidity = 0; + m_status = vmime::create (); onClose(); } @@ -527,7 +520,7 @@ ref IMAPFolder::getMessage(const int num) if (!isOpen()) throw exceptions::illegal_state("Folder not open"); - if (num < 1 || num > m_messageCount) + if (num < 1 || num > getMessageCount()) throw exceptions::message_not_found(); return vmime::create (thisRef().dynamicCast (), num); @@ -654,7 +647,7 @@ std::vector > IMAPFolder::getMessagesByUID(const std::vector type() == IMAPParser::msg_att_item::UID) { - msgFullUID = IMAPUtils::makeGlobalUID(m_uidValidity, (*it)->unique_id()->value()); + msgFullUID = IMAPUtils::makeGlobalUID(m_status->getUIDValidity(), (*it)->unique_id()->value()); msgUID = (*it)->unique_id()->value(); break; @@ -677,7 +670,7 @@ int IMAPFolder::getMessageCount() if (!isOpen()) throw exceptions::illegal_state("Folder not open"); - return (m_messageCount); + return m_status->getMessageCount(); } @@ -1009,7 +1002,7 @@ void IMAPFolder::deleteMessages(const int from, const int to) command << "STORE " << from << ":"; - if (to == -1) command << m_messageCount; + if (to == -1) command << getMessageCount(); else command << to; command << " +FLAGS.SILENT (\\Deleted)"; @@ -1028,7 +1021,7 @@ void IMAPFolder::deleteMessages(const int from, const int to) } // Update local flags - const int to2 = (to == -1) ? m_messageCount : to; + const int to2 = (to == -1) ? getMessageCount() : to; const int count = to - from + 1; for (std::vector ::iterator it = @@ -1085,7 +1078,7 @@ void IMAPFolder::deleteMessages(const std::vector & nums) command.imbue(std::locale::classic()); command << "STORE "; - command << IMAPUtils::listToSet(list, m_messageCount, true); + command << IMAPUtils::listToSet(list, getMessageCount(), true); command << " +FLAGS.SILENT (\\Deleted)"; // Send the request @@ -1148,7 +1141,7 @@ void IMAPFolder::setMessageFlags(const int from, const int to, const int flags, setMessageFlags(oss.str(), flags, mode); // Update local flags - const int to2 = (to == -1) ? m_messageCount : to; + const int to2 = (to == -1) ? getMessageCount() : to; const int count = to - from + 1; switch (mode) @@ -1234,7 +1227,7 @@ void IMAPFolder::setMessageFlags(const std::vector & nums, const int flags, std::sort(list.begin(), list.end()); // Delegates call - setMessageFlags(IMAPUtils::listToSet(list, m_messageCount, true), flags, mode); + setMessageFlags(IMAPUtils::listToSet(list, getMessageCount(), true), flags, mode); // Update local flags switch (mode) @@ -1449,32 +1442,6 @@ void IMAPFolder::addMessage(utility::inputStream& is, const int size, const int m_connection->getParser()->lastLine(), "bad response"); } - // Notify message added - std::vector nums; - nums.push_back(m_messageCount + 1); - - events::messageCountEvent event - (thisRef().dynamicCast (), - events::messageCountEvent::TYPE_ADDED, nums); - - m_messageCount++; - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - events::messageCountEvent event - ((*it)->thisRef().dynamicCast (), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->m_messageCount++; - (*it)->notifyMessageCount(event); - } - } - processStatusUpdate(resp); } @@ -1542,31 +1509,6 @@ void IMAPFolder::expunge() } } - m_messageCount -= nums.size(); - - // Notify message expunged - events::messageCountEvent event - (thisRef().dynamicCast (), - events::messageCountEvent::TYPE_REMOVED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - (*it)->m_messageCount = m_messageCount; - - events::messageCountEvent event - ((*it)->thisRef().dynamicCast (), - events::messageCountEvent::TYPE_REMOVED, nums); - - (*it)->notifyMessageCount(event); - } - } - processStatusUpdate(resp); } @@ -1619,22 +1561,11 @@ void IMAPFolder::rename(const folder::path& newPath) notifyFolder(event); - // Notify folders with the same path and sub-folders + // Notify sub-folders for (std::list ::iterator it = store->m_folders.begin() ; it != store->m_folders.end() ; ++it) { - if ((*it) != this && (*it)->getFullPath() == oldPath) - { - (*it)->m_path = newPath; - (*it)->m_name = newPath.getLastComponent(); - - events::folderEvent event - ((*it)->thisRef().dynamicCast (), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); - - (*it)->notifyFolder(event); - } - else if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) + if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) { folder::path oldPath((*it)->m_path); @@ -1669,24 +1600,6 @@ void IMAPFolder::copyMessage(const folder::path& dest, const int num) // Delegate message copy copyMessages(set.str(), dest); - - // Notify message count changed - std::vector nums; - nums.push_back(num); - - for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it)->getFullPath() == dest) - { - events::messageCountEvent event - ((*it)->thisRef().dynamicCast (), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->m_messageCount++; - (*it)->notifyMessageCount(event); - } - } } @@ -1712,30 +1625,6 @@ void IMAPFolder::copyMessages(const folder::path& dest, const int from, const in // Delegate message copy copyMessages(set.str(), dest); - - // Notify message count changed - const int to2 = (to == -1) ? m_messageCount : to; - const int count = to - from + 1; - - std::vector nums; - nums.resize(count); - - for (int i = from, j = 0 ; i <= to2 ; ++i, ++j) - nums[j] = i; - - for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it)->getFullPath() == dest) - { - events::messageCountEvent event - ((*it)->thisRef().dynamicCast (), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->m_messageCount += count; - (*it)->notifyMessageCount(event); - } - } } @@ -1749,24 +1638,7 @@ void IMAPFolder::copyMessages(const folder::path& dest, const std::vector & throw exceptions::illegal_state("Folder not open"); // Delegate message copy - copyMessages(IMAPUtils::listToSet(nums, m_messageCount), dest); - - // Notify message count changed - const int count = nums.size(); - - for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it)->getFullPath() == dest) - { - events::messageCountEvent event - ((*it)->thisRef().dynamicCast (), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->m_messageCount += count; - (*it)->notifyMessageCount(event); - } - } + copyMessages(IMAPUtils::listToSet(nums, getMessageCount()), dest); } @@ -1861,8 +1733,7 @@ ref IMAPFolder::getStatus() ref status = vmime::create (); status->updateFromResponse(responseData->mailbox_data()); - m_messageCount = status->getMessageCount(); - m_uidValidity = status->getUIDValidity(); + m_status->updateFromResponse(responseData->mailbox_data()); return status; } @@ -1978,10 +1849,13 @@ void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) m_status->updateFromResponse(code); } + else if ((*it)->response_data() && (*it)->response_data()->mailbox_data()) + { + m_status->updateFromResponse((*it)->response_data()->mailbox_data()); + } } - m_messageCount = m_status->getMessageCount(); - m_uidValidity = m_status->getUIDValidity(); + // TODO: notification } } // imap diff --git a/src/net/imap/IMAPFolderStatus.cpp b/src/net/imap/IMAPFolderStatus.cpp index 009f6ba4..14a77024 100644 --- a/src/net/imap/IMAPFolderStatus.cpp +++ b/src/net/imap/IMAPFolderStatus.cpp @@ -35,6 +35,17 @@ namespace net { namespace imap { +IMAPFolderStatus::IMAPFolderStatus() + : m_count(0), + m_unseen(0), + m_recent(0), + m_uidValidity(0), + m_uidNext(0), + m_highestModSeq(0) +{ +} + + unsigned int IMAPFolderStatus::getMessageCount() const { return m_count; @@ -73,44 +84,55 @@ vmime_uint64 IMAPFolderStatus::getHighestModSeq() const void IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp) { - const IMAPParser::status_att_list* statusAttList = resp->status_att_list(); - - for (std::vector ::const_iterator - jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt) + if (resp->type() == IMAPParser::mailbox_data::STATUS) { - switch ((*jt)->type()) + const IMAPParser::status_att_list* statusAttList = resp->status_att_list(); + + for (std::vector ::const_iterator + jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt) { - case IMAPParser::status_att_val::MESSAGES: + switch ((*jt)->type()) + { + case IMAPParser::status_att_val::MESSAGES: - m_count = (*jt)->value_as_number()->value(); - break; + m_count = (*jt)->value_as_number()->value(); + break; - case IMAPParser::status_att_val::UNSEEN: + case IMAPParser::status_att_val::UNSEEN: - m_unseen = (*jt)->value_as_number()->value(); - break; + m_unseen = (*jt)->value_as_number()->value(); + break; - case IMAPParser::status_att_val::RECENT: + case IMAPParser::status_att_val::RECENT: - m_recent = (*jt)->value_as_number()->value(); - break; + m_recent = (*jt)->value_as_number()->value(); + break; - case IMAPParser::status_att_val::UIDNEXT: + case IMAPParser::status_att_val::UIDNEXT: - m_uidNext = (*jt)->value_as_number()->value(); - break; + m_uidNext = (*jt)->value_as_number()->value(); + break; - case IMAPParser::status_att_val::UIDVALIDITY: + case IMAPParser::status_att_val::UIDVALIDITY: - m_uidValidity = (*jt)->value_as_number()->value(); - break; + m_uidValidity = (*jt)->value_as_number()->value(); + break; - case IMAPParser::status_att_val::HIGHESTMODSEQ: + case IMAPParser::status_att_val::HIGHESTMODSEQ: - m_highestModSeq = (*jt)->value_as_mod_sequence_value()->value(); - break; + m_highestModSeq = (*jt)->value_as_mod_sequence_value()->value(); + break; + } } } + else if (resp->type() == IMAPParser::mailbox_data::EXISTS) + { + m_count = resp->number()->value(); + } + else if (resp->type() == IMAPParser::mailbox_data::RECENT) + { + m_recent = resp->number()->value(); + } } diff --git a/src/net/imap/IMAPMessage.cpp b/src/net/imap/IMAPMessage.cpp index 185af73e..76b6a454 100644 --- a/src/net/imap/IMAPMessage.cpp +++ b/src/net/imap/IMAPMessage.cpp @@ -30,6 +30,7 @@ #include "vmime/net/imap/IMAPParser.hpp" #include "vmime/net/imap/IMAPMessage.hpp" #include "vmime/net/imap/IMAPFolder.hpp" +#include "vmime/net/imap/IMAPFolderStatus.hpp" #include "vmime/net/imap/IMAPStore.hpp" #include "vmime/net/imap/IMAPConnection.hpp" #include "vmime/net/imap/IMAPUtils.hpp" @@ -386,7 +387,7 @@ void IMAPMessage::processFetchResponse } case IMAPParser::msg_att_item::UID: { - m_uid = IMAPUtils::makeGlobalUID(folder->m_uidValidity, (*it)->unique_id()->value()); + m_uid = IMAPUtils::makeGlobalUID(folder->m_status->getUIDValidity(), (*it)->unique_id()->value()); break; } case IMAPParser::msg_att_item::MODSEQ: diff --git a/vmime/exception.hpp b/vmime/exception.hpp index f11079c5..a70c46b6 100644 --- a/vmime/exception.hpp +++ b/vmime/exception.hpp @@ -538,6 +538,21 @@ public: }; +/** Folder is already open in the same session. + */ + +class VMIME_EXPORT folder_already_open : public net_exception +{ +public: + + folder_already_open(const exception& other = NO_EXCEPTION); + ~folder_already_open() throw(); + + exception* clone() const; + const char* name() const throw(); +}; + + /** Message not found (does not exist). */ diff --git a/vmime/net/folder.hpp b/vmime/net/folder.hpp index dbab6900..b601f8f6 100644 --- a/vmime/net/folder.hpp +++ b/vmime/net/folder.hpp @@ -140,6 +140,8 @@ public: * If set to true and if the requested mode is not available, the opening * will fail. * @throw net_exception if an error occurs + * @throw exceptions::folder_already_open if the folder is already open + * in the same session */ virtual void open(const int mode, bool failIfModeIsNotAvailable = false) = 0; diff --git a/vmime/net/imap/IMAPFolder.hpp b/vmime/net/imap/IMAPFolder.hpp index 48e07603..7830d276 100644 --- a/vmime/net/imap/IMAPFolder.hpp +++ b/vmime/net/imap/IMAPFolder.hpp @@ -178,8 +178,6 @@ private: int m_type; int m_flags; - int m_messageCount; - vmime_uint32 m_uidValidity; ref m_status; std::vector m_messages; diff --git a/vmime/net/imap/IMAPFolderStatus.hpp b/vmime/net/imap/IMAPFolderStatus.hpp index 1cad217c..77373f1a 100644 --- a/vmime/net/imap/IMAPFolderStatus.hpp +++ b/vmime/net/imap/IMAPFolderStatus.hpp @@ -48,6 +48,8 @@ class VMIME_EXPORT IMAPFolderStatus : public folderStatus { public: + IMAPFolderStatus(); + // Inherited from folderStatus unsigned int getMessageCount() const; unsigned int getUnseenCount() const;