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>
35 #include <libcitadel.h>
38 #include "sysdep_decls.h"
39 #include "citserver.h"
45 #include "internet_addressing.h"
46 #include "serv_imap.h"
47 #include "imap_tools.h"
48 #include "imap_fetch.h"
49 #include "imap_misc.h"
51 #include "ctdl_module.h"
55 * Implements the SETACL command.
57 void imap_setacl(int num_parms, ConstStr *Params) {
59 IReply("BAD not yet implemented FIXME");
65 * Implements the DELETEACL command.
67 void imap_deleteacl(int num_parms, ConstStr *Params) {
69 IReply("BAD not yet implemented FIXME");
75 * Given the bits returned by CtdlRoomAccess(), populate a string buffer
76 * with IMAP ACL format flags. This code is common to GETACL and MYRIGHTS.
78 void imap_acl_flags(StrBuf *rights, int ra)
82 /* l - lookup (mailbox is visible to LIST/LSUB commands)
83 * r - read (SELECT the mailbox, perform STATUS et al)
84 * s - keep seen/unseen information across sessions (STORE SEEN flag)
86 if ( (ra & UA_KNOWN) /* known rooms */
87 || ((ra & UA_GOTOALLOWED) && (ra & UA_ZAPPED)) /* zapped rooms */
89 StrBufAppendBufPlain(rights, HKEY("l"), 0);
90 StrBufAppendBufPlain(rights, HKEY("r"), 0);
91 StrBufAppendBufPlain(rights, HKEY("s"), 0);
93 /* Only output the remaining flags if the room is known */
95 /* w - write (set or clear flags other than SEEN or DELETED, not supported in Citadel */
97 /* i - insert (perform APPEND, COPY into mailbox) */
98 /* p - post (send mail to submission address for mailbox - not enforced) */
99 /* c - create (CREATE new sub-mailboxes) */
100 if (ra & UA_POSTALLOWED) {
101 StrBufAppendBufPlain(rights, HKEY("i"), 0);
102 StrBufAppendBufPlain(rights, HKEY("p"), 0);
103 StrBufAppendBufPlain(rights, HKEY("c"), 0);
106 /* d - delete messages (STORE DELETED flag, perform EXPUNGE) */
107 if (ra & UA_DELETEALLOWED) {
108 StrBufAppendBufPlain(rights, HKEY("d"), 0);
111 /* a - administer (perform SETACL/DELETEACL/GETACL/LISTRIGHTS) */
112 if (ra & UA_ADMINALLOWED) {
114 * This is the correct place to put the "a" flag. We are leaving
115 * it commented out for now, because it implies that we could
116 * perform any of SETACL/DELETEACL/GETACL/LISTRIGHTS. Since these
117 * commands are not yet implemented, omitting the flag should
118 * theoretically prevent compliant clients from attempting to
121 * StrBufAppendBufPlain(rights, HKEY("a"), 0);
129 * Implements the GETACL command.
131 void imap_getacl(int num_parms, ConstStr *Params) {
132 char roomname[ROOMNAMELEN];
133 char savedroom[ROOMNAMELEN];
136 struct ctdluser temp;
137 struct cdbdata *cdbus;
141 if (num_parms != 3) {
142 IReply("BAD usage error");
147 * Search for the specified room or folder
149 ret = imap_grabroom(roomname, Params[2].Key, 1);
151 IReply("NO Invalid mailbox name or access denied");
156 * CtdlUserGoto() formally takes us to the desired room. (If another
157 * folder is selected, save its name so we can return there!!!!!)
159 if (IMAP->selected) {
160 strcpy(savedroom, CC->room.QRname);
162 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
168 * Traverse the userlist
170 rights = NewStrBuf();
171 cdb_rewind(CDB_USERS);
172 while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL)
174 memset(&temp, 0, sizeof temp);
175 memcpy(&temp, cdbus->ptr, sizeof temp);
178 CtdlRoomAccess(&CC->room, &temp, &ra, NULL);
179 if (!IsEmptyStr(temp.fullname)) {
180 imap_acl_flags(rights, ra);
181 if (StrLength(rights) > 0) {
183 IPutStr(temp.fullname, strlen(temp.fullname));
185 iaputs(SKEY( rights));
193 * If another folder is selected, go back to that room so we can resume
194 * our happy day without violent explosions.
196 if (IMAP->selected) {
197 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
200 IReply("OK GETACL completed");
205 * Implements the LISTRIGHTS command.
207 void imap_listrights(int num_parms, ConstStr *Params) {
208 char roomname[ROOMNAMELEN];
209 char savedroom[ROOMNAMELEN];
213 struct ctdluser temp;
215 if (num_parms != 4) {
216 IReply("BAD usage error");
221 * Search for the specified room/folder
223 ret = imap_grabroom(roomname, Params[2].Key, 1);
225 IReply("NO Invalid mailbox name or access denied");
230 * Search for the specified user
233 valid = validate_recipients(Params[3].Key, NULL, 0);
235 if (valid->num_local == 1) {
236 ret = CtdlGetUser(&temp, valid->recp_local);
238 free_recipients(valid);
241 IReply("NO Invalid user name or access denied");
246 * CtdlUserGoto() formally takes us to the desired room. (If another
247 * folder is selected, save its name so we can return there!!!!!)
249 if (IMAP->selected) {
250 strcpy(savedroom, CC->room.QRname);
252 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
255 * Now output the list of rights
257 IAPuts("* LISTRIGHTS ");
262 IPutStr(HKEY("")); /* FIXME ... do something here */
266 * If another folder is selected, go back to that room so we can resume
267 * our happy day without violent explosions.
269 if (IMAP->selected) {
270 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
273 IReply("OK LISTRIGHTS completed");
279 * Implements the MYRIGHTS command.
281 void imap_myrights(int num_parms, ConstStr *Params) {
282 char roomname[ROOMNAMELEN];
283 char savedroom[ROOMNAMELEN];
289 if (num_parms != 3) {
290 IReply("BAD usage error");
294 ret = imap_grabroom(roomname, Params[2].Key, 1);
296 IReply("NO Invalid mailbox name or access denied");
301 * CtdlUserGoto() formally takes us to the desired room. (If another
302 * folder is selected, save its name so we can return there!!!!!)
304 if (IMAP->selected) {
305 strcpy(savedroom, CC->room.QRname);
307 CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
309 CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
310 rights = NewStrBuf();
311 imap_acl_flags(rights, ra);
313 IAPuts("* MYRIGHTS ");
316 IPutStr(SKEY(rights));
322 * If a different folder was previously selected, return there now.
324 if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
325 CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
328 IReply("OK MYRIGHTS completed");