operator-select.cc (5515B)
1 /* -*- Mode: c++; -*- */ 2 /* -------------------------------------------------------------------- 3 * Filename: 4 * operator-select.cc 5 * 6 * Description: 7 * Implementation of the SELECT command. 8 * 9 * Authors: 10 * Andreas Aardal Hanssen <andreas-binc curly bincimap spot org> 11 * 12 * Bugs: 13 * 14 * ChangeLog: 15 * 16 * -------------------------------------------------------------------- 17 * Copyright 2002-2005 Andreas Aardal Hanssen 18 * 19 * This program is free software; you can redistribute it and/or modify 20 * it under the terms of the GNU General Public License as published by 21 * the Free Software Foundation; either version 2 of the License, or 22 * (at your option) any later version. 23 * 24 * This program is distributed in the hope that it will be useful, 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * GNU General Public License for more details. 28 * 29 * You should have received a copy of the GNU General Public License 30 * along with this program; if not, write to the Free Software 31 * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. 32 * -------------------------------------------------------------------- 33 */ 34 #include <string> 35 36 #include "depot.h" 37 #include "io.h" 38 #include "mailbox.h" 39 #include "operators.h" 40 #include "recursivedescent.h" 41 #include "storage.h" 42 #include "pendingupdates.h" 43 #include "session.h" 44 #include "convert.h" 45 46 using namespace ::std; 47 using namespace Binc; 48 49 //---------------------------------------------------------------------- 50 SelectOperator::SelectOperator(void) 51 { 52 } 53 54 //---------------------------------------------------------------------- 55 SelectOperator::~SelectOperator(void) 56 { 57 } 58 59 //---------------------------------------------------------------------- 60 const string SelectOperator::getName(void) const 61 { 62 return "SELECT"; 63 } 64 65 //---------------------------------------------------------------------- 66 int SelectOperator::getState(void) const 67 { 68 return Session::NONAUTHENTICATED 69 | Session::AUTHENTICATED 70 | Session::SELECTED; 71 } 72 73 //------------------------------------------------------------------------ 74 Operator::ProcessResult SelectOperator::process(Depot &depot, 75 Request &command) 76 { 77 Session &session = Session::getInstance(); 78 IO &com = IOFactory::getInstance().get(1); 79 IO &logger = IOFactory::getInstance().get(2); 80 81 const bool examine = (command.getName() == "EXAMINE"); 82 83 const string &srcmailbox = command.getMailbox(); 84 const string &canonmailbox = toCanonMailbox(srcmailbox); 85 if (canonmailbox == "") { 86 session.setLastError("invalid mailbox"); 87 return NO; 88 } 89 90 Mailbox *mailbox = depot.getSelected(); 91 if (mailbox != 0) { 92 mailbox->closeMailbox(); 93 depot.resetSelected(); 94 mailbox = 0; 95 } 96 97 mailbox = depot.get(canonmailbox); 98 if (mailbox == 0) { 99 session.setLastError(depot.getLastError()); 100 return NO; 101 } 102 103 string mailboxFilename = depot.mailboxToFilename(canonmailbox); 104 if (mailboxFilename == "") { 105 session.setLastError("invalid mailbox"); 106 return NO; 107 } 108 109 mailbox->setReadOnly(examine); 110 111 if (!mailbox->selectMailbox(canonmailbox, mailboxFilename)) { 112 logger << "selecting mailbox failed" << endl; 113 session.setLastError(mailbox->getLastError()); 114 return NO; 115 } 116 117 // find first unseen 118 int unseen = -1; 119 Mailbox::iterator i 120 = mailbox->begin(SequenceSet::all(), Mailbox::SKIP_EXPUNGED | Mailbox::SQNR_MODE); 121 for (; i != mailbox->end(); ++i) { 122 Message &message = *i; 123 124 if (unseen == -1 && ((message.getStdFlags() & Message::F_SEEN) == 0)) { 125 unseen = i.getSqnr(); 126 break; 127 } 128 } 129 130 // show pending updates with only exists and recent response. do not 131 // re-scan. 132 pendingUpdates(mailbox, PendingUpdates::EXISTS 133 | PendingUpdates::RECENT, 134 false, true); 135 136 // unseen 137 if (unseen != -1) 138 com << "*" << " OK [UNSEEN " << unseen << "] Message " 139 << unseen << " is first unseen" << endl; 140 141 // uidvalidity 142 com << "*" << " OK [UIDVALIDITY " << mailbox->getUidValidity() << "]" 143 << endl; 144 145 // uidnext 146 com << "*" << " OK [UIDNEXT " << toString(mailbox->getUidNext()) << "] " 147 << toString(mailbox->getUidNext()) << " is the next UID" << endl; 148 149 // flags 150 com << "*" 151 << " FLAGS (\\Answered \\Flagged \\Deleted \\Recent \\Seen \\Draft)" 152 << endl; 153 154 // permanentflags 155 com << "*" 156 << " OK [PERMANENTFLAGS (\\Answered \\Flagged \\Deleted " 157 << "\\Seen \\Draft)] Limited" 158 << endl; 159 160 session.setState(Session::SELECTED); 161 depot.setSelected(mailbox); 162 163 logger.setLogPrefix(session.getUserID() + "@" + session.getIP() 164 + ":" + srcmailbox); 165 166 session.setResponseCode(examine ? "READ-ONLY" : "READ-WRITE"); 167 return OK; 168 } 169 170 //---------------------------------------------------------------------- 171 Operator::ParseResult SelectOperator::parse(Request &c_in) const 172 { 173 Session &session = Session::getInstance(); 174 175 if (c_in.getUidMode()) 176 return REJECT; 177 178 Operator::ParseResult res; 179 if ((res = expectSPACE()) != ACCEPT) { 180 session.setLastError("Expected SPACE after" + c_in.getName()); 181 return res; 182 } 183 184 string mailbox; 185 if ((res = expectMailbox(mailbox)) != ACCEPT) { 186 session.setLastError("Expected mailbox after " + c_in.getName() 187 + " SPACE"); 188 return res; 189 } 190 191 if ((res = expectCRLF()) != ACCEPT) { 192 session.setLastError("Expected CRLF after " + c_in.getName() 193 + " SPACE mailbox"); 194 return res; 195 } 196 197 c_in.setMailbox(mailbox); 198 return ACCEPT; 199 }