aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/net/imap/IMAPFolder.cpp361
-rw-r--r--src/net/imap/IMAPMessage.cpp5
-rw-r--r--src/net/imap/IMAPUtils.cpp213
-rw-r--r--src/net/maildir/maildirFolder.cpp380
-rw-r--r--src/net/maildir/maildirMessage.cpp2
-rw-r--r--src/net/maildir/maildirUtils.cpp32
-rw-r--r--src/net/messageSet.cpp369
-rw-r--r--src/net/pop3/POP3Folder.cpp173
-rw-r--r--src/net/pop3/POP3Utils.cpp32
9 files changed, 739 insertions, 828 deletions
diff --git a/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp
index 3a38182e..dd7f2512 100644
--- a/src/net/imap/IMAPFolder.cpp
+++ b/src/net/imap/IMAPFolder.cpp
@@ -529,135 +529,93 @@ ref <message> IMAPFolder::getMessage(const int num)
}
-std::vector <ref <message> > IMAPFolder::getMessages(const int from, const int to)
+std::vector <ref <message> > IMAPFolder::getMessages(const messageSet& msgs)
{
- const int messageCount = m_status->getMessageCount();
- const int to2 = (to == -1 ? messageCount : to);
-
if (!isOpen())
throw exceptions::illegal_state("Folder not open");
- else if (to2 < from || from < 1 || to2 < 1 || from > messageCount || to2 > messageCount)
- throw exceptions::message_not_found();
-
- std::vector <ref <message> > v;
- ref <IMAPFolder> thisFolder = thisRef().dynamicCast <IMAPFolder>();
-
- for (int i = from ; i <= to2 ; ++i)
- v.push_back(vmime::create <IMAPMessage>(thisFolder, i));
-
- return (v);
-}
-
-
-std::vector <ref <message> > IMAPFolder::getMessages(const std::vector <int>& nums)
-{
- if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
-
- std::vector <ref <message> > v;
- ref <IMAPFolder> thisFolder = thisRef().dynamicCast <IMAPFolder>();
-
- for (std::vector <int>::const_iterator it = nums.begin() ; it != nums.end() ; ++it)
- v.push_back(vmime::create <IMAPMessage>(thisFolder, *it));
-
- return (v);
-}
-
-
-ref <message> IMAPFolder::getMessageByUID(const message::uid& uid)
-{
- std::vector <message::uid> uids;
- uids.push_back(uid);
-
- std::vector <ref <message> > msgs = getMessagesByUID(uids);
-
- if (msgs.size() == 0)
- throw exceptions::message_not_found();
-
- return msgs[0];
-}
-
-std::vector <ref <message> > IMAPFolder::getMessagesByUID(const std::vector <message::uid>& uids)
-{
- if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
-
- if (uids.size() == 0)
+ if (msgs.isEmpty() == 0)
return std::vector <ref <message> >();
- // C: . UID FETCH uuuu1,uuuu2,uuuu3 UID
- // S: * nnnn1 FETCH (UID uuuu1)
- // S: * nnnn2 FETCH (UID uuuu2)
- // S: * nnnn3 FETCH (UID uuuu3)
- // S: . OK UID FETCH completed
+ std::vector <ref <message> > messages;
- // Prepare command and arguments
- std::ostringstream cmd;
- cmd.imbue(std::locale::classic());
+ if (msgs.isNumberSet())
+ {
+ const std::vector <int> numbers = IMAPUtils::messageSetToNumberList(msgs);
- cmd << "UID FETCH " << uids[0];
+ ref <IMAPFolder> thisFolder = thisRef().dynamicCast <IMAPFolder>();
- for (std::vector <message::uid>::size_type i = 1, n = uids.size() ; i < n ; ++i)
- cmd << "," << uids[i];
+ for (std::vector <int>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it)
+ messages.push_back(vmime::create <IMAPMessage>(thisFolder, *it));
+ }
+ else if (msgs.isUIDSet())
+ {
+ // C: . UID FETCH uuuu1,uuuu2,uuuu3 UID
+ // S: * nnnn1 FETCH (UID uuuu1)
+ // S: * nnnn2 FETCH (UID uuuu2)
+ // S: * nnnn3 FETCH (UID uuuu3)
+ // S: . OK UID FETCH completed
- cmd << " UID";
+ // Prepare command and arguments
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
- // Send the request
- m_connection->send(true, cmd.str(), true);
+ cmd << "UID FETCH " << IMAPUtils::messageSetToSequenceSet(msgs) << " UID";
- // Get the response
- utility::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
+ // Send the request
+ m_connection->send(true, cmd.str(), true);
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("UID FETCH ... UID", resp->getErrorLog(), "bad response");
- }
+ // Get the response
+ utility::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
- // Process the response
- const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
- resp->continue_req_or_response_data();
+ if (resp->isBad() || resp->response_done()->response_tagged()->
+ resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
+ {
+ throw exceptions::command_error("UID FETCH ... UID", resp->getErrorLog(), "bad response");
+ }
- std::vector <ref <message> > messages;
+ // Process the response
+ const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
+ resp->continue_req_or_response_data();
- for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respDataList.begin() ; it != respDataList.end() ; ++it)
- {
- if ((*it)->response_data() == NULL)
+ for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
+ it = respDataList.begin() ; it != respDataList.end() ; ++it)
{
- throw exceptions::command_error("UID FETCH ... UID",
- resp->getErrorLog(), "invalid response");
- }
+ if ((*it)->response_data() == NULL)
+ {
+ throw exceptions::command_error("UID FETCH ... UID",
+ resp->getErrorLog(), "invalid response");
+ }
- const IMAPParser::message_data* messageData =
- (*it)->response_data()->message_data();
+ const IMAPParser::message_data* messageData =
+ (*it)->response_data()->message_data();
- // We are only interested in responses of type "FETCH"
- if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH)
- continue;
+ // We are only interested in responses of type "FETCH"
+ if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH)
+ continue;
- // Get Process fetch response for this message
- const int msgNum = static_cast <int>(messageData->number());
- message::uid msgUID;
+ // Get Process fetch response for this message
+ const int msgNum = static_cast <int>(messageData->number());
+ message::uid msgUID;
- // Find UID in message attributes
- const std::vector <IMAPParser::msg_att_item*> atts = messageData->msg_att()->items();
+ // Find UID in message attributes
+ const std::vector <IMAPParser::msg_att_item*> atts = messageData->msg_att()->items();
- for (std::vector <IMAPParser::msg_att_item*>::const_iterator
- it = atts.begin() ; it != atts.end() ; ++it)
- {
- if ((*it)->type() == IMAPParser::msg_att_item::UID)
+ for (std::vector <IMAPParser::msg_att_item*>::const_iterator
+ it = atts.begin() ; it != atts.end() ; ++it)
{
- msgUID = (*it)->unique_id()->value();
- break;
+ if ((*it)->type() == IMAPParser::msg_att_item::UID)
+ {
+ msgUID = (*it)->unique_id()->value();
+ break;
+ }
}
- }
- if (!msgUID.empty())
- {
- ref <IMAPFolder> thisFolder = thisRef().dynamicCast <IMAPFolder>();
- messages.push_back(vmime::create <IMAPMessage>(thisFolder, msgNum, msgUID));
+ if (!msgUID.empty())
+ {
+ ref <IMAPFolder> thisFolder = thisRef().dynamicCast <IMAPFolder>();
+ messages.push_back(vmime::create <IMAPMessage>(thisFolder, msgNum, msgUID));
+ }
}
}
@@ -816,7 +774,9 @@ void IMAPFolder::fetchMessages(std::vector <ref <message> >& msg, const int opti
}
// Send the request
- const string command = IMAPUtils::buildFetchRequest(m_connection, list, options);
+ const string command = IMAPUtils::buildFetchRequest
+ (m_connection, messageSet::byNumber(list), options);
+
m_connection->send(true, command, true);
// Get the response
@@ -945,17 +905,11 @@ void IMAPFolder::onStoreDisconnected()
}
-void IMAPFolder::deleteMessage(const int num)
-{
- deleteMessages(num, num);
-}
-
-
-void IMAPFolder::deleteMessages(const int from, const int to)
+void IMAPFolder::deleteMessages(const messageSet& msgs)
{
ref <IMAPStore> store = m_store.acquire();
- if (from < 1 || (to < from && to != -1))
+ if (msgs.isEmpty())
throw exceptions::invalid_argument();
if (!store)
@@ -969,19 +923,10 @@ void IMAPFolder::deleteMessages(const int from, const int to)
std::ostringstream command;
command.imbue(std::locale::classic());
- command << "STORE ";
-
- if (from == to)
- {
- command << from;
- }
+ if (msgs.isUIDSet())
+ command << "UID STORE" << IMAPUtils::messageSetToSequenceSet(msgs);
else
- {
- command << from << ":";
-
- if (to == -1) command << m_status->getMessageCount();
- else command << to;
- }
+ command << "STORE" << IMAPUtils::messageSetToSequenceSet(msgs);
command << " +FLAGS (\\Deleted)";
@@ -1002,116 +947,16 @@ void IMAPFolder::deleteMessages(const int from, const int to)
}
-void IMAPFolder::deleteMessages(const std::vector <int>& nums)
+void IMAPFolder::setMessageFlags(const messageSet& msgs, const int flags, const int mode)
{
- ref <IMAPStore> store = m_store.acquire();
-
- if (nums.empty())
- throw exceptions::invalid_argument();
-
- if (!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 <int> list;
-
- list.resize(nums.size());
- std::copy(nums.begin(), nums.end(), list.begin());
-
- std::sort(list.begin(), list.end());
-
// Build the request text
std::ostringstream command;
command.imbue(std::locale::classic());
- command << "STORE ";
- command << IMAPUtils::listToSet(list, m_status->getMessageCount(), true);
- command << " +FLAGS (\\Deleted)";
-
- // Send the request
- m_connection->send(true, command.str(), true);
-
- // Get the response
- utility::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("STORE",
- resp->getErrorLog(), "bad response");
- }
-
- processStatusUpdate(resp);
-}
-
-
-void IMAPFolder::setMessageFlags(const int from, const int to, const int flags, const int mode)
-{
- ref <IMAPStore> store = m_store.acquire();
-
- if (from < 1 || (to < from && to != -1))
- throw exceptions::invalid_argument();
-
- if (!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");
-
- std::ostringstream oss;
- oss.imbue(std::locale::classic());
-
- if (from == to)
- {
- oss << from;
- }
+ if (msgs.isUIDSet())
+ command << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs);
else
- {
- if (to == -1)
- oss << from << ":*";
- else
- oss << from << ":" << to;
- }
-
- setMessageFlagsImpl(oss.str(), flags, mode);
-}
-
-
-void IMAPFolder::setMessageFlags(const std::vector <int>& nums, const int flags, const int mode)
-{
- ref <IMAPStore> store = m_store.acquire();
-
- if (!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 <int> list;
-
- 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);
-}
-
-
-void IMAPFolder::setMessageFlagsImpl(const string& set, const int flags, const int mode)
-{
- // Build the request text
- std::ostringstream command;
- command.imbue(std::locale::classic());
-
- command << "STORE " << set;
+ command << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs);
switch (mode)
{
@@ -1364,27 +1209,7 @@ void IMAPFolder::rename(const folder::path& newPath)
}
-void IMAPFolder::copyMessage(const folder::path& dest, const int num)
-{
- ref <IMAPStore> store = m_store.acquire();
-
- if (!store)
- throw exceptions::illegal_state("Store disconnected");
- else if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
-
- // Construct set
- std::ostringstream set;
- set.imbue(std::locale::classic());
-
- set << num;
-
- // Delegate message copy
- copyMessagesImpl(set.str(), dest);
-}
-
-
-void IMAPFolder::copyMessages(const folder::path& dest, const int from, const int to)
+void IMAPFolder::copyMessages(const folder::path& dest, const messageSet& set)
{
ref <IMAPStore> store = m_store.acquire();
@@ -1392,44 +1217,12 @@ void IMAPFolder::copyMessages(const folder::path& dest, const int from, const in
throw exceptions::illegal_state("Store disconnected");
else if (!isOpen())
throw exceptions::illegal_state("Folder not open");
- else if (from < 1 || (to < from && to != -1))
- throw exceptions::invalid_argument();
-
- // Construct set
- std::ostringstream set;
- set.imbue(std::locale::classic());
- if (to == -1)
- set << from << ":*";
- else
- set << from << ":" << to;
-
- // Delegate message copy
- copyMessagesImpl(set.str(), dest);
-}
-
-
-void IMAPFolder::copyMessages(const folder::path& dest, const std::vector <int>& nums)
-{
- ref <IMAPStore> store = m_store.acquire();
-
- if (!store)
- throw exceptions::illegal_state("Store disconnected");
- else if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
-
- // Delegate message copy
- copyMessagesImpl(IMAPUtils::listToSet(nums, m_status->getMessageCount()), dest);
-}
-
-
-void IMAPFolder::copyMessagesImpl(const string& set, const folder::path& dest)
-{
// Build the request text
std::ostringstream command;
command.imbue(std::locale::classic());
- command << "COPY " << set << " ";
+ command << "COPY " << IMAPUtils::messageSetToSequenceSet(set) << " ";
command << IMAPUtils::quoteString(IMAPUtils::pathToString
(m_connection->hierarchySeparator(), dest));
@@ -1599,6 +1392,8 @@ std::vector <int> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid&
}
}
+ processStatusUpdate(resp);
+
return v;
}
diff --git a/src/net/imap/IMAPMessage.cpp b/src/net/imap/IMAPMessage.cpp
index 96114e94..33599689 100644
--- a/src/net/imap/IMAPMessage.cpp
+++ b/src/net/imap/IMAPMessage.cpp
@@ -531,7 +531,10 @@ void IMAPMessage::setFlags(const int flags, const int mode)
if (!folder)
throw exceptions::folder_not_found();
- folder->setMessageFlags(m_num, m_num, flags, mode);
+ if (!m_uid.empty())
+ folder->setMessageFlags(messageSet::byUID(m_uid), flags, mode);
+ else
+ folder->setMessageFlags(messageSet::byNumber(m_num), flags, mode);
}
diff --git a/src/net/imap/IMAPUtils.cpp b/src/net/imap/IMAPUtils.cpp
index dc583f84..b5f8b38d 100644
--- a/src/net/imap/IMAPUtils.cpp
+++ b/src/net/imap/IMAPUtils.cpp
@@ -472,98 +472,6 @@ const string IMAPUtils::messageFlagList(const int flags)
// static
-const string IMAPUtils::listToSet(const std::vector <int>& list, const int max,
- const bool alreadySorted)
-{
- // Sort a copy of the list (if not already sorted)
- std::vector <int> temp;
-
- if (!alreadySorted)
- {
- temp.resize(list.size());
- std::copy(list.begin(), list.end(), temp.begin());
-
- std::sort(temp.begin(), temp.end());
- }
-
- const std::vector <int>& theList = (alreadySorted ? list : temp);
-
- // Build the set
- std::ostringstream res;
- res.imbue(std::locale::classic());
-
- int previous = -1, setBegin = -1;
-
- for (std::vector <int>::const_iterator it = theList.begin() ;
- it != theList.end() ; ++it)
- {
- const int current = *it;
-
- if (previous == -1)
- {
- res << current;
-
- previous = current;
- setBegin = current;
- }
- else
- {
- if (current == previous + 1)
- {
- previous = current;
- }
- else
- {
- if (setBegin != previous)
- {
- res << ":" << previous << "," << current;
-
- previous = current;
- setBegin = current;
- }
- else
- {
- if (setBegin != current) // skip duplicates
- res << "," << current;
-
- previous = current;
- setBegin = current;
- }
- }
- }
- }
-
- if (previous != setBegin)
- {
- if (previous == max)
- res << ":*";
- else
- res << ":" << previous;
- }
-
- return (res.str());
-}
-
-
-// static
-const string IMAPUtils::listToSet(const std::vector <message::uid>& list)
-{
- if (list.size() == 0)
- return "";
-
- std::ostringstream res;
- res.imbue(std::locale::classic());
-
- res << list[0];
-
- for (std::vector <message::uid>::size_type i = 1, n = list.size() ; i < n ; ++i)
- res << "," << list[i];
-
- return res.str();
-}
-
-
-// static
const string IMAPUtils::dateTime(const vmime::datetime& date)
{
std::ostringstream res;
@@ -633,8 +541,8 @@ const string IMAPUtils::dateTime(const vmime::datetime& date)
// static
-const string IMAPUtils::buildFetchRequestImpl
- (ref <IMAPConnection> cnt, const string& mode, const string& set, const int options)
+const string IMAPUtils::buildFetchRequest
+ (ref <IMAPConnection> cnt, const messageSet& msgs, const int options)
{
// Example:
// C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])
@@ -702,10 +610,10 @@ const string IMAPUtils::buildFetchRequestImpl
std::ostringstream command;
command.imbue(std::locale::classic());
- if (mode == "uid")
- command << "UID FETCH " << set << " (";
+ if (msgs.isUIDSet())
+ command << "UID FETCH " << messageSetToSequenceSet(msgs) << " (";
else
- command << "FETCH " << set << " (";
+ command << "FETCH " << messageSetToSequenceSet(msgs) << " (";
for (std::vector <string>::const_iterator it = items.begin() ;
it != items.end() ; ++it)
@@ -721,22 +629,6 @@ const string IMAPUtils::buildFetchRequestImpl
// static
-const string IMAPUtils::buildFetchRequest
- (ref <IMAPConnection> cnt, const std::vector <int>& list, const int options)
-{
- return buildFetchRequestImpl(cnt, "number", listToSet(list, -1, false), options);
-}
-
-
-// static
-const string IMAPUtils::buildFetchRequest
- (ref <IMAPConnection> cnt, const std::vector <message::uid>& list, const int options)
-{
- return buildFetchRequestImpl(cnt, "uid", listToSet(list), options);
-}
-
-
-// static
void IMAPUtils::convertAddressList
(const IMAPParser::address_list& src, mailboxList& dest)
{
@@ -756,6 +648,101 @@ void IMAPUtils::convertAddressList
}
+
+class IMAPUIDMessageSetEnumerator : public messageSetEnumerator
+{
+public:
+
+ IMAPUIDMessageSetEnumerator()
+ : m_first(true)
+ {
+ }
+
+ void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range)
+ {
+ if (!m_first)
+ m_oss << ",";
+
+ if (range.getFirst() == range.getLast())
+ m_oss << range.getFirst();
+ else
+ m_oss << range.getFirst() << ":" << range.getLast();
+
+ m_first = false;
+ }
+
+ void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range)
+ {
+ if (!m_first)
+ m_oss << ",";
+
+ if (range.getFirst() == range.getLast())
+ m_oss << range.getFirst();
+ else
+ m_oss << range.getFirst() << ":" << range.getLast();
+
+ m_first = false;
+ }
+
+ const std::string str() const
+ {
+ return m_oss.str();
+ }
+
+private:
+
+ std::ostringstream m_oss;
+ bool m_first;
+};
+
+
+class IMAPMessageSetEnumerator : public messageSetEnumerator
+{
+public:
+
+ void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range)
+ {
+ for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i)
+ m_list.push_back(i);
+ }
+
+ void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */)
+ {
+ // Not used
+ }
+
+ const std::vector <int>& list() const
+ {
+ return m_list;
+ }
+
+public:
+
+ std::vector <int> m_list;
+};
+
+
+
+// static
+const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs)
+{
+ IMAPUIDMessageSetEnumerator en;
+ msgs.enumerate(en);
+
+ return en.str();
+}
+
+
+// static
+const std::vector <int> IMAPUtils::messageSetToNumberList(const messageSet& msgs)
+{
+ IMAPMessageSetEnumerator en;
+ msgs.enumerate(en);
+
+ return en.list();
+}
+
+
} // imap
} // net
} // vmime
diff --git a/src/net/maildir/maildirFolder.cpp b/src/net/maildir/maildirFolder.cpp
index 3042d4b5..42a2c5ff 100644
--- a/src/net/maildir/maildirFolder.cpp
+++ b/src/net/maildir/maildirFolder.cpp
@@ -419,49 +419,32 @@ ref <message> maildirFolder::getMessage(const int num)
}
-std::vector <ref <message> > maildirFolder::getMessages(const int from, const int to)
-{
- const int to2 = (to == -1 ? m_messageCount : to);
-
- if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
- else if (to2 < from || from < 1 || to2 < 1 || from > m_messageCount || to2 > m_messageCount)
- throw exceptions::message_not_found();
-
- std::vector <ref <message> > v;
- ref <maildirFolder> thisFolder = thisRef().dynamicCast <maildirFolder>();
-
- for (int i = from ; i <= to2 ; ++i)
- v.push_back(vmime::create <maildirMessage>(thisFolder, i));
-
- return (v);
-}
-
-
-std::vector <ref <message> > maildirFolder::getMessages(const std::vector <int>& nums)
+std::vector <ref <message> > maildirFolder::getMessages(const messageSet& msgs)
{
if (!isOpen())
throw exceptions::illegal_state("Folder not open");
- std::vector <ref <message> > v;
- ref <maildirFolder> thisFolder = thisRef().dynamicCast <maildirFolder>();
-
- for (std::vector <int>::const_iterator it = nums.begin() ; it != nums.end() ; ++it)
- v.push_back(vmime::create <maildirMessage>(thisFolder, *it));
-
- return (v);
-}
+ if (msgs.isNumberSet())
+ {
+ const std::vector <int> numbers = maildirUtils::messageSetToNumberList(msgs);
+ std::vector <ref <message> > messages;
+ ref <maildirFolder> thisFolder = thisRef().dynamicCast <maildirFolder>();
-ref <message> maildirFolder::getMessageByUID(const message::uid& /* uid */)
-{
- throw exceptions::operation_not_supported();
-}
+ for (std::vector <int>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it)
+ {
+ if (*it < 1|| *it > m_messageCount)
+ throw exceptions::message_not_found();
+ messages.push_back(vmime::create <maildirMessage>(thisFolder, *it));
+ }
-std::vector <ref <message> > maildirFolder::getMessagesByUID(const std::vector <message::uid>& /* uids */)
-{
- throw exceptions::operation_not_supported();
+ return messages;
+ }
+ else
+ {
+ throw exceptions::operation_not_supported();
+ }
}
@@ -590,35 +573,18 @@ void maildirFolder::rename(const folder::path& newPath)
}
-void maildirFolder::deleteMessage(const int num)
-{
- // Mark messages as deleted
- setMessageFlags(num, num, message::FLAG_DELETED, message::FLAG_MODE_ADD);
-}
-
-
-void maildirFolder::deleteMessages(const int from, const int to)
-{
- // Mark messages as deleted
- setMessageFlags(from, to, message::FLAG_DELETED, message::FLAG_MODE_ADD);
-}
-
-
-void maildirFolder::deleteMessages(const std::vector <int>& nums)
+void maildirFolder::deleteMessages(const messageSet& msgs)
{
// Mark messages as deleted
- setMessageFlags(nums, message::FLAG_DELETED, message::FLAG_MODE_ADD);
+ setMessageFlags(msgs, message::FLAG_DELETED, message::FLAG_MODE_ADD);
}
void maildirFolder::setMessageFlags
- (const int from, const int to, const int flags, const int mode)
+ (const messageSet& msgs, const int flags, const int mode)
{
ref <maildirStore> store = m_store.acquire();
- if (from < 1 || (to < from && to != -1))
- throw exceptions::invalid_argument();
-
if (!store)
throw exceptions::illegal_state("Store disconnected");
else if (!isOpen())
@@ -626,210 +592,116 @@ void maildirFolder::setMessageFlags
else if (m_mode == MODE_READ_ONLY)
throw exceptions::illegal_state("Folder is read-only");
- // Construct the list of message numbers
- const int to2 = (to == -1) ? m_messageCount : to;
- const int count = to - from + 1;
-
- std::vector <int> nums;
- nums.resize(count);
+ if (msgs.isNumberSet())
+ {
+ const std::vector <int> nums = maildirUtils::messageSetToNumberList(msgs);
- for (int i = from, j = 0 ; i <= to2 ; ++i, ++j)
- nums[j] = i;
+ // Change message flags
+ ref <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
- // Change message flags
- setMessageFlagsImpl(nums, flags, mode);
+ utility::file::path curDirPath = store->getFormat()->
+ folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
- // Update local flags
- switch (mode)
- {
- case message::FLAG_MODE_ADD:
- {
- for (std::vector <maildirMessage*>::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:
- {
- for (std::vector <maildirMessage*>::iterator it =
- m_messages.begin() ; it != m_messages.end() ; ++it)
+ for (std::vector <int>::const_iterator it =
+ nums.begin() ; it != nums.end() ; ++it)
{
- if ((*it)->getNumber() >= from && (*it)->getNumber() <= to2 &&
- (*it)->m_flags != message::FLAG_UNDEFINED)
- {
- (*it)->m_flags &= ~flags;
- }
- }
+ const int num = *it - 1;
- break;
- }
- default:
- case message::FLAG_MODE_SET:
- {
- for (std::vector <maildirMessage*>::iterator it =
- m_messages.begin() ; it != m_messages.end() ; ++it)
- {
- if ((*it)->getNumber() >= from && (*it)->getNumber() <= to2 &&
- (*it)->m_flags != message::FLAG_UNDEFINED)
+ try
{
- (*it)->m_flags = flags;
- }
- }
-
- break;
- }
-
- }
-
- // Notify message flags changed
- ref <events::messageChangedEvent> event =
- vmime::create <events::messageChangedEvent>
- (thisRef().dynamicCast <folder>(),
- events::messageChangedEvent::TYPE_FLAGS, nums);
-
- notifyMessageChanged(event);
-
- // TODO: notify other folders with the same path
-}
-
+ const utility::file::path::component path = m_messageInfos[num].path;
+ ref <utility::file> file = fsf->create(curDirPath / path);
-void maildirFolder::setMessageFlags
- (const std::vector <int>& nums, const int flags, const int mode)
-{
- ref <maildirStore> store = m_store.acquire();
-
- if (!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");
+ int newFlags = maildirUtils::extractFlags(path);
- // Sort the list of message numbers
- std::vector <int> list;
+ switch (mode)
+ {
+ case message::FLAG_MODE_ADD: newFlags |= flags; break;
+ case message::FLAG_MODE_REMOVE: newFlags &= ~flags; break;
+ default:
+ case message::FLAG_MODE_SET: newFlags = flags; break;
+ }
- list.resize(nums.size());
- std::copy(nums.begin(), nums.end(), list.begin());
+ const utility::file::path::component newPath = maildirUtils::buildFilename
+ (maildirUtils::extractId(path), newFlags);
- std::sort(list.begin(), list.end());
+ file->rename(curDirPath / newPath);
- // Change message flags
- setMessageFlagsImpl(list, flags, mode);
+ if (flags & message::FLAG_DELETED)
+ m_messageInfos[num].type = messageInfos::TYPE_DELETED;
+ else
+ m_messageInfos[num].type = messageInfos::TYPE_CUR;
- // Update local flags
- switch (mode)
- {
- case message::FLAG_MODE_ADD:
- {
- for (std::vector <maildirMessage*>::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)
+ m_messageInfos[num].path = newPath;
+ }
+ catch (exceptions::filesystem_exception& e)
{
- (*it)->m_flags |= flags;
+ // Ignore (not important)
}
}
- break;
- }
- case message::FLAG_MODE_REMOVE:
- {
- for (std::vector <maildirMessage*>::iterator it =
- m_messages.begin() ; it != m_messages.end() ; ++it)
+ // Update local flags
+ switch (mode)
+ {
+ case message::FLAG_MODE_ADD:
{
- if (std::binary_search(list.begin(), list.end(), (*it)->getNumber()) &&
- (*it)->m_flags != message::FLAG_UNDEFINED)
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it)
{
- (*it)->m_flags &= ~flags;
+ if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) &&
+ (*it)->m_flags != message::FLAG_UNDEFINED)
+ {
+ (*it)->m_flags |= flags;
+ }
}
- }
- break;
- }
- default:
- case message::FLAG_MODE_SET:
- {
- for (std::vector <maildirMessage*>::iterator it =
- m_messages.begin() ; it != m_messages.end() ; ++it)
+ break;
+ }
+ case message::FLAG_MODE_REMOVE:
{
- if (std::binary_search(list.begin(), list.end(), (*it)->getNumber()) &&
- (*it)->m_flags != message::FLAG_UNDEFINED)
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it)
{
- (*it)->m_flags = flags;
+ if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) &&
+ (*it)->m_flags != message::FLAG_UNDEFINED)
+ {
+ (*it)->m_flags &= ~flags;
+ }
}
- }
-
- break;
- }
-
- }
-
- // Notify message flags changed
- ref <events::messageChangedEvent> event =
- vmime::create <events::messageChangedEvent>
- (thisRef().dynamicCast <folder>(),
- events::messageChangedEvent::TYPE_FLAGS, nums);
-
- notifyMessageChanged(event);
- // TODO: notify other folders with the same path
-}
-
-
-void maildirFolder::setMessageFlagsImpl
- (const std::vector <int>& nums, const int flags, const int mode)
-{
- ref <maildirStore> store = m_store.acquire();
-
- ref <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
-
- utility::file::path curDirPath = store->getFormat()->
- folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
-
- for (std::vector <int>::const_iterator it =
- nums.begin() ; it != nums.end() ; ++it)
- {
- const int num = *it - 1;
-
- try
+ break;
+ }
+ default:
+ case message::FLAG_MODE_SET:
{
- const utility::file::path::component path = m_messageInfos[num].path;
- ref <utility::file> file = fsf->create(curDirPath / path);
-
- int newFlags = maildirUtils::extractFlags(path);
-
- switch (mode)
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it)
{
- case message::FLAG_MODE_ADD: newFlags |= flags; break;
- case message::FLAG_MODE_REMOVE: newFlags &= ~flags; break;
- default:
- case message::FLAG_MODE_SET: newFlags = flags; break;
+ if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) &&
+ (*it)->m_flags != message::FLAG_UNDEFINED)
+ {
+ (*it)->m_flags = flags;
+ }
}
- const utility::file::path::component newPath = maildirUtils::buildFilename
- (maildirUtils::extractId(path), newFlags);
+ break;
+ }
- file->rename(curDirPath / newPath);
+ }
- if (flags & message::FLAG_DELETED)
- m_messageInfos[num].type = messageInfos::TYPE_DELETED;
- else
- m_messageInfos[num].type = messageInfos::TYPE_CUR;
+ // Notify message flags changed
+ ref <events::messageChangedEvent> event =
+ vmime::create <events::messageChangedEvent>
+ (thisRef().dynamicCast <folder>(),
+ events::messageChangedEvent::TYPE_FLAGS, nums);
- m_messageInfos[num].path = newPath;
- }
- catch (exceptions::filesystem_exception& e)
- {
- // Ignore (not important)
- }
+ notifyMessageChanged(event);
+
+ // TODO: notify other folders with the same path
+ }
+ else
+ {
+ throw exceptions::operation_not_supported();
}
}
@@ -1032,46 +904,7 @@ void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath,
}
-void maildirFolder::copyMessage(const folder::path& dest, const int num)
-{
- ref <maildirStore> store = m_store.acquire();
-
- if (!store)
- throw exceptions::illegal_state("Store disconnected");
- else if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
-
- copyMessages(dest, num, num);
-}
-
-
-void maildirFolder::copyMessages(const folder::path& dest, const int from, const int to)
-{
- ref <maildirStore> store = m_store.acquire();
-
- if (!store)
- throw exceptions::illegal_state("Store disconnected");
- else if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
- else if (from < 1 || (to < from && to != -1))
- throw exceptions::invalid_argument();
-
- // Construct the list of message numbers
- const int to2 = (to == -1) ? m_messageCount : to;
- const int count = to - from + 1;
-
- std::vector <int> nums;
- nums.resize(count);
-
- for (int i = from, j = 0 ; i <= to2 ; ++i, ++j)
- nums[j] = i;
-
- // Copy messages
- copyMessagesImpl(dest, nums);
-}
-
-
-void maildirFolder::copyMessages(const folder::path& dest, const std::vector <int>& nums)
+void maildirFolder::copyMessages(const folder::path& dest, const messageSet& msgs)
{
ref <maildirStore> store = m_store.acquire();
@@ -1080,15 +913,6 @@ void maildirFolder::copyMessages(const folder::path& dest, const std::vector <in
else if (!isOpen())
throw exceptions::illegal_state("Folder not open");
- // Copy messages
- copyMessagesImpl(dest, nums);
-}
-
-
-void maildirFolder::copyMessagesImpl(const folder::path& dest, const std::vector <int>& nums)
-{
- ref <maildirStore> store = m_store.acquire();
-
ref <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
utility::file::path curDirPath = store->getFormat()->folderPathToFileSystemPath
@@ -1121,6 +945,8 @@ void maildirFolder::copyMessagesImpl(const folder::path& dest, const std::vector
}
// Copy messages
+ const std::vector <int> nums = maildirUtils::messageSetToNumberList(msgs);
+
try
{
for (std::vector <int>::const_iterator it =
diff --git a/src/net/maildir/maildirMessage.cpp b/src/net/maildir/maildirMessage.cpp
index e63d5edf..a7c2a22f 100644
--- a/src/net/maildir/maildirMessage.cpp
+++ b/src/net/maildir/maildirMessage.cpp
@@ -140,7 +140,7 @@ void maildirMessage::setFlags(const int flags, const int mode)
if (!folder)
throw exceptions::folder_not_found();
- folder->setMessageFlags(m_num, m_num, flags, mode);
+ folder->setMessageFlags(messageSet::byNumber(m_num), flags, mode);
}
diff --git a/src/net/maildir/maildirUtils.cpp b/src/net/maildir/maildirUtils.cpp
index 9028fa59..c4ba2857 100644
--- a/src/net/maildir/maildirUtils.cpp
+++ b/src/net/maildir/maildirUtils.cpp
@@ -214,6 +214,38 @@ void maildirUtils::recursiveFSDelete(ref <utility::file> dir)
+class maildirMessageSetEnumerator : public messageSetEnumerator
+{
+public:
+
+ void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range)
+ {
+ for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i)
+ list.push_back(i);
+ }
+
+ void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */)
+ {
+ // Not supported
+ }
+
+public:
+
+ std::vector <int> list;
+};
+
+
+// static
+const std::vector <int> maildirUtils::messageSetToNumberList(const messageSet& msgs)
+{
+ maildirMessageSetEnumerator en;
+ msgs.enumerate(en);
+
+ return en.list;
+}
+
+
+
//
// messageIdComparator
//
diff --git a/src/net/messageSet.cpp b/src/net/messageSet.cpp
new file mode 100644
index 00000000..04f1debb
--- /dev/null
+++ b/src/net/messageSet.cpp
@@ -0,0 +1,369 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2013 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 3 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#include "vmime/net/messageSet.hpp"
+
+#include <iterator>
+#include <algorithm>
+#include <typeinfo>
+
+
+namespace vmime {
+namespace net {
+
+
+// messageRange
+
+messageRange::messageRange()
+{
+}
+
+
+messageRange::~messageRange()
+{
+}
+
+
+// numberMessageRange
+
+numberMessageRange::numberMessageRange(const int number)
+ : m_first(number), m_last(number)
+{
+ if (number < 1)
+ throw std::invalid_argument("number");
+}
+
+
+numberMessageRange::numberMessageRange(const int first, const int last)
+ : m_first(first), m_last(last)
+{
+ if (first < 1)
+ throw std::invalid_argument("first");
+ else if (last != -1 && last < first)
+ throw std::invalid_argument("last");
+}
+
+
+numberMessageRange::numberMessageRange(const numberMessageRange& other)
+ : messageRange(), m_first(other.m_first), m_last(other.m_last)
+{
+}
+
+
+int numberMessageRange::getFirst() const
+{
+ return m_first;
+}
+
+
+int numberMessageRange::getLast() const
+{
+ return m_last;
+}
+
+
+void numberMessageRange::enumerate(messageSetEnumerator& en) const
+{
+ en.enumerateNumberMessageRange(*this);
+}
+
+
+messageRange* numberMessageRange::clone() const
+{
+ return new numberMessageRange(*this);
+}
+
+
+// UIDMessageRange
+
+UIDMessageRange::UIDMessageRange(const message::uid& uid)
+ : m_first(uid), m_last(uid)
+{
+}
+
+
+UIDMessageRange::UIDMessageRange(const message::uid& first, const message::uid& last)
+ : m_first(first), m_last(last)
+{
+}
+
+
+UIDMessageRange::UIDMessageRange(const UIDMessageRange& other)
+ : messageRange(), m_first(other.m_first), m_last(other.m_last)
+{
+}
+
+
+const message::uid UIDMessageRange::getFirst() const
+{
+ return m_first;
+}
+
+
+const message::uid UIDMessageRange::getLast() const
+{
+ return m_last;
+}
+
+
+void UIDMessageRange::enumerate(messageSetEnumerator& en) const
+{
+ en.enumerateUIDMessageRange(*this);
+}
+
+
+messageRange* UIDMessageRange::clone() const
+{
+ return new UIDMessageRange(*this);
+}
+
+
+// messageSet
+
+
+messageSet::messageSet()
+{
+}
+
+
+messageSet::messageSet(const messageSet& other)
+ : object()
+{
+ m_ranges.resize(other.m_ranges.size());
+
+ for (unsigned int i = 0, n = other.m_ranges.size() ; i < n ; ++i)
+ m_ranges[i] = other.m_ranges[i]->clone();
+}
+
+
+messageSet::~messageSet()
+{
+ for (unsigned int i = 0, n = m_ranges.size() ; i < n ; ++i)
+ delete m_ranges[i];
+}
+
+
+// static
+messageSet messageSet::byNumber(const int number)
+{
+ messageSet set;
+ set.m_ranges.push_back(new numberMessageRange(number));
+
+ return set;
+}
+
+
+// static
+messageSet messageSet::byNumber(const int first, const int last)
+{
+ messageSet set;
+ set.m_ranges.push_back(new numberMessageRange(first, last));
+
+ return set;
+}
+
+
+// static
+messageSet messageSet::byNumber(const std::vector <int>& numbers)
+{
+ // Sort a copy of the list
+ std::vector <int> sortedNumbers;
+
+ sortedNumbers.resize(numbers.size());
+
+ std::copy(numbers.begin(), numbers.end(), sortedNumbers.begin());
+ std::sort(sortedNumbers.begin(), sortedNumbers.end());
+
+ // Build the set by detecting ranges of continuous numbers
+ int previous = -1, rangeStart = -1;
+ messageSet set;
+
+ for (std::vector <int>::const_iterator it = sortedNumbers.begin() ;
+ it != sortedNumbers.end() ; ++it)
+ {
+ const int current = *it;
+
+ if (current == previous)
+ continue; // skip duplicates
+
+ if (previous == -1)
+ {
+ previous = current;
+ rangeStart = current;
+ }
+ else
+ {
+ if (current == previous + 1)
+ {
+ previous = current;
+ }
+ else
+ {
+ set.m_ranges.push_back(new numberMessageRange(rangeStart, previous));
+
+ previous = current;
+ rangeStart = current;
+ }
+ }
+ }
+
+ set.m_ranges.push_back(new numberMessageRange(rangeStart, previous));
+
+ return set;
+}
+
+
+// static
+messageSet messageSet::byUID(const message::uid& uid)
+{
+ messageSet set;
+ set.m_ranges.push_back(new UIDMessageRange(uid));
+
+ return set;
+}
+
+
+messageSet messageSet::byUID(const message::uid& first, const message::uid& last)
+{
+ messageSet set;
+ set.m_ranges.push_back(new UIDMessageRange(first, last));
+
+ return set;
+}
+
+
+messageSet messageSet::byUID(const std::vector <message::uid>& uids)
+{
+ std::vector <vmime_uint32> numericUIDs;
+
+ for (unsigned int i = 0, n = uids.size() ; i < n ; ++i)
+ {
+ const string uid = uids[i];
+ int numericUID = 0;
+
+ const string::value_type* p = uid.c_str();
+
+ for ( ; *p >= '0' && *p <= '9' ; ++p)
+ numericUID = (numericUID * 10) + (*p - '0');
+
+ if (*p != '\0')
+ {
+ messageSet set;
+
+ // Non-numeric UID, fall back to plain UID list (single-UID ranges)
+ for (unsigned int i = 0, n = uids.size() ; i < n ; ++i)
+ set.m_ranges.push_back(new UIDMessageRange(uids[i]));
+
+ return set;
+ }
+
+ numericUIDs.push_back(numericUID);
+ }
+
+ // Sort a copy of the list
+ std::vector <vmime_uint32> sortedUIDs;
+
+ sortedUIDs.resize(numericUIDs.size());
+
+ std::copy(numericUIDs.begin(), numericUIDs.end(), sortedUIDs.begin());
+ std::sort(sortedUIDs.begin(), sortedUIDs.end());
+
+ // Build the set by detecting ranges of continuous numbers
+ vmime_uint32 previous = -1U, rangeStart = -1U;
+ messageSet set;
+
+ for (std::vector <vmime_uint32>::const_iterator it = sortedUIDs.begin() ;
+ it != sortedUIDs.end() ; ++it)
+ {
+ const vmime_uint32 current = *it;
+
+ if (current == previous)
+ continue; // skip duplicates
+
+ if (previous == -1U)
+ {
+ previous = current;
+ rangeStart = current;
+ }
+ else
+ {
+ if (current == previous + 1)
+ {
+ previous = current;
+ }
+ else
+ {
+ set.m_ranges.push_back(new UIDMessageRange
+ (static_cast <std::ostringstream*>(&(std::ostringstream() << rangeStart))->str(),
+ static_cast <std::ostringstream*>(&(std::ostringstream() << previous))->str()));
+
+ previous = current;
+ rangeStart = current;
+ }
+ }
+ }
+
+ set.m_ranges.push_back(new UIDMessageRange
+ (static_cast <std::ostringstream*>(&(std::ostringstream() << rangeStart))->str(),
+ static_cast <std::ostringstream*>(&(std::ostringstream() << previous))->str()));
+
+ return set;
+}
+
+
+void messageSet::addRange(const messageRange& range)
+{
+ if (!m_ranges.empty() && typeid(*m_ranges[0]) != typeid(range))
+ throw std::invalid_argument("range");
+
+ m_ranges.push_back(range.clone());
+}
+
+
+void messageSet::enumerate(messageSetEnumerator& en) const
+{
+ for (unsigned int i = 0, n = m_ranges.size() ; i < n ; ++i)
+ m_ranges[i]->enumerate(en);
+}
+
+
+bool messageSet::isEmpty() const
+{
+ return m_ranges.empty();
+}
+
+
+bool messageSet::isNumberSet() const
+{
+ return !isEmpty() && dynamic_cast <numberMessageRange*>(m_ranges[0]) != NULL;
+}
+
+
+bool messageSet::isUIDSet() const
+{
+ return !isEmpty() && dynamic_cast <UIDMessageRange*>(m_ranges[0]) != NULL;
+}
+
+
+} // net
+} // vmime
diff --git a/src/net/pop3/POP3Folder.cpp b/src/net/pop3/POP3Folder.cpp
index 9dc4589b..6a652de0 100644
--- a/src/net/pop3/POP3Folder.cpp
+++ b/src/net/pop3/POP3Folder.cpp
@@ -230,62 +230,36 @@ ref <message> POP3Folder::getMessage(const int num)
}
-std::vector <ref <message> > POP3Folder::getMessages(const int from, const int to)
+std::vector <ref <message> > POP3Folder::getMessages(const messageSet& msgs)
{
ref <POP3Store> store = m_store.acquire();
- const int to2 = (to == -1 ? m_messageCount : to);
-
if (!store)
throw exceptions::illegal_state("Store disconnected");
else if (!isOpen())
throw exceptions::illegal_state("Folder not open");
- else if (to2 < from || from < 1 || to2 < 1 || from > m_messageCount || to2 > m_messageCount)
- throw exceptions::message_not_found();
-
- std::vector <ref <message> > v;
- ref <POP3Folder> thisFolder = thisRef().dynamicCast <POP3Folder>();
-
- for (int i = from ; i <= to2 ; ++i)
- v.push_back(vmime::create <POP3Message>(thisFolder, i));
-
- return (v);
-}
-
-
-ref <message> POP3Folder::getMessageByUID(const message::uid& /* uid */)
-{
- throw exceptions::operation_not_supported();
-}
-
-
-std::vector <ref <message> > POP3Folder::getMessagesByUID(const std::vector <message::uid>& /* uids */)
-{
- throw exceptions::operation_not_supported();
-}
+ if (msgs.isNumberSet())
+ {
+ const std::vector <int> numbers = POP3Utils::messageSetToNumberList(msgs);
-std::vector <ref <message> > POP3Folder::getMessages(const std::vector <int>& nums)
-{
- ref <POP3Store> store = m_store.acquire();
+ std::vector <ref <message> > messages;
+ ref <POP3Folder> thisFolder = thisRef().dynamicCast <POP3Folder>();
- if (!store)
- throw exceptions::illegal_state("Store disconnected");
- else if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
+ for (std::vector <int>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it)
+ {
+ if (*it < 1|| *it > m_messageCount)
+ throw exceptions::message_not_found();
- std::vector <ref <message> > v;
- ref <POP3Folder> thisFolder = thisRef().dynamicCast <POP3Folder>();
+ messages.push_back(vmime::create <POP3Message>(thisFolder, *it));
+ }
- for (std::vector <int>::const_iterator it = nums.begin() ; it != nums.end() ; ++it)
+ return messages;
+ }
+ else
{
- if (*it < 1|| *it > m_messageCount)
- throw exceptions::message_not_found();
-
- v.push_back(vmime::create <POP3Message>(thisFolder, *it));
+ throw exceptions::operation_not_supported();
}
-
- return (v);
}
@@ -560,99 +534,11 @@ void POP3Folder::onStoreDisconnected()
}
-void POP3Folder::deleteMessage(const int num)
+void POP3Folder::deleteMessages(const messageSet& msgs)
{
ref <POP3Store> store = m_store.acquire();
- if (!store)
- throw exceptions::illegal_state("Store disconnected");
- else if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
-
- POP3Command::DELE(num)->send(store->getConnection());
-
- ref <POP3Response> response =
- POP3Response::readResponse(store->getConnection());
-
- if (!response->isSuccess())
- throw exceptions::command_error("DELE", response->getFirstLine());
-
- // Update local flags
- for (std::map <POP3Message*, int>::iterator it =
- m_messages.begin() ; it != m_messages.end() ; ++it)
- {
- POP3Message* msg = (*it).first;
-
- if (msg->getNumber() == num)
- msg->m_deleted = true;
- }
-
- // Notify message flags changed
- std::vector <int> nums;
- nums.push_back(num);
-
- ref <events::messageChangedEvent> event =
- vmime::create <events::messageChangedEvent>
- (thisRef().dynamicCast <folder>(),
- events::messageChangedEvent::TYPE_FLAGS, nums);
-
- notifyMessageChanged(event);
-}
-
-
-void POP3Folder::deleteMessages(const int from, const int to)
-{
- ref <POP3Store> store = m_store.acquire();
-
- if (from < 1 || (to < from && to != -1))
- throw exceptions::invalid_argument();
-
- if (!store)
- throw exceptions::illegal_state("Store disconnected");
- else if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
-
- const int to2 = (to == -1 ? m_messageCount : to);
-
- for (int i = from ; i <= to2 ; ++i)
- {
- POP3Command::DELE(i)->send(store->getConnection());
-
- ref <POP3Response> response =
- POP3Response::readResponse(store->getConnection());
-
- if (!response->isSuccess())
- throw exceptions::command_error("DELE", response->getFirstLine());
- }
-
- // Update local flags
- for (std::map <POP3Message*, int>::iterator it =
- m_messages.begin() ; it != m_messages.end() ; ++it)
- {
- POP3Message* msg = (*it).first;
-
- if (msg->getNumber() >= from && msg->getNumber() <= to2)
- msg->m_deleted = true;
- }
-
- // Notify message flags changed
- std::vector <int> nums;
-
- for (int i = from ; i <= to2 ; ++i)
- nums.push_back(i);
-
- ref <events::messageChangedEvent> event =
- vmime::create <events::messageChangedEvent>
- (thisRef().dynamicCast <folder>(),
- events::messageChangedEvent::TYPE_FLAGS, nums);
-
- notifyMessageChanged(event);
-}
-
-
-void POP3Folder::deleteMessages(const std::vector <int>& nums)
-{
- ref <POP3Store> store = m_store.acquire();
+ const std::vector <int> nums = POP3Utils::messageSetToNumberList(msgs);
if (nums.empty())
throw exceptions::invalid_argument();
@@ -702,14 +588,7 @@ void POP3Folder::deleteMessages(const std::vector <int>& nums)
}
-void POP3Folder::setMessageFlags(const int /* from */, const int /* to */,
- const int /* flags */, const int /* mode */)
-{
- throw exceptions::operation_not_supported();
-}
-
-
-void POP3Folder::setMessageFlags(const std::vector <int>& /* nums */,
+void POP3Folder::setMessageFlags(const messageSet& /* msgs */,
const int /* flags */, const int /* mode */)
{
throw exceptions::operation_not_supported();
@@ -736,19 +615,7 @@ void POP3Folder::addMessage(utility::inputStream& /* is */, const int /* size */
}
-void POP3Folder::copyMessage(const folder::path& /* dest */, const int /* num */)
-{
- throw exceptions::operation_not_supported();
-}
-
-
-void POP3Folder::copyMessages(const folder::path& /* dest */, const int /* from */, const int /* to */)
-{
- throw exceptions::operation_not_supported();
-}
-
-
-void POP3Folder::copyMessages(const folder::path& /* dest */, const std::vector <int>& /* nums */)
+void POP3Folder::copyMessages(const folder::path& /* dest */, const messageSet& /* msgs */)
{
throw exceptions::operation_not_supported();
}
diff --git a/src/net/pop3/POP3Utils.cpp b/src/net/pop3/POP3Utils.cpp
index f239627f..e2722104 100644
--- a/src/net/pop3/POP3Utils.cpp
+++ b/src/net/pop3/POP3Utils.cpp
@@ -73,6 +73,38 @@ void POP3Utils::parseMultiListOrUidlResponse(ref <POP3Response> response, std::m
}
+
+class POP3MessageSetEnumerator : public messageSetEnumerator
+{
+public:
+
+ void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range)
+ {
+ for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i)
+ list.push_back(i);
+ }
+
+ void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */)
+ {
+ // Not supported
+ }
+
+public:
+
+ std::vector <int> list;
+};
+
+
+// static
+const std::vector <int> POP3Utils::messageSetToNumberList(const messageSet& msgs)
+{
+ POP3MessageSetEnumerator en;
+ msgs.enumerate(en);
+
+ return en.list;
+}
+
+
} // pop3
} // net
} // vmime