citadel
About: Citadel is an advanced messaging and collaboration system for groupware and BBS applications (preferred OS: Linux).
  Fossies Dox: citadel.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Loading...
Searching...
No Matches
imap_metadata.c
Go to the documentation of this file.
1/*
2 * IMAP METADATA extension
3 *
4 * This is an implementation of the Bynari variant of the METADATA extension.
5 *
6 * Copyright (c) 2007-2017 by the citadel.org team
7 *
8 * This program is open source software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23
24#include "../../sysdep.h"
25#include <stdlib.h>
26#include <unistd.h>
27#include <stdio.h>
28#include <fcntl.h>
29#include <signal.h>
30#include <pwd.h>
31#include <errno.h>
32#include <sys/types.h>
33#include <time.h>
34#include <sys/wait.h>
35#include <ctype.h>
36#include <string.h>
37#include <limits.h>
38#include <libcitadel.h>
39#include "../../citadel.h"
40#include "../../server.h"
41#include "../../sysdep_decls.h"
42#include "../../citserver.h"
43#include "../../support.h"
44#include "../../config.h"
45#include "../../user_ops.h"
46#include "../../database.h"
47#include "../../msgbase.h"
48#include "../../internet_addressing.h"
49#include "serv_imap.h"
50#include "imap_tools.h"
51#include "imap_fetch.h"
52#include "imap_misc.h"
53#include "../../genstamp.h"
54#include "../../ctdl_module.h"
55
56/*
57 * Implements the SETMETADATA command.
58 *
59 * Again, the only thing we're interested in setting here is the folder type.
60 *
61 * Attempting to set anything else calls a stub which fools the client into
62 * thinking that there is no remaining space available to store annotations.
63 */
64void imap_setmetadata(int num_parms, ConstStr *Params) {
65 char roomname[ROOMNAMELEN];
66 char savedroom[ROOMNAMELEN];
67 int msgs, new;
68 int ret;
69 int setting_user_value = 0;
70 char set_value[32];
71 int set_view = VIEW_BBS;
72 visit vbuf;
73
74 if (num_parms != 6) {
75 IReply("BAD usage error");
76 return;
77 }
78
79 /*
80 * Don't allow other types of metadata to be set
81 */
82 if (strcasecmp(Params[3].Key, "/vendor/kolab/folder-type")) {
83 IReply("NO [METADATA TOOMANY] SETMETADATA failed");
84 return;
85 }
86
87 if (!strcasecmp(Params[4].Key, "(value.shared")) {
88 setting_user_value = 0; /* global view */
89 }
90 else if (!strcasecmp(Params[4].Key, "(value.priv")) {
91 setting_user_value = 1; /* per-user view */
92 }
93 else {
94 IReply("NO [METADATA TOOMANY] SETMETADATA failed");
95 return;
96 }
97
98 /*
99 * Extract the folder type without any parentheses. Then learn
100 * the Citadel view type based on the supplied folder type.
101 */
102 extract_token(set_value, Params[5].Key, 0, ')', sizeof set_value);
103 if (!strncasecmp(set_value, "mail", 4)) {
104 set_view = VIEW_MAILBOX;
105 }
106 else if (!strncasecmp(set_value, "event", 5)) {
107 set_view = VIEW_CALENDAR;
108 }
109 else if (!strncasecmp(set_value, "contact", 7)) {
110 set_view = VIEW_ADDRESSBOOK;
111 }
112 else if (!strncasecmp(set_value, "journal", 7)) {
113 set_view = VIEW_JOURNAL;
114 }
115 else if (!strncasecmp(set_value, "note", 4)) {
116 set_view = VIEW_NOTES;
117 }
118 else if (!strncasecmp(set_value, "task", 4)) {
119 set_view = VIEW_TASKS;
120 }
121 else {
122 set_view = VIEW_MAILBOX;
123 }
124
125 ret = imap_grabroom(roomname, Params[2].Key, 1);
126 if (ret != 0) {
127 IReply("NO Invalid mailbox name or access denied");
128 return;
129 }
130
131 /*
132 * CtdlUserGoto() formally takes us to the desired room. (If another
133 * folder is selected, save its name so we can return there!!!!!)
134 */
135 if (IMAP->selected) {
136 strcpy(savedroom, CC->room.QRname);
137 }
138 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
139
140 /*
141 * Always set the per-user view to the requested one.
142 */
143 CtdlGetRelationship(&vbuf, &CC->user, &CC->room);
144 vbuf.v_view = set_view;
145 CtdlSetRelationship(&vbuf, &CC->user, &CC->room);
146
147 /* If this is a "value.priv" set operation, we're done. */
148
149 if (setting_user_value)
150 {
151 IReply("OK SETANNOTATION complete");
152 }
153
154 /* If this is a "value.shared" set operation, we are allowed to perform it
155 * under certain conditions.
156 */
157 else if ( (is_room_aide()) /* aide or room aide */
158 || ( (CC->room.QRflags & QR_MAILBOX)
159 && (CC->user.usernum == atol(CC->room.QRname)) /* mailbox owner */
160 )
161 || (msgs == 0) /* hack: if room is empty, assume we just created it */
162 ) {
163 CtdlGetRoomLock(&CC->room, CC->room.QRname);
164 CC->room.QRdefaultview = set_view;
165 CtdlPutRoomLock(&CC->room);
166 IReply("OK SETANNOTATION complete");
167 }
168
169 /* If we got to this point, we don't have permission to set the default view. */
170 else {
171 IReply("NO [METADATA TOOMANY] SETMETADATA failed");
172 }
173
174 /*
175 * If a different folder was previously selected, return there now.
176 */
177 if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
178 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
179 }
180 return;
181}
182
183
184/*
185 * Implements the GETMETADATA command.
186 *
187 * Regardless of what the client asked for, we are going to supply them with
188 * the folder type. It's the only metadata we have anyway.
189 */
190void imap_getmetadata(int num_parms, ConstStr *Params) {
191 char roomname[ROOMNAMELEN];
192 char savedroom[ROOMNAMELEN];
193 int msgs, new;
194 int ret;
195 int found = 0;
196
197/* this doesn't work if you have rooms/floors with spaces.
198 we need this for the bynari connector.
199 if (num_parms > 5) {
200 IReply("BAD usage error");
201 return;
202 }
203*/
204 ret = imap_grabroom(roomname, Params[2].Key, 1);
205 if (ret != 0) {
206 IReply("NO Invalid mailbox name or access denied");
207 return;
208 }
209
210 /*
211 * CtdlUserGoto() formally takes us to the desired room. (If another
212 * folder is selected, save its name so we can return there!!!!!)
213 */
214 if (IMAP->selected) {
215 strcpy(savedroom, CC->room.QRname);
216 }
217 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
218
219 IAPuts("* METADATA ");
220 IPutCParamStr(2);
221 IAPuts(" \"/vendor/kolab/folder-type\" (\"value.shared\" \"");
222
223 /* If it's one of our hard-coded default rooms, we know what to do... */
224
225 if (CC->room.QRname[10] == '.')
226 {
227 if (!strcasecmp(&CC->room.QRname[11], MAILROOM)) {
228 found = 1;
229 IAPuts("mail.inbox");
230 }
231 else if (!strcasecmp(&CC->room.QRname[11], SENTITEMS)) {
232 found = 1;
233 IAPuts("mail.sentitems");
234 }
235 else if (!strcasecmp(&CC->room.QRname[11], USERDRAFTROOM)) {
236 found = 1;
237 IAPuts("mail.drafts");
238 }
239 else if (!strcasecmp(&CC->room.QRname[11], USERCALENDARROOM)) {
240 found = 1;
241 IAPuts("event.default");
242 }
243 else if (!strcasecmp(&CC->room.QRname[11], USERCONTACTSROOM)) {
244 found = 1;
245 IAPuts("contact.default");
246 }
247 else if (!strcasecmp(&CC->room.QRname[11], USERNOTESROOM)) {
248 found = 1;
249 IAPuts("note.default");
250 }
251 else if (!strcasecmp(&CC->room.QRname[11], USERTASKSROOM)) {
252 found = 1;
253 IAPuts("task.default");
254 }
255 }
256
257 /* Otherwise, use the view for this room to determine the type of data.
258 * We are going with the default view rather than the user's view, because
259 * the default view almost always defines the actual contents, while the
260 * user's view might only make changes to presentation. It also saves us
261 * an extra database access because we don't need to load the visit record.
262 */
263 if (!found)
264 {
265 if (CC->room.QRdefaultview == VIEW_CALENDAR) {
266 IAPuts("event");
267 }
268 else if (CC->room.QRdefaultview == VIEW_ADDRESSBOOK) {
269 IAPuts("contact");
270 }
271 else if (CC->room.QRdefaultview == VIEW_TASKS) {
272 IAPuts("task");
273 }
274 else if (CC->room.QRdefaultview == VIEW_NOTES) {
275 IAPuts("note");
276 }
277 else if (CC->room.QRdefaultview == VIEW_JOURNAL) {
278 IAPuts("journal");
279 }
280 }
281 /* If none of the above conditions were met, consider it an ordinary mailbox. */
282
283 if (!found) {
284 IAPuts("mail");
285 }
286
287 /* "mail.outbox" and "junkemail" are not implemented. */
288
289 IAPuts("\")\r\n");
290
291 /*
292 * If a different folder was previously selected, return there now.
293 */
294 if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
295 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
296 }
297
298 IReply("OK GETMETADATA complete");
299 return;
300}
301
#define ROOMNAMELEN
Definition: citadel.h:51
#define CC
Definition: context.h:136
void CtdlGetRelationship(visit *vbuf, struct ctdluser *rel_user, struct ctdlroom *rel_room)
Definition: user_ops.c:277
int CtdlGetRoomLock(struct ctdlroom *qrbuf, const char *room_name)
Definition: room_ops.c:347
void CtdlSetRelationship(visit *newvisit, struct ctdluser *rel_user, struct ctdlroom *rel_room)
Definition: user_ops.c:265
void CtdlUserGoto(char *where, int display_result, int transiently, int *msgs, int *new, long *oldest, long *newest)
Definition: room_ops.c:618
void CtdlPutRoomLock(struct ctdlroom *qrbuf)
Definition: room_ops.c:395
void imap_getmetadata(int num_parms, ConstStr *Params)
void imap_setmetadata(int num_parms, ConstStr *Params)
Definition: imap_metadata.c:64
#define IAPuts(Msg)
Definition: imap_tools.h:39
#define IPutCParamStr(n)
Definition: imap_tools.h:53
#define IReply(msg)
Definition: imap_tools.h:45
#define QR_MAILBOX
Definition: ipcdef.h:53
int imap_grabroom(char *returned_roomname, const char *foldername, int zapped_ok)
Definition: serv_imap.c:1047
#define IMAP
Definition: serv_imap.h:104
visit vbuf
Definition: serv_migrate.c:503
int v_view
Definition: server.h:253
#define MAILROOM
Definition: sysconfig.h:61
#define USERDRAFTROOM
Definition: sysconfig.h:69
#define SENTITEMS
Definition: sysconfig.h:62
#define USERCONTACTSROOM
Definition: sysconfig.h:67
#define USERTASKSROOM
Definition: sysconfig.h:66
#define USERCALENDARROOM
Definition: sysconfig.h:65
#define USERNOTESROOM
Definition: sysconfig.h:68
int is_room_aide(void)
Definition: user_ops.c:382