Implemented IMAP SEARCH
This commit is contained in:
parent
edcb4b4b1f
commit
1a0a22a311
@ -66,6 +66,14 @@ zone = "UT" / "GMT" ; Universal Time
|
||||
; hours+min. (HHMM)
|
||||
*/
|
||||
|
||||
static const char* dayNames[] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
|
||||
static const char* monthNames[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
void datetime::parseImpl(
|
||||
const parsingContext& /* ctx */,
|
||||
@ -590,14 +598,6 @@ void datetime::generateImpl(
|
||||
size_t* newLinePos
|
||||
) const {
|
||||
|
||||
static const char* dayNames[] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
static const char* monthNames[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
const int z = ((m_zone < 0) ? -m_zone : m_zone);
|
||||
const int zh = z / 60;
|
||||
const int zm = z % 60;
|
||||
@ -775,6 +775,14 @@ void datetime::getDate(int& year, int& month, int& day) const {
|
||||
}
|
||||
|
||||
|
||||
string datetime::getDate() const {
|
||||
|
||||
std::ostringstream date;
|
||||
date << m_day << "-" << monthNames[m_month - 1] << "-" << m_year;
|
||||
return date.str();
|
||||
}
|
||||
|
||||
|
||||
void datetime::setTime(
|
||||
const int hour,
|
||||
const int minute,
|
||||
|
@ -216,6 +216,8 @@ public:
|
||||
void getTime(int& hour, int& minute, int& second) const;
|
||||
void getDate(int& year, int& month, int& day) const;
|
||||
|
||||
string getDate() const;
|
||||
|
||||
// Set
|
||||
void setYear(const int year);
|
||||
void setMonth(const int month);
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "vmime/net/folderStatus.hpp"
|
||||
#include "vmime/net/fetchAttributes.hpp"
|
||||
#include "vmime/net/folderAttributes.hpp"
|
||||
#include "vmime/net/searchAttributes.hpp"
|
||||
|
||||
#include "vmime/utility/path.hpp"
|
||||
#include "vmime/utility/stream.hpp"
|
||||
@ -406,6 +407,36 @@ public:
|
||||
*/
|
||||
virtual std::vector <size_t> getMessageNumbersStartingOnUID(const message::uid& uid) = 0;
|
||||
|
||||
/** Return the sequence numbers of messages matching the searchAttributes.
|
||||
*
|
||||
* @param sa the searchAttributes containing search tokens to match messages to
|
||||
* @param charset optional charset name, the string tokens are assumed to be encoded
|
||||
* in the provided encoding OR need to be in US-ASCII if no charset is provided
|
||||
* @throw exceptions::net_exception if an error occurs
|
||||
*
|
||||
* Quirks: some servers will not accept any encoding other than US-ASCII,
|
||||
* other servers will accept UTF-8 but will fail utf-8
|
||||
*/
|
||||
virtual std::vector <size_t> getMessageNumbersMatchingSearchAttributes(
|
||||
const searchAttributes& sa,
|
||||
const vmime::charset* charset = nullptr
|
||||
) = 0;
|
||||
|
||||
/** Return the UIDs of messages matching the searchAttributes.
|
||||
*
|
||||
* @param sa the searchAttributes containing search tokens to match messages to
|
||||
* @param charset optional charset name, the string tokens are assumed to be encoded
|
||||
* in the provided encoding OR need to be in US-ASCII if no charset is provided
|
||||
* @throw exceptions::net_exception if an error occurs
|
||||
*
|
||||
* Quirks: some servers will not accept any encoding other than US-ASCII,
|
||||
* other servers will accept UTF-8 but will fail utf-8
|
||||
*/
|
||||
virtual std::vector <message::uid> getMessageUIDsMatchingSearchAttributes(
|
||||
const searchAttributes& sa,
|
||||
const vmime::charset* charset = nullptr
|
||||
) = 0;
|
||||
|
||||
// Event listeners
|
||||
void addMessageChangedListener(events::messageChangedListener* l);
|
||||
void removeMessageChangedListener(events::messageChangedListener* l);
|
||||
|
@ -354,6 +354,25 @@ shared_ptr <IMAPCommand> IMAPCommand::SEARCH(
|
||||
return createCommand(cmd.str());
|
||||
}
|
||||
|
||||
shared_ptr <IMAPCommand> IMAPCommand::UIDSEARCH(
|
||||
const std::vector <string>& keys,
|
||||
const vmime::charset* charset
|
||||
) {
|
||||
|
||||
std::ostringstream cmd;
|
||||
cmd.imbue(std::locale::classic());
|
||||
cmd << "UID SEARCH";
|
||||
|
||||
if (charset) {
|
||||
cmd << " CHARSET " << charset->getName();
|
||||
}
|
||||
|
||||
for (size_t i = 0, n = keys.size() ; i < n ; ++i) {
|
||||
cmd << " " << keys[i];
|
||||
}
|
||||
|
||||
return createCommand(cmd.str());
|
||||
}
|
||||
|
||||
// static
|
||||
shared_ptr <IMAPCommand> IMAPCommand::STARTTLS() {
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
static shared_ptr <IMAPCommand> APPEND(const string& mailboxName, const std::vector <string>& flags, vmime::datetime* date, const size_t size);
|
||||
static shared_ptr <IMAPCommand> COPY(const messageSet& msgs, const string& mailboxName);
|
||||
static shared_ptr <IMAPCommand> SEARCH(const std::vector <string>& keys, const vmime::charset* charset);
|
||||
static shared_ptr <IMAPCommand> UIDSEARCH(const std::vector <string>& keys, const vmime::charset* charset);
|
||||
static shared_ptr <IMAPCommand> STARTTLS();
|
||||
static shared_ptr <IMAPCommand> CAPABILITY();
|
||||
static shared_ptr <IMAPCommand> NOOP();
|
||||
|
@ -1501,6 +1501,99 @@ std::vector <size_t> IMAPFolder::getMessageNumbersStartingOnUID(const message::u
|
||||
return seqNumbers;
|
||||
}
|
||||
|
||||
std::vector <size_t> IMAPFolder::getMessageNumbersMatchingSearchAttributes(
|
||||
const searchAttributes& sa,
|
||||
const vmime::charset* charset
|
||||
) {
|
||||
|
||||
auto searchKeys = sa.generate();
|
||||
|
||||
IMAPCommand::SEARCH(searchKeys, charset)->send(m_connection);
|
||||
|
||||
// Get the response
|
||||
scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
|
||||
|
||||
if (resp->isBad() ||
|
||||
resp->response_done->response_tagged->resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
|
||||
|
||||
throw exceptions::command_error("SEARCH", resp->getErrorLog(), "bad response");
|
||||
}
|
||||
|
||||
auto& respDataList = resp->continue_req_or_response_data;
|
||||
|
||||
std::vector <size_t> seqNumbers;
|
||||
|
||||
for (auto it = respDataList.begin() ; it != respDataList.end() ; ++it) {
|
||||
|
||||
if (!(*it)->response_data) {
|
||||
throw exceptions::command_error("SEARCH", resp->getErrorLog(), "invalid response");
|
||||
}
|
||||
|
||||
auto *mailboxData = (*it)->response_data->mailbox_data.get();
|
||||
|
||||
// We are only interested in responses of type "SEARCH"
|
||||
if (!mailboxData ||
|
||||
mailboxData->type != IMAPParser::mailbox_data::SEARCH) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto &nzn : mailboxData->search_nz_number_list) {
|
||||
seqNumbers.push_back(nzn->value);
|
||||
}
|
||||
}
|
||||
|
||||
processStatusUpdate(resp.get());
|
||||
|
||||
return seqNumbers;
|
||||
}
|
||||
|
||||
std::vector <message::uid> IMAPFolder::getMessageUIDsMatchingSearchAttributes(
|
||||
const searchAttributes& sa,
|
||||
const vmime::charset* charset
|
||||
) {
|
||||
|
||||
auto searchKeys = sa.generate();
|
||||
|
||||
IMAPCommand::UIDSEARCH(searchKeys, charset)->send(m_connection);
|
||||
|
||||
// Get the response
|
||||
scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
|
||||
|
||||
if (resp->isBad() ||
|
||||
resp->response_done->response_tagged->resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
|
||||
|
||||
throw exceptions::command_error("UIDSEARCH", resp->getErrorLog(), "bad response");
|
||||
}
|
||||
|
||||
auto& respDataList = resp->continue_req_or_response_data;
|
||||
|
||||
std::vector <message::uid> uidNumbers;
|
||||
|
||||
for (auto it = respDataList.begin() ; it != respDataList.end() ; ++it) {
|
||||
|
||||
if (!(*it)->response_data) {
|
||||
throw exceptions::command_error("UIDSEARCH", resp->getErrorLog(), "invalid response");
|
||||
}
|
||||
|
||||
auto *mailboxData = (*it)->response_data->mailbox_data.get();
|
||||
|
||||
// We are only interested in responses of type "SEARCH"
|
||||
if (!mailboxData ||
|
||||
mailboxData->type != IMAPParser::mailbox_data::SEARCH) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto &nzn : mailboxData->search_nz_number_list) {
|
||||
uidNumbers.push_back(nzn->value);
|
||||
}
|
||||
}
|
||||
|
||||
processStatusUpdate(resp.get());
|
||||
|
||||
return uidNumbers;
|
||||
}
|
||||
|
||||
void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) {
|
||||
|
||||
|
@ -94,8 +94,18 @@ public:
|
||||
std::vector <shared_ptr <message> > getMessages(const messageSet& msgs);
|
||||
|
||||
std::vector <size_t> getMessageNumbersStartingOnUID(const message::uid& uid);
|
||||
|
||||
std::vector <size_t> getMessageNumbersMatchingSearchAttributes(
|
||||
const searchAttributes& sa,
|
||||
const vmime::charset* charset = nullptr
|
||||
) override;
|
||||
|
||||
size_t getMessageCount();
|
||||
std::vector <message::uid> getMessageUIDsMatchingSearchAttributes(
|
||||
const searchAttributes& sa,
|
||||
const vmime::charset* charset = nullptr
|
||||
) override;
|
||||
|
||||
size_t getMessageCount();
|
||||
|
||||
shared_ptr <folder> getFolder(const folder::path::component& name);
|
||||
std::vector <shared_ptr <folder> > getFolders(const bool recursive = false);
|
||||
|
@ -1355,6 +1355,21 @@ std::vector <size_t> maildirFolder::getMessageNumbersStartingOnUID(const message
|
||||
throw exceptions::operation_not_supported();
|
||||
}
|
||||
|
||||
std::vector <size_t> maildirFolder::getMessageNumbersMatchingSearchAttributes(
|
||||
const searchAttributes&,
|
||||
const vmime::charset*
|
||||
) {
|
||||
|
||||
throw exceptions::operation_not_supported();
|
||||
}
|
||||
|
||||
std::vector <message::uid> maildirFolder::getMessageUIDsMatchingSearchAttributes(
|
||||
const searchAttributes&,
|
||||
const vmime::charset*
|
||||
) {
|
||||
|
||||
throw exceptions::operation_not_supported();
|
||||
}
|
||||
|
||||
} // maildir
|
||||
} // net
|
||||
|
@ -147,6 +147,16 @@ public:
|
||||
|
||||
std::vector <size_t> getMessageNumbersStartingOnUID(const message::uid& uid);
|
||||
|
||||
std::vector <size_t> getMessageNumbersMatchingSearchAttributes(
|
||||
const searchAttributes& sa,
|
||||
const vmime::charset* charset = nullptr
|
||||
) override;
|
||||
|
||||
std::vector <message::uid> getMessageUIDsMatchingSearchAttributes(
|
||||
const searchAttributes& sa,
|
||||
const vmime::charset* charset = nullptr
|
||||
) override;
|
||||
|
||||
private:
|
||||
|
||||
void scanFolder();
|
||||
|
@ -812,6 +812,21 @@ std::vector <size_t> POP3Folder::getMessageNumbersStartingOnUID(const message::u
|
||||
throw exceptions::operation_not_supported();
|
||||
}
|
||||
|
||||
std::vector <size_t> POP3Folder::getMessageNumbersMatchingSearchAttributes(
|
||||
const searchAttributes&,
|
||||
const vmime::charset*
|
||||
) {
|
||||
|
||||
throw exceptions::operation_not_supported();
|
||||
}
|
||||
|
||||
std::vector <message::uid> POP3Folder::getMessageUIDsMatchingSearchAttributes(
|
||||
const searchAttributes&,
|
||||
const vmime::charset*
|
||||
) {
|
||||
|
||||
throw exceptions::operation_not_supported();
|
||||
}
|
||||
|
||||
} // pop3
|
||||
} // net
|
||||
|
@ -144,6 +144,16 @@ public:
|
||||
|
||||
std::vector <size_t> getMessageNumbersStartingOnUID(const message::uid& uid);
|
||||
|
||||
std::vector <size_t> getMessageNumbersMatchingSearchAttributes(
|
||||
const searchAttributes& sa,
|
||||
const vmime::charset* charset = nullptr
|
||||
) override;
|
||||
|
||||
std::vector <message::uid> getMessageUIDsMatchingSearchAttributes(
|
||||
const searchAttributes& sa,
|
||||
const vmime::charset* charset = nullptr
|
||||
) override;
|
||||
|
||||
private:
|
||||
|
||||
void registerMessage(POP3Message* msg);
|
||||
|
440
src/vmime/net/searchAttributes.cpp
Normal file
440
src/vmime/net/searchAttributes.cpp
Normal file
@ -0,0 +1,440 @@
|
||||
#include "vmime/net/searchAttributes.hpp"
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||
|
||||
namespace vmime {
|
||||
namespace net {
|
||||
|
||||
namespace helpers {
|
||||
|
||||
class keylessToken : public searchToken {
|
||||
|
||||
public:
|
||||
keylessToken(const char* token)
|
||||
: searchToken(token) {
|
||||
}
|
||||
|
||||
void generate(std::ostringstream& out) const {
|
||||
out << m_token;
|
||||
}
|
||||
};
|
||||
|
||||
template < class TYPE >
|
||||
class typedSearchToken : public searchToken {
|
||||
|
||||
public:
|
||||
typedSearchToken(const char* token, const TYPE& keyword)
|
||||
: searchToken(token)
|
||||
, m_keyword(keyword) {
|
||||
}
|
||||
|
||||
typedSearchToken(const char* token, const TYPE&& keyword)
|
||||
: searchToken(token)
|
||||
, m_keyword(std::move(keyword)) {
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
TYPE m_keyword;
|
||||
};
|
||||
|
||||
// Represents a string search token with the search string quoted
|
||||
class stringToken : public typedSearchToken< string > {
|
||||
|
||||
public:
|
||||
stringToken(const char* token, const string& keyword)
|
||||
: typedSearchToken(token, keyword) {
|
||||
}
|
||||
|
||||
void generate(std::ostringstream& out) const override {
|
||||
out << m_token << " \"" << m_keyword << "\"";
|
||||
};
|
||||
};
|
||||
|
||||
class headerToken : public typedSearchToken< const char* > {
|
||||
|
||||
public:
|
||||
headerToken(const char* token, const char* header)
|
||||
: typedSearchToken(token, header) {
|
||||
}
|
||||
|
||||
headerToken(const char* token, const char* header, const string& headerKeyword)
|
||||
: typedSearchToken(token, header)
|
||||
, m_headerKeyword(headerKeyword) {
|
||||
}
|
||||
|
||||
void generate(std::ostringstream& out) const override {
|
||||
out << m_token << " " << m_keyword << " \"" << m_headerKeyword << "\"";
|
||||
};
|
||||
|
||||
protected:
|
||||
string m_headerKeyword;
|
||||
};
|
||||
|
||||
class dateToken : public typedSearchToken< vmime::datetime > {
|
||||
|
||||
public:
|
||||
dateToken(const char* token, const vmime::datetime& date)
|
||||
: typedSearchToken(token, date) {
|
||||
}
|
||||
|
||||
// RFC claims that we need to disregard time information
|
||||
void generate(std::ostringstream& out) const override {
|
||||
out << m_token << " " << m_keyword.getDate();
|
||||
};
|
||||
};
|
||||
|
||||
class numberToken : public typedSearchToken< int > {
|
||||
|
||||
public:
|
||||
numberToken(const char* token, uint32_t keyword)
|
||||
: typedSearchToken(token, keyword) {
|
||||
}
|
||||
|
||||
void generate(std::ostringstream& out) const override {
|
||||
out << m_token << " " << m_keyword;
|
||||
};
|
||||
};
|
||||
|
||||
class flagToken : public typedSearchToken< vmime::net::message::Flags > {
|
||||
|
||||
public:
|
||||
flagToken(const char* token, vmime::net::message::Flags keyword)
|
||||
: typedSearchToken(token, keyword) {
|
||||
}
|
||||
|
||||
void generate(std::ostringstream& out) const override {
|
||||
out << m_token << " ";
|
||||
switch (m_keyword) {
|
||||
case vmime::net::message::Flags::FLAG_SEEN: out << "Seen"; break;
|
||||
case vmime::net::message::Flags::FLAG_REPLIED: out << "Answered"; break;
|
||||
case vmime::net::message::Flags::FLAG_MARKED: out << "Flagged"; break;
|
||||
case vmime::net::message::Flags::FLAG_DRAFT: out << "Draft"; break;
|
||||
case vmime::net::message::Flags::FLAG_DELETED: out << "Deleted"; break;
|
||||
default: throw exceptions::operation_not_supported();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class tokenMessageSetEnumerator : public messageSetEnumerator {
|
||||
|
||||
public:
|
||||
|
||||
tokenMessageSetEnumerator()
|
||||
: m_first(true) {
|
||||
|
||||
m_oss.imbue(std::locale::classic());
|
||||
}
|
||||
|
||||
void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) {
|
||||
|
||||
if (!m_first) {
|
||||
m_oss << ",";
|
||||
}
|
||||
|
||||
if (range.getFirst() == range.getLast()) {
|
||||
m_oss << range.getFirst();
|
||||
} else if (range.getLast() == size_t(-1)) {
|
||||
m_oss << range.getFirst() << ":*";
|
||||
} else {
|
||||
m_oss << range.getFirst() << ":" << range.getLast();
|
||||
}
|
||||
|
||||
m_first = false;
|
||||
}
|
||||
|
||||
void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range) {
|
||||
|
||||
if (!m_first) {
|
||||
m_oss << ",";
|
||||
}
|
||||
|
||||
if (range.getFirst() == range.getLast()) {
|
||||
m_oss << range.getFirst();
|
||||
} else if (range.getLast() == size_t(-1)) {
|
||||
m_oss << range.getFirst() << ":*";
|
||||
} else {
|
||||
m_oss << range.getFirst() << ":" << range.getLast();
|
||||
}
|
||||
|
||||
m_first = false;
|
||||
}
|
||||
|
||||
const std::string str() const {
|
||||
|
||||
return m_oss.str();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::ostringstream m_oss;
|
||||
bool m_first;
|
||||
};
|
||||
|
||||
|
||||
class messageSetToken : public typedSearchToken< vmime::net::messageSet > {
|
||||
|
||||
public:
|
||||
messageSetToken(const char *token, const vmime::net::messageSet& keyword)
|
||||
: typedSearchToken(token, keyword) {
|
||||
}
|
||||
|
||||
messageSetToken(const char *token, const vmime::net::messageSet&& keyword)
|
||||
: typedSearchToken(token, std::move(keyword)) {
|
||||
}
|
||||
|
||||
void generate(std::ostringstream& out) const override {
|
||||
if (*m_token) {
|
||||
out << m_token << " (";
|
||||
}
|
||||
else {
|
||||
out << "(";
|
||||
}
|
||||
tokenMessageSetEnumerator enu;
|
||||
m_keyword.enumerate(enu);
|
||||
out << enu.str();
|
||||
out << ")";
|
||||
}
|
||||
};
|
||||
|
||||
// Contains a list of tokens which the server will interpret as AND
|
||||
class tokenVectorToken : public typedSearchToken< std::vector< vmime::shared_ptr< const searchToken > > > {
|
||||
|
||||
public:
|
||||
tokenVectorToken(const char* token, const std::vector< vmime::shared_ptr< const searchToken > >& tokensAndKeywords)
|
||||
: typedSearchToken(token, tokensAndKeywords) {
|
||||
|
||||
if (0 == m_keyword.size()) {
|
||||
throw exceptions::invalid_argument();
|
||||
}
|
||||
}
|
||||
|
||||
tokenVectorToken(const char* token, const std::vector< vmime::shared_ptr< const searchToken > >&& tokensAndKeywords)
|
||||
: typedSearchToken(token, tokensAndKeywords) {
|
||||
|
||||
if (0 == m_keyword.size()) {
|
||||
throw exceptions::invalid_argument();
|
||||
}
|
||||
}
|
||||
|
||||
void generate(std::ostringstream& out) const override {
|
||||
out << m_token;
|
||||
if (*m_token)
|
||||
out << " (";
|
||||
else
|
||||
out << "(";
|
||||
|
||||
m_keyword[0]->generate(out);
|
||||
for (size_t i = 1; i < m_keyword.size(); i++) {
|
||||
out << " ";
|
||||
m_keyword[i]->generate(out);
|
||||
}
|
||||
|
||||
out << ")";
|
||||
};
|
||||
};
|
||||
|
||||
// A pair of tokens, used with OR
|
||||
class tokenPairToken : public typedSearchToken< std::pair< vmime::shared_ptr< const searchToken >, vmime::shared_ptr< const searchToken > > > {
|
||||
|
||||
public:
|
||||
tokenPairToken(const char* token, const std::pair< vmime::shared_ptr< const searchToken >, vmime::shared_ptr< const searchToken > >& pair)
|
||||
: typedSearchToken(token, pair) {
|
||||
}
|
||||
|
||||
void generate(std::ostringstream& out) const override {
|
||||
out << m_token << " ";
|
||||
m_keyword.first->generate(out);
|
||||
out << " ";
|
||||
m_keyword.second->generate(out);
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace helpers
|
||||
|
||||
searchTokenPtr searchTokenFactory::AND(const std::vector< searchTokenPtr >&&keywords) {
|
||||
return vmime::make_shared<helpers::tokenVectorToken>("", std::move(keywords));
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::ANSWERED() {
|
||||
return vmime::make_shared<helpers::keylessToken>("ANSWERED");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::BCC(const string& keyword) {
|
||||
return vmime::make_shared<helpers::stringToken>("BCC", keyword);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::BEFORE(const datetime& keyword) {
|
||||
return vmime::make_shared<helpers::dateToken>("BEFORE", keyword);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::BODY(const string& keyword) {
|
||||
return vmime::make_shared<helpers::stringToken>("BODY", keyword);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::CC(const string& keyword) {
|
||||
return vmime::make_shared<helpers::stringToken>("CC", keyword);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::DELETED() {
|
||||
return vmime::make_shared<helpers::keylessToken>("DELETED");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::DRAFT() {
|
||||
return vmime::make_shared<helpers::keylessToken>("DRAFT");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::FLAGGED() {
|
||||
return vmime::make_shared<helpers::keylessToken>("FLAGGED");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::FROM(const string& keyword) {
|
||||
return vmime::make_shared<helpers::stringToken>("FROM", keyword);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::HEADER(const char* fieldName) {
|
||||
return vmime::make_shared<helpers::headerToken>("HEADER", fieldName);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::HEADER(const char* fieldName, const string& fieldContents) {
|
||||
return vmime::make_shared<helpers::headerToken>("HEADER", fieldName, fieldContents);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::KEYWORD(vmime::net::message::Flags flag) {
|
||||
return vmime::make_shared<helpers::flagToken>("KEYWORD", flag);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::LARGER(uint32_t size) {
|
||||
return vmime::make_shared<helpers::numberToken>("LARGER", size);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::MESSAGESET(const vmime::net::messageSet& set) {
|
||||
return vmime::make_shared<helpers::messageSetToken>("", set);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::MESSAGESET(const vmime::net::messageSet&& set) {
|
||||
return vmime::make_shared<helpers::messageSetToken>("", std::move(set));
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::NEW() {
|
||||
return vmime::make_shared<helpers::keylessToken>("NEW");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::NOT(const searchTokenPtr& token) {
|
||||
return vmime::make_shared<helpers::tokenVectorToken>("NOT", std::vector< vmime::shared_ptr< const searchToken > >({token}));
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::OLD() {
|
||||
return vmime::make_shared<helpers::keylessToken>("OLD");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::ON(const datetime& date) {
|
||||
return vmime::make_shared<helpers::dateToken>("ON", date);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::OR(const searchTokenPtr& tokenA, const searchTokenPtr& tokenB) {
|
||||
return vmime::make_shared<helpers::tokenPairToken>("OR", std::make_pair(tokenA, tokenB));
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::RECENT() {
|
||||
return vmime::make_shared<helpers::keylessToken>("RECENT");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::SEEN() {
|
||||
return vmime::make_shared<helpers::keylessToken>("SEEN");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::SENTBEFORE(const datetime& date) {
|
||||
return vmime::make_shared<helpers::dateToken>("SENTBEFORE", date);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::SENTON(const datetime& date) {
|
||||
return vmime::make_shared<helpers::dateToken>("SENTON", date);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::SENTSINCE(const datetime& date) {
|
||||
return vmime::make_shared<helpers::dateToken>("SENTSINCE", date);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::SINCE(const datetime& date) {
|
||||
return vmime::make_shared<helpers::dateToken>("SINCE", date);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::SMALLER(uint32_t size) {
|
||||
return vmime::make_shared<helpers::numberToken>("SMALLER", size);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::SUBJECT(const string& keyword) {
|
||||
return vmime::make_shared<helpers::stringToken>("SUBJECT", keyword);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::TEXT(const string& keyword) {
|
||||
return vmime::make_shared<helpers::stringToken>("TEXT", keyword);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::TO(const string& keyword) {
|
||||
return vmime::make_shared<helpers::stringToken>("TO", keyword);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::UID(const vmime::net::messageSet& set) {
|
||||
return vmime::make_shared<helpers::messageSetToken>("UID", set);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::UID(const vmime::net::messageSet&& set) {
|
||||
return vmime::make_shared<helpers::messageSetToken>("UID", std::move(set));
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::UNANSWERED() {
|
||||
return vmime::make_shared<helpers::keylessToken>("UNANSWERED");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::UNDELETED() {
|
||||
return vmime::make_shared<helpers::keylessToken>("UNDELETED");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::UNDRAFT() {
|
||||
return vmime::make_shared<helpers::keylessToken>("UNDRAFT");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::UNFLAGGED() {
|
||||
return vmime::make_shared<helpers::keylessToken>("UNFLAGGED");
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::UNKEYWORD(vmime::net::message::Flags flag) {
|
||||
return vmime::make_shared<helpers::flagToken>("UNKEYWORD", flag);
|
||||
}
|
||||
|
||||
searchTokenPtr searchTokenFactory::UNSEEN() {
|
||||
return vmime::make_shared<helpers::keylessToken>("UNSEEN");
|
||||
}
|
||||
|
||||
searchAttributes::searchAttributes(std::vector< vmime::shared_ptr< const searchToken > >&& tokens)
|
||||
: m_andTokens(std::move(tokens)) {
|
||||
}
|
||||
|
||||
void searchAttributes::add(const vmime::shared_ptr< const searchToken >& token) {
|
||||
m_andTokens.push_back(token);
|
||||
}
|
||||
|
||||
std::vector< string > searchAttributes::generate() const {
|
||||
|
||||
std::vector< string > keys;
|
||||
|
||||
for (auto& token : m_andTokens) {
|
||||
std::ostringstream key;
|
||||
key.imbue(std::locale::classic());
|
||||
|
||||
token->generate(key);
|
||||
|
||||
keys.push_back(key.str());
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
|
||||
} // net
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES
|
139
src/vmime/net/searchAttributes.hpp
Normal file
139
src/vmime/net/searchAttributes.hpp
Normal file
@ -0,0 +1,139 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002 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_SEARCHATTRIBUTES_HPP_INCLUDED
|
||||
#define VMIME_NET_SEARCHATTRIBUTES_HPP_INCLUDED
|
||||
|
||||
|
||||
#include "vmime/config.hpp"
|
||||
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "vmime/types.hpp"
|
||||
#include "vmime/utility/stringUtils.hpp"
|
||||
#include "vmime/dateTime.hpp"
|
||||
#include "vmime/net/message.hpp"
|
||||
#include "vmime/net/messageSet.hpp"
|
||||
|
||||
namespace vmime {
|
||||
namespace net {
|
||||
|
||||
class searchToken : public object {
|
||||
|
||||
public:
|
||||
searchToken(const char* token)
|
||||
: m_token(token) {
|
||||
|
||||
if (nullptr == m_token) {
|
||||
throw exceptions::invalid_argument();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void generate(std::ostringstream& out) const = 0;
|
||||
|
||||
protected:
|
||||
const char* m_token;
|
||||
};
|
||||
|
||||
typedef vmime::shared_ptr< const searchToken> searchTokenPtr;
|
||||
|
||||
class searchTokenFactory : public object {
|
||||
|
||||
public:
|
||||
static searchTokenPtr AND(const std::vector< searchTokenPtr >&);
|
||||
static searchTokenPtr AND(const std::vector< searchTokenPtr >&&);
|
||||
static searchTokenPtr ANSWERED();
|
||||
static searchTokenPtr BCC(const string&);
|
||||
static searchTokenPtr BEFORE(const datetime&);
|
||||
static searchTokenPtr BODY(const string&);
|
||||
static searchTokenPtr CC(const string&);
|
||||
static searchTokenPtr DELETED();
|
||||
static searchTokenPtr DRAFT();
|
||||
static searchTokenPtr FLAGGED();
|
||||
static searchTokenPtr FROM(const string&);
|
||||
static searchTokenPtr HEADER(const char* fieldName);
|
||||
static searchTokenPtr HEADER(const char* filedName, const string& fieldContents);
|
||||
static searchTokenPtr KEYWORD(vmime::net::message::Flags);
|
||||
static searchTokenPtr LARGER(uint32_t);
|
||||
static searchTokenPtr MESSAGESET(const vmime::net::messageSet&);
|
||||
static searchTokenPtr MESSAGESET(const vmime::net::messageSet&&);
|
||||
static searchTokenPtr NEW();
|
||||
static searchTokenPtr NOT(const searchTokenPtr&);
|
||||
static searchTokenPtr OLD();
|
||||
static searchTokenPtr ON(const datetime&);
|
||||
static searchTokenPtr OR(const searchTokenPtr&, const searchTokenPtr&);
|
||||
static searchTokenPtr RECENT();
|
||||
static searchTokenPtr SEEN();
|
||||
static searchTokenPtr SENTBEFORE(const datetime&);
|
||||
static searchTokenPtr SENTON(const datetime&);
|
||||
static searchTokenPtr SENTSINCE(const datetime&);
|
||||
static searchTokenPtr SINCE(const datetime&);
|
||||
static searchTokenPtr SMALLER(uint32_t);
|
||||
static searchTokenPtr SUBJECT(const string&);
|
||||
static searchTokenPtr TEXT(const string&);
|
||||
static searchTokenPtr TO(const string&);
|
||||
static searchTokenPtr UID(const vmime::net::messageSet&);
|
||||
static searchTokenPtr UID(const vmime::net::messageSet&&);
|
||||
static searchTokenPtr UNANSWERED();
|
||||
static searchTokenPtr UNDELETED();
|
||||
static searchTokenPtr UNDRAFT();
|
||||
static searchTokenPtr UNFLAGGED();
|
||||
static searchTokenPtr UNKEYWORD(vmime::net::message::Flags);
|
||||
static searchTokenPtr UNSEEN();
|
||||
};
|
||||
|
||||
/** Holds a set of attributes to match messages against when searching folder contents.
|
||||
*/
|
||||
class VMIME_EXPORT searchAttributes : public object {
|
||||
|
||||
public:
|
||||
searchAttributes() = default;
|
||||
searchAttributes(std::vector< vmime::shared_ptr< const searchToken > >&&);
|
||||
|
||||
/** Adds a new search token that will be used to match messages against. Multiple tokens are
|
||||
* treated as an AND operation.
|
||||
*
|
||||
* @param token the search token to add
|
||||
*/
|
||||
void add(const vmime::shared_ptr< const searchToken >& token);
|
||||
|
||||
std::vector< string > generate() const;
|
||||
|
||||
protected:
|
||||
|
||||
std::vector< vmime::shared_ptr< const searchToken > > m_andTokens;
|
||||
};
|
||||
|
||||
|
||||
} // net
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES
|
||||
|
||||
|
||||
#endif // VMIME_NET_SEARCHATTRIBUTES_HPP_INCLUDED
|
Loading…
Reference in New Issue
Block a user