"Fossies" - the Fresh Open Source Software Archive

Member "citadel/modules/imap/imap_store.c" (5 Jun 2021, 6415 Bytes) of package /linux/www/citadel.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "imap_store.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 8.24_vs_9.01.

    1 /*
    2  * Implements the STORE command in IMAP.
    3  *
    4  * Copyright (c) 2001-2009 by the citadel.org team
    5  *
    6  * This program is open source software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License as published by
    8  * the Free Software Foundation; either version 3 of the License, or
    9  * (at your option) any later version.
   10  *
   11  * This program is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License
   17  * along with this program; if not, write to the Free Software
   18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19  */
   20 
   21 #include "ctdl_module.h"
   22 
   23 #include <stdlib.h>
   24 #include <unistd.h>
   25 #include <stdio.h>
   26 #include <fcntl.h>
   27 #include <signal.h>
   28 #include <pwd.h>
   29 #include <errno.h>
   30 #include <sys/types.h>
   31 #include <time.h>
   32 #include <sys/wait.h>
   33 #include <ctype.h>
   34 #include <string.h>
   35 #include <limits.h>
   36 #include <libcitadel.h>
   37 #include "citadel.h"
   38 #include "server.h"
   39 #include "sysdep_decls.h"
   40 #include "citserver.h"
   41 #include "support.h"
   42 #include "config.h"
   43 #include "user_ops.h"
   44 #include "database.h"
   45 #include "room_ops.h"
   46 #include "msgbase.h"
   47 #include "internet_addressing.h"
   48 #include "serv_imap.h"
   49 #include "imap_tools.h"
   50 #include "imap_fetch.h"
   51 #include "imap_store.h"
   52 #include "genstamp.h"
   53 
   54 
   55 /*
   56  * imap_do_store() calls imap_do_store_msg() to tweak the settings of
   57  * an individual message.
   58  *
   59  * We also implement the ".SILENT" protocol option here.  :(
   60  */
   61 void imap_do_store_msg(int seq, const char *oper, unsigned int bits_to_twiddle) {
   62     citimap *Imap = IMAP;
   63 
   64     if (!strncasecmp(oper, "FLAGS", 5)) {
   65         Imap->flags[seq] &= IMAP_MASK_SYSTEM;
   66         Imap->flags[seq] |= bits_to_twiddle;
   67     }
   68     else if (!strncasecmp(oper, "+FLAGS", 6)) {
   69         Imap->flags[seq] |= bits_to_twiddle;
   70     }
   71     else if (!strncasecmp(oper, "-FLAGS", 6)) {
   72         Imap->flags[seq] &= (~bits_to_twiddle);
   73     }
   74 }
   75 
   76 
   77 /*
   78  * imap_store() calls imap_do_store() to perform the actual bit twiddling
   79  * on the flags.
   80  */
   81 void imap_do_store(citimap_command *Cmd) {
   82     int i, j;
   83     unsigned int bits_to_twiddle = 0;
   84     const char *oper;
   85     char flag[32];
   86     char whichflags[256];
   87     char num_flags;
   88     int silent = 0;
   89     long *ss_msglist;
   90     int num_ss = 0;
   91     int last_item_twiddled = (-1);
   92     citimap *Imap = IMAP;
   93 
   94     if (Cmd->num_parms < 2) return;
   95     oper = Cmd->Params[0].Key;
   96     if (cbmstrcasestr(oper, ".SILENT")) {
   97         silent = 1;
   98     }
   99 
  100     /*
  101      * ss_msglist is an array of message numbers to manipulate.  We
  102      * are going to supply this array to CtdlSetSeen() later.
  103      */
  104     ss_msglist = malloc(Imap->num_msgs * sizeof(long));
  105     if (ss_msglist == NULL) return;
  106 
  107     /*
  108      * Ok, go ahead and parse the flags.
  109      */
  110     for (i=1; i<Cmd->num_parms; ++i) {///TODO: why strcpy? 
  111         strcpy(whichflags, Cmd->Params[i].Key);
  112         if (whichflags[0]=='(') {
  113             safestrncpy(whichflags, &whichflags[1], 
  114                 sizeof whichflags);
  115         }
  116         if (whichflags[strlen(whichflags)-1]==')') {
  117             whichflags[strlen(whichflags)-1]=0;
  118         }
  119         striplt(whichflags);
  120 
  121         /* A client might twiddle more than one bit at a time.
  122          * Note that we check for the flag names without the leading
  123          * backslash because imap_parameterize() strips them out.
  124          */
  125         num_flags = num_tokens(whichflags, ' ');
  126         for (j=0; j<num_flags; ++j) {
  127             extract_token(flag, whichflags, j, ' ', sizeof flag);
  128 
  129             if ((!strcasecmp(flag, "\\Deleted"))
  130                || (!strcasecmp(flag, "Deleted"))) {
  131                 if (CtdlDoIHavePermissionToDeleteMessagesFromThisRoom()) {
  132                     bits_to_twiddle |= IMAP_DELETED;
  133                 }
  134             }
  135             if ((!strcasecmp(flag, "\\Seen"))
  136                || (!strcasecmp(flag, "Seen"))) {
  137                 bits_to_twiddle |= IMAP_SEEN;
  138             }
  139             if ((!strcasecmp(flag, "\\Answered")) 
  140                || (!strcasecmp(flag, "Answered"))) {
  141                 bits_to_twiddle |= IMAP_ANSWERED;
  142             }
  143         }
  144     }
  145 
  146     if (Imap->num_msgs > 0) {
  147         for (i = 0; i < Imap->num_msgs; ++i) {
  148             if (Imap->flags[i] & IMAP_SELECTED) {
  149                 last_item_twiddled = i;
  150 
  151                 ss_msglist[num_ss++] = Imap->msgids[i];
  152                 imap_do_store_msg(i, oper, bits_to_twiddle);
  153 
  154                 if (!silent) {
  155                     IAPrintf("* %d FETCH (", i+1);
  156                     imap_fetch_flags(i);
  157                     IAPuts(")\r\n");
  158                 }
  159 
  160             }
  161         }
  162     }
  163 
  164     /*
  165      * Now manipulate the database -- all in one shot.
  166      */
  167     if ( (last_item_twiddled >= 0) && (num_ss > 0) ) {
  168 
  169         if (bits_to_twiddle & IMAP_SEEN) {
  170             CtdlSetSeen(ss_msglist, num_ss,
  171                 ((Imap->flags[last_item_twiddled] & IMAP_SEEN) ? 1 : 0),
  172                 ctdlsetseen_seen,
  173                 NULL, NULL
  174             );
  175         }
  176 
  177         if (bits_to_twiddle & IMAP_ANSWERED) {
  178             CtdlSetSeen(ss_msglist, num_ss,
  179                 ((Imap->flags[last_item_twiddled] & IMAP_ANSWERED) ? 1 : 0),
  180                 ctdlsetseen_answered,
  181                 NULL, NULL
  182             );
  183         }
  184 
  185     }
  186 
  187     free(ss_msglist);
  188     imap_do_expunge();      // Citadel always expunges immediately.
  189     imap_rescan_msgids();
  190 }
  191 
  192 
  193 /*
  194  * This function is called by the main command loop.
  195  */
  196 void imap_store(int num_parms, ConstStr *Params) {
  197     citimap_command Cmd;
  198     int num_items;
  199 
  200     if (num_parms < 3) {
  201         IReply("BAD invalid parameters");
  202         return;
  203     }
  204 
  205     if (imap_is_message_set(Params[2].Key)) {
  206         imap_pick_range(Params[2].Key, 0);
  207     }
  208     else {
  209         IReply("BAD invalid parameters");
  210         return;
  211     }
  212 
  213     memset(&Cmd, 0, sizeof(citimap_command));
  214     Cmd.CmdBuf = NewStrBufPlain(NULL, StrLength(IMAP->Cmd.CmdBuf));
  215     MakeStringOf(Cmd.CmdBuf, 3);
  216 
  217     num_items = imap_extract_data_items(&Cmd);
  218     if (num_items < 1) {
  219         IReply("BAD invalid data item list");
  220         FreeStrBuf(&Cmd.CmdBuf);
  221         free(Cmd.Params);
  222         return;
  223     }
  224 
  225     imap_do_store(&Cmd);
  226     IReply("OK STORE completed");
  227     FreeStrBuf(&Cmd.CmdBuf);
  228     free(Cmd.Params);
  229 }
  230 
  231 /*
  232  * This function is called by the main command loop.
  233  */
  234 void imap_uidstore(int num_parms, ConstStr *Params) {
  235     citimap_command Cmd;
  236     int num_items;
  237 
  238     if (num_parms < 4) {
  239         IReply("BAD invalid parameters");
  240         return;
  241     }
  242 
  243     if (imap_is_message_set(Params[3].Key)) {
  244         imap_pick_range(Params[3].Key, 1);
  245     }
  246     else {
  247         IReply("BAD invalid parameters");
  248         return;
  249     }
  250 
  251     memset(&Cmd, 0, sizeof(citimap_command));
  252     Cmd.CmdBuf = NewStrBufPlain(NULL, StrLength(IMAP->Cmd.CmdBuf));
  253     MakeStringOf(Cmd.CmdBuf, 4);
  254 
  255     num_items = imap_extract_data_items(&Cmd);
  256     if (num_items < 1) {
  257         IReply("BAD invalid data item list");
  258         FreeStrBuf(&Cmd.CmdBuf);
  259         free(Cmd.Params);
  260         return;
  261     }
  262 
  263     imap_do_store(&Cmd);
  264     IReply("OK UID STORE completed");
  265     FreeStrBuf(&Cmd.CmdBuf);
  266     free(Cmd.Params);
  267 }
  268 
  269