aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/imap/IMAPFolder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/imap/IMAPFolder.cpp')
-rw-r--r--src/net/imap/IMAPFolder.cpp334
1 files changed, 108 insertions, 226 deletions
diff --git a/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp
index cbcfd418..60133a29 100644
--- a/src/net/imap/IMAPFolder.cpp
+++ b/src/net/imap/IMAPFolder.cpp
@@ -381,9 +381,10 @@ void IMAPFolder::create(const int type)
}
// Notify folder created
- events::folderEvent event
- (thisRef().dynamicCast <folder>(),
- events::folderEvent::TYPE_CREATED, m_path, m_path);
+ ref <events::folderEvent> event =
+ vmime::create <events::folderEvent>
+ (thisRef().dynamicCast <folder>(),
+ events::folderEvent::TYPE_CREATED, m_path, m_path);
notifyFolder(event);
}
@@ -418,9 +419,10 @@ void IMAPFolder::destroy()
}
// Notify folder deleted
- events::folderEvent event
- (thisRef().dynamicCast <folder>(),
- events::folderEvent::TYPE_DELETED, m_path, m_path);
+ ref <events::folderEvent> event =
+ vmime::create <events::folderEvent>
+ (thisRef().dynamicCast <folder>(),
+ events::folderEvent::TYPE_DELETED, m_path, m_path);
notifyFolder(event);
}
@@ -674,6 +676,15 @@ int IMAPFolder::getMessageCount()
}
+vmime_uint64 IMAPFolder::getHighestModSequence() const
+{
+ if (!isOpen())
+ throw exceptions::illegal_state("Folder not open");
+
+ return m_status->getHighestModSeq();
+}
+
+
ref <folder> IMAPFolder::getFolder(const folder::path::component& name)
{
ref <IMAPStore> store = m_store.acquire();
@@ -965,7 +976,7 @@ void IMAPFolder::deleteMessages(const int from, const int to)
else command << to;
}
- command << " +FLAGS.SILENT (\\Deleted)";
+ command << " +FLAGS (\\Deleted)";
// Send the request
m_connection->send(true, command.str(), true);
@@ -980,33 +991,6 @@ void IMAPFolder::deleteMessages(const int from, const int to)
resp->getErrorLog(), "bad response");
}
- // Update local flags
- const int to2 = (to == -1) ? m_status->getMessageCount() : to;
- const int count = to - from + 1;
-
- for (std::vector <IMAPMessage*>::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 <int> nums;
- nums.resize(count);
-
- for (int i = from, j = 0 ; i <= to2 ; ++i, ++j)
- nums[j] = i;
-
- events::messageChangedEvent event
- (thisRef().dynamicCast <folder>(),
- events::messageChangedEvent::TYPE_FLAGS, nums);
-
- notifyMessageChanged(event);
-
processStatusUpdate(resp);
}
@@ -1039,7 +1023,7 @@ void IMAPFolder::deleteMessages(const std::vector <int>& nums)
command << "STORE ";
command << IMAPUtils::listToSet(list, m_status->getMessageCount(), true);
- command << " +FLAGS.SILENT (\\Deleted)";
+ command << " +FLAGS (\\Deleted)";
// Send the request
m_connection->send(true, command.str(), true);
@@ -1054,24 +1038,6 @@ void IMAPFolder::deleteMessages(const std::vector <int>& nums)
resp->getErrorLog(), "bad response");
}
- // Update local flags
- for (std::vector <IMAPMessage*>::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
- (thisRef().dynamicCast <folder>(),
- events::messageChangedEvent::TYPE_FLAGS, list);
-
- notifyMessageChanged(event);
-
processStatusUpdate(resp);
}
@@ -1093,77 +1059,19 @@ void IMAPFolder::setMessageFlags(const int from, const int to, const int flags,
std::ostringstream oss;
oss.imbue(std::locale::classic());
- if (to == -1)
- oss << from << ":*";
- else
- oss << from << ":" << to;
-
- setMessageFlagsImpl(oss.str(), flags, mode);
-
- // Update local flags
- const int to2 = (to == -1) ? m_status->getMessageCount() : to;
- const int count = to - from + 1;
-
- switch (mode)
- {
- case message::FLAG_MODE_ADD:
- {
- for (std::vector <IMAPMessage*>::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 |= flags;
- }
- }
-
- break;
- }
- case message::FLAG_MODE_REMOVE:
+ if (from == to)
{
- for (std::vector <IMAPMessage*>::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 &= ~flags;
- }
- }
-
- break;
+ oss << from;
}
- default:
- case message::FLAG_MODE_SET:
+ else
{
- for (std::vector <IMAPMessage*>::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 = flags;
- }
- }
-
- break;
- }
-
+ if (to == -1)
+ oss << from << ":*";
+ else
+ oss << from << ":" << to;
}
- // Notify message flags changed
- std::vector <int> nums;
- nums.resize(count);
-
- for (int i = from, j = 0 ; i <= to2 ; ++i, ++j)
- nums[j] = i;
-
- events::messageChangedEvent event
- (thisRef().dynamicCast <folder>(),
- events::messageChangedEvent::TYPE_FLAGS, nums);
-
- notifyMessageChanged(event);
+ setMessageFlagsImpl(oss.str(), flags, mode);
}
@@ -1183,67 +1091,10 @@ void IMAPFolder::setMessageFlags(const std::vector <int>& nums, const int flags,
list.resize(nums.size());
std::copy(nums.begin(), nums.end(), list.begin());
-
std::sort(list.begin(), list.end());
// Delegates call
setMessageFlagsImpl(IMAPUtils::listToSet(list, m_status->getMessageCount(), true), flags, mode);
-
- // Update local flags
- switch (mode)
- {
- case message::FLAG_MODE_ADD:
- {
- for (std::vector <IMAPMessage*>::iterator it =
- m_messages.begin() ; it != m_messages.end() ; ++it)
- {
- if (std::binary_search(list.begin(), list.end(), (*it)->getNumber()) &&
- (*it)->m_flags != message::FLAG_UNDEFINED)
- {
- (*it)->m_flags |= flags;
- }
- }
-
- break;
- }
- case message::FLAG_MODE_REMOVE:
- {
- for (std::vector <IMAPMessage*>::iterator it =
- m_messages.begin() ; it != m_messages.end() ; ++it)
- {
- if (std::binary_search(list.begin(), list.end(), (*it)->getNumber()) &&
- (*it)->m_flags != message::FLAG_UNDEFINED)
- {
- (*it)->m_flags &= ~flags;
- }
- }
-
- break;
- }
- default:
- case message::FLAG_MODE_SET:
- {
- for (std::vector <IMAPMessage*>::iterator it =
- m_messages.begin() ; it != m_messages.end() ; ++it)
- {
- if (std::binary_search(list.begin(), list.end(), (*it)->getNumber()) &&
- (*it)->m_flags != message::FLAG_UNDEFINED)
- {
- (*it)->m_flags = flags;
- }
- }
-
- break;
- }
-
- }
-
- // Notify message flags changed
- events::messageChangedEvent event
- (thisRef().dynamicCast <folder>(),
- events::messageChangedEvent::TYPE_FLAGS, nums);
-
- notifyMessageChanged(event);
}
@@ -1257,10 +1108,10 @@ void IMAPFolder::setMessageFlagsImpl(const string& set, const int flags, const i
switch (mode)
{
- case message::FLAG_MODE_ADD: command << " +FLAGS.SILENT "; break;
- case message::FLAG_MODE_REMOVE: command << " -FLAGS.SILENT "; break;
+ case message::FLAG_MODE_ADD: command << " +FLAGS "; break;
+ case message::FLAG_MODE_REMOVE: command << " -FLAGS "; break;
default:
- case message::FLAG_MODE_SET: command << " FLAGS.SILENT "; break;
+ case message::FLAG_MODE_SET: command << " FLAGS "; break;
}
const string flagList = IMAPUtils::messageFlagList(flags);
@@ -1367,7 +1218,7 @@ void IMAPFolder::addMessage(utility::inputStream& is, const int size, const int
if (progress)
progress->start(total);
- const socket::size_type blockSize = std::min(is.getBlockSize(),
+ const socket::size_type blockSize = std::min(is.getBlockSize(),
static_cast <size_t>(m_connection->getSocket()->getBlockSize()));
std::vector <char> vbuffer(blockSize);
@@ -1430,45 +1281,6 @@ void IMAPFolder::expunge()
resp->getErrorLog(), "bad response");
}
- // Update the numbering of the messages
- const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
- resp->continue_req_or_response_data();
-
- std::vector <int> nums;
-
- 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("EXPUNGE",
- resp->getErrorLog(), "invalid response");
- }
-
- const IMAPParser::message_data* messageData =
- (*it)->response_data()->message_data();
-
- // We are only interested in responses of type "EXPUNGE"
- if (messageData == NULL ||
- messageData->type() != IMAPParser::message_data::EXPUNGE)
- {
- continue;
- }
-
- const int number = messageData->number();
-
- nums.push_back(number);
-
- for (std::vector <IMAPMessage*>::iterator jt =
- m_messages.begin() ; jt != m_messages.end() ; ++jt)
- {
- if ((*jt)->m_num == number)
- (*jt)->m_expunged = true;
- else if ((*jt)->m_num > number)
- (*jt)->m_num--;
- }
- }
-
processStatusUpdate(resp);
}
@@ -1515,9 +1327,10 @@ void IMAPFolder::rename(const folder::path& newPath)
m_path = newPath;
m_name = newPath.getLastComponent();
- events::folderEvent event
- (thisRef().dynamicCast <folder>(),
- events::folderEvent::TYPE_RENAMED, oldPath, newPath);
+ ref <events::folderEvent> event =
+ vmime::create <events::folderEvent>
+ (thisRef().dynamicCast <folder>(),
+ events::folderEvent::TYPE_RENAMED, oldPath, newPath);
notifyFolder(event);
@@ -1531,9 +1344,10 @@ void IMAPFolder::rename(const folder::path& newPath)
(*it)->m_path.renameParent(oldPath, newPath);
- events::folderEvent event
- ((*it)->thisRef().dynamicCast <folder>(),
- events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path);
+ ref <events::folderEvent> event =
+ vmime::create <events::folderEvent>
+ ((*it)->thisRef().dynamicCast <folder>(),
+ events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path);
(*it)->notifyFolder(event);
}
@@ -1784,6 +1598,11 @@ std::vector <int> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid&
void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp)
{
+ std::vector <ref <events::event> > events;
+
+ ref <IMAPFolderStatus> oldStatus = m_status->clone().dynamicCast <IMAPFolderStatus>();
+ int expungedMessageCount = 0;
+
// Process tagged response
if (resp->response_done() && resp->response_done()->response_tagged() &&
resp->response_done()->response_tagged()
@@ -1813,11 +1632,74 @@ void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp)
{
m_status->updateFromResponse((*it)->response_data()->mailbox_data());
}
+ else if ((*it)->response_data() && (*it)->response_data()->message_data())
+ {
+ const IMAPParser::message_data* msgData = (*it)->response_data()->message_data();
+ const int msgNumber = msgData->number();
+
+ if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::FETCH)
+ {
+ // Message changed
+ for (std::vector <IMAPMessage*>::iterator mit =
+ m_messages.begin() ; mit != m_messages.end() ; ++mit)
+ {
+ if ((*mit)->getNumber() == msgNumber)
+ (*mit)->processFetchResponse(/* options */ 0, msgData);
+ }
+
+ events.push_back(vmime::create <events::messageChangedEvent>
+ (thisRef().dynamicCast <folder>(),
+ events::messageChangedEvent::TYPE_FLAGS,
+ std::vector <int>(1, msgNumber)));
+ }
+ else if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::EXPUNGE)
+ {
+ // A message has been expunged, renumber messages
+ for (std::vector <IMAPMessage*>::iterator jt =
+ m_messages.begin() ; jt != m_messages.end() ; ++jt)
+ {
+ if ((*jt)->getNumber() == msgNumber)
+ (*jt)->setExpunged();
+ else if ((*jt)->getNumber() > msgNumber)
+ (*jt)->renumber((*jt)->getNumber() - 1);
+ }
+
+ events.push_back(vmime::create <events::messageCountEvent>
+ (thisRef().dynamicCast <folder>(),
+ events::messageCountEvent::TYPE_REMOVED,
+ std::vector <int>(1, msgNumber)));
+
+ expungedMessageCount++;
+ }
+ }
}
- // TODO: notification
+ // New messages arrived
+ if (m_status->getMessageCount() > oldStatus->getMessageCount() - expungedMessageCount)
+ {
+ std::vector <int> newMessageNumbers;
+
+ for (int msgNumber = oldStatus->getMessageCount() - expungedMessageCount ;
+ msgNumber <= m_status->getMessageCount() ; ++msgNumber)
+ {
+ newMessageNumbers.push_back(msgNumber);
+ }
+
+ events.push_back(vmime::create <events::messageCountEvent>
+ (thisRef().dynamicCast <folder>(),
+ events::messageCountEvent::TYPE_ADDED,
+ newMessageNumbers));
+ }
+
+ // Dispatch notifications
+ for (std::vector <ref <events::event> >::iterator evit =
+ events.begin() ; evit != events.end() ; ++evit)
+ {
+ notifyEvent(*evit);
+ }
}
+
} // imap
} // net
} // vmime