/** * @file operator-select.cc * @brief Implementation of the SELECT command. * @author Andreas Aardal Hanssen * @date 2002-2005 */ #include "convert.h" #include "depot.h" #include "iodevice.h" #include "iofactory.h" #include "mailbox.h" #include "operators.h" #include "pendingupdates.h" #include "recursivedescent.h" #include "session.h" #include using namespace Binc; using std::endl; using std::string; SelectOperator::SelectOperator() {} SelectOperator::~SelectOperator() {} const string SelectOperator::getName() const { return "SELECT"; } Session::State SelectOperator::getState() const { return Session::State(Session::NONAUTHENTICATED | Session::AUTHENTICATED | Session::SELECTED); } Operator::ProcessResult SelectOperator::process(Depot &depot, Request &command) { Session &session = Session::getInstance(); const bool examine = (command.getName() == "EXAMINE"); const string &srcmailbox = command.getMailbox(); const string &canonmailbox = toCanonMailbox(srcmailbox); Mailbox *mailbox = depot.getSelected(); if (mailbox != nullptr) { mailbox->closeMailbox(); depot.resetSelected(); mailbox = nullptr; } mailbox = depot.get(canonmailbox); if (mailbox == nullptr) { session.setLastError(depot.getLastError()); return ProcessResult::NO; } mailbox->setReadOnly(examine); if (!mailbox->selectMailbox(canonmailbox, depot.mailboxToFilename(canonmailbox))) { bincWarning << "selecting mailbox failed: " << mailbox->getLastError() << endl; session.setLastError(mailbox->getLastError()); return ProcessResult::NO; } // find first unseen int unseen = -1; Mailbox::iterator i = mailbox->begin(SequenceSet::all(), Mailbox::SKIP_EXPUNGED | Mailbox::SQNR_MODE); for (; i != mailbox->end(); ++i) { Message &message = *i; if (unseen == -1 && ((message.getStdFlags() & Message::F_SEEN) == 0)) { unseen = i.getSqnr(); break; } } // show pending updates with only exists and recent response. do not // re-scan. pendingUpdates(mailbox, PendingUpdates::EXISTS | PendingUpdates::RECENT, false, true); // unseen if (unseen != -1) { bincClient << "*" << " OK [UNSEEN " << unseen << "] Message " << unseen << " is first unseen" << endl; } // uidvalidity bincClient << "*" << " OK [UIDVALIDITY " << mailbox->getUidValidity() << "]" << endl; // uidnext bincClient << "*" << " OK [UIDNEXT " << std::to_string(mailbox->getUidNext()) << "] " << std::to_string(mailbox->getUidNext()) << " is the next UID" << endl; // flags bincClient << "*" << " FLAGS (\\Answered \\Flagged \\Deleted \\Recent \\Seen \\Draft \\*)" << endl; // permanentflags bincClient << "*" << " OK [PERMANENTFLAGS (\\Answered \\Flagged \\Deleted " << "\\Seen \\Draft \\*)] Limited" << endl; session.setState(Session::SELECTED); depot.setSelected(mailbox); session.setResponseCode(examine ? "READ-ONLY" : "READ-WRITE"); return ProcessResult::OK; } Parser::ParseResult SelectOperator::parse(Request &c_in, Parser &p) { constexpr auto ACCEPT = Parser::ParseResult::ACCEPT; Session &session = Session::getInstance(); if (c_in.getUidMode()) return Parser::ParseResult::REJECT; Parser::ParseResult res; if ((res = p.expectSPACE()) != ACCEPT) { session.setLastError("Expected SPACE after" + c_in.getName()); return res; } string mailbox; if ((res = p.expectMailbox(mailbox)) != ACCEPT) { session.setLastError("Expected mailbox after " + c_in.getName() + " SPACE"); return res; } if ((res = p.expectCRLF()) != ACCEPT) { session.setLastError("Expected CRLF after " + c_in.getName() + " SPACE mailbox"); return res; } c_in.setMailbox(mailbox); return ACCEPT; }