2 * Functions which implement RFC2086 (and maybe RFC4314) (IMAP ACL extension)
4 * Copyright (c) 2007-2017 by the citadel.org team
6 * This program is open source software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <sys/types.h>
31 #if TIME_WITH_SYS_TIME
32 # include <sys/time.h>
36 # include <sys/time.h>
46 #include <libcitadel.h>
49 #include "sysdep_decls.h"
50 #include "citserver.h"
56 #include "internet_addressing.h"
57 #include "serv_imap.h"
58 #include "imap_tools.h"
59 #include "imap_fetch.h"
60 #include "imap_misc.h"
62 #include "ctdl_module.h"
66 * Implements the SETACL command.
68 void imap_setacl(int num_parms, ConstStr *Params) {
70 IReply("BAD not yet implemented FIXME");
76 * Implements the DELETEACL command.
78 void imap_deleteacl(int num_parms, ConstStr *Params) {
80 IReply("BAD not yet implemented FIXME");
86 * Given the bits returned by CtdlRoomAccess(), populate a string buffer
87 * with IMAP ACL format flags. This code is common to GETACL and MYRIGHTS.
89 void imap_acl_flags(StrBuf *rights, int ra)
93 /* l - lookup (mailbox is visible to LIST/LSUB commands)
94 * r - read (SELECT the mailbox, perform STATUS et al)
95 * s - keep seen/unseen information across sessions (STORE SEEN flag)
97 if ( (ra & UA_KNOWN) /* known rooms */
98 || ((ra & UA_GOTOALLOWED) && (ra & UA_ZAPPED)) /* zapped rooms */
100 StrBufAppendBufPlain(rights, HKEY("l"), 0);
101 StrBufAppendBufPlain(rights, HKEY("r"), 0);
102 StrBufAppendBufPlain(rights, HKEY("s"), 0);
104 /* Only output the remaining flags if the room is known */
106 /* w - write (set or clear flags other than SEEN or DELETED, not supported in Citadel */
108 /* i - insert (perform APPEND, COPY into mailbox) */
109 /* p - post (send mail to submission address for mailbox - not enforced) */
110 /* c - create (CREATE new sub-mailboxes) */
111 if (ra & UA_POSTALLOWED) {
112 StrBufAppendBufPlain(rights, HKEY("i"), 0);
113 StrBufAppendBufPlain(rights, HKEY("p"), 0);
114 StrBufAppendBufPlain(rights, HKEY("c"), 0);
117 /* d - delete messages (STORE DELETED flag, perform EXPUNGE) */
118 if (ra & UA_DELETEALLOWED) {
119 StrBufAppendBufPlain(rights, HKEY("d"), 0);
122 /* a - administer (perform SETACL/DELETEACL/GETACL/LISTRIGHTS) */
123 if (ra & UA_ADMINALLOWED) {
125 * This is the correct place to put the "a" flag. We are leaving
126 * it commented out for now, because it implies that we could
127 * perform any of SETACL/DELETEACL/GETACL/LISTRIGHTS. Since these
128 * commands are not yet implemented, omitting the flag should
129 * theoretically prevent compliant clients from attempting to
132 * StrBufAppendBufPlain(rights, HKEY("a"), 0);
140 * Implements the GETACL command.
142 void imap_getacl(int num_parms, ConstStr *Params) {
143 char roomname[ROOMNAMELEN];
144 char savedroom[ROOMNAMELEN];
147 struct ctdluser temp;
148 struct cdbdata *cdbus;
152 if (num_parms != 3) {
153 IReply("BAD usage error");
158 * Search for the specified room or folder
160 ret = imap_grabroom(roomname, Params[2].Key, 1);
162 IReply("NO Invalid mailbox name or access denied");
167 * CtdlUserGoto() formally takes us to the desired room. (If another
168 * folder is selected, save its name so we can return there!!!!!)
170 if (IMAP->selected) {
171 strcpy(savedroom, CC->room.QRname);
173 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
179 * Traverse the userlist
181 rights = NewStrBuf();
182 cdb_rewind(CDB_USERS);
183 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 (StrLength(rights) > 0) {
194 IPutStr(temp.fullname, strlen(temp.fullname));
196 iaputs(SKEY( rights));
204 * If another folder is selected, go back to that room so we can resume
205 * our happy day without violent explosions.
207 if (IMAP->selected) {
208 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
211 IReply("OK GETACL completed");
216 * Implements the LISTRIGHTS command.
218 void imap_listrights(int num_parms, ConstStr *Params) {
219 char roomname[ROOMNAMELEN];
220 char savedroom[ROOMNAMELEN];
224 struct ctdluser temp;
226 if (num_parms != 4) {
227 IReply("BAD usage error");
232 * Search for the specified room/folder
234 ret = imap_grabroom(roomname, Params[2].Key, 1);
236 IReply("NO Invalid mailbox name or access denied");
241 * Search for the specified user
244 valid = validate_recipients(Params[3].Key, NULL, 0);
246 if (valid->num_local == 1) {
247 ret = CtdlGetUser(&temp, valid->recp_local);
249 free_recipients(valid);
252 IReply("NO Invalid user name or access denied");
257 * CtdlUserGoto() formally takes us to the desired room. (If another
258 * folder is selected, save its name so we can return there!!!!!)
260 if (IMAP->selected) {
261 strcpy(savedroom, CC->room.QRname);
263 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
266 * Now output the list of rights
268 IAPuts("* LISTRIGHTS ");
273 IPutStr(HKEY("")); /* FIXME ... do something here */
277 * If another folder is selected, go back to that room so we can resume
278 * our happy day without violent explosions.
280 if (IMAP->selected) {
281 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
284 IReply("OK LISTRIGHTS completed");
290 * Implements the MYRIGHTS command.
292 void imap_myrights(int num_parms, ConstStr *Params) {
293 char roomname[ROOMNAMELEN];
294 char savedroom[ROOMNAMELEN];
300 if (num_parms != 3) {
301 IReply("BAD usage error");
305 ret = imap_grabroom(roomname, Params[2].Key, 1);
307 IReply("NO Invalid mailbox name or access denied");
312 * CtdlUserGoto() formally takes us to the desired room. (If another
313 * folder is selected, save its name so we can return there!!!!!)
315 if (IMAP->selected) {
316 strcpy(savedroom, CC->room.QRname);
318 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
320 CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
321 rights = NewStrBuf();
322 imap_acl_flags(rights, ra);
324 IAPuts("* MYRIGHTS ");
327 IPutStr(SKEY(rights));
333 * If a different folder was previously selected, return there now.
335 if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
336 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
339 IReply("OK MYRIGHTS completed");