171b1f26cd2dcec8301beaa296315f8c52ca9fe8
[citadel.git] / citadel / imap_store.c
1 /*
2  * $Id$
3  *
4  * Implements the STORE command in IMAP.
5  *
6  */
7
8
9 #include "sysdep.h"
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <fcntl.h>
14 #include <signal.h>
15 #include <pwd.h>
16 #include <errno.h>
17 #include <sys/types.h>
18 #include <sys/time.h>
19 #include <sys/wait.h>
20 #include <ctype.h>
21 #include <string.h>
22 #include <limits.h>
23 #include "citadel.h"
24 #include "server.h"
25 #include <time.h>
26 #include "sysdep_decls.h"
27 #include "citserver.h"
28 #include "support.h"
29 #include "config.h"
30 #include "dynloader.h"
31 #include "room_ops.h"
32 #include "user_ops.h"
33 #include "policy.h"
34 #include "database.h"
35 #include "msgbase.h"
36 #include "tools.h"
37 #include "internet_addressing.h"
38 #include "serv_imap.h"
39 #include "imap_tools.h"
40 #include "imap_fetch.h"
41 #include "imap_store.h"
42 #include "genstamp.h"
43
44
45
46
47
48
49 /*
50  * imap_do_store() calls imap_do_store_msg() to output the deta of an
51  * individual message, once it has been successfully loaded from disk.
52  */
53 void imap_do_store_msg(int seq, char *oper, unsigned int bits_to_twiddle) {
54         
55         if (!strncasecmp(oper, "FLAGS", 5)) {
56                 IMAP->flags[seq] &= IMAP_MASK_SYSTEM;
57                 IMAP->flags[seq] |= bits_to_twiddle;
58         }
59         else if (!strncasecmp(oper, "+FLAGS", 6)) {
60                 IMAP->flags[seq] |= bits_to_twiddle;
61         }
62         else if (!strncasecmp(oper, "-FLAGS", 6)) {
63                 IMAP->flags[seq] &= (~bits_to_twiddle);
64         }
65
66         if (bits_to_twiddle & IMAP_SEEN) {
67                 CtdlSetSeen(IMAP->msgids[seq],
68                                 ((IMAP->flags[seq] & IMAP_SEEN) ? 1 : 0) );
69         }
70
71         cprintf("* %d FETCH (", seq+1);
72         imap_fetch_flags(seq);
73         cprintf(")\r\n");
74 }
75
76
77
78 /*
79  * imap_store() calls imap_do_store() to perform the actual bit twiddling
80  * on flags.  We brazenly ignore the ".silent" protocol option because it's not
81  * harmful to send the data anyway.  Fix it yourself if you don't like that.
82  */
83 void imap_do_store(int num_items, char **itemlist) {
84         int i;
85         unsigned int bits_to_twiddle = 0;
86         char *oper;
87         char flag[SIZ];
88
89         if (num_items < 2) return;
90         oper = itemlist[0];
91
92         for (i=1; i<num_items; ++i) {
93                 strcpy(flag, itemlist[i]);
94                 if (flag[0]=='(') strcpy(flag, &flag[1]);
95                 if (flag[strlen(flag)-1]==')') flag[strlen(flag)-1]=0;
96                 striplt(flag);
97
98                 if (!strcasecmp(flag, "\\Deleted")) {
99                   if (CtdlDoIHavePermissionToDeleteMessagesFromThisRoom()) {
100                         bits_to_twiddle |= IMAP_DELETED;
101                   }
102                 }
103
104                 if (!strcasecmp(flag, "\\Seen")) {
105                         bits_to_twiddle |= IMAP_SEEN;
106                 }
107         }
108         
109         if (IMAP->num_msgs > 0) {
110                 for (i = 0; i < IMAP->num_msgs; ++i) {
111                         if (IMAP->flags[i] && IMAP_SELECTED) {
112                                 imap_do_store_msg(i, oper, bits_to_twiddle);
113                         }
114                 }
115         }
116 }
117
118
119 /*
120  * This function is called by the main command loop.
121  */
122 void imap_store(int num_parms, char *parms[]) {
123         char items[1024];
124         char *itemlist[256];
125         int num_items;
126         int i;
127
128         if (num_parms < 3) {
129                 cprintf("%s BAD invalid parameters\r\n", parms[0]);
130                 return;
131         }
132
133         if (imap_is_message_set(parms[2])) {
134                 imap_pick_range(parms[2], 0);
135         }
136         else {
137                 cprintf("%s BAD invalid parameters\r\n", parms[0]);
138                 return;
139         }
140
141         strcpy(items, "");
142         for (i=3; i<num_parms; ++i) {
143                 strcat(items, parms[i]);
144                 if (i < (num_parms-1)) strcat(items, " ");
145         }
146
147         num_items = imap_extract_data_items(itemlist, items);
148         if (num_items < 1) {
149                 cprintf("%s BAD invalid data item list\r\n", parms[0]);
150                 return;
151         }
152
153         imap_do_store(num_items, itemlist);
154         cprintf("%s OK STORE completed\r\n", parms[0]);
155 }
156
157 /*
158  * This function is called by the main command loop.
159  */
160 void imap_uidstore(int num_parms, char *parms[]) {
161         char items[1024];
162         char *itemlist[256];
163         int num_items;
164         int i;
165
166         if (num_parms < 4) {
167                 cprintf("%s BAD invalid parameters\r\n", parms[0]);
168                 return;
169         }
170
171         if (imap_is_message_set(parms[3])) {
172                 imap_pick_range(parms[3], 1);
173         }
174         else {
175                 cprintf("%s BAD invalid parameters\r\n", parms[0]);
176                 return;
177         }
178
179         strcpy(items, "");
180         for (i=4; i<num_parms; ++i) {
181                 strcat(items, parms[i]);
182                 if (i < (num_parms-1)) strcat(items, " ");
183         }
184
185         num_items = imap_extract_data_items(itemlist, items);
186         if (num_items < 1) {
187                 cprintf("%s BAD invalid data item list\r\n", parms[0]);
188                 return;
189         }
190
191         imap_do_store(num_items, itemlist);
192         cprintf("%s OK UID STORE completed\r\n", parms[0]);
193 }
194
195