Added basic support for IMAP CONDSTORE extension.
Process CAPABILITY in IMAP greeting response. Renamed getUniqueId() to getUID() for consistency.
This commit is contained in:
parent
ebc0db9bf9
commit
54084253e6
@ -204,6 +204,7 @@ libvmime_messaging_sources = [
|
|||||||
'net/defaultConnectionInfos.cpp', 'net/defaultConnectionInfos.hpp',
|
'net/defaultConnectionInfos.cpp', 'net/defaultConnectionInfos.hpp',
|
||||||
'net/events.cpp', 'net/events.hpp',
|
'net/events.cpp', 'net/events.hpp',
|
||||||
'net/folder.cpp', 'net/folder.hpp',
|
'net/folder.cpp', 'net/folder.hpp',
|
||||||
|
'net/folderStatus.hpp',
|
||||||
'net/message.cpp', 'net/message.hpp',
|
'net/message.cpp', 'net/message.hpp',
|
||||||
'net/securedConnectionInfos.hpp',
|
'net/securedConnectionInfos.hpp',
|
||||||
'net/service.cpp', 'net/service.hpp',
|
'net/service.cpp', 'net/service.hpp',
|
||||||
@ -245,6 +246,7 @@ libvmime_messaging_proto_sources = [
|
|||||||
'net/pop3/POP3Store.cpp', 'net/pop3/POP3Store.hpp',
|
'net/pop3/POP3Store.cpp', 'net/pop3/POP3Store.hpp',
|
||||||
'net/pop3/POP3SStore.cpp', 'net/pop3/POP3SStore.hpp',
|
'net/pop3/POP3SStore.cpp', 'net/pop3/POP3SStore.hpp',
|
||||||
'net/pop3/POP3Folder.cpp', 'net/pop3/POP3Folder.hpp',
|
'net/pop3/POP3Folder.cpp', 'net/pop3/POP3Folder.hpp',
|
||||||
|
'net/pop3/POP3FolderStatus.cpp', 'net/pop3/POP3FolderStatus.hpp',
|
||||||
'net/pop3/POP3Message.cpp', 'net/pop3/POP3Message.hpp',
|
'net/pop3/POP3Message.cpp', 'net/pop3/POP3Message.hpp',
|
||||||
'net/pop3/POP3Response.cpp', 'net/pop3/POP3Response.hpp',
|
'net/pop3/POP3Response.cpp', 'net/pop3/POP3Response.hpp',
|
||||||
'net/pop3/POP3Utils.cpp', 'net/pop3/POP3Utils.hpp'
|
'net/pop3/POP3Utils.cpp', 'net/pop3/POP3Utils.hpp'
|
||||||
@ -271,6 +273,7 @@ libvmime_messaging_proto_sources = [
|
|||||||
'net/imap/IMAPStore.cpp', 'net/imap/IMAPStore.hpp',
|
'net/imap/IMAPStore.cpp', 'net/imap/IMAPStore.hpp',
|
||||||
'net/imap/IMAPSStore.cpp', 'net/imap/IMAPSStore.hpp',
|
'net/imap/IMAPSStore.cpp', 'net/imap/IMAPSStore.hpp',
|
||||||
'net/imap/IMAPFolder.cpp', 'net/imap/IMAPFolder.hpp',
|
'net/imap/IMAPFolder.cpp', 'net/imap/IMAPFolder.hpp',
|
||||||
|
'net/imap/IMAPFolderStatus.cpp', 'net/imap/IMAPFolderStatus.hpp',
|
||||||
'net/imap/IMAPMessage.cpp', 'net/imap/IMAPMessage.hpp',
|
'net/imap/IMAPMessage.cpp', 'net/imap/IMAPMessage.hpp',
|
||||||
'net/imap/IMAPTag.cpp', 'net/imap/IMAPTag.hpp',
|
'net/imap/IMAPTag.cpp', 'net/imap/IMAPTag.hpp',
|
||||||
'net/imap/IMAPUtils.cpp', 'net/imap/IMAPUtils.hpp',
|
'net/imap/IMAPUtils.cpp', 'net/imap/IMAPUtils.hpp',
|
||||||
@ -286,6 +289,7 @@ libvmime_messaging_proto_sources = [
|
|||||||
'net/maildir/maildirServiceInfos.cpp', 'net/maildir/maildirServiceInfos.hpp',
|
'net/maildir/maildirServiceInfos.cpp', 'net/maildir/maildirServiceInfos.hpp',
|
||||||
'net/maildir/maildirStore.cpp', 'net/maildir/maildirStore.hpp',
|
'net/maildir/maildirStore.cpp', 'net/maildir/maildirStore.hpp',
|
||||||
'net/maildir/maildirFolder.cpp', 'net/maildir/maildirFolder.hpp',
|
'net/maildir/maildirFolder.cpp', 'net/maildir/maildirFolder.hpp',
|
||||||
|
'net/maildir/maildirFolderStatus.cpp', 'net/maildir/maildirFolderStatus.hpp',
|
||||||
'net/maildir/maildirMessage.cpp', 'net/maildir/maildirMessage.hpp',
|
'net/maildir/maildirMessage.cpp', 'net/maildir/maildirMessage.hpp',
|
||||||
'net/maildir/maildirUtils.cpp', 'net/maildir/maildirUtils.hpp',
|
'net/maildir/maildirUtils.cpp', 'net/maildir/maildirUtils.hpp',
|
||||||
'net/maildir/maildirFormat.cpp', 'net/maildir/maildirFormat.hpp',
|
'net/maildir/maildirFormat.cpp', 'net/maildir/maildirFormat.hpp',
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#include "vmime/exception.hpp"
|
#include "vmime/exception.hpp"
|
||||||
#include "vmime/platform.hpp"
|
#include "vmime/platform.hpp"
|
||||||
|
|
||||||
|
#include "vmime/utility/stringUtils.hpp"
|
||||||
|
|
||||||
#include "vmime/net/defaultConnectionInfos.hpp"
|
#include "vmime/net/defaultConnectionInfos.hpp"
|
||||||
|
|
||||||
#if VMIME_HAVE_SASL_SUPPORT
|
#if VMIME_HAVE_SASL_SUPPORT
|
||||||
@ -66,7 +68,7 @@ namespace imap {
|
|||||||
IMAPConnection::IMAPConnection(ref <IMAPStore> store, ref <security::authenticator> auth)
|
IMAPConnection::IMAPConnection(ref <IMAPStore> store, ref <security::authenticator> auth)
|
||||||
: m_store(store), m_auth(auth), m_socket(NULL), m_parser(NULL), m_tag(NULL),
|
: m_store(store), m_auth(auth), m_socket(NULL), m_parser(NULL), m_tag(NULL),
|
||||||
m_hierarchySeparator('\0'), m_state(STATE_NONE), m_timeoutHandler(NULL),
|
m_hierarchySeparator('\0'), m_state(STATE_NONE), m_timeoutHandler(NULL),
|
||||||
m_secured(false), m_firstTag(true), m_capabilitiesFetched(false)
|
m_secured(false), m_firstTag(true), m_capabilitiesFetched(false), m_noModSeq(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,6 +157,12 @@ void IMAPConnection::connect()
|
|||||||
needAuth = true;
|
needAuth = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (greet->resp_cond_auth()->resp_text()->resp_text_code() &&
|
||||||
|
greet->resp_cond_auth()->resp_text()->resp_text_code()->capability_data())
|
||||||
|
{
|
||||||
|
processCapabilityResponseData(greet->resp_cond_auth()->resp_text()->resp_text_code()->capability_data());
|
||||||
|
}
|
||||||
|
|
||||||
#if VMIME_HAVE_TLS_SUPPORT
|
#if VMIME_HAVE_TLS_SUPPORT
|
||||||
// Setup secured connection, if requested
|
// Setup secured connection, if requested
|
||||||
const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS)
|
const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS)
|
||||||
@ -266,6 +274,10 @@ void IMAPConnection::authenticate()
|
|||||||
internalDisconnect();
|
internalDisconnect();
|
||||||
throw exceptions::authentication_error(m_parser->lastLine());
|
throw exceptions::authentication_error(m_parser->lastLine());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Server capabilities may change when logged in
|
||||||
|
if (!processCapabilityResponseData(resp))
|
||||||
|
invalidateCapabilities();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -397,6 +409,9 @@ void IMAPConnection::authenticateSASL()
|
|||||||
|
|
||||||
// Send response
|
// Send response
|
||||||
send(false, saslContext->encodeB64(resp, respLen), true);
|
send(false, saslContext->encodeB64(resp, respLen), true);
|
||||||
|
|
||||||
|
// Server capabilities may change when logged in
|
||||||
|
invalidateCapabilities();
|
||||||
}
|
}
|
||||||
catch (exceptions::sasl_exception& e)
|
catch (exceptions::sasl_exception& e)
|
||||||
{
|
{
|
||||||
@ -506,6 +521,23 @@ const std::vector <string> IMAPConnection::getCapabilities()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IMAPConnection::hasCapability(const string& capa)
|
||||||
|
{
|
||||||
|
if (!m_capabilitiesFetched)
|
||||||
|
fetchCapabilities();
|
||||||
|
|
||||||
|
const string normCapa = utility::stringUtils::toUpper(capa);
|
||||||
|
|
||||||
|
for (unsigned int i = 0, n = m_capabilities.size() ; i < n ; ++i)
|
||||||
|
{
|
||||||
|
if (m_capabilities[i] == normCapa)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void IMAPConnection::invalidateCapabilities()
|
void IMAPConnection::invalidateCapabilities()
|
||||||
{
|
{
|
||||||
m_capabilities.clear();
|
m_capabilities.clear();
|
||||||
@ -519,35 +551,50 @@ void IMAPConnection::fetchCapabilities()
|
|||||||
|
|
||||||
utility::auto_ptr <IMAPParser::response> resp(m_parser->readResponse());
|
utility::auto_ptr <IMAPParser::response> resp(m_parser->readResponse());
|
||||||
|
|
||||||
std::vector <string> res;
|
|
||||||
|
|
||||||
if (resp->response_done()->response_tagged()->
|
if (resp->response_done()->response_tagged()->
|
||||||
resp_cond_state()->status() == IMAPParser::resp_cond_state::OK)
|
resp_cond_state()->status() == IMAPParser::resp_cond_state::OK)
|
||||||
{
|
{
|
||||||
const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
|
processCapabilityResponseData(resp);
|
||||||
resp->continue_req_or_response_data();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0 ; i < respDataList.size() ; ++i)
|
|
||||||
{
|
|
||||||
if (respDataList[i]->response_data() == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const IMAPParser::capability_data* capaData =
|
bool IMAPConnection::processCapabilityResponseData(const IMAPParser::response* resp)
|
||||||
respDataList[i]->response_data()->capability_data();
|
{
|
||||||
|
const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
|
||||||
|
resp->continue_req_or_response_data();
|
||||||
|
|
||||||
if (capaData == NULL)
|
for (unsigned int i = 0 ; i < respDataList.size() ; ++i)
|
||||||
continue;
|
{
|
||||||
|
if (respDataList[i]->response_data() == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
std::vector <IMAPParser::capability*> caps = capaData->capabilities();
|
const IMAPParser::capability_data* capaData =
|
||||||
|
respDataList[i]->response_data()->capability_data();
|
||||||
|
|
||||||
for (unsigned int j = 0 ; j < caps.size() ; ++j)
|
if (capaData == NULL)
|
||||||
{
|
continue;
|
||||||
if (caps[j]->auth_type())
|
|
||||||
res.push_back("AUTH=" + caps[j]->auth_type()->name());
|
processCapabilityResponseData(capaData);
|
||||||
else
|
return true;
|
||||||
res.push_back(caps[j]->atom()->value());
|
}
|
||||||
}
|
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_data* capaData)
|
||||||
|
{
|
||||||
|
std::vector <string> res;
|
||||||
|
|
||||||
|
std::vector <IMAPParser::capability*> caps = capaData->capabilities();
|
||||||
|
|
||||||
|
for (unsigned int j = 0 ; j < caps.size() ; ++j)
|
||||||
|
{
|
||||||
|
if (caps[j]->auth_type())
|
||||||
|
res.push_back("AUTH=" + caps[j]->auth_type()->name());
|
||||||
|
else
|
||||||
|
res.push_back(utility::stringUtils::toUpper(caps[j]->atom()->value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_capabilities = res;
|
m_capabilities = res;
|
||||||
@ -756,6 +803,18 @@ ref <const socket> IMAPConnection::getSocket() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IMAPConnection::isMODSEQDisabled() const
|
||||||
|
{
|
||||||
|
return m_noModSeq;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IMAPConnection::disableMODSEQ()
|
||||||
|
{
|
||||||
|
m_noModSeq = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // imap
|
} // imap
|
||||||
} // net
|
} // net
|
||||||
} // vmime
|
} // vmime
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "vmime/net/imap/IMAPMessage.hpp"
|
#include "vmime/net/imap/IMAPMessage.hpp"
|
||||||
#include "vmime/net/imap/IMAPUtils.hpp"
|
#include "vmime/net/imap/IMAPUtils.hpp"
|
||||||
#include "vmime/net/imap/IMAPConnection.hpp"
|
#include "vmime/net/imap/IMAPConnection.hpp"
|
||||||
|
#include "vmime/net/imap/IMAPFolderStatus.hpp"
|
||||||
|
|
||||||
#include "vmime/message.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)
|
m_open(false), m_type(type), m_flags(flags), m_messageCount(0), m_uidValidity(0)
|
||||||
{
|
{
|
||||||
store->registerFolder(this);
|
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
|
oss << IMAPUtils::quoteString(IMAPUtils::pathToString
|
||||||
(connection->hierarchySeparator(), getFullPath()));
|
(connection->hierarchySeparator(), getFullPath()));
|
||||||
|
|
||||||
|
if (m_connection->hasCapability("CONDSTORE"))
|
||||||
|
oss << " (CONDSTORE)";
|
||||||
|
|
||||||
connection->send(true, oss.str(), true);
|
connection->send(true, oss.str(), true);
|
||||||
|
|
||||||
// Read the response
|
// 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());
|
m_uidValidity = static_cast <unsigned int>(code->nz_number()->value());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IMAPParser::resp_text_code::NOMODSEQ:
|
||||||
|
|
||||||
|
connection->disableMODSEQ();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -255,6 +266,8 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processStatusUpdate(resp);
|
||||||
|
|
||||||
// Check for access mode (read-only or read-write)
|
// Check for access mode (read-only or read-write)
|
||||||
const IMAPParser::resp_text_code* respTextCode = resp->response_done()->
|
const IMAPParser::resp_text_code* respTextCode = resp->response_done()->
|
||||||
response_tagged()->resp_cond_state()->resp_text()->resp_text_code();
|
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
|
// 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);
|
m_connection->send(true, command, true);
|
||||||
|
|
||||||
// Get the response
|
// Get the response
|
||||||
@ -856,19 +869,17 @@ void IMAPFolder::fetchMessages(std::vector <ref <message> >& msg, const int opti
|
|||||||
|
|
||||||
if (progress)
|
if (progress)
|
||||||
progress->stop(total);
|
progress->stop(total);
|
||||||
|
|
||||||
|
processStatusUpdate(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void IMAPFolder::fetchMessage(ref <message> msg, const int options)
|
void IMAPFolder::fetchMessage(ref <message> msg, const int options)
|
||||||
{
|
{
|
||||||
ref <IMAPStore> store = m_store.acquire();
|
std::vector <ref <message> > msgs;
|
||||||
|
msgs.push_back(msg);
|
||||||
|
|
||||||
if (!store)
|
fetchMessages(msgs, options, /* progress */ NULL);
|
||||||
throw exceptions::illegal_state("Store disconnected");
|
|
||||||
else if (!isOpen())
|
|
||||||
throw exceptions::illegal_state("Folder not open");
|
|
||||||
|
|
||||||
msg.dynamicCast <IMAPMessage>()->fetch(thisRef().dynamicCast <IMAPFolder>(), options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -973,6 +984,8 @@ void IMAPFolder::deleteMessage(const int num)
|
|||||||
events::messageChangedEvent::TYPE_FLAGS, nums);
|
events::messageChangedEvent::TYPE_FLAGS, nums);
|
||||||
|
|
||||||
notifyMessageChanged(event);
|
notifyMessageChanged(event);
|
||||||
|
|
||||||
|
processStatusUpdate(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1040,6 +1053,8 @@ void IMAPFolder::deleteMessages(const int from, const int to)
|
|||||||
events::messageChangedEvent::TYPE_FLAGS, nums);
|
events::messageChangedEvent::TYPE_FLAGS, nums);
|
||||||
|
|
||||||
notifyMessageChanged(event);
|
notifyMessageChanged(event);
|
||||||
|
|
||||||
|
processStatusUpdate(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1103,6 +1118,8 @@ void IMAPFolder::deleteMessages(const std::vector <int>& nums)
|
|||||||
events::messageChangedEvent::TYPE_FLAGS, list);
|
events::messageChangedEvent::TYPE_FLAGS, list);
|
||||||
|
|
||||||
notifyMessageChanged(event);
|
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",
|
throw exceptions::command_error("STORE",
|
||||||
m_connection->getParser()->lastLine(), "bad response");
|
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);
|
(*it)->notifyMessageCount(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processStatusUpdate(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1545,6 +1566,8 @@ void IMAPFolder::expunge()
|
|||||||
(*it)->notifyMessageCount(event);
|
(*it)->notifyMessageCount(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processStatusUpdate(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1624,6 +1647,8 @@ void IMAPFolder::rename(const folder::path& newPath)
|
|||||||
(*it)->notifyFolder(event);
|
(*it)->notifyFolder(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processStatusUpdate(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1767,16 +1792,30 @@ void IMAPFolder::copyMessages(const string& set, const folder::path& dest)
|
|||||||
throw exceptions::command_error("COPY",
|
throw exceptions::command_error("COPY",
|
||||||
m_connection->getParser()->lastLine(), "bad response");
|
m_connection->getParser()->lastLine(), "bad response");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processStatusUpdate(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void IMAPFolder::status(int& count, int& unseen)
|
void IMAPFolder::status(int& count, int& unseen)
|
||||||
{
|
{
|
||||||
ref <IMAPStore> store = m_store.acquire();
|
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
unseen = 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
|
// Build the request text
|
||||||
std::ostringstream command;
|
std::ostringstream command;
|
||||||
command.imbue(std::locale::classic());
|
command.imbue(std::locale::classic());
|
||||||
@ -1784,7 +1823,14 @@ void IMAPFolder::status(int& count, int& unseen)
|
|||||||
command << "STATUS ";
|
command << "STATUS ";
|
||||||
command << IMAPUtils::quoteString(IMAPUtils::pathToString
|
command << IMAPUtils::quoteString(IMAPUtils::pathToString
|
||||||
(m_connection->hierarchySeparator(), getFullPath()));
|
(m_connection->hierarchySeparator(), getFullPath()));
|
||||||
command << " (MESSAGES UNSEEN)";
|
command << " (";
|
||||||
|
|
||||||
|
command << "MESSAGES" << ' ' << "UNSEEN" << ' ' << "UIDNEXT" << ' ' << "UIDVALIDITY";
|
||||||
|
|
||||||
|
if (m_connection->hasCapability("CONDSTORE"))
|
||||||
|
command << ' ' << "HIGHESTMODSEQ";
|
||||||
|
|
||||||
|
command << ")";
|
||||||
|
|
||||||
// Send the request
|
// Send the request
|
||||||
m_connection->send(true, command.str(), true);
|
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
|
for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
|
||||||
it = respDataList.begin() ; it != respDataList.end() ; ++it)
|
it = respDataList.begin() ; it != respDataList.end() ; ++it)
|
||||||
{
|
{
|
||||||
if ((*it)->response_data() == NULL)
|
if ((*it)->response_data() != NULL)
|
||||||
{
|
{
|
||||||
throw exceptions::command_error("STATUS",
|
const IMAPParser::response_data* responseData = (*it)->response_data();
|
||||||
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 (responseData->mailbox_data() &&
|
|
||||||
responseData->mailbox_data()->type() == IMAPParser::mailbox_data::STATUS)
|
|
||||||
{
|
|
||||||
const IMAPParser::status_att_list* statusAttList =
|
|
||||||
responseData->mailbox_data()->status_att_list();
|
|
||||||
|
|
||||||
for (std::vector <IMAPParser::status_att_val*>::const_iterator
|
|
||||||
jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt)
|
|
||||||
{
|
{
|
||||||
switch ((*jt)->type())
|
ref <IMAPFolderStatus> status = vmime::create <IMAPFolderStatus>();
|
||||||
{
|
status->updateFromResponse(responseData->mailbox_data());
|
||||||
case IMAPParser::status_att_val::MESSAGES:
|
|
||||||
|
|
||||||
count = (*jt)->value_as_number()->value();
|
m_messageCount = status->getMessageCount();
|
||||||
break;
|
m_uidValidity = status->getUIDValidity();
|
||||||
|
|
||||||
case IMAPParser::status_att_val::UNSEEN:
|
return status;
|
||||||
|
|
||||||
unseen = (*jt)->value_as_number()->value();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify message count changed (new messages)
|
throw exceptions::command_error("STATUS",
|
||||||
if (m_messageCount != count)
|
m_connection->getParser()->lastLine(), "invalid response");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IMAPFolder::noop()
|
||||||
|
{
|
||||||
|
ref <IMAPStore> store = m_store.acquire();
|
||||||
|
|
||||||
|
if (!store)
|
||||||
|
throw exceptions::illegal_state("Store disconnected");
|
||||||
|
|
||||||
|
m_connection->send(true, "NOOP", true);
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
const int oldCount = m_messageCount;
|
throw exceptions::command_error("NOOP", m_connection->getParser()->lastLine());
|
||||||
|
|
||||||
m_messageCount = count;
|
|
||||||
|
|
||||||
if (count > oldCount)
|
|
||||||
{
|
|
||||||
std::vector <int> nums;
|
|
||||||
nums.reserve(count - oldCount);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
notifyMessageCount(event);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
events::messageCountEvent event
|
|
||||||
((*it)->thisRef().dynamicCast <folder>(),
|
|
||||||
events::messageCountEvent::TYPE_ADDED, nums);
|
|
||||||
|
|
||||||
(*it)->notifyMessageCount(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
} // imap
|
||||||
} // net
|
} // net
|
||||||
} // vmime
|
} // vmime
|
||||||
|
158
src/net/imap/IMAPFolderStatus.cpp
Normal file
158
src/net/imap/IMAPFolderStatus.cpp
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||||
|
//
|
||||||
|
// 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/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/net/imap/IMAPFolderStatus.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace imap {
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int IMAPFolderStatus::getMessageCount() const
|
||||||
|
{
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int IMAPFolderStatus::getUnseenCount() const
|
||||||
|
{
|
||||||
|
return m_unseen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int IMAPFolderStatus::getRecentCount() const
|
||||||
|
{
|
||||||
|
return m_recent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vmime_uint32 IMAPFolderStatus::getUIDValidity() const
|
||||||
|
{
|
||||||
|
return m_uidValidity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vmime_uint32 IMAPFolderStatus::getUIDNext() const
|
||||||
|
{
|
||||||
|
return m_uidNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vmime_uint64 IMAPFolderStatus::getHighestModSeq() const
|
||||||
|
{
|
||||||
|
return m_highestModSeq;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp)
|
||||||
|
{
|
||||||
|
const IMAPParser::status_att_list* statusAttList = resp->status_att_list();
|
||||||
|
|
||||||
|
for (std::vector <IMAPParser::status_att_val*>::const_iterator
|
||||||
|
jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt)
|
||||||
|
{
|
||||||
|
switch ((*jt)->type())
|
||||||
|
{
|
||||||
|
case IMAPParser::status_att_val::MESSAGES:
|
||||||
|
|
||||||
|
m_count = (*jt)->value_as_number()->value();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAPParser::status_att_val::UNSEEN:
|
||||||
|
|
||||||
|
m_unseen = (*jt)->value_as_number()->value();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAPParser::status_att_val::RECENT:
|
||||||
|
|
||||||
|
m_recent = (*jt)->value_as_number()->value();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAPParser::status_att_val::UIDNEXT:
|
||||||
|
|
||||||
|
m_uidNext = (*jt)->value_as_number()->value();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAPParser::status_att_val::UIDVALIDITY:
|
||||||
|
|
||||||
|
m_uidValidity = (*jt)->value_as_number()->value();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAPParser::status_att_val::HIGHESTMODSEQ:
|
||||||
|
|
||||||
|
m_highestModSeq = (*jt)->value_as_mod_sequence_value()->value();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IMAPFolderStatus::updateFromResponse(const IMAPParser::resp_text_code* resp)
|
||||||
|
{
|
||||||
|
switch (resp->type())
|
||||||
|
{
|
||||||
|
case IMAPParser::resp_text_code::UIDVALIDITY:
|
||||||
|
|
||||||
|
m_uidValidity = resp->nz_number()->value();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAPParser::resp_text_code::UIDNEXT:
|
||||||
|
|
||||||
|
m_uidNext = resp->nz_number()->value();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAPParser::resp_text_code::UNSEEN:
|
||||||
|
|
||||||
|
m_unseen = resp->nz_number()->value();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAPParser::resp_text_code::HIGHESTMODSEQ:
|
||||||
|
|
||||||
|
m_highestModSeq = resp->mod_sequence_value()->value();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAPParser::resp_text_code::NOMODSEQ:
|
||||||
|
|
||||||
|
m_highestModSeq = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // imap
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
|
@ -98,15 +98,15 @@ private:
|
|||||||
|
|
||||||
IMAPMessage::IMAPMessage(ref <IMAPFolder> folder, const int num)
|
IMAPMessage::IMAPMessage(ref <IMAPFolder> 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_structure(NULL)
|
m_expunged(false), m_modseq(0), m_structure(NULL)
|
||||||
{
|
{
|
||||||
folder->registerMessage(this);
|
folder->registerMessage(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IMAPMessage::IMAPMessage(ref <IMAPFolder> folder, const int num, const uid& uniqueId)
|
IMAPMessage::IMAPMessage(ref <IMAPFolder> folder, const int num, const uid& uid)
|
||||||
: 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_uid(uniqueId), m_structure(NULL)
|
m_expunged(false), m_uid(uid), m_modseq(0), m_structure(NULL)
|
||||||
{
|
{
|
||||||
folder->registerMessage(this);
|
folder->registerMessage(this);
|
||||||
}
|
}
|
||||||
@ -133,9 +133,15 @@ int IMAPMessage::getNumber() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const message::uid IMAPMessage::getUniqueId() const
|
const message::uid IMAPMessage::getUID() const
|
||||||
{
|
{
|
||||||
return (m_uid);
|
return m_uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vmime_uint64 IMAPMessage::getModSequence() const
|
||||||
|
{
|
||||||
|
return m_modseq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -358,59 +364,6 @@ void IMAPMessage::extractImpl(ref <const part> p, utility::outputStream& os,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void IMAPMessage::fetch(ref <IMAPFolder> msgFolder, const int options)
|
|
||||||
{
|
|
||||||
ref <IMAPFolder> folder = m_folder.acquire();
|
|
||||||
|
|
||||||
if (folder != msgFolder)
|
|
||||||
throw exceptions::folder_not_found();
|
|
||||||
|
|
||||||
// Send the request
|
|
||||||
std::vector <int> list;
|
|
||||||
list.push_back(m_num);
|
|
||||||
|
|
||||||
const string command = IMAPUtils::buildFetchRequest(list, options);
|
|
||||||
|
|
||||||
folder->m_connection->send(true, command, true);
|
|
||||||
|
|
||||||
// Get the response
|
|
||||||
utility::auto_ptr <IMAPParser::response> resp(folder->m_connection->readResponse());
|
|
||||||
|
|
||||||
if (resp->isBad() || resp->response_done()->response_tagged()->
|
|
||||||
resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
|
|
||||||
{
|
|
||||||
throw exceptions::command_error("FETCH",
|
|
||||||
folder->m_connection->getParser()->lastLine(), "bad 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)
|
|
||||||
{
|
|
||||||
throw exceptions::command_error("FETCH",
|
|
||||||
folder->m_connection->getParser()->lastLine(), "invalid response");
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (static_cast <int>(messageData->number()) != m_num)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Process fetch response for this message
|
|
||||||
processFetchResponse(options, messageData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void IMAPMessage::processFetchResponse
|
void IMAPMessage::processFetchResponse
|
||||||
(const int options, const IMAPParser::message_data* msgData)
|
(const int options, const IMAPParser::message_data* msgData)
|
||||||
{
|
{
|
||||||
@ -436,6 +389,11 @@ void IMAPMessage::processFetchResponse
|
|||||||
m_uid = IMAPUtils::makeGlobalUID(folder->m_uidValidity, (*it)->unique_id()->value());
|
m_uid = IMAPUtils::makeGlobalUID(folder->m_uidValidity, (*it)->unique_id()->value());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case IMAPParser::msg_att_item::MODSEQ:
|
||||||
|
{
|
||||||
|
m_modseq = (*it)->mod_sequence_value()->value();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case IMAPParser::msg_att_item::ENVELOPE:
|
case IMAPParser::msg_att_item::ENVELOPE:
|
||||||
{
|
{
|
||||||
if (!(options & folder::FETCH_FULL_HEADER))
|
if (!(options & folder::FETCH_FULL_HEADER))
|
||||||
@ -731,7 +689,11 @@ ref <vmime::message> IMAPMessage::getParsedMessage()
|
|||||||
}
|
}
|
||||||
catch (exceptions::unfetched_object&)
|
catch (exceptions::unfetched_object&)
|
||||||
{
|
{
|
||||||
fetch(m_folder.acquire(), IMAPFolder::FETCH_STRUCTURE);
|
std::vector <ref <message> > msgs;
|
||||||
|
msgs.push_back(thisRef().dynamicCast <IMAPMessage>());
|
||||||
|
|
||||||
|
m_folder.acquire()->fetchMessages(msgs, IMAPFolder::FETCH_STRUCTURE, /* progress */ NULL);
|
||||||
|
|
||||||
structure = getStructure();
|
structure = getStructure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +153,12 @@ ref <connectionInfos> IMAPStore::getConnectionInfos() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <IMAPConnection> IMAPStore::getConnection()
|
||||||
|
{
|
||||||
|
return m_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void IMAPStore::disconnect()
|
void IMAPStore::disconnect()
|
||||||
{
|
{
|
||||||
if (!isConnected())
|
if (!isConnected())
|
||||||
@ -187,6 +193,13 @@ void IMAPStore::noop()
|
|||||||
{
|
{
|
||||||
throw exceptions::command_error("NOOP", m_connection->getParser()->lastLine());
|
throw exceptions::command_error("NOOP", m_connection->getParser()->lastLine());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (std::list <IMAPFolder*>::iterator it = m_folders.begin() ;
|
||||||
|
it != m_folders.end() ; ++it)
|
||||||
|
{
|
||||||
|
(*it)->noop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -634,7 +634,7 @@ const string IMAPUtils::dateTime(const vmime::datetime& date)
|
|||||||
|
|
||||||
// static
|
// static
|
||||||
const string IMAPUtils::buildFetchRequestImpl
|
const string IMAPUtils::buildFetchRequestImpl
|
||||||
(const string& mode, const string& set, const int options)
|
(ref <IMAPConnection> cnt, const string& mode, const string& set, const int options)
|
||||||
{
|
{
|
||||||
// Example:
|
// Example:
|
||||||
// C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])
|
// C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])
|
||||||
@ -655,8 +655,14 @@ const string IMAPUtils::buildFetchRequestImpl
|
|||||||
items.push_back("BODYSTRUCTURE");
|
items.push_back("BODYSTRUCTURE");
|
||||||
|
|
||||||
if (options & folder::FETCH_UID)
|
if (options & folder::FETCH_UID)
|
||||||
|
{
|
||||||
items.push_back("UID");
|
items.push_back("UID");
|
||||||
|
|
||||||
|
// Also fetch MODSEQ if CONDSTORE is supported
|
||||||
|
if (cnt->hasCapability("CONDSTORE") && !cnt->isMODSEQDisabled())
|
||||||
|
items.push_back("MODSEQ");
|
||||||
|
}
|
||||||
|
|
||||||
if (options & folder::FETCH_FULL_HEADER)
|
if (options & folder::FETCH_FULL_HEADER)
|
||||||
items.push_back("RFC822.HEADER");
|
items.push_back("RFC822.HEADER");
|
||||||
else
|
else
|
||||||
@ -715,16 +721,18 @@ const string IMAPUtils::buildFetchRequestImpl
|
|||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
const string IMAPUtils::buildFetchRequest(const std::vector <int>& list, const int options)
|
const string IMAPUtils::buildFetchRequest
|
||||||
|
(ref <IMAPConnection> cnt, const std::vector <int>& list, const int options)
|
||||||
{
|
{
|
||||||
return buildFetchRequestImpl("number", listToSet(list, -1, false), options);
|
return buildFetchRequestImpl(cnt, "number", listToSet(list, -1, false), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
const string IMAPUtils::buildFetchRequest(const std::vector <message::uid>& list, const int options)
|
const string IMAPUtils::buildFetchRequest
|
||||||
|
(ref <IMAPConnection> cnt, const std::vector <message::uid>& list, const int options)
|
||||||
{
|
{
|
||||||
return buildFetchRequestImpl("uid", listToSet(list), options);
|
return buildFetchRequestImpl(cnt, "uid", listToSet(list), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -749,7 +757,7 @@ void IMAPUtils::convertAddressList
|
|||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
unsigned int IMAPUtils::extractUIDFromGlobalUID(const message::uid& uid)
|
vmime_uint32 IMAPUtils::extractUIDFromGlobalUID(const message::uid& uid)
|
||||||
{
|
{
|
||||||
message::uid::size_type colonPos = uid.find(':');
|
message::uid::size_type colonPos = uid.find(':');
|
||||||
|
|
||||||
@ -758,7 +766,7 @@ unsigned int IMAPUtils::extractUIDFromGlobalUID(const message::uid& uid)
|
|||||||
std::istringstream iss(uid);
|
std::istringstream iss(uid);
|
||||||
iss.imbue(std::locale::classic());
|
iss.imbue(std::locale::classic());
|
||||||
|
|
||||||
unsigned int n = 0;
|
vmime_uint32 n = 0;
|
||||||
iss >> n;
|
iss >> n;
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
@ -768,7 +776,7 @@ unsigned int IMAPUtils::extractUIDFromGlobalUID(const message::uid& uid)
|
|||||||
std::istringstream iss(uid.substr(colonPos + 1));
|
std::istringstream iss(uid.substr(colonPos + 1));
|
||||||
iss.imbue(std::locale::classic());
|
iss.imbue(std::locale::classic());
|
||||||
|
|
||||||
unsigned int n = 0;
|
vmime_uint32 n = 0;
|
||||||
iss >> n;
|
iss >> n;
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
@ -777,7 +785,7 @@ unsigned int IMAPUtils::extractUIDFromGlobalUID(const message::uid& uid)
|
|||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
const message::uid IMAPUtils::makeGlobalUID(const unsigned int UIDValidity, const unsigned int messageUID)
|
const message::uid IMAPUtils::makeGlobalUID(const vmime_uint32 UIDValidity, const vmime_uint32 messageUID)
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss.imbue(std::locale::classic());
|
oss.imbue(std::locale::classic());
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "vmime/net/maildir/maildirMessage.hpp"
|
#include "vmime/net/maildir/maildirMessage.hpp"
|
||||||
#include "vmime/net/maildir/maildirUtils.hpp"
|
#include "vmime/net/maildir/maildirUtils.hpp"
|
||||||
#include "vmime/net/maildir/maildirFormat.hpp"
|
#include "vmime/net/maildir/maildirFormat.hpp"
|
||||||
|
#include "vmime/net/maildir/maildirFolderStatus.hpp"
|
||||||
|
|
||||||
#include "vmime/utility/smartPtr.hpp"
|
#include "vmime/utility/smartPtr.hpp"
|
||||||
|
|
||||||
@ -1162,6 +1163,18 @@ void maildirFolder::notifyMessagesCopied(const folder::path& dest)
|
|||||||
|
|
||||||
|
|
||||||
void maildirFolder::status(int& count, int& unseen)
|
void maildirFolder::status(int& count, int& unseen)
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
unseen = 0;
|
||||||
|
|
||||||
|
ref <folderStatus> status = getStatus();
|
||||||
|
|
||||||
|
count = status->getMessageCount();
|
||||||
|
unseen = status->getUnseenCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <folderStatus> maildirFolder::getStatus()
|
||||||
{
|
{
|
||||||
ref <maildirStore> store = m_store.acquire();
|
ref <maildirStore> store = m_store.acquire();
|
||||||
|
|
||||||
@ -1169,16 +1182,18 @@ void maildirFolder::status(int& count, int& unseen)
|
|||||||
|
|
||||||
scanFolder();
|
scanFolder();
|
||||||
|
|
||||||
count = m_messageCount;
|
ref <maildirFolderStatus> status = vmime::create <maildirFolderStatus>();
|
||||||
unseen = m_unreadMessageCount;
|
|
||||||
|
status->setMessageCount(m_messageCount);
|
||||||
|
status->setUnseenCount(m_unreadMessageCount);
|
||||||
|
|
||||||
// Notify message count changed (new messages)
|
// Notify message count changed (new messages)
|
||||||
if (count > oldCount)
|
if (m_messageCount > oldCount)
|
||||||
{
|
{
|
||||||
std::vector <int> nums;
|
std::vector <int> nums;
|
||||||
nums.reserve(count - oldCount);
|
nums.reserve(m_messageCount - oldCount);
|
||||||
|
|
||||||
for (int i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j)
|
for (int i = oldCount + 1, j = 0 ; i <= m_messageCount ; ++i, ++j)
|
||||||
nums[j] = i;
|
nums[j] = i;
|
||||||
|
|
||||||
events::messageCountEvent event
|
events::messageCountEvent event
|
||||||
@ -1207,6 +1222,8 @@ void maildirFolder::status(int& count, int& unseen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
67
src/net/maildir/maildirFolderStatus.cpp
Normal file
67
src/net/maildir/maildirFolderStatus.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||||
|
//
|
||||||
|
// 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/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/net/maildir/maildirFolderStatus.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace maildir {
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int maildirFolderStatus::getMessageCount() const
|
||||||
|
{
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int maildirFolderStatus::getUnseenCount() const
|
||||||
|
{
|
||||||
|
return m_unseen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void maildirFolderStatus::setMessageCount(const unsigned int count)
|
||||||
|
{
|
||||||
|
m_count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void maildirFolderStatus::setUnseenCount(const unsigned int unseen)
|
||||||
|
{
|
||||||
|
m_unseen = unseen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // maildir
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
|
@ -261,7 +261,7 @@ int maildirMessage::getNumber() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const message::uid maildirMessage::getUniqueId() const
|
const message::uid maildirMessage::getUID() const
|
||||||
{
|
{
|
||||||
return (m_uid);
|
return (m_uid);
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "vmime/net/pop3/POP3Message.hpp"
|
#include "vmime/net/pop3/POP3Message.hpp"
|
||||||
#include "vmime/net/pop3/POP3Command.hpp"
|
#include "vmime/net/pop3/POP3Command.hpp"
|
||||||
#include "vmime/net/pop3/POP3Response.hpp"
|
#include "vmime/net/pop3/POP3Response.hpp"
|
||||||
|
#include "vmime/net/pop3/POP3FolderStatus.hpp"
|
||||||
|
|
||||||
#include "vmime/net/pop3/POP3Utils.hpp"
|
#include "vmime/net/pop3/POP3Utils.hpp"
|
||||||
|
|
||||||
@ -751,13 +752,23 @@ void POP3Folder::copyMessages(const folder::path& /* dest */, const std::vector
|
|||||||
|
|
||||||
|
|
||||||
void POP3Folder::status(int& count, int& unseen)
|
void POP3Folder::status(int& count, int& unseen)
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
unseen = 0;
|
||||||
|
|
||||||
|
ref <folderStatus> status = getStatus();
|
||||||
|
|
||||||
|
count = status->getMessageCount();
|
||||||
|
unseen = status->getUnseenCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <folderStatus> POP3Folder::getStatus()
|
||||||
{
|
{
|
||||||
ref <POP3Store> store = m_store.acquire();
|
ref <POP3Store> store = m_store.acquire();
|
||||||
|
|
||||||
if (!store)
|
if (!store)
|
||||||
throw exceptions::illegal_state("Store disconnected");
|
throw exceptions::illegal_state("Store disconnected");
|
||||||
else if (!isOpen())
|
|
||||||
throw exceptions::illegal_state("Folder not open");
|
|
||||||
|
|
||||||
POP3Command::STAT()->send(store->getConnection());
|
POP3Command::STAT()->send(store->getConnection());
|
||||||
|
|
||||||
@ -767,10 +778,16 @@ void POP3Folder::status(int& count, int& unseen)
|
|||||||
if (!response->isSuccess())
|
if (!response->isSuccess())
|
||||||
throw exceptions::command_error("STAT", response->getFirstLine());
|
throw exceptions::command_error("STAT", response->getFirstLine());
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int count = 0;
|
||||||
|
|
||||||
std::istringstream iss(response->getText());
|
std::istringstream iss(response->getText());
|
||||||
iss >> count;
|
iss >> count;
|
||||||
|
|
||||||
unseen = count;
|
ref <POP3FolderStatus> status = vmime::create <POP3FolderStatus>();
|
||||||
|
|
||||||
|
status->setMessageCount(count);
|
||||||
|
status->setUnseenCount(count);
|
||||||
|
|
||||||
// Update local message count
|
// Update local message count
|
||||||
if (m_messageCount != count)
|
if (m_messageCount != count)
|
||||||
@ -811,6 +828,8 @@ void POP3Folder::status(int& count, int& unseen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
67
src/net/pop3/POP3FolderStatus.cpp
Normal file
67
src/net/pop3/POP3FolderStatus.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||||
|
//
|
||||||
|
// 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/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/net/pop3/POP3FolderStatus.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace pop3 {
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int POP3FolderStatus::getMessageCount() const
|
||||||
|
{
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int POP3FolderStatus::getUnseenCount() const
|
||||||
|
{
|
||||||
|
return m_unseen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void POP3FolderStatus::setMessageCount(const unsigned int count)
|
||||||
|
{
|
||||||
|
m_count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void POP3FolderStatus::setUnseenCount(const unsigned int unseen)
|
||||||
|
{
|
||||||
|
m_unseen = unseen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // pop3
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
|
@ -72,7 +72,7 @@ int POP3Message::getNumber() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const message::uid POP3Message::getUniqueId() const
|
const message::uid POP3Message::getUID() const
|
||||||
{
|
{
|
||||||
return (m_uid);
|
return (m_uid);
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "vmime/message.hpp"
|
#include "vmime/message.hpp"
|
||||||
#include "vmime/net/message.hpp"
|
#include "vmime/net/message.hpp"
|
||||||
#include "vmime/net/events.hpp"
|
#include "vmime/net/events.hpp"
|
||||||
|
#include "vmime/net/folderStatus.hpp"
|
||||||
|
|
||||||
#include "vmime/utility/path.hpp"
|
#include "vmime/utility/path.hpp"
|
||||||
#include "vmime/utility/stream.hpp"
|
#include "vmime/utility/stream.hpp"
|
||||||
@ -334,6 +335,8 @@ public:
|
|||||||
virtual void copyMessages(const folder::path& dest, const std::vector <int>& nums) = 0;
|
virtual void copyMessages(const folder::path& dest, const std::vector <int>& nums) = 0;
|
||||||
|
|
||||||
/** Request folder status without opening it.
|
/** Request folder status without opening it.
|
||||||
|
*
|
||||||
|
* \deprecated Use the new getStatus() method
|
||||||
*
|
*
|
||||||
* @param count will receive the number of messages in the folder
|
* @param count will receive the number of messages in the folder
|
||||||
* @param unseen will receive the number of unseen messages in the folder
|
* @param unseen will receive the number of unseen messages in the folder
|
||||||
@ -341,6 +344,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void status(int& count, int& unseen) = 0;
|
virtual void status(int& count, int& unseen) = 0;
|
||||||
|
|
||||||
|
/** Request folder status without opening it.
|
||||||
|
*
|
||||||
|
* @return current folder status
|
||||||
|
* @throw net_exception if an error occurs
|
||||||
|
*/
|
||||||
|
virtual ref <folderStatus> getStatus() = 0;
|
||||||
|
|
||||||
/** Expunge deleted messages.
|
/** Expunge deleted messages.
|
||||||
*
|
*
|
||||||
* @throw net_exception if an error occurs
|
* @throw net_exception if an error occurs
|
||||||
|
68
vmime/net/folderStatus.hpp
Normal file
68
vmime/net/folderStatus.hpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_NET_FOLDERSTATUS_HPP_INCLUDED
|
||||||
|
#define VMIME_NET_FOLDERSTATUS_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/base.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
|
||||||
|
|
||||||
|
/** Holds the status of a mail store folder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class VMIME_EXPORT folderStatus : public object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Returns the total number of messages in the folder.
|
||||||
|
*
|
||||||
|
* @return number of messages
|
||||||
|
*/
|
||||||
|
virtual unsigned int getMessageCount() const = 0;
|
||||||
|
|
||||||
|
/** Returns the number of unseen messages in the folder.
|
||||||
|
*
|
||||||
|
* @return number of unseen messages
|
||||||
|
*/
|
||||||
|
virtual unsigned int getUnseenCount() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES
|
||||||
|
|
||||||
|
#endif // VMIME_NET_FOLDERSTATUS_HPP_INCLUDED
|
@ -96,6 +96,7 @@ public:
|
|||||||
void fetchCapabilities();
|
void fetchCapabilities();
|
||||||
void invalidateCapabilities();
|
void invalidateCapabilities();
|
||||||
const std::vector <string> getCapabilities();
|
const std::vector <string> getCapabilities();
|
||||||
|
bool hasCapability(const string& capa);
|
||||||
|
|
||||||
ref <security::authenticator> getAuthenticator();
|
ref <security::authenticator> getAuthenticator();
|
||||||
|
|
||||||
@ -104,6 +105,9 @@ public:
|
|||||||
|
|
||||||
ref <const socket> getSocket() const;
|
ref <const socket> getSocket() const;
|
||||||
|
|
||||||
|
bool isMODSEQDisabled() const;
|
||||||
|
void disableMODSEQ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void authenticate();
|
void authenticate();
|
||||||
@ -115,6 +119,9 @@ private:
|
|||||||
void startTLS();
|
void startTLS();
|
||||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
bool processCapabilityResponseData(const IMAPParser::response* resp);
|
||||||
|
void processCapabilityResponseData(const IMAPParser::capability_data* capaData);
|
||||||
|
|
||||||
|
|
||||||
weak_ref <IMAPStore> m_store;
|
weak_ref <IMAPStore> m_store;
|
||||||
|
|
||||||
@ -140,6 +147,8 @@ private:
|
|||||||
std::vector <string> m_capabilities;
|
std::vector <string> m_capabilities;
|
||||||
bool m_capabilitiesFetched;
|
bool m_capabilitiesFetched;
|
||||||
|
|
||||||
|
bool m_noModSeq;
|
||||||
|
|
||||||
|
|
||||||
void internalDisconnect();
|
void internalDisconnect();
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
|
|
||||||
#include "vmime/net/folder.hpp"
|
#include "vmime/net/folder.hpp"
|
||||||
|
|
||||||
|
#include "vmime/net/imap/IMAPParser.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace vmime {
|
namespace vmime {
|
||||||
namespace net {
|
namespace net {
|
||||||
@ -47,6 +49,7 @@ namespace imap {
|
|||||||
class IMAPStore;
|
class IMAPStore;
|
||||||
class IMAPMessage;
|
class IMAPMessage;
|
||||||
class IMAPConnection;
|
class IMAPConnection;
|
||||||
|
class IMAPFolderStatus;
|
||||||
|
|
||||||
|
|
||||||
/** IMAP folder implementation.
|
/** IMAP folder implementation.
|
||||||
@ -62,7 +65,7 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
IMAPFolder(const folder::path& path, ref <IMAPStore> store, const int type = TYPE_UNDEFINED, const int flags = FLAG_UNDEFINED);
|
IMAPFolder(const folder::path& path, ref <IMAPStore> store, const int type = TYPE_UNDEFINED, const int flags = FLAG_UNDEFINED);
|
||||||
IMAPFolder(const IMAPFolder&) : folder() { }
|
IMAPFolder(const IMAPFolder&);
|
||||||
|
|
||||||
~IMAPFolder();
|
~IMAPFolder();
|
||||||
|
|
||||||
@ -118,6 +121,9 @@ public:
|
|||||||
void copyMessages(const folder::path& dest, const std::vector <int>& nums);
|
void copyMessages(const folder::path& dest, const std::vector <int>& nums);
|
||||||
|
|
||||||
void status(int& count, int& unseen);
|
void status(int& count, int& unseen);
|
||||||
|
ref <folderStatus> getStatus();
|
||||||
|
|
||||||
|
void noop();
|
||||||
|
|
||||||
void expunge();
|
void expunge();
|
||||||
|
|
||||||
@ -148,6 +154,18 @@ private:
|
|||||||
void copyMessages(const string& set, const folder::path& dest);
|
void copyMessages(const string& set, const folder::path& dest);
|
||||||
|
|
||||||
|
|
||||||
|
/** Process status updates ("unsolicited responses") contained in the
|
||||||
|
* specified response. Example:
|
||||||
|
*
|
||||||
|
* C: a006 NOOP
|
||||||
|
* S: * 930 EXISTS <-- this is a status update
|
||||||
|
* S: a006 OK Success
|
||||||
|
*
|
||||||
|
* @param resp parsed IMAP response
|
||||||
|
*/
|
||||||
|
void processStatusUpdate(const IMAPParser::response* resp);
|
||||||
|
|
||||||
|
|
||||||
weak_ref <IMAPStore> m_store;
|
weak_ref <IMAPStore> m_store;
|
||||||
ref <IMAPConnection> m_connection;
|
ref <IMAPConnection> m_connection;
|
||||||
|
|
||||||
@ -161,8 +179,8 @@ private:
|
|||||||
int m_flags;
|
int m_flags;
|
||||||
|
|
||||||
int m_messageCount;
|
int m_messageCount;
|
||||||
|
vmime_uint32 m_uidValidity;
|
||||||
unsigned int m_uidValidity;
|
ref <IMAPFolderStatus> m_status;
|
||||||
|
|
||||||
std::vector <IMAPMessage*> m_messages;
|
std::vector <IMAPMessage*> m_messages;
|
||||||
};
|
};
|
||||||
|
117
vmime/net/imap/IMAPFolderStatus.hpp
Normal file
117
vmime/net/imap/IMAPFolderStatus.hpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_NET_IMAP_IMAPFOLDERSTATUS_HPP_INCLUDED
|
||||||
|
#define VMIME_NET_IMAP_IMAPFOLDERSTATUS_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/net/folderStatus.hpp"
|
||||||
|
|
||||||
|
#include "vmime/net/imap/IMAPParser.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace imap {
|
||||||
|
|
||||||
|
|
||||||
|
/** Holds the status of an IMAP folder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class VMIME_EXPORT IMAPFolderStatus : public folderStatus
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Inherited from folderStatus
|
||||||
|
unsigned int getMessageCount() const;
|
||||||
|
unsigned int getUnseenCount() const;
|
||||||
|
|
||||||
|
/** Returns the the number of messages with the Recent flag set.
|
||||||
|
*
|
||||||
|
* @return number of messages flagged Recent
|
||||||
|
*/
|
||||||
|
unsigned int getRecentCount() const;
|
||||||
|
|
||||||
|
/** Returns the UID validity of the folder for the current session.
|
||||||
|
* If the server is capable of persisting UIDs accross sessions,
|
||||||
|
* this value should never change for a folder.
|
||||||
|
*
|
||||||
|
* @return UID validity of the folder
|
||||||
|
*/
|
||||||
|
vmime_uint32 getUIDValidity() const;
|
||||||
|
|
||||||
|
/** Returns the UID value that will be assigned to a new message
|
||||||
|
* in the folder. If the server does not support the UIDPLUS
|
||||||
|
* extension, it will return 0.
|
||||||
|
*
|
||||||
|
* @return UID of the next message
|
||||||
|
*/
|
||||||
|
vmime_uint32 getUIDNext() const;
|
||||||
|
|
||||||
|
/** Returns the highest modification sequence of all messages
|
||||||
|
* in the folder, or 0 if not available for this folder, or not
|
||||||
|
* supported by the server. The server must support the CONDSTORE
|
||||||
|
* extension for this to be available.
|
||||||
|
*
|
||||||
|
* @return highest modification sequence
|
||||||
|
*/
|
||||||
|
vmime_uint64 getHighestModSeq() const;
|
||||||
|
|
||||||
|
|
||||||
|
/** Reads the folder status from the specified IMAP response.
|
||||||
|
*
|
||||||
|
* @param resp parsed IMAP response
|
||||||
|
*/
|
||||||
|
void updateFromResponse(const IMAPParser::mailbox_data* resp);
|
||||||
|
|
||||||
|
/** Reads the folder status from the specified IMAP response.
|
||||||
|
*
|
||||||
|
* @param resp parsed IMAP response
|
||||||
|
*/
|
||||||
|
void updateFromResponse(const IMAPParser::resp_text_code* resp);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
unsigned int m_count;
|
||||||
|
unsigned int m_unseen;
|
||||||
|
unsigned int m_recent;
|
||||||
|
vmime_uint32 m_uidValidity;
|
||||||
|
vmime_uint32 m_uidNext;
|
||||||
|
vmime_uint64 m_highestModSeq;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // imap
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
|
||||||
|
|
||||||
|
#endif // VMIME_NET_IMAP_IMAPFOLDERSTATUS_HPP_INCLUDED
|
@ -57,7 +57,7 @@ private:
|
|||||||
friend class vmime::creator; // vmime::create <IMAPMessage>
|
friend class vmime::creator; // vmime::create <IMAPMessage>
|
||||||
|
|
||||||
IMAPMessage(ref <IMAPFolder> folder, const int num);
|
IMAPMessage(ref <IMAPFolder> folder, const int num);
|
||||||
IMAPMessage(ref <IMAPFolder> folder, const int num, const uid& uniqueId);
|
IMAPMessage(ref <IMAPFolder> folder, const int num, const uid& uid);
|
||||||
IMAPMessage(const IMAPMessage&) : message() { }
|
IMAPMessage(const IMAPMessage&) : message() { }
|
||||||
|
|
||||||
~IMAPMessage();
|
~IMAPMessage();
|
||||||
@ -66,7 +66,19 @@ public:
|
|||||||
|
|
||||||
int getNumber() const;
|
int getNumber() const;
|
||||||
|
|
||||||
const uid getUniqueId() const;
|
const uid getUID() const;
|
||||||
|
|
||||||
|
/** Returns the modification sequence for this message.
|
||||||
|
*
|
||||||
|
* Every time metadata for this message changes, the modification
|
||||||
|
* sequence is updated, and is greater than the previous one. The
|
||||||
|
* server must support the CONDSTORE extension for this to be
|
||||||
|
* available.
|
||||||
|
*
|
||||||
|
* @return modification sequence, or zero if not supported by
|
||||||
|
* the underlying protocol
|
||||||
|
*/
|
||||||
|
vmime_uint64 getModSequence() const;
|
||||||
|
|
||||||
int getSize() const;
|
int getSize() const;
|
||||||
|
|
||||||
@ -89,8 +101,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void fetch(ref <IMAPFolder> folder, const int options);
|
|
||||||
|
|
||||||
void processFetchResponse(const int options, const IMAPParser::message_data* msgData);
|
void processFetchResponse(const int options, const IMAPParser::message_data* msgData);
|
||||||
|
|
||||||
/** Recursively fetch part header for all parts in the structure.
|
/** Recursively fetch part header for all parts in the structure.
|
||||||
@ -132,6 +142,7 @@ private:
|
|||||||
int m_flags;
|
int m_flags;
|
||||||
bool m_expunged;
|
bool m_expunged;
|
||||||
uid m_uid;
|
uid m_uid;
|
||||||
|
vmime_uint64 m_modseq;
|
||||||
|
|
||||||
ref <header> m_header;
|
ref <header> m_header;
|
||||||
ref <structure> m_structure;
|
ref <structure> m_structure;
|
||||||
|
@ -1288,6 +1288,211 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// seq-number = nz-number / "*"
|
||||||
|
// ; message sequence number (COPY, FETCH, STORE
|
||||||
|
// ; commands) or unique identifier (UID COPY,
|
||||||
|
// ; UID FETCH, UID STORE commands).
|
||||||
|
|
||||||
|
class seq_number : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
seq_number()
|
||||||
|
: m_number(NULL), m_star(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~seq_number()
|
||||||
|
{
|
||||||
|
delete m_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
||||||
|
{
|
||||||
|
DEBUG_ENTER_COMPONENT("seq_number");
|
||||||
|
|
||||||
|
string::size_type pos = *currentPos;
|
||||||
|
|
||||||
|
if (parser.check <one_char <'*'> >(line, &pos, true))
|
||||||
|
{
|
||||||
|
m_star = true;
|
||||||
|
m_number = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_star = false;
|
||||||
|
m_number = parser.get <IMAPParser::number>(line, &pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
*currentPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
IMAPParser::number* m_number;
|
||||||
|
bool m_star;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const IMAPParser::number* number() const { return m_number; }
|
||||||
|
bool star() const { return m_star; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// seq-range = seq-number ":" seq-number
|
||||||
|
// ; two seq-number values and all values between
|
||||||
|
// ; these two regardless of order.
|
||||||
|
// ; Example: 2:4 and 4:2 are equivalent and indicate
|
||||||
|
// ; values 2, 3, and 4.
|
||||||
|
|
||||||
|
class seq_range : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
seq_range()
|
||||||
|
: m_first(NULL), m_last(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~seq_range()
|
||||||
|
{
|
||||||
|
delete m_first;
|
||||||
|
delete m_last;
|
||||||
|
}
|
||||||
|
|
||||||
|
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
||||||
|
{
|
||||||
|
DEBUG_ENTER_COMPONENT("seq_range");
|
||||||
|
|
||||||
|
string::size_type pos = *currentPos;
|
||||||
|
|
||||||
|
m_first = parser.get <seq_number>(line, &pos);
|
||||||
|
|
||||||
|
parser.check <one_char <'*'> >(line, &pos);
|
||||||
|
|
||||||
|
m_last = parser.get <seq_number>(line, &pos);
|
||||||
|
|
||||||
|
*currentPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
IMAPParser::seq_number* m_first;
|
||||||
|
IMAPParser::seq_number* m_last;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const IMAPParser::seq_number* first() const { return m_first; }
|
||||||
|
const IMAPParser::seq_number* last() const { return m_last; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// sequence-set = (seq-number / seq-range) *("," sequence-set)
|
||||||
|
// ; set of seq-number values, regardless of order.
|
||||||
|
// ; Servers MAY coalesce overlaps and/or execute the
|
||||||
|
// ; sequence in any order.
|
||||||
|
// ; Example: a message sequence number set of
|
||||||
|
// ; 2,4:7,9,12:* for a mailbox with 15 messages is
|
||||||
|
// ; equivalent to 2,4,5,6,7,9,12,13,14,15
|
||||||
|
|
||||||
|
class sequence_set : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
sequence_set()
|
||||||
|
: m_number(NULL), m_range(NULL), m_nextSet(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~sequence_set()
|
||||||
|
{
|
||||||
|
delete m_number;
|
||||||
|
delete m_range;
|
||||||
|
delete m_nextSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
||||||
|
{
|
||||||
|
DEBUG_ENTER_COMPONENT("sequence_set");
|
||||||
|
|
||||||
|
string::size_type pos = *currentPos;
|
||||||
|
|
||||||
|
if ((m_range = parser.get <IMAPParser::seq_range>(line, &pos, true)) == NULL)
|
||||||
|
m_number = parser.get <IMAPParser::seq_number>(line, &pos);
|
||||||
|
|
||||||
|
if (parser.check <one_char <','> >(line, &pos, true))
|
||||||
|
m_nextSet = parser.get <sequence_set>(line, &pos);
|
||||||
|
|
||||||
|
*currentPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
IMAPParser::seq_number* m_number;
|
||||||
|
IMAPParser::seq_range* m_range;
|
||||||
|
IMAPParser::sequence_set* m_nextSet;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const IMAPParser::seq_number* seq_number() const { return m_number; }
|
||||||
|
const IMAPParser::seq_range* seq_range() const { return m_range; }
|
||||||
|
const IMAPParser::sequence_set* next_sequence_set() const { return m_nextSet; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// mod-sequence-value = 1*DIGIT
|
||||||
|
// ;; Positive unsigned 64-bit integer
|
||||||
|
// ;; (mod-sequence)
|
||||||
|
// ;; (1 <= n < 18,446,744,073,709,551,615)
|
||||||
|
|
||||||
|
class mod_sequence_value : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
mod_sequence_value()
|
||||||
|
: m_value(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos)
|
||||||
|
{
|
||||||
|
DEBUG_ENTER_COMPONENT("mod_sequence_value");
|
||||||
|
|
||||||
|
string::size_type pos = *currentPos;
|
||||||
|
|
||||||
|
bool valid = true;
|
||||||
|
vmime_uint64 val = 0;
|
||||||
|
|
||||||
|
while (valid && pos < line.length())
|
||||||
|
{
|
||||||
|
const char c = line[pos];
|
||||||
|
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
{
|
||||||
|
val = (val * 10) + (c - '0');
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_value = val;
|
||||||
|
|
||||||
|
*currentPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
vmime_uint64 m_value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const vmime_uint64 value() const { return m_value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// flag ::= "\Answered" / "\Flagged" / "\Deleted" /
|
// flag ::= "\Answered" / "\Flagged" / "\Deleted" /
|
||||||
// "\Seen" / "\Draft" / flag_keyword / flag_extension
|
// "\Seen" / "\Draft" / flag_keyword / flag_extension
|
||||||
@ -1665,249 +1870,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// resp_text_code ::= "ALERT" / "PARSE" /
|
|
||||||
// "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
|
|
||||||
// "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
|
|
||||||
// "UIDVALIDITY" SPACE nz_number /
|
|
||||||
// "UNSEEN" SPACE nz_number /
|
|
||||||
// atom [SPACE 1*<any TEXT_CHAR except "]">]
|
|
||||||
|
|
||||||
class resp_text_code : public component
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
resp_text_code()
|
|
||||||
: m_nz_number(NULL), m_atom(NULL), m_flag_list(NULL), m_text(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~resp_text_code()
|
|
||||||
{
|
|
||||||
delete (m_nz_number);
|
|
||||||
delete (m_atom);
|
|
||||||
delete (m_flag_list);
|
|
||||||
delete (m_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
|
||||||
{
|
|
||||||
DEBUG_ENTER_COMPONENT("resp_text_code");
|
|
||||||
|
|
||||||
string::size_type pos = *currentPos;
|
|
||||||
|
|
||||||
// "ALERT"
|
|
||||||
if (parser.checkWithArg <special_atom>(line, &pos, "alert", true))
|
|
||||||
{
|
|
||||||
m_type = ALERT;
|
|
||||||
}
|
|
||||||
// "PARSE"
|
|
||||||
else if (parser.checkWithArg <special_atom>(line, &pos, "parse", true))
|
|
||||||
{
|
|
||||||
m_type = PARSE;
|
|
||||||
}
|
|
||||||
// "PERMANENTFLAGS" SPACE flag_list
|
|
||||||
else if (parser.checkWithArg <special_atom>(line, &pos, "permanentflags", true))
|
|
||||||
{
|
|
||||||
m_type = PERMANENTFLAGS;
|
|
||||||
|
|
||||||
parser.check <SPACE>(line, &pos);
|
|
||||||
|
|
||||||
m_flag_list = parser.get <IMAPParser::flag_list>(line, &pos);
|
|
||||||
}
|
|
||||||
// "READ-ONLY"
|
|
||||||
else if (parser.checkWithArg <special_atom>(line, &pos, "read-only", true))
|
|
||||||
{
|
|
||||||
m_type = READ_ONLY;
|
|
||||||
}
|
|
||||||
// "READ-WRITE"
|
|
||||||
else if (parser.checkWithArg <special_atom>(line, &pos, "read-write", true))
|
|
||||||
{
|
|
||||||
m_type = READ_WRITE;
|
|
||||||
}
|
|
||||||
// "TRYCREATE"
|
|
||||||
else if (parser.checkWithArg <special_atom>(line, &pos, "trycreate", true))
|
|
||||||
{
|
|
||||||
m_type = TRYCREATE;
|
|
||||||
}
|
|
||||||
// "UIDVALIDITY" SPACE nz_number
|
|
||||||
else if (parser.checkWithArg <special_atom>(line, &pos, "uidvalidity", true))
|
|
||||||
{
|
|
||||||
m_type = UIDVALIDITY;
|
|
||||||
|
|
||||||
parser.check <SPACE>(line, &pos);
|
|
||||||
m_nz_number = parser.get <IMAPParser::nz_number>(line, &pos);
|
|
||||||
}
|
|
||||||
// "UNSEEN" SPACE nz_number
|
|
||||||
else if (parser.checkWithArg <special_atom>(line, &pos, "unseen", true))
|
|
||||||
{
|
|
||||||
m_type = UNSEEN;
|
|
||||||
|
|
||||||
parser.check <SPACE>(line, &pos);
|
|
||||||
m_nz_number = parser.get <IMAPParser::nz_number>(line, &pos);
|
|
||||||
}
|
|
||||||
// atom [SPACE 1*<any TEXT_CHAR except "]">]
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_type = OTHER;
|
|
||||||
|
|
||||||
m_atom = parser.get <IMAPParser::atom>(line, &pos);
|
|
||||||
|
|
||||||
if (parser.check <SPACE>(line, &pos, true))
|
|
||||||
m_text = parser.get <text_except <']'> >(line, &pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
*currentPos = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
ALERT,
|
|
||||||
PARSE,
|
|
||||||
PERMANENTFLAGS,
|
|
||||||
READ_ONLY,
|
|
||||||
READ_WRITE,
|
|
||||||
TRYCREATE,
|
|
||||||
UIDVALIDITY,
|
|
||||||
UNSEEN,
|
|
||||||
OTHER
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Type m_type;
|
|
||||||
|
|
||||||
IMAPParser::nz_number* m_nz_number;
|
|
||||||
IMAPParser::atom* m_atom;
|
|
||||||
IMAPParser::flag_list* m_flag_list;
|
|
||||||
IMAPParser::text* m_text;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Type type() const { return (m_type); }
|
|
||||||
|
|
||||||
const IMAPParser::nz_number* nz_number() const { return (m_nz_number); }
|
|
||||||
const IMAPParser::atom* atom() const { return (m_atom); }
|
|
||||||
const IMAPParser::flag_list* flag_list() const { return (m_flag_list); }
|
|
||||||
const IMAPParser::text* text() const { return (m_text); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
|
|
||||||
// ;; text SHOULD NOT begin with "[" or "="
|
|
||||||
|
|
||||||
class resp_text : public component
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
resp_text()
|
|
||||||
: m_resp_text_code(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~resp_text()
|
|
||||||
{
|
|
||||||
delete (m_resp_text_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
|
||||||
{
|
|
||||||
DEBUG_ENTER_COMPONENT("resp_text");
|
|
||||||
|
|
||||||
string::size_type pos = *currentPos;
|
|
||||||
|
|
||||||
if (parser.check <one_char <'['> >(line, &pos, true))
|
|
||||||
{
|
|
||||||
m_resp_text_code = parser.get <IMAPParser::resp_text_code>(line, &pos);
|
|
||||||
|
|
||||||
parser.check <one_char <']'> >(line, &pos);
|
|
||||||
parser.check <SPACE>(line, &pos, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
text_mime2* text1 = parser.get <text_mime2>(line, &pos, true);
|
|
||||||
|
|
||||||
if (text1 != NULL)
|
|
||||||
{
|
|
||||||
m_text = text1->value();
|
|
||||||
delete (text1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IMAPParser::text* text2 =
|
|
||||||
parser.get <IMAPParser::text>(line, &pos, true);
|
|
||||||
|
|
||||||
if (text2 != NULL)
|
|
||||||
{
|
|
||||||
m_text = text2->value();
|
|
||||||
delete (text2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Empty response text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*currentPos = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
IMAPParser::resp_text_code* m_resp_text_code;
|
|
||||||
string m_text;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
const IMAPParser::resp_text_code* resp_text_code() const { return (m_resp_text_code); }
|
|
||||||
const string& text() const { return (m_text); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// continue_req ::= "+" SPACE (resp_text / base64)
|
|
||||||
//
|
|
||||||
|
|
||||||
class continue_req : public component
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
continue_req()
|
|
||||||
: m_resp_text(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~continue_req()
|
|
||||||
{
|
|
||||||
delete (m_resp_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
|
||||||
{
|
|
||||||
DEBUG_ENTER_COMPONENT("continue_req");
|
|
||||||
|
|
||||||
string::size_type pos = *currentPos;
|
|
||||||
|
|
||||||
parser.check <one_char <'+'> >(line, &pos);
|
|
||||||
parser.check <SPACE>(line, &pos);
|
|
||||||
|
|
||||||
m_resp_text = parser.get <IMAPParser::resp_text>(line, &pos);
|
|
||||||
|
|
||||||
parser.check <CRLF>(line, &pos);
|
|
||||||
|
|
||||||
*currentPos = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
IMAPParser::resp_text* m_resp_text;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
const IMAPParser::resp_text* resp_text() const { return (m_resp_text); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// auth_type ::= atom
|
// auth_type ::= atom
|
||||||
// ;; Defined by [IMAP-AUTH]
|
// ;; Defined by [IMAP-AUTH]
|
||||||
@ -1965,6 +1927,13 @@ public:
|
|||||||
// ("UIDVALIDITY" SP nz-number) /
|
// ("UIDVALIDITY" SP nz-number) /
|
||||||
// ("UNSEEN" SP number)
|
// ("UNSEEN" SP number)
|
||||||
//
|
//
|
||||||
|
// IMAP Extension for Conditional STORE (RFC-4551):
|
||||||
|
//
|
||||||
|
// status-att-val =/ "HIGHESTMODSEQ" SP mod-sequence-valzer
|
||||||
|
// ;; extends non-terminal defined in [IMAPABNF].
|
||||||
|
// ;; Value 0 denotes that the mailbox doesn't
|
||||||
|
// ;; support persistent mod-sequences
|
||||||
|
//
|
||||||
|
|
||||||
class status_att_val : public component
|
class status_att_val : public component
|
||||||
{
|
{
|
||||||
@ -1976,30 +1945,41 @@ public:
|
|||||||
|
|
||||||
string::size_type pos = *currentPos;
|
string::size_type pos = *currentPos;
|
||||||
|
|
||||||
if (parser.checkWithArg <special_atom>(line, &pos, "messages", true))
|
// "HIGHESTMODSEQ" SP mod-sequence-valzer
|
||||||
|
if (parser.checkWithArg <special_atom>(line, &pos, "highestmodseq", true))
|
||||||
{
|
{
|
||||||
m_type = MESSAGES;
|
m_type = HIGHESTMODSEQ;
|
||||||
}
|
|
||||||
else if (parser.checkWithArg <special_atom>(line, &pos, "recent", true))
|
parser.check <SPACE>(line, &pos);
|
||||||
{
|
m_value = parser.get <IMAPParser::mod_sequence_value>(line, &pos);
|
||||||
m_type = RECENT;
|
|
||||||
}
|
|
||||||
else if (parser.checkWithArg <special_atom>(line, &pos, "uidnext", true))
|
|
||||||
{
|
|
||||||
m_type = UIDNEXT;
|
|
||||||
}
|
|
||||||
else if (parser.checkWithArg <special_atom>(line, &pos, "uidvalidity", true))
|
|
||||||
{
|
|
||||||
m_type = UIDVALIDITY;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parser.checkWithArg <special_atom>(line, &pos, "unseen");
|
if (parser.checkWithArg <special_atom>(line, &pos, "messages", true))
|
||||||
m_type = UNSEEN;
|
{
|
||||||
}
|
m_type = MESSAGES;
|
||||||
|
}
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "recent", true))
|
||||||
|
{
|
||||||
|
m_type = RECENT;
|
||||||
|
}
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "uidnext", true))
|
||||||
|
{
|
||||||
|
m_type = UIDNEXT;
|
||||||
|
}
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "uidvalidity", true))
|
||||||
|
{
|
||||||
|
m_type = UIDVALIDITY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parser.checkWithArg <special_atom>(line, &pos, "unseen");
|
||||||
|
m_type = UNSEEN;
|
||||||
|
}
|
||||||
|
|
||||||
parser.check <SPACE>(line, &pos);
|
parser.check <SPACE>(line, &pos);
|
||||||
m_value = parser.get <IMAPParser::number>(line, &pos);
|
m_value = parser.get <IMAPParser::number>(line, &pos);
|
||||||
|
}
|
||||||
|
|
||||||
*currentPos = pos;
|
*currentPos = pos;
|
||||||
}
|
}
|
||||||
@ -2007,6 +1987,10 @@ public:
|
|||||||
|
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
|
// Extensions
|
||||||
|
HIGHESTMODSEQ,
|
||||||
|
|
||||||
|
// Standard IMAP
|
||||||
MESSAGES,
|
MESSAGES,
|
||||||
RECENT,
|
RECENT,
|
||||||
UIDNEXT,
|
UIDNEXT,
|
||||||
@ -2027,6 +2011,11 @@ public:
|
|||||||
{
|
{
|
||||||
return dynamic_cast <IMAPParser::number *>(m_value);
|
return dynamic_cast <IMAPParser::number *>(m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IMAPParser::mod_sequence_value* value_as_mod_sequence_value() const
|
||||||
|
{
|
||||||
|
return dynamic_cast <IMAPParser::mod_sequence_value *>(m_value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -3882,6 +3871,9 @@ public:
|
|||||||
// "BODY" section ["<" number ">"] SPACE nstring /
|
// "BODY" section ["<" number ">"] SPACE nstring /
|
||||||
// "UID" SPACE uniqueid
|
// "UID" SPACE uniqueid
|
||||||
//
|
//
|
||||||
|
// IMAP Extension for Conditional STORE (RFC-4551):
|
||||||
|
//
|
||||||
|
// msg_att_item /= "MODSEQ" SP "(" mod_sequence_value ")"
|
||||||
|
|
||||||
class msg_att_item : public component
|
class msg_att_item : public component
|
||||||
{
|
{
|
||||||
@ -3890,7 +3882,7 @@ public:
|
|||||||
msg_att_item()
|
msg_att_item()
|
||||||
: m_date_time(NULL), m_number(NULL), m_envelope(NULL),
|
: m_date_time(NULL), m_number(NULL), m_envelope(NULL),
|
||||||
m_uniqueid(NULL), m_nstring(NULL), m_body(NULL), m_flag_list(NULL),
|
m_uniqueid(NULL), m_nstring(NULL), m_body(NULL), m_flag_list(NULL),
|
||||||
m_section(NULL)
|
m_section(NULL), m_mod_sequence_value(NULL)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -3905,6 +3897,7 @@ public:
|
|||||||
delete (m_body);
|
delete (m_body);
|
||||||
delete (m_flag_list);
|
delete (m_flag_list);
|
||||||
delete (m_section);
|
delete (m_section);
|
||||||
|
delete m_mod_sequence_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
||||||
@ -4015,6 +4008,18 @@ public:
|
|||||||
m_body = parser.get <IMAPParser::body>(line, &pos);
|
m_body = parser.get <IMAPParser::body>(line, &pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// "MODSEQ" SP "(" mod_sequence_value ")"
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "modseq", true))
|
||||||
|
{
|
||||||
|
m_type = MODSEQ;
|
||||||
|
|
||||||
|
parser.check <SPACE>(line, &pos);
|
||||||
|
parser.check <one_char <'('> >(line, &pos);
|
||||||
|
|
||||||
|
m_mod_sequence_value = parser.get <IMAPParser::mod_sequence_value>(line, &pos);
|
||||||
|
|
||||||
|
parser.check <one_char <')'> >(line, &pos);
|
||||||
|
}
|
||||||
// "UID" SPACE uniqueid
|
// "UID" SPACE uniqueid
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4042,7 +4047,8 @@ public:
|
|||||||
BODY,
|
BODY,
|
||||||
BODY_SECTION,
|
BODY_SECTION,
|
||||||
BODY_STRUCTURE,
|
BODY_STRUCTURE,
|
||||||
UID
|
UID,
|
||||||
|
MODSEQ
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -4057,6 +4063,7 @@ public:
|
|||||||
IMAPParser::xbody* m_body;
|
IMAPParser::xbody* m_body;
|
||||||
IMAPParser::flag_list* m_flag_list;
|
IMAPParser::flag_list* m_flag_list;
|
||||||
IMAPParser::section* m_section;
|
IMAPParser::section* m_section;
|
||||||
|
IMAPParser::mod_sequence_value* m_mod_sequence_value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -4070,6 +4077,7 @@ public:
|
|||||||
const IMAPParser::xbody* body() const { return (m_body); }
|
const IMAPParser::xbody* body() const { return (m_body); }
|
||||||
const IMAPParser::flag_list* flag_list() const { return (m_flag_list); }
|
const IMAPParser::flag_list* flag_list() const { return (m_flag_list); }
|
||||||
const IMAPParser::section* section() const { return (m_section); }
|
const IMAPParser::section* section() const { return (m_section); }
|
||||||
|
const IMAPParser::mod_sequence_value* mod_sequence_value() { return m_mod_sequence_value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -4188,6 +4196,307 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// resp_text_code ::= "ALERT" / "PARSE" /
|
||||||
|
// capability-data /
|
||||||
|
// "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
|
||||||
|
// "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
|
||||||
|
// "UIDVALIDITY" SPACE nz_number /
|
||||||
|
// "UNSEEN" SPACE nz_number /
|
||||||
|
// atom [SPACE 1*<any TEXT_CHAR except "]">]
|
||||||
|
//
|
||||||
|
// IMAP Extension for Conditional STORE (RFC-4551):
|
||||||
|
//
|
||||||
|
// resp-text-code =/ "HIGHESTMODSEQ" SP mod-sequence-value /
|
||||||
|
// "NOMODSEQ" /
|
||||||
|
// "MODIFIED" SP set
|
||||||
|
|
||||||
|
class resp_text_code : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
resp_text_code()
|
||||||
|
: m_nz_number(NULL), m_atom(NULL), m_flag_list(NULL),
|
||||||
|
m_text(NULL), m_capability_data(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~resp_text_code()
|
||||||
|
{
|
||||||
|
delete (m_nz_number);
|
||||||
|
delete (m_atom);
|
||||||
|
delete (m_flag_list);
|
||||||
|
delete (m_text);
|
||||||
|
delete m_capability_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
||||||
|
{
|
||||||
|
DEBUG_ENTER_COMPONENT("resp_text_code");
|
||||||
|
|
||||||
|
string::size_type pos = *currentPos;
|
||||||
|
|
||||||
|
// "ALERT"
|
||||||
|
if (parser.checkWithArg <special_atom>(line, &pos, "alert", true))
|
||||||
|
{
|
||||||
|
m_type = ALERT;
|
||||||
|
}
|
||||||
|
// "PARSE"
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "parse", true))
|
||||||
|
{
|
||||||
|
m_type = PARSE;
|
||||||
|
}
|
||||||
|
// capability_data
|
||||||
|
else if ((m_capability_data = parser.get <IMAPParser::capability_data>(line, &pos, true)))
|
||||||
|
{
|
||||||
|
m_type = CAPABILITY;
|
||||||
|
}
|
||||||
|
// "PERMANENTFLAGS" SPACE flag_list
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "permanentflags", true))
|
||||||
|
{
|
||||||
|
m_type = PERMANENTFLAGS;
|
||||||
|
|
||||||
|
parser.check <SPACE>(line, &pos);
|
||||||
|
|
||||||
|
m_flag_list = parser.get <IMAPParser::flag_list>(line, &pos);
|
||||||
|
}
|
||||||
|
// "READ-ONLY"
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "read-only", true))
|
||||||
|
{
|
||||||
|
m_type = READ_ONLY;
|
||||||
|
}
|
||||||
|
// "READ-WRITE"
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "read-write", true))
|
||||||
|
{
|
||||||
|
m_type = READ_WRITE;
|
||||||
|
}
|
||||||
|
// "TRYCREATE"
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "trycreate", true))
|
||||||
|
{
|
||||||
|
m_type = TRYCREATE;
|
||||||
|
}
|
||||||
|
// "UIDVALIDITY" SPACE nz_number
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "uidvalidity", true))
|
||||||
|
{
|
||||||
|
m_type = UIDVALIDITY;
|
||||||
|
|
||||||
|
parser.check <SPACE>(line, &pos);
|
||||||
|
m_nz_number = parser.get <IMAPParser::nz_number>(line, &pos);
|
||||||
|
}
|
||||||
|
// "UIDNEXT" SPACE nz_number
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "uidnext", true))
|
||||||
|
{
|
||||||
|
m_type = UIDNEXT;
|
||||||
|
|
||||||
|
parser.check <SPACE>(line, &pos);
|
||||||
|
m_nz_number = parser.get <IMAPParser::nz_number>(line, &pos);
|
||||||
|
}
|
||||||
|
// "UNSEEN" SPACE nz_number
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "unseen", true))
|
||||||
|
{
|
||||||
|
m_type = UNSEEN;
|
||||||
|
|
||||||
|
parser.check <SPACE>(line, &pos);
|
||||||
|
m_nz_number = parser.get <IMAPParser::nz_number>(line, &pos);
|
||||||
|
}
|
||||||
|
// "HIGHESTMODSEQ" SP mod-sequence-value
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "highestmodseq", true))
|
||||||
|
{
|
||||||
|
m_type = HIGHESTMODSEQ;
|
||||||
|
|
||||||
|
parser.check <SPACE>(line, &pos);
|
||||||
|
m_mod_sequence_value = parser.get <IMAPParser::mod_sequence_value>(line, &pos);
|
||||||
|
}
|
||||||
|
// "NOMODSEQ"
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "nomodseq", true))
|
||||||
|
{
|
||||||
|
m_type = NOMODSEQ;
|
||||||
|
}
|
||||||
|
// "MODIFIED" SP sequence-set
|
||||||
|
else if (parser.checkWithArg <special_atom>(line, &pos, "modified", true))
|
||||||
|
{
|
||||||
|
m_type = MODIFIED;
|
||||||
|
|
||||||
|
parser.check <SPACE>(line, &pos);
|
||||||
|
|
||||||
|
m_sequence_set = parser.get <IMAPParser::sequence_set>(line, &pos);
|
||||||
|
}
|
||||||
|
// atom [SPACE 1*<any TEXT_CHAR except "]">]
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_type = OTHER;
|
||||||
|
|
||||||
|
m_atom = parser.get <IMAPParser::atom>(line, &pos);
|
||||||
|
|
||||||
|
if (parser.check <SPACE>(line, &pos, true))
|
||||||
|
m_text = parser.get <text_except <']'> >(line, &pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
*currentPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
// Extensions
|
||||||
|
HIGHESTMODSEQ,
|
||||||
|
NOMODSEQ,
|
||||||
|
MODIFIED,
|
||||||
|
|
||||||
|
// Standard IMAP
|
||||||
|
ALERT,
|
||||||
|
PARSE,
|
||||||
|
CAPABILITY,
|
||||||
|
PERMANENTFLAGS,
|
||||||
|
READ_ONLY,
|
||||||
|
READ_WRITE,
|
||||||
|
TRYCREATE,
|
||||||
|
UIDVALIDITY,
|
||||||
|
UIDNEXT,
|
||||||
|
UNSEEN,
|
||||||
|
OTHER
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Type m_type;
|
||||||
|
|
||||||
|
IMAPParser::nz_number* m_nz_number;
|
||||||
|
IMAPParser::atom* m_atom;
|
||||||
|
IMAPParser::flag_list* m_flag_list;
|
||||||
|
IMAPParser::text* m_text;
|
||||||
|
IMAPParser::mod_sequence_value* m_mod_sequence_value;
|
||||||
|
IMAPParser::sequence_set* m_sequence_set;
|
||||||
|
IMAPParser::capability_data* m_capability_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Type type() const { return (m_type); }
|
||||||
|
|
||||||
|
const IMAPParser::nz_number* nz_number() const { return (m_nz_number); }
|
||||||
|
const IMAPParser::atom* atom() const { return (m_atom); }
|
||||||
|
const IMAPParser::flag_list* flag_list() const { return (m_flag_list); }
|
||||||
|
const IMAPParser::text* text() const { return (m_text); }
|
||||||
|
const IMAPParser::mod_sequence_value* mod_sequence_value() const { return m_mod_sequence_value; }
|
||||||
|
const IMAPParser::sequence_set* sequence_set() const { return m_sequence_set; }
|
||||||
|
const IMAPParser::capability_data* capability_data() const { return m_capability_data; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
|
||||||
|
// ;; text SHOULD NOT begin with "[" or "="
|
||||||
|
|
||||||
|
class resp_text : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
resp_text()
|
||||||
|
: m_resp_text_code(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~resp_text()
|
||||||
|
{
|
||||||
|
delete (m_resp_text_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
||||||
|
{
|
||||||
|
DEBUG_ENTER_COMPONENT("resp_text");
|
||||||
|
|
||||||
|
string::size_type pos = *currentPos;
|
||||||
|
|
||||||
|
if (parser.check <one_char <'['> >(line, &pos, true))
|
||||||
|
{
|
||||||
|
m_resp_text_code = parser.get <IMAPParser::resp_text_code>(line, &pos);
|
||||||
|
|
||||||
|
parser.check <one_char <']'> >(line, &pos);
|
||||||
|
parser.check <SPACE>(line, &pos, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
text_mime2* text1 = parser.get <text_mime2>(line, &pos, true);
|
||||||
|
|
||||||
|
if (text1 != NULL)
|
||||||
|
{
|
||||||
|
m_text = text1->value();
|
||||||
|
delete (text1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IMAPParser::text* text2 =
|
||||||
|
parser.get <IMAPParser::text>(line, &pos, true);
|
||||||
|
|
||||||
|
if (text2 != NULL)
|
||||||
|
{
|
||||||
|
m_text = text2->value();
|
||||||
|
delete (text2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Empty response text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*currentPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
IMAPParser::resp_text_code* m_resp_text_code;
|
||||||
|
string m_text;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const IMAPParser::resp_text_code* resp_text_code() const { return (m_resp_text_code); }
|
||||||
|
const string& text() const { return (m_text); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// continue_req ::= "+" SPACE (resp_text / base64)
|
||||||
|
//
|
||||||
|
|
||||||
|
class continue_req : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
continue_req()
|
||||||
|
: m_resp_text(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~continue_req()
|
||||||
|
{
|
||||||
|
delete (m_resp_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void go(IMAPParser& parser, string& line, string::size_type* currentPos)
|
||||||
|
{
|
||||||
|
DEBUG_ENTER_COMPONENT("continue_req");
|
||||||
|
|
||||||
|
string::size_type pos = *currentPos;
|
||||||
|
|
||||||
|
parser.check <one_char <'+'> >(line, &pos);
|
||||||
|
parser.check <SPACE>(line, &pos);
|
||||||
|
|
||||||
|
m_resp_text = parser.get <IMAPParser::resp_text>(line, &pos);
|
||||||
|
|
||||||
|
parser.check <CRLF>(line, &pos);
|
||||||
|
|
||||||
|
*currentPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
IMAPParser::resp_text* m_resp_text;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const IMAPParser::resp_text* resp_text() const { return (m_resp_text); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text
|
// resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text
|
||||||
// ;; Status condition
|
// ;; Status condition
|
||||||
|
@ -86,6 +86,7 @@ public:
|
|||||||
|
|
||||||
bool isSecuredConnection() const;
|
bool isSecuredConnection() const;
|
||||||
ref <connectionInfos> getConnectionInfos() const;
|
ref <connectionInfos> getConnectionInfos() const;
|
||||||
|
ref <IMAPConnection> getConnection();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "vmime/net/folder.hpp"
|
#include "vmime/net/folder.hpp"
|
||||||
#include "vmime/net/message.hpp"
|
#include "vmime/net/message.hpp"
|
||||||
#include "vmime/net/imap/IMAPParser.hpp"
|
#include "vmime/net/imap/IMAPParser.hpp"
|
||||||
|
#include "vmime/net/imap/IMAPConnection.hpp"
|
||||||
|
|
||||||
#include "vmime/mailboxList.hpp"
|
#include "vmime/mailboxList.hpp"
|
||||||
|
|
||||||
@ -104,19 +105,23 @@ public:
|
|||||||
|
|
||||||
/** Construct a fetch request for the specified messages, designated by their sequence numbers.
|
/** Construct a fetch request for the specified messages, designated by their sequence numbers.
|
||||||
*
|
*
|
||||||
|
* @param cnt connection
|
||||||
* @param list list of message numbers
|
* @param list list of message numbers
|
||||||
* @param options fetch options
|
* @param options fetch options
|
||||||
* @return fetch request
|
* @return fetch request
|
||||||
*/
|
*/
|
||||||
static const string buildFetchRequest(const std::vector <int>& list, const int options);
|
static const string buildFetchRequest
|
||||||
|
(ref <IMAPConnection> cnt, const std::vector <int>& list, const int options);
|
||||||
|
|
||||||
/** Construct a fetch request for the specified messages, designated by their UIDs.
|
/** Construct a fetch request for the specified messages, designated by their UIDs.
|
||||||
*
|
*
|
||||||
|
* @param cnt connection
|
||||||
* @param list list of message UIDs
|
* @param list list of message UIDs
|
||||||
* @param options fetch options
|
* @param options fetch options
|
||||||
* @return fetch request
|
* @return fetch request
|
||||||
*/
|
*/
|
||||||
static const string buildFetchRequest(const std::vector <message::uid>& list, const int options);
|
static const string buildFetchRequest
|
||||||
|
(ref <IMAPConnection> cnt, const std::vector <message::uid>& list, const int options);
|
||||||
|
|
||||||
/** Convert a parser-style address list to a mailbox list.
|
/** Convert a parser-style address list to a mailbox list.
|
||||||
*
|
*
|
||||||
@ -130,7 +135,7 @@ public:
|
|||||||
* @param uid globally unique UID (as returned by makeGlobalUID(), for example)
|
* @param uid globally unique UID (as returned by makeGlobalUID(), for example)
|
||||||
* @return message UID
|
* @return message UID
|
||||||
*/
|
*/
|
||||||
static unsigned int extractUIDFromGlobalUID(const message::uid& uid);
|
static vmime_uint32 extractUIDFromGlobalUID(const message::uid& uid);
|
||||||
|
|
||||||
/** Construct a globally unique UID from UID Validity and a message UID.
|
/** Construct a globally unique UID from UID Validity and a message UID.
|
||||||
*
|
*
|
||||||
@ -138,12 +143,12 @@ public:
|
|||||||
* @param messageUID UID of the message
|
* @param messageUID UID of the message
|
||||||
* @return global UID
|
* @return global UID
|
||||||
*/
|
*/
|
||||||
static const message::uid makeGlobalUID(const unsigned int UIDValidity, const unsigned int messageUID);
|
static const message::uid makeGlobalUID(const vmime_uint32 UIDValidity, const vmime_uint32 messageUID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static const string buildFetchRequestImpl
|
static const string buildFetchRequestImpl
|
||||||
(const string& mode, const string& set, const int options);
|
(ref <IMAPConnection> cnt, const string& mode, const string& set, const int options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,6 +117,7 @@ public:
|
|||||||
void copyMessages(const folder::path& dest, const std::vector <int>& nums);
|
void copyMessages(const folder::path& dest, const std::vector <int>& nums);
|
||||||
|
|
||||||
void status(int& count, int& unseen);
|
void status(int& count, int& unseen);
|
||||||
|
ref <folderStatus> getStatus();
|
||||||
|
|
||||||
void expunge();
|
void expunge();
|
||||||
|
|
||||||
|
70
vmime/net/maildir/maildirFolderStatus.hpp
Normal file
70
vmime/net/maildir/maildirFolderStatus.hpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_NET_MAILDIR_MAILDIRFOLDERSTATUS_HPP_INCLUDED
|
||||||
|
#define VMIME_NET_MAILDIR_MAILDIRFOLDERSTATUS_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/net/folderStatus.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace maildir {
|
||||||
|
|
||||||
|
|
||||||
|
/** Holds the status of a Maildir folder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class VMIME_EXPORT maildirFolderStatus : public folderStatus
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Inherited from folderStatus
|
||||||
|
unsigned int getMessageCount() const;
|
||||||
|
unsigned int getUnseenCount() const;
|
||||||
|
|
||||||
|
void setMessageCount(const unsigned int count);
|
||||||
|
void setUnseenCount(const unsigned int unseen);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
unsigned int m_count;
|
||||||
|
unsigned int m_unseen;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // maildir
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
|
||||||
|
|
||||||
|
#endif // VMIME_NET_MAILDIR_MAILDIRFOLDERSTATUS_HPP_INCLUDED
|
@ -62,7 +62,7 @@ public:
|
|||||||
|
|
||||||
int getNumber() const;
|
int getNumber() const;
|
||||||
|
|
||||||
const uid getUniqueId() const;
|
const uid getUID() const;
|
||||||
|
|
||||||
int getSize() const;
|
int getSize() const;
|
||||||
|
|
||||||
|
@ -204,11 +204,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual int getNumber() const = 0;
|
virtual int getNumber() const = 0;
|
||||||
|
|
||||||
/** Return the unique identified of this message (must fetch before).
|
/** Return the unique identifier (UID) of this message in its
|
||||||
|
* folder (must fetch before).
|
||||||
*
|
*
|
||||||
* @return UID of the message
|
* @return UID of the message
|
||||||
*/
|
*/
|
||||||
virtual const uid getUniqueId() const = 0;
|
virtual const uid getUID() const = 0;
|
||||||
|
|
||||||
/** Return the size of the message (must fetch before).
|
/** Return the size of the message (must fetch before).
|
||||||
*
|
*
|
||||||
|
@ -114,6 +114,7 @@ public:
|
|||||||
void copyMessages(const folder::path& dest, const std::vector <int>& nums);
|
void copyMessages(const folder::path& dest, const std::vector <int>& nums);
|
||||||
|
|
||||||
void status(int& count, int& unseen);
|
void status(int& count, int& unseen);
|
||||||
|
ref <folderStatus> getStatus();
|
||||||
|
|
||||||
void expunge();
|
void expunge();
|
||||||
|
|
||||||
|
70
vmime/net/pop3/POP3FolderStatus.hpp
Normal file
70
vmime/net/pop3/POP3FolderStatus.hpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_NET_POP3_POP3FOLDERSTATUS_HPP_INCLUDED
|
||||||
|
#define VMIME_NET_POP3_POP3FOLDERSTATUS_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/net/folderStatus.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace pop3 {
|
||||||
|
|
||||||
|
|
||||||
|
/** Holds the status of a POP3 folder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class VMIME_EXPORT POP3FolderStatus : public folderStatus
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Inherited from folderStatus
|
||||||
|
unsigned int getMessageCount() const;
|
||||||
|
unsigned int getUnseenCount() const;
|
||||||
|
|
||||||
|
void setMessageCount(const unsigned int count);
|
||||||
|
void setUnseenCount(const unsigned int unseen);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
unsigned int m_count;
|
||||||
|
unsigned int m_unseen;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // pop3
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
|
||||||
|
|
||||||
|
#endif // VMIME_NET_POP3_POP3FOLDERSTATUS_HPP_INCLUDED
|
@ -62,7 +62,7 @@ public:
|
|||||||
|
|
||||||
int getNumber() const;
|
int getNumber() const;
|
||||||
|
|
||||||
const uid getUniqueId() const;
|
const uid getUID() const;
|
||||||
|
|
||||||
int getSize() const;
|
int getSize() const;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user