]> code.citadel.org Git - citadel.git/blob - citadel/imap_tools.c
* Implemented the IMAP CREATE command
[citadel.git] / citadel / imap_tools.c
1 /*
2  * $Id$
3  *
4  * Utility functions for the IMAP module.
5  *
6  */
7
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <stdio.h>
11 #include <ctype.h>
12 #include <string.h>
13 #include "citadel.h"
14 #include "sysdep_decls.h"
15 #include "tools.h"
16 #include "room_ops.h"
17 #include "internet_addressing.h"
18 #include "imap_tools.h"
19
20
21 /*
22  * Output a string to the IMAP client, either as a literal or quoted.
23  * (We do a literal if it has any double-quotes or backslashes.)
24  */
25 void imap_strout(char *buf) {
26         int i;
27         int is_literal = 0;
28
29         if (buf == NULL) {              /* yeah, we handle this */
30                 cprintf("NIL");
31                 return;
32         }
33
34         for (i=0; i<strlen(buf); ++i) {
35                 if ( (buf[i]=='\"') || (buf[i]=='\\') ) is_literal = 1;
36         }
37
38         if (is_literal) {
39                 cprintf("{%d}\r\n%s", strlen(buf), buf);
40         }
41
42         else {
43                 cprintf("\"%s\"", buf);
44         }
45 }
46
47         
48
49
50
51 /*
52  * Break a command down into tokens, taking into consideration the
53  * possibility of escaping spaces using quoted tokens
54  */
55 int imap_parameterize(char **args, char *buf) {
56         int num = 0;
57         int start = 0;
58         int i;
59         int in_quote = 0;
60         int original_len;
61
62         strcat(buf, " ");
63
64         original_len = strlen(buf);
65
66         for (i=0; i<original_len; ++i) {
67
68                 if ( (isspace(buf[i])) && (!in_quote) ) {
69                         buf[i] = 0;
70                         args[num] = &buf[start];
71                         start = i+1;
72                         if (args[num][0] == '\"') {
73                                 ++args[num];
74                                 args[num][strlen(args[num])-1] = 0;
75                         }
76                         ++num;
77                 }
78
79                 else if ( (buf[i] == '\"') && (!in_quote) ) {
80                         in_quote = 1;
81                 }
82
83                 else if ( (buf[i] == '\"') && (in_quote) ) {
84                         in_quote = 0;
85                 }
86
87         }
88
89         return(num);
90 }
91                         
92 /*
93  * Convert a struct quickroom to an IMAP-compatible mailbox name.
94  */
95 void imap_mailboxname(char *buf, int bufsize, struct quickroom *qrbuf) {
96         struct floor *fl;
97
98         /*
99          * For mailboxes, just do it straight...
100          */
101         if (qrbuf->QRflags & QR_MAILBOX) {
102                 safestrncpy(buf, qrbuf->QRname, bufsize);
103                 strcpy(buf, &buf[11]);
104                 if (!strcasecmp(buf, MAILROOM)) strcpy(buf, "INBOX");
105         }
106
107         /*
108          * Otherwise, prefix the floor name as a "public folders" moniker
109          */
110         else {
111                 fl = cgetfloor(qrbuf->QRfloor);
112                 snprintf(buf, bufsize, "%s|%s",
113                         fl->f_name,
114                         qrbuf->QRname);
115         }
116 }
117
118
119 /*
120  * Convert an inputted folder name to our best guess as to what an equivalent
121  * room name should be.
122  *
123  * If an error occurs, it returns -1.  Otherwise...
124  *
125  * The lower eight bits of the return value are the floor number on which the
126  * room most likely resides.   The upper eight bits may contain flags,
127  * including IR_MAILBOX if we're dealing with a personal room.
128  *
129  */
130 int imap_roomname(char *rbuf, int bufsize, char *foldername) {
131         int levels;
132         char buf[SIZ];
133         int i;
134         struct floor *fl;
135
136         if (foldername == NULL) return(-1);
137         levels = num_parms(foldername);
138
139         /* When we can support hierarchial mailboxes, take this out. */
140         if (levels > 2) return(-1);
141
142         /*
143          * Convert the crispy idiot's reserved names to our reserved names.
144          */
145         if (!strcasecmp(foldername, "INBOX")) {
146                 safestrncpy(rbuf, MAILROOM, bufsize);
147                 return(0 | IR_MAILBOX);
148         }
149
150         if (levels > 1) {
151                 extract(buf, foldername, 0);
152                 for (i=0; i<MAXFLOORS; ++i) {
153                         fl = cgetfloor(i);
154                         if (fl->f_flags & F_INUSE) {
155                                 if (!strcasecmp(buf, fl->f_name)) {
156                                         extract(rbuf, foldername, 1);
157                                         return(i);
158                                 }
159                         }
160                 }
161
162                 extract(rbuf, buf, 1);
163                 return(0);
164         }
165
166         safestrncpy(rbuf, foldername, bufsize);
167         return(0 | IR_MAILBOX);
168 }
169
170
171
172
173
174 /*
175  * Output a struct internet_address_list in the form an IMAP client wants
176  */
177 void imap_ial_out(struct internet_address_list *ialist) {
178         struct internet_address_list *iptr;
179
180         if (ialist == NULL) {
181                 cprintf("NIL");
182                 return;
183         }
184
185         cprintf("(");   
186
187         for (iptr = ialist; iptr != NULL; iptr = iptr->next) {
188                 cprintf("(");   
189                 imap_strout(iptr->ial_name);
190                 cprintf(" NIL ");
191                 imap_strout(iptr->ial_user);
192                 cprintf(" ");
193                 imap_strout(iptr->ial_node);
194                 cprintf(")");   
195         }
196
197         cprintf(")");
198 }