2 * Functions which implement RFC2086 (and maybe RFC4314) (IMAP ACL extension)
5 * Copyright (c) 2007-2009 by the citadel.org team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include <sys/types.h>
32 #if TIME_WITH_SYS_TIME
33 # include <sys/time.h>
37 # include <sys/time.h>
47 #include <libcitadel.h>
50 #include "sysdep_decls.h"
51 #include "citserver.h"
57 #include "internet_addressing.h"
58 #include "imap_tools.h"
59 #include "serv_imap.h"
60 #include "imap_fetch.h"
61 #include "imap_misc.h"
63 #include "ctdl_module.h"
67 * Implements the SETACL command.
69 void imap_setacl(int num_parms, ConstStr *Params) {
71 cprintf("%s BAD not yet implemented FIXME\r\n", Params[0].Key);
77 * Implements the DELETEACL command.
79 void imap_deleteacl(int num_parms, ConstStr *Params) {
81 cprintf("%s BAD not yet implemented FIXME\r\n", Params[0].Key);
87 * Given the bits returned by CtdlRoomAccess(), populate a string buffer
88 * with IMAP ACL format flags. This code is common to GETACL and MYRIGHTS.
90 void imap_acl_flags(char *rights, int ra)
94 /* l - lookup (mailbox is visible to LIST/LSUB commands)
95 * r - read (SELECT the mailbox, perform STATUS et al)
96 * s - keep seen/unseen information across sessions (STORE SEEN flag)
98 if ( (ra & UA_KNOWN) /* known rooms */
99 || ((ra & UA_GOTOALLOWED) && (ra & UA_ZAPPED)) /* zapped rooms */
105 /* Only output the remaining flags if the room is known */
107 /* w - write (set or clear flags other than SEEN or DELETED, not supported in Citadel */
109 /* i - insert (perform APPEND, COPY into mailbox) */
110 /* p - post (send mail to submission address for mailbox - not enforced) */
111 /* c - create (CREATE new sub-mailboxes) */
112 if (ra & UA_POSTALLOWED) {
118 /* d - delete messages (STORE DELETED flag, perform EXPUNGE) */
119 if (ra & UA_DELETEALLOWED) {
123 /* a - administer (perform SETACL/DELETEACL/GETACL/LISTRIGHTS) */
124 if (ra & UA_ADMINALLOWED) {
126 * This is the correct place to put the "a" flag. We are leaving
127 * it commented out for now, because it implies that we could
128 * perform any of SETACL/DELETEACL/GETACL/LISTRIGHTS. Since these
129 * commands are not yet implemented, omitting the flag should
130 * theoretically prevent compliant clients from attempting to
133 * strcat(rights, "a");
141 * Implements the GETACL command.
143 void imap_getacl(int num_parms, ConstStr *Params) {
144 char roomname[ROOMNAMELEN];
145 char savedroom[ROOMNAMELEN];
148 struct ctdluser temp;
149 struct cdbdata *cdbus;
153 if (num_parms != 3) {
154 cprintf("%s BAD usage error\r\n", Params[0].Key);
159 * Search for the specified room or folder
161 ret = imap_grabroom(roomname, Params[2].Key, 1);
163 cprintf("%s NO Invalid mailbox name or access denied\r\n", Params[0].Key);
168 * CtdlUserGoto() formally takes us to the desired room. (If another
169 * folder is selected, save its name so we can return there!!!!!)
171 if (IMAP->selected) {
172 strcpy(savedroom, CC->room.QRname);
174 CtdlUserGoto(roomname, 0, 0, &msgs, &new);
178 imap_strout(&Params[2]);
181 * Traverse the userlist
183 cdb_rewind(CDB_USERS);
184 while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) {
185 memset(&temp, 0, sizeof temp);
186 memcpy(&temp, cdbus->ptr, sizeof temp);
189 CtdlRoomAccess(&CC->room, &temp, &ra, NULL);
190 if (!IsEmptyStr(temp.fullname)) {
191 imap_acl_flags(rights, ra);
192 if (!IsEmptyStr(rights)) {
194 plain_imap_strout(temp.fullname);
195 cprintf(" %s", rights);
203 * If another folder is selected, go back to that room so we can resume
204 * our happy day without violent explosions.
206 if (IMAP->selected) {
207 CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
210 cprintf("%s OK GETACL completed\r\n", Params[0].Key);
215 * Implements the LISTRIGHTS command.
217 void imap_listrights(int num_parms, ConstStr *Params) {
218 char roomname[ROOMNAMELEN];
219 char savedroom[ROOMNAMELEN];
222 struct recptypes *valid;
223 struct ctdluser temp;
225 if (num_parms != 4) {
226 cprintf("%s BAD usage error\r\n", Params[0].Key);
231 * Search for the specified room/folder
233 ret = imap_grabroom(roomname, Params[2].Key, 1);
235 cprintf("%s NO Invalid mailbox name or access denied\r\n", Params[0].Key);
240 * Search for the specified user
243 valid = validate_recipients(Params[3].Key, NULL, 0);
245 if (valid->num_local == 1) {
246 ret = CtdlGetUser(&temp, valid->recp_local);
248 free_recipients(valid);
251 cprintf("%s NO Invalid user name or access denied\r\n", Params[0].Key);
256 * CtdlUserGoto() formally takes us to the desired room. (If another
257 * folder is selected, save its name so we can return there!!!!!)
259 if (IMAP->selected) {
260 strcpy(savedroom, CC->room.QRname);
262 CtdlUserGoto(roomname, 0, 0, &msgs, &new);
265 * Now output the list of rights
267 cprintf("* LISTRIGHTS ");
268 imap_strout(&Params[2]);
270 imap_strout(&Params[3]);
272 plain_imap_strout(""); /* FIXME ... do something here */
276 * If another folder is selected, go back to that room so we can resume
277 * our happy day without violent explosions.
279 if (IMAP->selected) {
280 CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
283 cprintf("%s OK LISTRIGHTS completed\r\n", Params[0].Key);
289 * Implements the MYRIGHTS command.
291 void imap_myrights(int num_parms, ConstStr *Params) {
292 char roomname[ROOMNAMELEN];
293 char savedroom[ROOMNAMELEN];
299 if (num_parms != 3) {
300 cprintf("%s BAD usage error\r\n", Params[0].Key);
304 ret = imap_grabroom(roomname, Params[2].Key, 1);
306 cprintf("%s NO Invalid mailbox name or access denied\r\n", Params[0].Key);
311 * CtdlUserGoto() formally takes us to the desired room. (If another
312 * folder is selected, save its name so we can return there!!!!!)
314 if (IMAP->selected) {
315 strcpy(savedroom, CC->room.QRname);
317 CtdlUserGoto(roomname, 0, 0, &msgs, &new);
319 CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
320 imap_acl_flags(rights, ra);
322 cprintf("* MYRIGHTS ");
323 imap_strout(&Params[2]);
324 cprintf(" %s\r\n", rights);
327 * If a different folder was previously selected, return there now.
329 if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
330 CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
333 cprintf("%s OK MYRIGHTS completed\r\n", Params[0].Key);