/** -------------------------------------------------------------------- * @file operator-store.cc * @brief Implementation of the STORE command * @author Andreas Aardal Hanssen * @date 2002-2005 * ------------------------------------------------------------------ **/ #include #include #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 newCustomFlags; vector::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::const_iterator it = newCustomFlags.begin(); it != newCustomFlags.end(); ++it) message.setCustomFlag(*it); break; case '-': flags &= ~newflags; for (vector::const_iterator it = newCustomFlags.begin(); it != newCustomFlags.end(); ++it) message.removeCustomFlag(*it); break; default: flags = newflags; message.resetCustomFlags(); for (vector::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; }