diff options
Diffstat (limited to 'src/operator-store.cc')
-rw-r--r-- | src/operator-store.cc | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/operator-store.cc b/src/operator-store.cc new file mode 100644 index 0000000..efb5a48 --- /dev/null +++ b/src/operator-store.cc @@ -0,0 +1,194 @@ +/** -------------------------------------------------------------------- + * @file operator-store.cc + * @brief Implementation of the STORE command + * @author Andreas Aardal Hanssen + * @date 2002-2005 + * ------------------------------------------------------------------ **/ +#include <string> +#include <iostream> + +#include "depot.h" +#include "imapparser.h" +#include "mailbox.h" +#include "operators.h" +#include "pendingupdates.h" +#include "recursivedescent.h" +#include "session.h" + +using namespace ::std; +using namespace Binc; + +//---------------------------------------------------------------------- +StoreOperator::StoreOperator(void) +{ +} + +//---------------------------------------------------------------------- +StoreOperator::~StoreOperator(void) +{ +} + +//---------------------------------------------------------------------- +const string StoreOperator::getName(void) const +{ + return "STORE"; +} + +//---------------------------------------------------------------------- +int StoreOperator::getState(void) const +{ + return Session::SELECTED; +} + +//------------------------------------------------------------------------ +Operator::ProcessResult StoreOperator::process(Depot &depot, + Request &command) +{ + Mailbox *mailbox = depot.getSelected(); + + // mask all passed flags together + unsigned int newflags = (unsigned int) Message::F_NONE; + vector<string> newCustomFlags; + vector<string>::const_iterator f_i = command.flags.begin(); + while (f_i != command.flags.end()) { + if (*f_i == "\\Deleted") newflags |= Message::F_DELETED; + else if (*f_i == "\\Answered") newflags |= Message::F_ANSWERED; + else if (*f_i == "\\Seen") newflags |= Message::F_SEEN; + else if (*f_i == "\\Draft") newflags |= Message::F_DRAFT; + else if (*f_i == "\\Flagged") newflags |= Message::F_FLAGGED; + else newCustomFlags.push_back(*f_i); + + ++f_i; + } + + // pass through all messages + unsigned int mode + = command.getUidMode() ? Mailbox::UID_MODE : Mailbox::SQNR_MODE; + + Mailbox::iterator i + = mailbox->begin(command.bset, Mailbox::SKIP_EXPUNGED | mode); + + for (; i != mailbox->end(); ++i) { + Message &message = *i; + + // get and reset the old flags + unsigned int flags = (unsigned int) message.getStdFlags(); + + bool recent = (flags & Message::F_RECENT) != 0; + flags &= (~Message::F_RECENT); + + // add, remove or set flags + switch (command.getMode()[0]) { + case '+': + flags |= newflags; + for (vector<string>::const_iterator it = newCustomFlags.begin(); + it != newCustomFlags.end(); ++it) + message.setCustomFlag(*it); + break; + case '-': + flags &= ~newflags; + for (vector<string>::const_iterator it = newCustomFlags.begin(); + it != newCustomFlags.end(); ++it) + message.removeCustomFlag(*it); + break; + default: + flags = newflags; + message.resetCustomFlags(); + for (vector<string>::const_iterator it = newCustomFlags.begin(); + it != newCustomFlags.end(); ++it) + message.setCustomFlag(*it); + break; + }; + + // set new flags, even if they weren't changed. + if (recent) flags |= Message::F_RECENT; + message.resetStdFlags(); + message.setStdFlag(flags); + } + + // commit flag changes to mailbox (might change mailbox) + mailbox->updateFlags(); + + // check mailbox for updates, and report them + if (command.getMode().find(".SILENT") != string::npos) + pendingUpdates(mailbox, PendingUpdates::EXISTS + | PendingUpdates::RECENT, false, false, false, + command.getUidMode()); + else + pendingUpdates(mailbox, PendingUpdates::EXISTS + | PendingUpdates::RECENT + | PendingUpdates::EXPUNGE + | PendingUpdates::FLAGS, false, false, false, + command.getUidMode()); + + return OK; +} + +//---------------------------------------------------------------------- +Operator::ParseResult StoreOperator::parse(Request & c_in) const +{ + Session &session = Session::getInstance(); + + Operator::ParseResult res; + if ((res = expectSPACE()) != ACCEPT) { + session.setLastError("Expected SPACE"); + return res; + } + + if ((res = expectSet(c_in.getSet())) != ACCEPT) { + session.setLastError("Expected Set"); + return res; + } + + if ((res = expectSPACE()) != ACCEPT) { + session.setLastError("Expected SPACE"); + return res; + } + + string mode; + if ((res = expectThisString("+")) == ACCEPT) + mode = "+"; + else if ((res = expectThisString("-")) == ACCEPT) + mode = "-"; + + if ((res = expectThisString("FLAGS")) != ACCEPT) { + session.setLastError("Expected FLAGS"); + return res; + } else + mode += "FLAGS"; + + if ((res = expectThisString(".SILENT")) == ACCEPT) mode += ".SILENT"; + + c_in.setMode(mode); + + if ((res = expectSPACE()) != ACCEPT) { + session.setLastError("Expected SPACE"); + return res; + } + + bool paren = false; + if ((res = expectThisString("(")) == ACCEPT) paren = true; + + if ((res = expectFlag(c_in.getFlags())) == ACCEPT) + while (1) { + if ((res = expectSPACE()) != ACCEPT) break; + + if ((res = expectFlag(c_in.getFlags())) != ACCEPT) { + session.setLastError("Expected flag after SPACE"); + return res; + } + } + + if (paren) + if ((res = expectThisString(")")) != ACCEPT) { + session.setLastError("Expected )"); + return res; + } + + if ((res = expectCRLF()) != ACCEPT) { + session.setLastError("Expected CRLF"); + return res; + } + + return ACCEPT; +} |