4 * Functions which implement RFC2086 (and maybe RFC4314) (IMAP ACL extension)
7 * Copyright (c) 2007-2009 by the citadel.org team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include <sys/types.h>
34 #if TIME_WITH_SYS_TIME
35 # include <sys/time.h>
39 # include <sys/time.h>
49 #include <libcitadel.h>
52 #include "sysdep_decls.h"
53 #include "citserver.h"
60 #include "internet_addressing.h"
61 #include "imap_tools.h"
62 #include "serv_imap.h"
63 #include "imap_fetch.h"
64 #include "imap_misc.h"
66 #include "ctdl_module.h"
70 * Implements the SETACL command.
72 void imap_setacl(int num_parms, ConstStr *Params) {
74 cprintf("%s BAD not yet implemented FIXME\r\n", Params[0].Key);
80 * Implements the DELETEACL command.
82 void imap_deleteacl(int num_parms, ConstStr *Params) {
84 cprintf("%s BAD not yet implemented FIXME\r\n", Params[0].Key);
90 * Given the bits returned by CtdlRoomAccess(), populate a string buffer
91 * with IMAP ACL format flags. This code is common to GETACL and MYRIGHTS.
93 void imap_acl_flags(char *rights, int ra)
97 /* l - lookup (mailbox is visible to LIST/LSUB commands)
98 * r - read (SELECT the mailbox, perform STATUS et al)
99 * s - keep seen/unseen information across sessions (STORE SEEN flag)
101 if ( (ra & UA_KNOWN) /* known rooms */
102 || ((ra & UA_GOTOALLOWED) && (ra & UA_ZAPPED)) /* zapped rooms */
108 /* Only output the remaining flags if the room is known */
110 /* w - write (set or clear flags other than SEEN or DELETED, not supported in Citadel */
112 /* i - insert (perform APPEND, COPY into mailbox) */
113 /* p - post (send mail to submission address for mailbox - not enforced) */
114 /* c - create (CREATE new sub-mailboxes) */
115 if (ra & UA_POSTALLOWED) {
121 /* d - delete messages (STORE DELETED flag, perform EXPUNGE) */
122 if (ra & UA_DELETEALLOWED) {
126 /* a - administer (perform SETACL/DELETEACL/GETACL/LISTRIGHTS) */
127 if (ra & UA_ADMINALLOWED) {
129 * This is the correct place to put the "a" flag. We are leaving
130 * it commented out for now, because it implies that we could
131 * perform any of SETACL/DELETEACL/GETACL/LISTRIGHTS. Since these
132 * commands are not yet implemented, omitting the flag should
133 * theoretically prevent compliant clients from attempting to
136 * strcat(rights, "a");
144 * Implements the GETACL command.
146 void imap_getacl(int num_parms, ConstStr *Params) {
147 char roomname[ROOMNAMELEN];
148 char savedroom[ROOMNAMELEN];
151 struct ctdluser temp;
152 struct cdbdata *cdbus;
156 if (num_parms != 3) {
157 cprintf("%s BAD usage error\r\n", Params[0].Key);
162 * Search for the specified room or folder
164 ret = imap_grabroom(roomname, Params[2].Key, 1);
166 cprintf("%s NO Invalid mailbox name or access denied\r\n", Params[0].Key);
171 * CtdlUserGoto() formally takes us to the desired room. (If another
172 * folder is selected, save its name so we can return there!!!!!)
174 if (IMAP->selected) {
175 strcpy(savedroom, CC->room.QRname);
177 CtdlUserGoto(roomname, 0, 0, &msgs, &new);
181 imap_strout(&Params[2]);
184 * Traverse the userlist
186 cdb_rewind(CDB_USERS);
187 while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) {
188 memset(&temp, 0, sizeof temp);
189 memcpy(&temp, cdbus->ptr, sizeof temp);
192 CtdlRoomAccess(&CC->room, &temp, &ra, NULL);
193 if (!IsEmptyStr(temp.fullname)) {
194 imap_acl_flags(rights, ra);
195 if (!IsEmptyStr(rights)) {
197 plain_imap_strout(temp.fullname);
198 cprintf(" %s", rights);
206 * If another folder is selected, go back to that room so we can resume
207 * our happy day without violent explosions.
209 if (IMAP->selected) {
210 CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
213 cprintf("%s OK GETACL completed\r\n", Params[0].Key);
218 * Implements the LISTRIGHTS command.
220 void imap_listrights(int num_parms, ConstStr *Params) {
221 char roomname[ROOMNAMELEN];
222 char savedroom[ROOMNAMELEN];
225 struct recptypes *valid;
226 struct ctdluser temp;
228 if (num_parms != 4) {
229 cprintf("%s BAD usage error\r\n", Params[0].Key);
234 * Search for the specified room/folder
236 ret = imap_grabroom(roomname, Params[2].Key, 1);
238 cprintf("%s NO Invalid mailbox name or access denied\r\n", Params[0].Key);
243 * Search for the specified user
246 valid = validate_recipients(Params[3].Key, NULL, 0);
248 if (valid->num_local == 1) {
249 ret = CtdlGetUser(&temp, valid->recp_local);
251 free_recipients(valid);
254 cprintf("%s NO Invalid user name or access denied\r\n", Params[0].Key);
259 * CtdlUserGoto() formally takes us to the desired room. (If another
260 * folder is selected, save its name so we can return there!!!!!)
262 if (IMAP->selected) {
263 strcpy(savedroom, CC->room.QRname);
265 CtdlUserGoto(roomname, 0, 0, &msgs, &new);
268 * Now output the list of rights
270 cprintf("* LISTRIGHTS ");
271 imap_strout(&Params[2]);
273 imap_strout(&Params[3]);
275 plain_imap_strout(""); /* FIXME ... do something here */
279 * If another folder is selected, go back to that room so we can resume
280 * our happy day without violent explosions.
282 if (IMAP->selected) {
283 CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
286 cprintf("%s OK LISTRIGHTS completed\r\n", Params[0].Key);
292 * Implements the MYRIGHTS command.
294 void imap_myrights(int num_parms, ConstStr *Params) {
295 char roomname[ROOMNAMELEN];
296 char savedroom[ROOMNAMELEN];
302 if (num_parms != 3) {
303 cprintf("%s BAD usage error\r\n", Params[0].Key);
307 ret = imap_grabroom(roomname, Params[2].Key, 1);
309 cprintf("%s NO Invalid mailbox name or access denied\r\n", Params[0].Key);
314 * CtdlUserGoto() formally takes us to the desired room. (If another
315 * folder is selected, save its name so we can return there!!!!!)
317 if (IMAP->selected) {
318 strcpy(savedroom, CC->room.QRname);
320 CtdlUserGoto(roomname, 0, 0, &msgs, &new);
322 CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
323 imap_acl_flags(rights, ra);
325 cprintf("* MYRIGHTS ");
326 imap_strout(&Params[2]);
327 cprintf(" %s\r\n", rights);
330 * If a different folder was previously selected, return there now.
332 if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
333 CtdlUserGoto(savedroom, 0, 0, &msgs, &new);
336 cprintf("%s OK MYRIGHTS completed\r\n", Params[0].Key);