2 * Functions which implement RFC2086 (and maybe RFC4314) (IMAP ACL extension)
5 * Copyright (c) 2007-2011 by the citadel.org team
7 * This program is open source 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 "serv_imap.h"
59 #include "imap_tools.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 IReply("BAD not yet implemented FIXME");
77 * Implements the DELETEACL command.
79 void imap_deleteacl(int num_parms, ConstStr *Params) {
81 IReply("BAD not yet implemented FIXME");
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(StrBuf *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 */
101 StrBufAppendBufPlain(rights, HKEY("l"), 0);
102 StrBufAppendBufPlain(rights, HKEY("r"), 0);
103 StrBufAppendBufPlain(rights, HKEY("s"), 0);
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) {
113 StrBufAppendBufPlain(rights, HKEY("i"), 0);
114 StrBufAppendBufPlain(rights, HKEY("p"), 0);
115 StrBufAppendBufPlain(rights, HKEY("c"), 0);
118 /* d - delete messages (STORE DELETED flag, perform EXPUNGE) */
119 if (ra & UA_DELETEALLOWED) {
120 StrBufAppendBufPlain(rights, HKEY("d"), 0);
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 * StrBufAppendBufPlain(rights, HKEY("a"), 0);
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 IReply("BAD usage error");
159 * Search for the specified room or folder
161 ret = imap_grabroom(roomname, Params[2].Key, 1);
163 IReply("NO Invalid mailbox name or access denied");
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, NULL, NULL);
180 * Traverse the userlist
182 rights = NewStrBuf();
183 cdb_rewind(CDB_USERS);
184 while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL)
186 memset(&temp, 0, sizeof temp);
187 memcpy(&temp, cdbus->ptr, sizeof temp);
190 CtdlRoomAccess(&CC->room, &temp, &ra, NULL);
191 if (!IsEmptyStr(temp.fullname)) {
192 imap_acl_flags(rights, ra);
193 if (StrLength(rights) > 0) {
195 IPutStr(temp.fullname, strlen(temp.fullname));
197 iaputs(SKEY( rights));
205 * If another folder is selected, go back to that room so we can resume
206 * our happy day without violent explosions.
208 if (IMAP->selected) {
209 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
212 IReply("OK GETACL completed");
217 * Implements the LISTRIGHTS command.
219 void imap_listrights(int num_parms, ConstStr *Params) {
220 char roomname[ROOMNAMELEN];
221 char savedroom[ROOMNAMELEN];
225 struct ctdluser temp;
227 if (num_parms != 4) {
228 IReply("BAD usage error");
233 * Search for the specified room/folder
235 ret = imap_grabroom(roomname, Params[2].Key, 1);
237 IReply("NO Invalid mailbox name or access denied");
242 * Search for the specified user
245 valid = validate_recipients(Params[3].Key, NULL, 0);
247 if (valid->num_local == 1) {
248 ret = CtdlGetUser(&temp, valid->recp_local);
250 free_recipients(valid);
253 IReply("NO Invalid user name or access denied");
258 * CtdlUserGoto() formally takes us to the desired room. (If another
259 * folder is selected, save its name so we can return there!!!!!)
261 if (IMAP->selected) {
262 strcpy(savedroom, CC->room.QRname);
264 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
267 * Now output the list of rights
269 IAPuts("* LISTRIGHTS ");
274 IPutStr(HKEY("")); /* FIXME ... do something here */
278 * If another folder is selected, go back to that room so we can resume
279 * our happy day without violent explosions.
281 if (IMAP->selected) {
282 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
285 IReply("OK LISTRIGHTS completed");
291 * Implements the MYRIGHTS command.
293 void imap_myrights(int num_parms, ConstStr *Params) {
294 char roomname[ROOMNAMELEN];
295 char savedroom[ROOMNAMELEN];
301 if (num_parms != 3) {
302 IReply("BAD usage error");
306 ret = imap_grabroom(roomname, Params[2].Key, 1);
308 IReply("NO Invalid mailbox name or access denied");
313 * CtdlUserGoto() formally takes us to the desired room. (If another
314 * folder is selected, save its name so we can return there!!!!!)
316 if (IMAP->selected) {
317 strcpy(savedroom, CC->room.QRname);
319 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
321 CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
322 rights = NewStrBuf();
323 imap_acl_flags(rights, ra);
325 IAPuts("* MYRIGHTS ");
328 IPutStr(SKEY(rights));
334 * If a different folder was previously selected, return there now.
336 if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
337 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
340 IReply("OK MYRIGHTS completed");