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