4 * Implements the STORE command in IMAP.
17 #include <sys/types.h>
19 #if TIME_WITH_SYS_TIME
20 # include <sys/time.h>
24 # include <sys/time.h>
36 #include "sysdep_decls.h"
37 #include "citserver.h"
40 #include "serv_extensions.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"
60 * imap_do_store() calls imap_do_store_msg() to tweak the settings of
61 * an individual message.
63 * We also implement the ".SILENT" protocol option here. Leave it to an
64 * idiot like Mark Crispin to make things unnecessarily complicated.
66 void imap_do_store_msg(int seq, char *oper, unsigned int bits_to_twiddle) {
69 if (!strncasecmp(oper, "FLAGS", 5)) {
70 IMAP->flags[seq] &= IMAP_MASK_SYSTEM;
71 IMAP->flags[seq] |= bits_to_twiddle;
72 silent = strncasecmp(&oper[5], ".SILENT", 7);
74 else if (!strncasecmp(oper, "+FLAGS", 6)) {
75 IMAP->flags[seq] |= bits_to_twiddle;
76 silent = strncasecmp(&oper[6], ".SILENT", 7);
78 else if (!strncasecmp(oper, "-FLAGS", 6)) {
79 IMAP->flags[seq] &= (~bits_to_twiddle);
80 silent = strncasecmp(&oper[6], ".SILENT", 7);
83 if (bits_to_twiddle & IMAP_SEEN) {
84 CtdlSetSeen(IMAP->msgids[seq],
85 ((IMAP->flags[seq] & IMAP_SEEN) ? 1 : 0),
89 if (bits_to_twiddle & IMAP_ANSWERED) {
90 CtdlSetSeen(IMAP->msgids[seq],
91 ((IMAP->flags[seq] & IMAP_ANSWERED) ? 1 : 0),
96 /* 'silent' is actually the value returned from a strncasecmp() so
97 * we want that option only if its value is zero. Seems backwards
98 * but that's the way it's supposed to be.
101 cprintf("* %d FETCH (", seq+1);
102 imap_fetch_flags(seq);
110 * imap_store() calls imap_do_store() to perform the actual bit twiddling
113 void imap_do_store(int num_items, char **itemlist) {
115 unsigned int bits_to_twiddle = 0;
118 char whichflags[SIZ];
121 if (num_items < 2) return;
124 for (i=1; i<num_items; ++i) {
125 strcpy(whichflags, itemlist[i]);
126 if (whichflags[0]=='(') strcpy(whichflags, &whichflags[1]);
127 if (whichflags[strlen(whichflags)-1]==')') {
128 whichflags[strlen(whichflags)-1]=0;
132 /* A client might twiddle more than one bit at a time */
133 num_flags = num_tokens(whichflags, ' ');
134 for (j=0; j<num_flags; ++j) {
135 extract_token(flag, whichflags, j, ' ');
137 if (!strcasecmp(flag, "\\Deleted")) {
138 if (CtdlDoIHavePermissionToDeleteMessagesFromThisRoom()) {
139 bits_to_twiddle |= IMAP_DELETED;
142 if (!strcasecmp(flag, "\\Seen")) {
143 bits_to_twiddle |= IMAP_SEEN;
145 if (!strcasecmp(flag, "\\Answered")) {
146 bits_to_twiddle |= IMAP_ANSWERED;
151 if (IMAP->num_msgs > 0) {
152 for (i = 0; i < IMAP->num_msgs; ++i) {
153 if (IMAP->flags[i] & IMAP_SELECTED) {
154 imap_do_store_msg(i, oper, bits_to_twiddle);
162 * This function is called by the main command loop.
164 void imap_store(int num_parms, char *parms[]) {
171 cprintf("%s BAD invalid parameters\r\n", parms[0]);
175 if (imap_is_message_set(parms[2])) {
176 imap_pick_range(parms[2], 0);
179 cprintf("%s BAD invalid parameters\r\n", parms[0]);
184 for (i=3; i<num_parms; ++i) {
185 strcat(items, parms[i]);
186 if (i < (num_parms-1)) strcat(items, " ");
189 num_items = imap_extract_data_items(itemlist, items);
191 cprintf("%s BAD invalid data item list\r\n", parms[0]);
195 imap_do_store(num_items, itemlist);
196 cprintf("%s OK STORE completed\r\n", parms[0]);
200 * This function is called by the main command loop.
202 void imap_uidstore(int num_parms, char *parms[]) {
209 cprintf("%s BAD invalid parameters\r\n", parms[0]);
213 if (imap_is_message_set(parms[3])) {
214 imap_pick_range(parms[3], 1);
217 cprintf("%s BAD invalid parameters\r\n", parms[0]);
222 for (i=4; i<num_parms; ++i) {
223 strcat(items, parms[i]);
224 if (i < (num_parms-1)) strcat(items, " ");
227 num_items = imap_extract_data_items(itemlist, items);
229 cprintf("%s BAD invalid data item list\r\n", parms[0]);
233 imap_do_store(num_items, itemlist);
234 cprintf("%s OK UID STORE completed\r\n", parms[0]);