diff options
Diffstat (limited to '')
-rw-r--r-- | src/net/imap/IMAPFolder.cpp | 185 |
1 files changed, 115 insertions, 70 deletions
diff --git a/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp index 1ee8ac3f..3c54bce8 100644 --- a/src/net/imap/IMAPFolder.cpp +++ b/src/net/imap/IMAPFolder.cpp @@ -34,6 +34,7 @@ #include "vmime/net/imap/IMAPMessage.hpp" #include "vmime/net/imap/IMAPUtils.hpp" #include "vmime/net/imap/IMAPConnection.hpp" +#include "vmime/net/imap/IMAPFolderStatus.hpp" #include "vmime/message.hpp" @@ -57,6 +58,8 @@ IMAPFolder::IMAPFolder(const folder::path& path, ref <IMAPStore> store, const in m_open(false), m_type(type), m_flags(flags), m_messageCount(0), m_uidValidity(0) { store->registerFolder(this); + + m_status = vmime::create <IMAPFolderStatus>(); } @@ -176,6 +179,9 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) oss << IMAPUtils::quoteString(IMAPUtils::pathToString (connection->hierarchySeparator(), getFullPath())); + if (m_connection->hasCapability("CONDSTORE")) + oss << " (CONDSTORE)"; + connection->send(true, oss.str(), true); // Read the response @@ -217,6 +223,11 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) m_uidValidity = static_cast <unsigned int>(code->nz_number()->value()); break; + case IMAPParser::resp_text_code::NOMODSEQ: + + connection->disableMODSEQ(); + break; + default: break; @@ -255,6 +266,8 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) } } + processStatusUpdate(resp); + // Check for access mode (read-only or read-write) const IMAPParser::resp_text_code* respTextCode = resp->response_done()-> response_tagged()->resp_cond_state()->resp_text()->resp_text_code(); @@ -792,7 +805,7 @@ void IMAPFolder::fetchMessages(std::vector <ref <message> >& msg, const int opti } // Send the request - const string command = IMAPUtils::buildFetchRequest(list, options); + const string command = IMAPUtils::buildFetchRequest(m_connection, list, options); m_connection->send(true, command, true); // Get the response @@ -856,19 +869,17 @@ void IMAPFolder::fetchMessages(std::vector <ref <message> >& msg, const int opti if (progress) progress->stop(total); + + processStatusUpdate(resp); } void IMAPFolder::fetchMessage(ref <message> msg, const int options) { - ref <IMAPStore> store = m_store.acquire(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); + std::vector <ref <message> > msgs; + msgs.push_back(msg); - msg.dynamicCast <IMAPMessage>()->fetch(thisRef().dynamicCast <IMAPFolder>(), options); + fetchMessages(msgs, options, /* progress */ NULL); } @@ -973,6 +984,8 @@ void IMAPFolder::deleteMessage(const int num) events::messageChangedEvent::TYPE_FLAGS, nums); notifyMessageChanged(event); + + processStatusUpdate(resp); } @@ -1040,6 +1053,8 @@ void IMAPFolder::deleteMessages(const int from, const int to) events::messageChangedEvent::TYPE_FLAGS, nums); notifyMessageChanged(event); + + processStatusUpdate(resp); } @@ -1103,6 +1118,8 @@ void IMAPFolder::deleteMessages(const std::vector <int>& nums) events::messageChangedEvent::TYPE_FLAGS, list); notifyMessageChanged(event); + + processStatusUpdate(resp); } @@ -1311,6 +1328,8 @@ void IMAPFolder::setMessageFlags(const string& set, const int flags, const int m throw exceptions::command_error("STORE", m_connection->getParser()->lastLine(), "bad response"); } + + processStatusUpdate(resp); } } @@ -1455,6 +1474,8 @@ void IMAPFolder::addMessage(utility::inputStream& is, const int size, const int (*it)->notifyMessageCount(event); } } + + processStatusUpdate(resp); } @@ -1545,6 +1566,8 @@ void IMAPFolder::expunge() (*it)->notifyMessageCount(event); } } + + processStatusUpdate(resp); } @@ -1624,6 +1647,8 @@ void IMAPFolder::rename(const folder::path& newPath) (*it)->notifyFolder(event); } } + + processStatusUpdate(resp); } @@ -1767,16 +1792,30 @@ void IMAPFolder::copyMessages(const string& set, const folder::path& dest) throw exceptions::command_error("COPY", m_connection->getParser()->lastLine(), "bad response"); } + + processStatusUpdate(resp); } void IMAPFolder::status(int& count, int& unseen) { - ref <IMAPStore> store = m_store.acquire(); - count = 0; unseen = 0; + ref <folderStatus> status = getStatus(); + + count = status->getMessageCount(); + unseen = status->getUnseenCount(); +} + + +ref <folderStatus> IMAPFolder::getStatus() +{ + ref <IMAPStore> store = m_store.acquire(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + // Build the request text std::ostringstream command; command.imbue(std::locale::classic()); @@ -1784,7 +1823,14 @@ void IMAPFolder::status(int& count, int& unseen) command << "STATUS "; command << IMAPUtils::quoteString(IMAPUtils::pathToString (m_connection->hierarchySeparator(), getFullPath())); - command << " (MESSAGES UNSEEN)"; + command << " ("; + + command << "MESSAGES" << ' ' << "UNSEEN" << ' ' << "UIDNEXT" << ' ' << "UIDVALIDITY"; + + if (m_connection->hasCapability("CONDSTORE")) + command << ' ' << "HIGHESTMODSEQ"; + + command << ")"; // Send the request m_connection->send(true, command.str(), true); @@ -1805,81 +1851,47 @@ void IMAPFolder::status(int& count, int& unseen) for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator it = respDataList.begin() ; it != respDataList.end() ; ++it) { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("STATUS", - m_connection->getParser()->lastLine(), "invalid response"); - } - - const IMAPParser::response_data* responseData = (*it)->response_data(); - - if (responseData->mailbox_data() && - responseData->mailbox_data()->type() == IMAPParser::mailbox_data::STATUS) + if ((*it)->response_data() != NULL) { - const IMAPParser::status_att_list* statusAttList = - responseData->mailbox_data()->status_att_list(); + const IMAPParser::response_data* responseData = (*it)->response_data(); - for (std::vector <IMAPParser::status_att_val*>::const_iterator - jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt) + if (responseData->mailbox_data() && + responseData->mailbox_data()->type() == IMAPParser::mailbox_data::STATUS) { - switch ((*jt)->type()) - { - case IMAPParser::status_att_val::MESSAGES: - - count = (*jt)->value_as_number()->value(); - break; - - case IMAPParser::status_att_val::UNSEEN: - - unseen = (*jt)->value_as_number()->value(); - break; + ref <IMAPFolderStatus> status = vmime::create <IMAPFolderStatus>(); + status->updateFromResponse(responseData->mailbox_data()); - default: + m_messageCount = status->getMessageCount(); + m_uidValidity = status->getUIDValidity(); - break; - } + return status; } } } - // Notify message count changed (new messages) - if (m_messageCount != count) - { - const int oldCount = m_messageCount; - - m_messageCount = count; - - if (count > oldCount) - { - std::vector <int> nums; - nums.reserve(count - oldCount); + throw exceptions::command_error("STATUS", + m_connection->getParser()->lastLine(), "invalid response"); +} - for (int i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) - nums[j] = i; - events::messageCountEvent event - (thisRef().dynamicCast <folder>(), - events::messageCountEvent::TYPE_ADDED, nums); +void IMAPFolder::noop() +{ + ref <IMAPStore> store = m_store.acquire(); - notifyMessageCount(event); + if (!store) + throw exceptions::illegal_state("Store disconnected"); - // Notify folders with the same path - for (std::list <IMAPFolder*>::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - (*it)->m_messageCount = count; + m_connection->send(true, "NOOP", true); - events::messageCountEvent event - ((*it)->thisRef().dynamicCast <folder>(), - events::messageCountEvent::TYPE_ADDED, nums); + utility::auto_ptr <IMAPParser::response> resp(m_connection->readResponse()); - (*it)->notifyMessageCount(event); - } - } - } + if (resp->isBad() || resp->response_done()->response_tagged()-> + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) + { + throw exceptions::command_error("NOOP", m_connection->getParser()->lastLine()); } + + processStatusUpdate(resp); } @@ -1939,6 +1951,39 @@ std::vector <int> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& } +void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) +{ + // Process tagged response + if (resp->response_done() && resp->response_done()->response_tagged() && + resp->response_done()->response_tagged() + ->resp_cond_state()->resp_text()->resp_text_code()) + { + const IMAPParser::resp_text_code* code = + resp->response_done()->response_tagged() + ->resp_cond_state()->resp_text()->resp_text_code(); + + m_status->updateFromResponse(code); + } + + // Process untagged responses + for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator + it = resp->continue_req_or_response_data().begin() ; + it != resp->continue_req_or_response_data().end() ; ++it) + { + if ((*it)->response_data() && (*it)->response_data()->resp_cond_state() && + (*it)->response_data()->resp_cond_state()->resp_text()->resp_text_code()) + { + const IMAPParser::resp_text_code* code = + (*it)->response_data()->resp_cond_state()->resp_text()->resp_text_code(); + + m_status->updateFromResponse(code); + } + } + + m_messageCount = m_status->getMessageCount(); + m_uidValidity = m_status->getUIDValidity(); +} + } // imap } // net } // vmime |