bincimap

Log | Files | Refs | LICENSE

operator-store.cc (5836B)


      1 /* -*- Mode: c++; -*- */
      2 /*  --------------------------------------------------------------------
      3  *  Filename:
      4  *    operator-store.cc
      5  *  
      6  *  Description:
      7  *    Implementation of the STORE 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 #ifdef HAVE_CONFIG_H
     35 #include <config.h>
     36 #endif
     37 
     38 #include <string>
     39 #include <iostream>
     40     
     41 #include "imapparser.h"
     42 #include "mailbox.h"
     43 #include "pendingupdates.h"
     44 #include "io.h"
     45 
     46 #include "recursivedescent.h"
     47 
     48 #include "session.h"
     49 #include "depot.h"
     50 #include "operators.h"
     51 
     52 using namespace ::std;
     53 using namespace Binc;
     54 
     55 //----------------------------------------------------------------------
     56 StoreOperator::StoreOperator(void)
     57 {
     58 }
     59 
     60 //----------------------------------------------------------------------
     61 StoreOperator::~StoreOperator(void)
     62 {
     63 }
     64 
     65 //----------------------------------------------------------------------
     66 const string StoreOperator::getName(void) const
     67 {
     68   return "STORE";
     69 }
     70 
     71 //----------------------------------------------------------------------
     72 int StoreOperator::getState(void) const
     73 {
     74   return Session::SELECTED;
     75 }
     76 
     77 //------------------------------------------------------------------------
     78 Operator::ProcessResult StoreOperator::process(Depot &depot,
     79 					       Request &command)
     80 {
     81   Mailbox *mailbox = depot.getSelected();
     82 
     83   // mask all passed flags together
     84   unsigned int newflags = (unsigned int) Message::F_NONE;
     85   vector<string>::const_iterator f_i = command.flags.begin();
     86   while (f_i != command.flags.end()) {
     87     if (*f_i == "\\Deleted") newflags |= Message::F_DELETED;
     88     if (*f_i == "\\Answered") newflags |= Message::F_ANSWERED;
     89     if (*f_i == "\\Seen") newflags |= Message::F_SEEN;
     90     if (*f_i == "\\Draft") newflags |= Message::F_DRAFT;
     91     if (*f_i == "\\Flagged") newflags |= Message::F_FLAGGED;
     92     ++f_i;
     93   }
     94 
     95   // pass through all messages
     96   unsigned int mode 
     97     = command.getUidMode() ? Mailbox::UID_MODE : Mailbox::SQNR_MODE;
     98 
     99   Mailbox::iterator i
    100     = mailbox->begin(command.bset, Mailbox::SKIP_EXPUNGED | mode);
    101 
    102   for (; i != mailbox->end(); ++i) {
    103     Message &message = *i;
    104 
    105     // get and reset the old flags
    106     unsigned int oldflags = (unsigned int) message.getStdFlags();
    107     unsigned int flags = oldflags;
    108     
    109     bool recent = (flags & Message::F_RECENT) != 0;
    110     flags &= (~Message::F_RECENT);
    111 
    112     // add, remove or set flags
    113     if (command.getMode()[0] == '+') flags |= newflags;
    114     else if (command.getMode()[0] == '-') flags &= ~newflags;
    115     else flags = newflags;
    116 
    117     // set new flags, even if they weren't changed.
    118     if (recent) flags |= Message::F_RECENT;
    119     message.resetStdFlags();
    120     message.setStdFlag(flags);
    121   }
    122 
    123   // commit flag changes to mailbox (might change mailbox)
    124   mailbox->updateFlags();
    125 
    126   // check mailbox for updates, and report them
    127   if (command.getMode().find(".SILENT") != string::npos)
    128     pendingUpdates(mailbox,
    129 		   PendingUpdates::EXISTS
    130 		   | PendingUpdates::RECENT, false, false, false,
    131 		   command.getUidMode());
    132   else
    133     pendingUpdates(mailbox,
    134 		   PendingUpdates::EXISTS 
    135 		   | PendingUpdates::RECENT
    136 		   | PendingUpdates::EXPUNGE
    137 		   | PendingUpdates::FLAGS, false, false, false,
    138 		   command.getUidMode());
    139 
    140   return OK;
    141 }
    142 
    143 //----------------------------------------------------------------------
    144 Operator::ParseResult StoreOperator::parse(Request & c_in) const
    145 {
    146   Session &session = Session::getInstance();
    147 
    148   Operator::ParseResult res;
    149   if ((res = expectSPACE()) != ACCEPT) {
    150     session.setLastError("Expected SPACE");
    151     return res;
    152   }
    153 
    154   if ((res = expectSet(c_in.getSet())) != ACCEPT) {
    155     session.setLastError("Expected Set");
    156     return res;
    157   }
    158 
    159   if ((res = expectSPACE()) != ACCEPT) {
    160     session.setLastError("Expected SPACE");
    161     return res;
    162   }
    163 
    164   string mode;
    165   if ((res = expectThisString("+")) == ACCEPT)
    166     mode = "+";
    167   else if ((res = expectThisString("-")) == ACCEPT)
    168     mode = "-";
    169 
    170   if ((res = expectThisString("FLAGS")) != ACCEPT) {
    171     session.setLastError("Expected FLAGS");
    172     return res;
    173   } else
    174     mode += "FLAGS";
    175 
    176   if ((res = expectThisString(".SILENT")) == ACCEPT)
    177     mode += ".SILENT";
    178 
    179   c_in.setMode(mode);
    180 
    181   if ((res = expectSPACE()) != ACCEPT) {
    182     session.setLastError("Expected SPACE");
    183     return res;
    184   }
    185 
    186   bool paren = false;
    187   if ((res = expectThisString("(")) == ACCEPT)
    188     paren = true;
    189      
    190   if ((res = expectFlag(c_in.getFlags())) == ACCEPT)
    191     while (1) {
    192       if ((res = expectSPACE()) != ACCEPT)
    193 	break;
    194 
    195       if ((res = expectFlag(c_in.getFlags())) != ACCEPT) {
    196 	session.setLastError("Expected flag after SPACE");
    197 	return res;
    198       }
    199     }
    200 
    201   if (paren)
    202     if ((res = expectThisString(")")) != ACCEPT) {
    203       session.setLastError("Expected )");
    204       return res;
    205     }
    206 
    207   if ((res = expectCRLF()) != ACCEPT) {
    208     session.setLastError("Expected CRLF");
    209     return res;
    210   }
    211 
    212   return ACCEPT;
    213 }