Commit 927c27f8 927c27f8e4bc2c8ae5699addfbcd833d8fec6e08 by Sergey Poznyakoff

Fix input operations and RFC-compliance in imap4d.

* imap4d/util.c (util_getword, util_getitem, util_token)
(util_unquote): Remove.
(imap4d_readline): Rewrite to reduce memory reallocation.  Add
support for non-synchronizing literals (RFC 2088).
(imap4d_readline_ex): Remove.
(util_do_command): Rewrite using new imap4d_readline.
(util_parse_internal_date0): Remove.
(imap4d_tokbuf_init, imap4d_tokbuf_destroy, imap4d_tokbuf_argc)
(imap4d_tokbuf_getarg, util_isdelim)
(imap4d_tokbuf_from_string): New functions.
* imap4d/append.c, imap4d/auth_gss.c, imap4d/authenticate.c,
imap4d/check.c, imap4d/close.c, imap4d/commands.c, imap4d/copy.c,
imap4d/create.c, imap4d/delete.c, imap4d/examine.c,
imap4d/imap4d.h, imap4d/list.c, imap4d/login.c, imap4d/logout.c,
imap4d/lsub.c, imap4d/expunge.c, imap4d/idle.c, imap4d/noop.c,
imap4d/rename.c, imap4d/search.c, imap4d/select.c,
imap4d/starttls.c, imap4d/status.c, imap4d/store.c,
imap4d/subscribe.c, imap4d/uid.c, imap4d/unsubscribe.c,
imap4d/version.c: Rewrite using new imap4d_readline.
* imap4d/namespace.c: Use new imap4d_readline.  Ensure that
each reported prefix ends with a hierarchy delimiter.
* imap4d/imap4d.c (imap4d_mainloop): Use new imap4d_readline.
* imap4d/fetch.c: Rewrite parser from scratch.
* imap4d/capability.c (imap4d_capability_init): Report LITERAL+
capability.

* imap4d/testsuite/imap4d/anystate.exp: Account for the LITERAL+
capability.
* imap4d/testsuite/imap4d/append.exp: Fix APPEND arguments (imap4d
requires exactly three arguments, as per RFC3501.
Fix octet count in literals returned by fetch (previous versions
failed to include the trailing CRLF).
* imap4d/testsuite/imap4d/create.exp: Likewise.
* imap4d/testsuite/imap4d/fetch.exp: Fix FETCH arguments (previous
versions incorrectly accepted header-list without parentheses.
Fix result of FETCH 4 BODY[2.2.1]: it returns entire part, in the
contrast to previous versions, which treated it as
BODY[2.2.1.TEXT].

* maidag/mailtmp.c (mail_tmp_finish): Ensure /dev/null is treated
as mailbox.
1 parent 7317a04a
1 2008-08-11 Sergey Poznyakoff <gray@gnu.org.ua>
2
3 Fix input operations and RFC-compliance in imap4d.
4
5 * imap4d/util.c (util_getword, util_getitem, util_token)
6 (util_unquote): Remove.
7 (imap4d_readline): Rewrite to reduce memory reallocation. Add
8 support for non-synchronizing literals (RFC 2088).
9 (imap4d_readline_ex): Remove.
10 (util_do_command): Rewrite using new imap4d_readline.
11 (util_parse_internal_date0): Remove.
12 (imap4d_tokbuf_init, imap4d_tokbuf_destroy, imap4d_tokbuf_argc)
13 (imap4d_tokbuf_getarg, util_isdelim)
14 (imap4d_tokbuf_from_string): New functions.
15 * imap4d/append.c, imap4d/auth_gss.c, imap4d/authenticate.c,
16 imap4d/check.c, imap4d/close.c, imap4d/commands.c, imap4d/copy.c,
17 imap4d/create.c, imap4d/delete.c, imap4d/examine.c,
18 imap4d/imap4d.h, imap4d/list.c, imap4d/login.c, imap4d/logout.c,
19 imap4d/lsub.c, imap4d/expunge.c, imap4d/idle.c, imap4d/noop.c,
20 imap4d/rename.c, imap4d/search.c, imap4d/select.c,
21 imap4d/starttls.c, imap4d/status.c, imap4d/store.c,
22 imap4d/subscribe.c, imap4d/uid.c, imap4d/unsubscribe.c,
23 imap4d/version.c: Rewrite using new imap4d_readline.
24 * imap4d/namespace.c: Use new imap4d_readline. Ensure that
25 each reported prefix ends with a hierarchy delimiter.
26 * imap4d/imap4d.c (imap4d_mainloop): Use new imap4d_readline.
27 * imap4d/fetch.c: Rewrite parser from scratch.
28 * imap4d/capability.c (imap4d_capability_init): Report LITERAL+
29 capability.
30
31 * imap4d/testsuite/imap4d/anystate.exp: Account for the LITERAL+
32 capability.
33 * imap4d/testsuite/imap4d/append.exp: Fix APPEND arguments (imap4d
34 requires exactly three arguments, as per RFC3501.
35 Fix octet count in literals returned by fetch (previous versions
36 failed to include the trailing CRLF).
37 * imap4d/testsuite/imap4d/create.exp: Likewise.
38 * imap4d/testsuite/imap4d/fetch.exp: Fix FETCH arguments (previous
39 versions incorrectly accepted header-list without parentheses.
40 Fix result of FETCH 4 BODY[2.2.1]: it returns entire part, in the
41 contrast to previous versions, which treated it as
42 BODY[2.2.1.TEXT].
43
44 * maidag/mailtmp.c (mail_tmp_finish): Ensure /dev/null is treated
45 as mailbox.
46
1 2008-08-08 Sergey Poznyakoff <gray@gnu.org.ua> 47 2008-08-08 Sergey Poznyakoff <gray@gnu.org.ua>
2 48
3 Fix imap appends for AMD mailboxes. 49 Fix imap appends for AMD mailboxes.
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2005, 2006, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2005, 2006, 2007,
3 2008 Free Software Foundation, Inc.
3 4
4 GNU Mailutils is free software; you can redistribute it and/or modify 5 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
...@@ -18,49 +19,6 @@ ...@@ -18,49 +19,6 @@
18 19
19 #include "imap4d.h" 20 #include "imap4d.h"
20 21
21 /* APPEND mbox [(flags)] [date_time] message_literal */
22 int
23 imap4d_append (struct imap4d_command *command, char *arg)
24 {
25 char *sp;
26 char *mboxname;
27 int flags = 0;
28 mu_mailbox_t dest_mbox = NULL;
29 int status;
30
31 mboxname = util_getword (arg, &sp);
32 if (!mboxname)
33 return util_finish (command, RESP_BAD, "Too few arguments");
34
35 util_unquote (&mboxname);
36
37 if (*sp == '(' && util_parse_attributes (sp+1, &sp, &flags))
38 return util_finish (command, RESP_BAD, "Missing closing parenthesis");
39
40 mboxname = namespace_getfullpath (mboxname, "/");
41 if (!mboxname)
42 return util_finish (command, RESP_NO, "Couldn't open mailbox");
43
44 status = mu_mailbox_create_default (&dest_mbox, mboxname);
45 if (status == 0)
46 {
47 /* It SHOULD NOT automatifcllly create the mailbox. */
48 status = mu_mailbox_open (dest_mbox, MU_STREAM_RDWR);
49 if (status == 0)
50 {
51 status = imap4d_append0 (dest_mbox, flags, sp);
52 mu_mailbox_close (dest_mbox);
53 }
54 mu_mailbox_destroy (&dest_mbox);
55 }
56
57 free (mboxname);
58 if (status == 0)
59 return util_finish (command, RESP_OK, "Completed");
60
61 return util_finish (command, RESP_NO, "[TRYCREATE] failed");
62 }
63
64 static int 22 static int
65 _append_date (mu_envelope_t envelope, char *buf, size_t len, size_t *pnwrite) 23 _append_date (mu_envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
66 { 24 {
...@@ -93,12 +51,18 @@ _append_size (mu_message_t msg, size_t *psize) ...@@ -93,12 +51,18 @@ _append_size (mu_message_t msg, size_t *psize)
93 mu_stream_t str; 51 mu_stream_t str;
94 int status = mu_message_get_stream (msg, &str); 52 int status = mu_message_get_stream (msg, &str);
95 if (status == 0) 53 if (status == 0)
96 status = mu_stream_size (str, psize); 54 {
55 mu_off_t size;
56 status = mu_stream_size (str, &size);
57 if (status == 0 && psize)
58 *psize = size;
59 }
97 return status; 60 return status;
98 } 61 }
99 62
100 int 63 int
101 imap4d_append0 (mu_mailbox_t mbox, int flags, char *text) 64 imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text,
65 char **err_text)
102 { 66 {
103 mu_stream_t stream; 67 mu_stream_t stream;
104 int rc = 0; 68 int rc = 0;
...@@ -118,23 +82,25 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *text) ...@@ -118,23 +82,25 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *text)
118 return 1; 82 return 1;
119 } 83 }
120 84
121 while (*text && isspace (*text))
122 text++;
123
124 /* If a date_time is specified, the internal date SHOULD be set in the 85 /* If a date_time is specified, the internal date SHOULD be set in the
125 resulting message; otherwise, the internal date of the resulting 86 resulting message; otherwise, the internal date of the resulting
126 message is set to the current date and time by default. */ 87 message is set to the current date and time by default. */
127 if (util_parse_internal_date0 (text, &t, &text) == 0) 88 if (date_time)
128 { 89 {
129 while (*text && isspace(*text)) 90 if (util_parse_internal_date (date_time, &t))
130 text++; 91 {
92 *err_text = "Invalid date/time format";
93 return 1;
94 }
131 } 95 }
132 else 96 else
133 {
134 time(&t); 97 time(&t);
135 } 98
136 tm = gmtime(&t); 99 tm = gmtime(&t);
137 100
101 while (*text && isspace (*text))
102 text++;
103
138 mu_stream_write (stream, text, strlen (text), len, &len); 104 mu_stream_write (stream, text, strlen (text), len, &len);
139 mu_message_set_stream (msg, stream, &tm); 105 mu_message_set_stream (msg, stream, &tm);
140 mu_message_set_size (msg, _append_size, &tm); 106 mu_message_set_size (msg, _append_size, &tm);
...@@ -159,3 +125,86 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *text) ...@@ -159,3 +125,86 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *text)
159 } 125 }
160 126
161 127
128 /* APPEND mbox [(flags)] [date_time] message_literal */
129 int
130 imap4d_append (struct imap4d_command *command, imap4d_tokbuf_t tok)
131 {
132 int i;
133 char *mboxname;
134 int flags = 0;
135 mu_mailbox_t dest_mbox = NULL;
136 int status;
137 int argc = imap4d_tokbuf_argc (tok);
138 char *date_time;
139 char *msg_text;
140 char *err_text = "[TRYCREATE] failed";
141
142 if (argc < 4)
143 return util_finish (command, RESP_BAD, "Too few arguments");
144
145 mboxname = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
146 if (!mboxname)
147 return util_finish (command, RESP_BAD, "Too few arguments");
148
149 i = IMAP4_ARG_2;
150 if (imap4d_tokbuf_getarg (tok, i)[0] == '(')
151 {
152 while (++i < argc)
153 {
154 int type;
155 char *arg = imap4d_tokbuf_getarg (tok, i);
156
157 if (!util_attribute_to_type (arg, &type))
158 flags |= type;
159 else if (arg[0] == ')')
160 break;
161 }
162 if (i == argc)
163 return util_finish (command, RESP_BAD, "Missing closing parenthesis");
164 i++;
165 }
166
167 switch (argc - i)
168 {
169 case 2:
170 /* Date/time is present */
171 date_time = imap4d_tokbuf_getarg (tok, i);
172 i++;
173 break;
174
175 case 1:
176 date_time = NULL;
177 break;
178
179 default:
180 return util_finish (command, RESP_BAD, "Too many arguments");
181 }
182
183 msg_text = imap4d_tokbuf_getarg (tok, i);
184
185 mboxname = namespace_getfullpath (mboxname, "/");
186 if (!mboxname)
187 return util_finish (command, RESP_NO, "Couldn't open mailbox");
188
189 status = mu_mailbox_create_default (&dest_mbox, mboxname);
190 if (status == 0)
191 {
192 /* It SHOULD NOT automatically create the mailbox. */
193 status = mu_mailbox_open (dest_mbox, MU_STREAM_RDWR);
194 if (status == 0)
195 {
196 status = imap4d_append0 (dest_mbox, flags, date_time, msg_text,
197 &err_text);
198 mu_mailbox_close (dest_mbox);
199 }
200 mu_mailbox_destroy (&dest_mbox);
201 }
202
203 free (mboxname);
204 if (status == 0)
205 return util_finish (command, RESP_OK, "Completed");
206
207 return util_finish (command, RESP_NO, err_text);
208 }
209
210
......
...@@ -119,7 +119,9 @@ auth_gssapi (struct imap4d_command *command, ...@@ -119,7 +119,9 @@ auth_gssapi (struct imap4d_command *command,
119 gss_ctx_id_t context; 119 gss_ctx_id_t context;
120 gss_cred_id_t cred_handle, server_creds; 120 gss_cred_id_t cred_handle, server_creds;
121 gss_OID mech_type; 121 gss_OID mech_type;
122 char *token_str; 122 char *token_str = NULL;
123 size_t token_size = 0;
124 size_t token_len;
123 unsigned char *tmp = NULL; 125 unsigned char *tmp = NULL;
124 size_t size; 126 size_t size;
125 gss_name_t server_name; 127 gss_name_t server_name;
...@@ -168,11 +170,10 @@ auth_gssapi (struct imap4d_command *command, ...@@ -168,11 +170,10 @@ auth_gssapi (struct imap4d_command *command,
168 170
169 for (;;) 171 for (;;)
170 { 172 {
171 token_str = imap4d_readline_ex (); 173 imap4d_getline (&token_str, &token_size, &token_len);
172 util_base64_decode (token_str, strlen (token_str), &tmp, &size); 174 util_base64_decode (token_str, token_len, &tmp, &size);
173 tokbuf.value = tmp; 175 tokbuf.value = tmp;
174 tokbuf.length = size; 176 tokbuf.length = size;
175 free (token_str);
176 177
177 maj_stat = gss_accept_sec_context (&min_stat, 178 maj_stat = gss_accept_sec_context (&min_stat,
178 &context, 179 &context,
...@@ -202,6 +203,7 @@ auth_gssapi (struct imap4d_command *command, ...@@ -202,6 +203,7 @@ auth_gssapi (struct imap4d_command *command,
202 display_status ("accept context", maj_stat, min_stat); 203 display_status ("accept context", maj_stat, min_stat);
203 maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); 204 maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
204 gss_release_buffer (&min_stat, &outbuf); 205 gss_release_buffer (&min_stat, &outbuf);
206 free (token_str);
205 return RESP_NO; 207 return RESP_NO;
206 } 208 }
207 209
...@@ -211,8 +213,7 @@ auth_gssapi (struct imap4d_command *command, ...@@ -211,8 +213,7 @@ auth_gssapi (struct imap4d_command *command,
211 util_send ("+ %*.*s\r\n", size, size, tmp); 213 util_send ("+ %*.*s\r\n", size, size, tmp);
212 free (tmp); 214 free (tmp);
213 gss_release_buffer (&min_stat, &outbuf); 215 gss_release_buffer (&min_stat, &outbuf);
214 token_str = imap4d_readline_ex (); 216 imap4d_getline (&token_str, &token_size, &token_len);
215 free (token_str);
216 } 217 }
217 218
218 /* Construct security-level data */ 219 /* Construct security-level data */
...@@ -224,6 +225,7 @@ auth_gssapi (struct imap4d_command *command, ...@@ -224,6 +225,7 @@ auth_gssapi (struct imap4d_command *command,
224 if (maj_stat != GSS_S_COMPLETE) 225 if (maj_stat != GSS_S_COMPLETE)
225 { 226 {
226 display_status ("wrap", maj_stat, min_stat); 227 display_status ("wrap", maj_stat, min_stat);
228 free (token_str);
227 return RESP_NO; 229 return RESP_NO;
228 } 230 }
229 231
...@@ -231,8 +233,8 @@ auth_gssapi (struct imap4d_command *command, ...@@ -231,8 +233,8 @@ auth_gssapi (struct imap4d_command *command,
231 util_send ("+ %*.*s\r\n", size, size, tmp); 233 util_send ("+ %*.*s\r\n", size, size, tmp);
232 free (tmp); 234 free (tmp);
233 235
234 token_str = imap4d_readline_ex (); 236 imap4d_getline (&token_str, &token_size, &token_len);
235 util_base64_decode (token_str, strlen (token_str), 237 util_base64_decode (token_str, token_len,
236 (unsigned char **) &tokbuf.value, &tokbuf.length); 238 (unsigned char **) &tokbuf.value, &tokbuf.length);
237 free (token_str); 239 free (token_str);
238 240
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2005, 2006, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2005, 2006, 2007,
3 2008 Free Software Foundation, Inc.
3 4
4 GNU Mailutils is free software; you can redistribute it and/or modify 5 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
...@@ -93,24 +94,30 @@ imap4d_auth_capability () ...@@ -93,24 +94,30 @@ imap4d_auth_capability ()
93 mu_list_do (imap_auth_list, _auth_capa, NULL); 94 mu_list_do (imap_auth_list, _auth_capa, NULL);
94 } 95 }
95 96
97 /*
98 6.2.1. AUTHENTICATE Command
99
100 Arguments: authentication mechanism name
101 */
102
96 int 103 int
97 imap4d_authenticate (struct imap4d_command *command, char *arg) 104 imap4d_authenticate (struct imap4d_command *command, imap4d_tokbuf_t tok)
98 { 105 {
99 char *sp = NULL;
100 char *auth_type; 106 char *auth_type;
101 struct auth_data adata; 107 struct auth_data adata;
102 108
103 auth_type = util_getword (arg, &sp); 109 if (imap4d_tokbuf_argc (tok) != 3)
104 util_unquote (&auth_type); 110 return util_finish (command, RESP_BAD, "Invalid arguments");
105 if (!auth_type) 111
106 return util_finish (command, RESP_BAD, "Too few arguments"); 112 auth_type = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
107 113
108 if (tls_required) 114 if (tls_required)
109 return util_finish (command, RESP_NO, "Command disabled: Use STARTTLS first"); 115 return util_finish (command, RESP_NO,
116 "Command disabled: Use STARTTLS first");
110 117
111 adata.command = command; 118 adata.command = command;
112 adata.auth_type = auth_type; 119 adata.auth_type = auth_type;
113 adata.arg = sp; 120 adata.arg = NULL;
114 adata.username = NULL; 121 adata.username = NULL;
115 122
116 if (mu_list_do (imap_auth_list, _auth_try, &adata) == 0) 123 if (mu_list_do (imap_auth_list, _auth_try, &adata) == 0)
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2003, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2003, 2005, 2007,
3 2008 Free Software Foundation, Inc.
3 4
4 GNU Mailutils is free software; you can redistribute it and/or modify 5 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
...@@ -50,6 +51,7 @@ imap4d_capability_init () ...@@ -50,6 +51,7 @@ imap4d_capability_init ()
50 "IMAP4rev1", 51 "IMAP4rev1",
51 "NAMESPACE", 52 "NAMESPACE",
52 "IDLE", 53 "IDLE",
54 "LITERAL+",
53 "X-VERSION", 55 "X-VERSION",
54 NULL 56 NULL
55 }; 57 };
...@@ -67,8 +69,11 @@ print_capa (void *item, void *data) ...@@ -67,8 +69,11 @@ print_capa (void *item, void *data)
67 } 69 }
68 70
69 int 71 int
70 imap4d_capability (struct imap4d_command *command, char *arg MU_ARG_UNUSED) 72 imap4d_capability (struct imap4d_command *command, imap4d_tokbuf_t tok)
71 { 73 {
74 if (imap4d_tokbuf_argc (tok) != 2)
75 return util_finish (command, RESP_BAD, "Invalid arguments");
76
72 util_send ("* CAPABILITY"); 77 util_send ("* CAPABILITY");
73 78
74 mu_list_do (capa_list, print_capa, NULL); 79 mu_list_do (capa_list, print_capa, NULL);
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -19,13 +19,20 @@ ...@@ -19,13 +19,20 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 /* 21 /*
22 * Do we need to do anything here? 22 6.4.1. CHECK Command
23 * FIXME: This is like noop we need to notify the client of 23
24 * new mails etc ... and do housekeeping. 24 Arguments: none
25 */ 25
26 Responses: no specific responses for this command
27
28 Result: OK - check completed
29 BAD - command unknown or arguments invalid
30 */
26 31
27 int 32 int
28 imap4d_check (struct imap4d_command *command, char *arg MU_ARG_UNUSED) 33 imap4d_check (struct imap4d_command *command, imap4d_tokbuf_t tok)
29 { 34 {
35 if (imap4d_tokbuf_argc (tok) != 2)
36 return util_finish (command, RESP_BAD, "Invalid arguments");
30 return util_finish (command, RESP_OK, "Completed"); 37 return util_finish (command, RESP_OK, "Completed");
31 } 38 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2004, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2004, 2005, 2007,
3 2008 Free Software Foundation, Inc.
3 4
4 GNU Mailutils is free software; you can redistribute it and/or modify 5 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
...@@ -19,17 +20,28 @@ ...@@ -19,17 +20,28 @@
19 #include "imap4d.h" 20 #include "imap4d.h"
20 21
21 /* 22 /*
22 */ 23 6.4.2. CLOSE Command
23 24
24 /* The CLOSE command permanently removes from the currently selected 25 Arguments: none
26
27 Responses: no specific responses for this command
28
29 Result: OK - close completed, now in authenticated state
30 NO - close failure: no mailbox selected
31 BAD - command unknown or arguments invalid
32
33 The CLOSE command permanently removes from the currently selected
25 mailbox all messages that have the \\Deleted flag set, and returns 34 mailbox all messages that have the \\Deleted flag set, and returns
26 to authenticated state from selected state. */ 35 to authenticated state from selected state. */
27 int 36 int
28 imap4d_close (struct imap4d_command *command, char *arg MU_ARG_UNUSED) 37 imap4d_close (struct imap4d_command *command, imap4d_tokbuf_t tok)
29 { 38 {
30 const char *msg = NULL; 39 const char *msg = NULL;
31 int status, flags; 40 int status, flags;
32 41
42 if (imap4d_tokbuf_argc (tok) != 2)
43 return util_finish (command, RESP_BAD, "Invalid arguments");
44
33 mu_mailbox_get_flags (mbox, &flags); 45 mu_mailbox_get_flags (mbox, &flags);
34 if ((flags & MU_STREAM_READ) == 0) 46 if ((flags & MU_STREAM_READ) == 0)
35 { 47 {
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2003, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2003, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2005, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -19,55 +19,69 @@ ...@@ -19,55 +19,69 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 /* 21 /*
22 * copy messages in argv[2] to mailbox in argv[3] 22 6.4.7. COPY Command
23
24 Arguments: message set
25 mailbox name
26
27 Responses: no specific responses for this command
28
29 Result: OK - copy completed
30 NO - copy error: can't copy those messages or to that
31 name
32 BAD - command unknown or arguments invalid
33
34 copy messages in argv[2] to mailbox in argv[3]
23 */ 35 */
24 36
25 int 37 int
26 imap4d_copy (struct imap4d_command *command, char *arg) 38 imap4d_copy (struct imap4d_command *command, imap4d_tokbuf_t tok)
27 { 39 {
28 int rc; 40 int rc;
29 char buffer[64]; 41 char *text;
42
43 if (imap4d_tokbuf_argc (tok) != 4)
44 return util_finish (command, RESP_BAD, "Invalid arguments");
45
46 rc = imap4d_copy0 (tok, 0, &text);
30 47
31 rc = imap4d_copy0 (arg, 0, buffer, sizeof buffer);
32 if (rc == RESP_NONE) 48 if (rc == RESP_NONE)
33 { 49 {
34 /* Reset the state ourself. */ 50 /* Reset the state ourself. */
35 int new_state = (rc == RESP_OK) ? command->success : command->failure; 51 int new_state = (rc == RESP_OK) ? command->success : command->failure;
36 if (new_state != STATE_NONE) 52 if (new_state != STATE_NONE)
37 state = new_state; 53 state = new_state;
38 return util_send ("%s %s\r\n", command->tag, buffer); 54 return util_send ("%s %s\r\n", command->tag, text);
39 } 55 }
40 return util_finish (command, rc, "%s", buffer); 56 return util_finish (command, rc, "%s", text);
41 } 57 }
42 58
43 int 59 int
44 imap4d_copy0 (char *arg, int isuid, char *resp, size_t resplen) 60 imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
45 { 61 {
46 int status; 62 int status;
47 char *msgset; 63 char *msgset;
48 char *name; 64 char *name;
49 char *mailbox_name; 65 char *mailbox_name;
50 const char *delim = "/"; 66 const char *delim = "/";
51 char *sp = NULL;
52 size_t *set = NULL; 67 size_t *set = NULL;
53 int n = 0; 68 int n = 0;
54 mu_mailbox_t cmbox = NULL; 69 mu_mailbox_t cmbox = NULL;
70 int arg = IMAP4_ARG_1 + !!isuid;
55 71
56 msgset = util_getword (arg, &sp); 72 if (imap4d_tokbuf_argc (tok) != arg + 2)
57 name = util_getword (NULL, &sp);
58
59 util_unquote (&name);
60 if (!msgset || !name || *name == '\0')
61 { 73 {
62 snprintf (resp, resplen, "Too few args"); 74 *err_text = "Invalid arguments";
63 return RESP_BAD; 75 return 1;
64 } 76 }
65 77
78 msgset = imap4d_tokbuf_getarg (tok, arg);
79 name = imap4d_tokbuf_getarg (tok, arg + 1);
66 /* Get the message numbers in set[]. */ 80 /* Get the message numbers in set[]. */
67 status = util_msgset (msgset, &set, &n, isuid); 81 status = util_msgset (msgset, &set, &n, isuid);
68 if (status != 0) 82 if (status != 0)
69 { 83 {
70 snprintf (resp, resplen, "Bogus number set"); 84 *err_text = "Bogus number set";
71 return RESP_BAD; 85 return RESP_BAD;
72 } 86 }
73 87
...@@ -75,7 +89,7 @@ imap4d_copy0 (char *arg, int isuid, char *resp, size_t resplen) ...@@ -75,7 +89,7 @@ imap4d_copy0 (char *arg, int isuid, char *resp, size_t resplen)
75 89
76 if (!mailbox_name) 90 if (!mailbox_name)
77 { 91 {
78 snprintf (resp, resplen, "NO Create failed."); 92 *err_text = "NO Create failed.";
79 return RESP_NO; 93 return RESP_NO;
80 } 94 }
81 95
...@@ -105,7 +119,7 @@ imap4d_copy0 (char *arg, int isuid, char *resp, size_t resplen) ...@@ -105,7 +119,7 @@ imap4d_copy0 (char *arg, int isuid, char *resp, size_t resplen)
105 119
106 if (status == 0) 120 if (status == 0)
107 { 121 {
108 snprintf (resp, resplen, "Completed"); 122 *err_text = "Completed";
109 return RESP_OK; 123 return RESP_OK;
110 } 124 }
111 125
...@@ -114,6 +128,6 @@ imap4d_copy0 (char *arg, int isuid, char *resp, size_t resplen) ...@@ -114,6 +128,6 @@ imap4d_copy0 (char *arg, int isuid, char *resp, size_t resplen)
114 of the text of the tagged NO response. This gives a hint to the 128 of the text of the tagged NO response. This gives a hint to the
115 client that it can attempt a CREATE command and retry the copy if 129 client that it can attempt a CREATE command and retry the copy if
116 the CREATE is successful. */ 130 the CREATE is successful. */
117 snprintf (resp, resplen, "NO [TRYCREATE] failed"); 131 *err_text = "NO [TRYCREATE] failed";
118 return RESP_NONE; 132 return RESP_NONE;
119 } 133 }
......
...@@ -63,25 +63,34 @@ mkdir_p (char *name, int delim) ...@@ -63,25 +63,34 @@ mkdir_p (char *name, int delim)
63 return 0; 63 return 0;
64 } 64 }
65 65
66 /*
67 6.3.3. CREATE Command
68
69 Arguments: mailbox name
70
71 Responses: no specific responses for this command
72
73 Result: OK - create completed
74 NO - create failure: can't create mailbox with that name
75 BAD - command unknown or arguments invalid
76 */
66 /* FIXME: How do we do this ??????: 77 /* FIXME: How do we do this ??????:
67 IF a new mailbox is created with the same name as a mailbox which was 78 IF a new mailbox is created with the same name as a mailbox which was
68 deleted, its unique identifiers MUST be greater than any unique identifiers 79 deleted, its unique identifiers MUST be greater than any unique identifiers
69 used in the previous incarnation of the mailbox. */ 80 used in the previous incarnation of the mailbox. */
70 int 81 int
71 imap4d_create (struct imap4d_command *command, char *arg) 82 imap4d_create (struct imap4d_command *command, imap4d_tokbuf_t tok)
72 { 83 {
73 char *name; 84 char *name;
74 char *sp = NULL;
75 const char *delim = "/"; 85 const char *delim = "/";
76 int isdir = 0; 86 int isdir = 0;
77 int rc = RESP_OK; 87 int rc = RESP_OK;
78 const char *msg = "Completed"; 88 const char *msg = "Completed";
79 89
80 name = util_getword (arg, &sp); 90 if (imap4d_tokbuf_argc (tok) != 3)
81 if (!name) 91 return util_finish (command, RESP_BAD, "Invalid arguments");
82 return util_finish (command, RESP_BAD, "Too few arguments");
83 92
84 util_unquote (&name); 93 name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
85 94
86 if (*name == '\0') 95 if (*name == '\0')
87 return util_finish (command, RESP_BAD, "Too few arguments"); 96 return util_finish (command, RESP_BAD, "Too few arguments");
...@@ -152,6 +161,5 @@ imap4d_create (struct imap4d_command *command, char *arg) ...@@ -152,6 +161,5 @@ imap4d_create (struct imap4d_command *command, char *arg)
152 msg = "already exists"; 161 msg = "already exists";
153 } 162 }
154 163
155 free (name);
156 return util_finish (command, rc, msg); 164 return util_finish (command, rc, msg);
157 } 165 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -19,20 +19,27 @@ ...@@ -19,20 +19,27 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 /* 21 /*
22 * 22 6.3.4. DELETE Command
23 */
24 23
24 Arguments: mailbox name
25
26 Responses: no specific responses for this command
27
28 Result: OK - delete completed
29 NO - delete failure: can't delete mailbox with that name
30 BAD - command unknown or arguments invalid
31 */
25 int 32 int
26 imap4d_delete (struct imap4d_command *command, char *arg) 33 imap4d_delete (struct imap4d_command *command, imap4d_tokbuf_t tok)
27 { 34 {
28 char *sp = NULL;
29 int rc = RESP_OK; 35 int rc = RESP_OK;
30 const char *msg = "Completed"; 36 const char *msg = "Completed";
31 const char *delim = "/"; 37 const char *delim = "/";
32 char *name; 38 char *name;
33 39
34 name = util_getword (arg, &sp); 40 if (imap4d_tokbuf_argc (tok) != 3)
35 util_unquote (&name); 41 return util_finish (command, RESP_BAD, "Invalid arguments");
42 name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
36 if (!name || *name == '\0') 43 if (!name || *name == '\0')
37 return util_finish (command, RESP_BAD, "Too few arguments"); 44 return util_finish (command, RESP_BAD, "Too few arguments");
38 45
...@@ -51,6 +58,5 @@ imap4d_delete (struct imap4d_command *command, char *arg) ...@@ -51,6 +58,5 @@ imap4d_delete (struct imap4d_command *command, char *arg)
51 rc = RESP_NO; 58 rc = RESP_NO;
52 msg = "Cannot remove"; 59 msg = "Cannot remove";
53 } 60 }
54 free (name);
55 return util_finish (command, rc, msg); 61 return util_finish (command, rc, msg);
56 } 62 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -19,11 +19,23 @@ ...@@ -19,11 +19,23 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 /* 21 /*
22 * copy things from select.c 22 6.3.2. EXAMINE Command
23 */
24 23
24 Arguments: mailbox name
25
26 Responses: REQUIRED untagged responses: FLAGS, EXISTS, RECENT
27 OPTIONAL OK untagged responses: UNSEEN, PERMANENTFLAGS
28
29 Result: OK - examine completed, now in selected state
30 NO - examine failure, now in authenticated state: no
31 such mailbox, can't access mailbox
32 BAD - command unknown or arguments invalid
33 */
25 int 34 int
26 imap4d_examine (struct imap4d_command *command, char *arg) 35 imap4d_examine (struct imap4d_command *command, imap4d_tokbuf_t tok)
27 { 36 {
28 return imap4d_select0 (command, arg, MU_STREAM_READ); 37 if (imap4d_tokbuf_argc (tok) != 3)
38 return util_finish (command, RESP_BAD, "Invalid arguments");
39 return imap4d_select0 (command, imap4d_tokbuf_getarg (tok, IMAP4_ARG_1),
40 MU_STREAM_READ);
29 } 41 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2005, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -19,16 +19,23 @@ ...@@ -19,16 +19,23 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 /* 21 /*
22 * 22 6.4.3. EXPUNGE Command
23 */ 23
24 Arguments: none
25
26 Responses: untagged responses: EXPUNGE
27
28 Result: OK - expunge completed
29 NO - expunge failure: can't expunge (e.g. permission
30 denied)
31 BAD - command unknown or arguments invalid
32 */
24 33
25 int 34 int
26 imap4d_expunge (struct imap4d_command *command, char *arg) 35 imap4d_expunge (struct imap4d_command *command, imap4d_tokbuf_t tok)
27 { 36 {
28 char *sp = NULL; 37 if (imap4d_tokbuf_argc (tok) != 2)
29 38 return util_finish (command, RESP_BAD, "Invalid arguments");
30 if (util_getword (arg, &sp))
31 return util_finish (command, RESP_NO, "Too many args");
32 39
33 /* FIXME: check for errors. */ 40 /* FIXME: check for errors. */
34 mu_mailbox_expunge (mbox); 41 mu_mailbox_expunge (mbox);
......
...@@ -19,13 +19,12 @@ ...@@ -19,13 +19,12 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 int 21 int
22 imap4d_idle (struct imap4d_command *command, char *arg) 22 imap4d_idle (struct imap4d_command *command, imap4d_tokbuf_t tok)
23 { 23 {
24 char *sp;
25 time_t start; 24 time_t start;
26 25
27 if (util_getword (arg, &sp)) 26 if (imap4d_tokbuf_argc (tok) != 2)
28 return util_finish (command, RESP_BAD, "Too many args"); 27 return util_finish (command, RESP_BAD, "Invalid arguments");
29 28
30 if (util_wait_input (0) == -1) 29 if (util_wait_input (0) == -1)
31 return util_finish (command, RESP_NO, "Cannot idle"); 30 return util_finish (command, RESP_NO, "Cannot idle");
...@@ -38,15 +37,10 @@ imap4d_idle (struct imap4d_command *command, char *arg) ...@@ -38,15 +37,10 @@ imap4d_idle (struct imap4d_command *command, char *arg)
38 { 37 {
39 if (util_wait_input (5)) 38 if (util_wait_input (5))
40 { 39 {
41 int rc; 40 imap4d_readline (tok);
42 char *p; 41 if (imap4d_tokbuf_argc (tok) == 1
43 char *cmd = imap4d_readline (); 42 && strcasecmp (imap4d_tokbuf_getarg (tok, IMAP4_ARG_TAG),
44 43 "done") == 0)
45 p = util_getword (cmd, &sp);
46 rc = strcasecmp (p, "done") == 0;
47
48 free (cmd);
49 if (rc)
50 break; 44 break;
51 } 45 }
52 else if (time (NULL) - start > idle_timeout) 46 else if (time (NULL) - start > idle_timeout)
......
...@@ -370,6 +370,7 @@ get_client_address (int fd, struct sockaddr_in *pcs) ...@@ -370,6 +370,7 @@ get_client_address (int fd, struct sockaddr_in *pcs)
370 static int 370 static int
371 imap4d_mainloop (int fd, FILE *infile, FILE *outfile) 371 imap4d_mainloop (int fd, FILE *infile, FILE *outfile)
372 { 372 {
373 imap4d_tokbuf_t tokp;
373 char *text; 374 char *text;
374 int debug_mode = isatty (fd); 375 int debug_mode = isatty (fd);
375 static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE, 376 static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE,
...@@ -400,14 +401,14 @@ imap4d_mainloop (int fd, FILE *infile, FILE *outfile) ...@@ -400,14 +401,14 @@ imap4d_mainloop (int fd, FILE *infile, FILE *outfile)
400 util_out ((state == STATE_AUTH) ? RESP_PREAUTH : RESP_OK, "%s", text); 401 util_out ((state == STATE_AUTH) ? RESP_PREAUTH : RESP_OK, "%s", text);
401 util_flush_output (); 402 util_flush_output ();
402 403
404 tokp = imap4d_tokbuf_init ();
403 while (1) 405 while (1)
404 { 406 {
405 char *cmd = imap4d_readline (); 407 imap4d_readline (tokp);
406 /* check for updates */ 408 /* check for updates */
407 imap4d_sync (); 409 imap4d_sync ();
408 util_do_command (cmd); 410 util_do_command (tokp);
409 imap4d_sync (); 411 imap4d_sync ();
410 free (cmd);
411 util_flush_output (); 412 util_flush_output ();
412 } 413 }
413 414
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
41 #include <stdlib.h> 41 #include <stdlib.h>
42 #include <unistd.h> 42 #include <unistd.h>
43 #include <string.h> 43 #include <string.h>
44 #include <setjmp.h>
44 #include <sys/wait.h> 45 #include <sys/wait.h>
45 #include <sys/types.h> 46 #include <sys/types.h>
46 #include <syslog.h> 47 #include <syslog.h>
...@@ -108,10 +109,12 @@ ...@@ -108,10 +109,12 @@
108 extern "C" { 109 extern "C" {
109 #endif 110 #endif
110 111
112 typedef struct imap4d_tokbuf *imap4d_tokbuf_t;
113
111 struct imap4d_command 114 struct imap4d_command
112 { 115 {
113 const char *name; 116 const char *name;
114 int (*func) (struct imap4d_command *, char *); 117 int (*func) (struct imap4d_command *, imap4d_tokbuf_t);
115 int states; 118 int states;
116 int failure; 119 int failure;
117 int success; 120 int success;
...@@ -192,47 +195,62 @@ extern int imap4d_transcript; ...@@ -192,47 +195,62 @@ extern int imap4d_transcript;
192 extern char *strtok_r (char *s, const char *delim, char **save_ptr); 195 extern char *strtok_r (char *s, const char *delim, char **save_ptr);
193 #endif 196 #endif
194 197
195 /* Imap4 commands */ 198 /* Input functions */
196 extern int imap4d_append (struct imap4d_command *, char *); 199 imap4d_tokbuf_t imap4d_tokbuf_init (void);
197 extern int imap4d_append0 (mu_mailbox_t mbox, int flags, char *text); 200 void imap4d_tokbuf_destroy (imap4d_tokbuf_t *tok);
198 extern int imap4d_authenticate (struct imap4d_command *, char *); 201 int imap4d_tokbuf_argc (imap4d_tokbuf_t tok);
202 char *imap4d_tokbuf_getarg (imap4d_tokbuf_t tok, int n);
203 void imap4d_readline (imap4d_tokbuf_t tok);
204 struct imap4d_tokbuf *imap4d_tokbuf_from_string (char *str);
205 int imap4d_getline (char **pbuf, size_t *psize, size_t *pnbytes);
206
207 #define IMAP4_ARG_TAG 0
208 #define IMAP4_ARG_COMMAND 1
209 #define IMAP4_ARG_1 2
210 #define IMAP4_ARG_2 3
211 #define IMAP4_ARG_3 4
212 #define IMAP4_ARG_4 5
213
214 /* Imap4 commands */
215 extern int imap4d_append (struct imap4d_command *, imap4d_tokbuf_t);
216 extern int imap4d_authenticate (struct imap4d_command *, imap4d_tokbuf_t);
199 extern void imap4d_auth_capability (void); 217 extern void imap4d_auth_capability (void);
200 extern int imap4d_capability (struct imap4d_command *, char *); 218 extern int imap4d_capability (struct imap4d_command *, imap4d_tokbuf_t);
201 extern int imap4d_check (struct imap4d_command *, char *); 219 extern int imap4d_check (struct imap4d_command *, imap4d_tokbuf_t);
202 extern int imap4d_close (struct imap4d_command *, char *); 220 extern int imap4d_close (struct imap4d_command *, imap4d_tokbuf_t);
203 extern int imap4d_copy (struct imap4d_command *, char *); 221 extern int imap4d_copy (struct imap4d_command *, imap4d_tokbuf_t);
204 extern int imap4d_copy0 (char *, int, char *, size_t); 222 extern int imap4d_copy0 (imap4d_tokbuf_t, int isuid, char **err_text);
205 extern int imap4d_create (struct imap4d_command *, char *); 223 extern int imap4d_create (struct imap4d_command *, imap4d_tokbuf_t);
206 extern int imap4d_delete (struct imap4d_command *, char *); 224 extern int imap4d_delete (struct imap4d_command *, imap4d_tokbuf_t);
207 extern int imap4d_examine (struct imap4d_command *, char *); 225 extern int imap4d_examine (struct imap4d_command *, imap4d_tokbuf_t);
208 extern int imap4d_expunge (struct imap4d_command *, char *); 226 extern int imap4d_expunge (struct imap4d_command *, imap4d_tokbuf_t);
209 extern int imap4d_fetch (struct imap4d_command *, char *); 227 extern int imap4d_fetch (struct imap4d_command *, imap4d_tokbuf_t);
210 extern int imap4d_fetch0 (char *, int, char *, size_t); 228 extern int imap4d_fetch0 (imap4d_tokbuf_t tok, int isuid, char **err_text);
211 extern int imap4d_list (struct imap4d_command *, char *); 229 extern int imap4d_list (struct imap4d_command *, imap4d_tokbuf_t);
212 extern int imap4d_lsub (struct imap4d_command *, char *); 230 extern int imap4d_lsub (struct imap4d_command *, imap4d_tokbuf_t);
213 extern int imap4d_login (struct imap4d_command *, char *); 231 extern int imap4d_login (struct imap4d_command *, imap4d_tokbuf_t);
214 extern int imap4d_logout (struct imap4d_command *, char *); 232 extern int imap4d_logout (struct imap4d_command *, imap4d_tokbuf_t);
215 extern int imap4d_noop (struct imap4d_command *, char *); 233 extern int imap4d_noop (struct imap4d_command *, imap4d_tokbuf_t);
216 extern int imap4d_rename (struct imap4d_command *, char *); 234 extern int imap4d_rename (struct imap4d_command *, imap4d_tokbuf_t);
217 extern int imap4d_preauth_setup (int fd); 235 extern int imap4d_preauth_setup (int fd);
218 extern int imap4d_search (struct imap4d_command *, char *); 236 extern int imap4d_search (struct imap4d_command *, imap4d_tokbuf_t);
219 extern int imap4d_search0 (char *arg, int isuid, char *replybuf, size_t replysize); 237 extern int imap4d_search0 (imap4d_tokbuf_t, int isuid, char **repyptr);
220 extern int imap4d_select (struct imap4d_command *, char *); 238 extern int imap4d_select (struct imap4d_command *, imap4d_tokbuf_t);
221 extern int imap4d_select0 (struct imap4d_command *, char *, int); 239 extern int imap4d_select0 (struct imap4d_command *, char *, int);
222 extern int imap4d_select_status (void); 240 extern int imap4d_select_status (void);
223 #ifdef WITH_TLS 241 #ifdef WITH_TLS
224 extern int imap4d_starttls (struct imap4d_command *, char *); 242 extern int imap4d_starttls (struct imap4d_command *, imap4d_tokbuf_t);
225 extern void starttls_init (void); 243 extern void starttls_init (void);
226 #endif /* WITH_TLS */ 244 #endif /* WITH_TLS */
227 extern int imap4d_status (struct imap4d_command *, char *); 245 extern int imap4d_status (struct imap4d_command *, imap4d_tokbuf_t);
228 extern int imap4d_store (struct imap4d_command *, char *); 246 extern int imap4d_store (struct imap4d_command *, imap4d_tokbuf_t);
229 extern int imap4d_store0 (char *, int, char *, size_t); 247 extern int imap4d_store0 (imap4d_tokbuf_t, int, char **);
230 extern int imap4d_subscribe (struct imap4d_command *, char *); 248 extern int imap4d_subscribe (struct imap4d_command *, imap4d_tokbuf_t);
231 extern int imap4d_uid (struct imap4d_command *, char *); 249 extern int imap4d_uid (struct imap4d_command *, imap4d_tokbuf_t);
232 extern int imap4d_unsubscribe (struct imap4d_command *, char *); 250 extern int imap4d_unsubscribe (struct imap4d_command *, imap4d_tokbuf_t);
233 extern int imap4d_namespace (struct imap4d_command *, char *); 251 extern int imap4d_namespace (struct imap4d_command *, imap4d_tokbuf_t);
234 extern int imap4d_version (struct imap4d_command *, char *); 252 extern int imap4d_version (struct imap4d_command *, imap4d_tokbuf_t);
235 extern int imap4d_idle (struct imap4d_command *, char *); 253 extern int imap4d_idle (struct imap4d_command *, imap4d_tokbuf_t);
236 254
237 extern int imap4d_check_home_dir (const char *dir, uid_t uid, gid_t gid); 255 extern int imap4d_check_home_dir (const char *dir, uid_t uid, gid_t gid);
238 256
...@@ -274,25 +292,17 @@ extern int util_start (char *); ...@@ -274,25 +292,17 @@ extern int util_start (char *);
274 extern int util_finish (struct imap4d_command *, int, const char *, ...) 292 extern int util_finish (struct imap4d_command *, int, const char *, ...)
275 MU_PRINTFLIKE(3,4); 293 MU_PRINTFLIKE(3,4);
276 extern int util_getstate (void); 294 extern int util_getstate (void);
277 extern int util_do_command (char *); 295 extern int util_do_command (imap4d_tokbuf_t);
278 extern char *imap4d_readline (void);
279 extern char *imap4d_readline_ex (void);
280 extern char *util_getword (char *, char **);
281 extern char *util_getitem (char *, const char *, char **);
282 extern int util_token (char *, size_t, char **);
283 extern void util_unquote (char **);
284 extern char *util_tilde_expansion (const char *, const char *); 296 extern char *util_tilde_expansion (const char *, const char *);
285 extern char *util_getfullpath (char *, const char *); 297 extern char *util_getfullpath (char *, const char *);
286 extern int util_msgset (char *, size_t **, int *, int); 298 extern int util_msgset (char *, size_t **, int *, int);
287 extern int util_upper (char *); 299 extern int util_upper (char *);
288 extern struct imap4d_command *util_getcommand (char *, 300 extern struct imap4d_command *util_getcommand (char *,
289 struct imap4d_command []); 301 struct imap4d_command []);
290 extern int util_parse_internal_date0 (char *date, time_t *timep, char **endp);
291 extern int util_parse_internal_date (char *date, time_t *timep); 302 extern int util_parse_internal_date (char *date, time_t *timep);
292 extern int util_parse_822_date (const char *date, time_t *timep); 303 extern int util_parse_822_date (const char *date, time_t *timep);
293 extern int util_parse_ctime_date (const char *date, time_t *timep); 304 extern int util_parse_ctime_date (const char *date, time_t *timep);
294 extern char *util_strcasestr (const char *haystack, const char *needle); 305 extern char *util_strcasestr (const char *haystack, const char *needle);
295 extern int util_parse_attributes (char *items, char **save, int *flags);
296 306
297 extern int util_base64_encode (const unsigned char *input, 307 extern int util_base64_encode (const unsigned char *input,
298 size_t input_len, 308 size_t input_len,
...@@ -330,6 +340,7 @@ void util_bye (void); ...@@ -330,6 +340,7 @@ void util_bye (void);
330 void util_atexit (void (*fp) (void)); 340 void util_atexit (void (*fp) (void));
331 void util_chdir (const char *homedir); 341 void util_chdir (const char *homedir);
332 int is_atom (const char *s); 342 int is_atom (const char *s);
343 int util_isdelim (const char *str);
333 344
334 #ifdef WITH_TLS 345 #ifdef WITH_TLS
335 int imap4d_init_tls_server (void); 346 int imap4d_init_tls_server (void);
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2002, 2005, 2006, 2 Copyright (C) 1999, 2001, 2002, 2005, 2006,
3 2007 Free Software Foundation, Inc. 3 2007, 2008 Free Software Foundation, Inc.
4 4
5 GNU Mailutils is free software; you can redistribute it and/or modify 5 GNU Mailutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
...@@ -106,6 +106,19 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) ...@@ -106,6 +106,19 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data)
106 } 106 }
107 107
108 /* 108 /*
109 6.3.8. LIST Command
110
111 Arguments: reference name
112 mailbox name with possible wildcards
113
114 Responses: untagged responses: LIST
115
116 Result: OK - list completed
117 NO - list failure: can't list that reference or name
118 BAD - command unknown or arguments invalid
119 */
120
121 /*
109 1- IMAP4 insists: the reference argument present in the 122 1- IMAP4 insists: the reference argument present in the
110 interpreted form SHOULD prefix the interpreted form. It SHOULD 123 interpreted form SHOULD prefix the interpreted form. It SHOULD
111 also be in the same form as the reference name argument. This 124 also be in the same form as the reference name argument. This
...@@ -126,21 +139,17 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) ...@@ -126,21 +139,17 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data)
126 but it does not match the hierarchy delimiter. */ 139 but it does not match the hierarchy delimiter. */
127 140
128 int 141 int
129 imap4d_list (struct imap4d_command *command, char *arg) 142 imap4d_list (struct imap4d_command *command, imap4d_tokbuf_t tok)
130 { 143 {
131 char *sp = NULL;
132 char *ref; 144 char *ref;
133 char *wcard; 145 char *wcard;
134 const char *delim = "/"; 146 const char *delim = "/";
135 147
136 ref = util_getword (arg, &sp); 148 if (imap4d_tokbuf_argc (tok) != 4)
137 wcard = util_getword (NULL, &sp); 149 return util_finish (command, RESP_BAD, "Invalid arguments");
138 if (!ref || !wcard)
139 return util_finish (command, RESP_BAD, "Too few arguments");
140 150
141 /* Remove the double quotes. */ 151 ref = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
142 util_unquote (&ref); 152 wcard = imap4d_tokbuf_getarg (tok, IMAP4_ARG_2);
143 util_unquote (&wcard);
144 153
145 /* If wildcard is empty, it is a special case: we have to 154 /* If wildcard is empty, it is a special case: we have to
146 return the hierarchy. */ 155 return the hierarchy. */
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2002, 2006, 2 Copyright (C) 1999, 2001, 2002, 2006,
3 2007 Free Software Foundation, Inc. 3 2007, 2008 Free Software Foundation, Inc.
4 4
5 GNU Mailutils is free software; you can redistribute it and/or modify 5 GNU Mailutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
...@@ -19,26 +19,32 @@ ...@@ -19,26 +19,32 @@
19 19
20 #include "imap4d.h" 20 #include "imap4d.h"
21 21
22 /*
23 6.2.2. LOGIN Command
24
25 Arguments: user name
26 password
27
28 Responses: no specific responses for this command
29
30 Result: OK - login completed, now in authenticated state
31 NO - login failure: user name or password rejected
32 BAD - command unknown or arguments invalid
33 */
22 int 34 int
23 imap4d_login (struct imap4d_command *command, char *arg) 35 imap4d_login (struct imap4d_command *command, imap4d_tokbuf_t tok)
24 { 36 {
25 char *sp = NULL, *username, *pass; 37 char *username, *pass;
26 int rc; 38 int rc;
27 39
28 if (login_disabled || tls_required) 40 if (login_disabled || tls_required)
29 return util_finish (command, RESP_NO, "Command disabled"); 41 return util_finish (command, RESP_NO, "Command disabled");
30 42
31 username = util_getword (arg, &sp); 43 if (imap4d_tokbuf_argc (tok) != 4)
32 pass = util_getword (NULL, &sp); 44 return util_finish (command, RESP_BAD, "Invalid arguments");
33
34 /* Remove the double quotes. */
35 util_unquote (&username);
36 util_unquote (&pass);
37 45
38 if (username == NULL || *username == '\0' || pass == NULL) 46 username = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
39 return util_finish (command, RESP_NO, "Too few args"); 47 pass = imap4d_tokbuf_getarg (tok, IMAP4_ARG_2);
40 else if (util_getword (NULL, &sp))
41 return util_finish (command, RESP_NO, "Too many args");
42 48
43 auth_data = mu_get_auth_by_name (username); 49 auth_data = mu_get_auth_by_name (username);
44 50
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -19,15 +19,21 @@ ...@@ -19,15 +19,21 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 /* 21 /*
22 * This needs to properly close the mailbox 22 6.1.3. LOGOUT Command
23 */ 23
24 Arguments: none
25
26 Responses: REQUIRED untagged response: BYE
27
28 Result: OK - logout completed
29 BAD - command unknown or arguments invalid
30 */
24 31
25 int 32 int
26 imap4d_logout (struct imap4d_command *command, char *arg) 33 imap4d_logout (struct imap4d_command *command, imap4d_tokbuf_t tok)
27 { 34 {
28 char *sp = NULL; 35 if (imap4d_tokbuf_argc (tok) != 2)
29 if (util_getword (arg, &sp)) 36 return util_finish (command, RESP_BAD, "Invalid arguments");
30 return util_finish (command, RESP_BAD, "Too many args");
31 imap4d_bye0 (OK, command); 37 imap4d_bye0 (OK, command);
32 return 0; 38 return 0;
33 } 39 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -19,13 +19,20 @@ ...@@ -19,13 +19,20 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 /* 21 /*
22 * 22 6.3.9. LSUB Command
23 */
24 23
24 Arguments: reference name
25 mailbox name with possible wildcards
26
27 Responses: untagged responses: LSUB
28
29 Result: OK - lsub completed
30 NO - lsub failure: can't list that reference or name
31 BAD - command unknown or arguments invalid
32 */
25 int 33 int
26 imap4d_lsub (struct imap4d_command *command, char *arg) 34 imap4d_lsub (struct imap4d_command *command, imap4d_tokbuf_t tok)
27 { 35 {
28 char *sp;
29 char *ref; 36 char *ref;
30 char *wcard; 37 char *wcard;
31 char *file = NULL; 38 char *file = NULL;
...@@ -33,14 +40,11 @@ imap4d_lsub (struct imap4d_command *command, char *arg) ...@@ -33,14 +40,11 @@ imap4d_lsub (struct imap4d_command *command, char *arg)
33 const char *delim = "/"; 40 const char *delim = "/";
34 FILE *fp; 41 FILE *fp;
35 42
36 ref = util_getword (arg, &sp); 43 if (imap4d_tokbuf_argc (tok) != 4)
37 wcard = util_getword (NULL, &sp); 44 return util_finish (command, RESP_BAD, "Invalid arguments");
38 if (!ref || !wcard)
39 return util_finish (command, RESP_BAD, "Too few arguments");
40 45
41 /* Remove the double quotes. */ 46 ref = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
42 util_unquote (&ref); 47 wcard = imap4d_tokbuf_getarg (tok, IMAP4_ARG_2);
43 util_unquote (&wcard);
44 48
45 asprintf (&pattern, "%s%s", ref, wcard); 49 asprintf (&pattern, "%s%s", ref, wcard);
46 if (!pattern) 50 if (!pattern)
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2005, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -89,8 +89,9 @@ print_namespace (int n) ...@@ -89,8 +89,9 @@ print_namespace (int n)
89 util_send ("("); 89 util_send ("(");
90 for (i = 0; i < namespace[n].subdir_c; i++) 90 for (i = 0; i < namespace[n].subdir_c; i++)
91 { 91 {
92 util_send ("(\"%s\" \"/\")", 92 char *dir = printable_pathname (namespace[n].subdir_v[i]);
93 printable_pathname (namespace[n].subdir_v[i])); 93 char *suf = (dir[0] && dir[strlen (dir) - 1] != '/') ? "/" : "";
94 util_send ("(\"%s%s\" \"/\")", dir, suf);
94 } 95 }
95 util_send (")"); 96 util_send (")");
96 } 97 }
...@@ -114,11 +115,27 @@ namespace_enumerate_all (nsfp_t f, void *closure) ...@@ -114,11 +115,27 @@ namespace_enumerate_all (nsfp_t f, void *closure)
114 || namespace_enumerate (NS_SHARED, f, closure); 115 || namespace_enumerate (NS_SHARED, f, closure);
115 } 116 }
116 117
118 /*
119 5. NAMESPACE Command
120
121 Arguments: none
122
123 Response: an untagged NAMESPACE response that contains the prefix
124 and hierarchy delimiter to the server's Personal
125 Namespace(s), Other Users' Namespace(s), and Shared
126 Namespace(s) that the server wishes to expose. The
127 response will contain a NIL for any namespace class
128 that is not available. Namespace_Response_Extensions
129 MAY be included in the response.
130 Namespace_Response_Extensions which are not on the IETF
131 standards track, MUST be prefixed with an "X-".
132 */
133
117 int 134 int
118 imap4d_namespace (struct imap4d_command *command, char *arg) 135 imap4d_namespace (struct imap4d_command *command, imap4d_tokbuf_t tok)
119 { 136 {
120 if (*arg) 137 if (imap4d_tokbuf_argc (tok) != 2)
121 return util_finish (command, RESP_BAD, "Too many arguments"); 138 return util_finish (command, RESP_BAD, "Invalid arguments");
122 139
123 util_send ("* NAMESPACE "); 140 util_send ("* NAMESPACE ");
124 141
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -19,13 +19,10 @@ ...@@ -19,13 +19,10 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 int 21 int
22 imap4d_noop (struct imap4d_command *command, char *arg) 22 imap4d_noop (struct imap4d_command *command, imap4d_tokbuf_t tok)
23 { 23 {
24 char *sp = NULL; 24 if (imap4d_tokbuf_argc (tok) != 2)
25 25 return util_finish (command, RESP_BAD, "Invalid arguments");
26 if (util_getword (arg, &sp))
27 return util_finish (command, RESP_BAD, "Too many args");
28
29 imap4d_sync (); 26 imap4d_sync ();
30 return util_finish (command, RESP_OK, "Completed"); 27 return util_finish (command, RESP_OK, "Completed");
31 } 28 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2005, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -19,30 +19,37 @@ ...@@ -19,30 +19,37 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 /* 21 /*
22 6.3.5. RENAME Command
23
24 Arguments: existing mailbox name
25 new mailbox name
26
27 Responses: no specific responses for this command
28
29 Result: OK - rename completed
30 NO - rename failure: can't rename mailbox with that name,
31 can't rename to mailbox with that name
32 BAD - command unknown or arguments invalid
33 */
34 /*
22 FIXME: Renaming a mailbox we must change the UIDVALIDITY 35 FIXME: Renaming a mailbox we must change the UIDVALIDITY
23 of the mailbox. */ 36 of the mailbox. */
24 37
25 int 38 int
26 imap4d_rename (struct imap4d_command *command, char *arg) 39 imap4d_rename (struct imap4d_command *command, imap4d_tokbuf_t tok)
27 { 40 {
28 char *oldname; 41 char *oldname;
29 char *newname; 42 char *newname;
30 char *sp = NULL;
31 int rc = RESP_OK; 43 int rc = RESP_OK;
32 const char *msg = "Completed"; 44 const char *msg = "Completed";
33 struct stat newst; 45 struct stat newst;
34 const char *delim = "/"; 46 const char *delim = "/";
35 47
36 oldname = util_getword (arg, &sp); 48 if (imap4d_tokbuf_argc (tok) != 4)
37 newname = util_getword (NULL, &sp); 49 return util_finish (command, RESP_BAD, "Invalid arguments");
38 if (!newname || !oldname)
39 return util_finish (command, RESP_BAD, "Too few arguments");
40
41 util_unquote (&newname);
42 util_unquote (&oldname);
43 50
44 if (*newname == '\0' || *oldname == '\0') 51 oldname = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
45 return util_finish (command, RESP_BAD, "Too few arguments"); 52 newname = imap4d_tokbuf_getarg (tok, IMAP4_ARG_2);
46 53
47 if (strcasecmp (newname, "INBOX") == 0) 54 if (strcasecmp (newname, "INBOX") == 0)
48 return util_finish (command, RESP_NO, "Name Inbox is reservered"); 55 return util_finish (command, RESP_NO, "Name Inbox is reservered");
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2002, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2002, 2005, 2007,
3 2008 Free Software Foundation, Inc.
3 4
4 GNU Mailutils is free software; you can redistribute it and/or modify 5 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
...@@ -223,11 +224,9 @@ struct mem_chain ...@@ -223,11 +224,9 @@ struct mem_chain
223 /* Parse buffer structure */ 224 /* Parse buffer structure */
224 struct parsebuf 225 struct parsebuf
225 { 226 {
226 char *token; /* Current token. Either points to tokbuf 227 imap4d_tokbuf_t tok; /* Token buffer */
227 or is allocated within `alloc' chain */ 228 int arg; /* Argument number */
228 char tokbuf[MAXTOKEN+1]; /* Token buffer for short tokens */ 229 char *token; /* Current token */
229
230 char *arg; /* Rest of command line to be parsed */
231 int isuid; /* UIDs instead of msgnos are required */ 230 int isuid; /* UIDs instead of msgnos are required */
232 char *err_mesg; /* Error message if a parse error occured */ 231 char *err_mesg; /* Error message if a parse error occured */
233 struct mem_chain *alloc; /* Chain of objects allocated during parsing */ 232 struct mem_chain *alloc; /* Chain of objects allocated during parsing */
...@@ -249,30 +248,45 @@ static int parse_gettoken (struct parsebuf *pb, int req); ...@@ -249,30 +248,45 @@ static int parse_gettoken (struct parsebuf *pb, int req);
249 static int search_run (struct parsebuf *pb); 248 static int search_run (struct parsebuf *pb);
250 static void do_search (struct parsebuf *pb); 249 static void do_search (struct parsebuf *pb);
251 250
251 /*
252 6.4.4. SEARCH Command
253
254 Arguments: OPTIONAL [CHARSET] specification
255 searching criteria (one or more)
256
257 Responses: REQUIRED untagged response: SEARCH
258
259 Result: OK - search completed
260 NO - search error: can't search that [CHARSET] or
261 criteria
262 BAD - command unknown or arguments invalid
263 */
264
252 int 265 int
253 imap4d_search (struct imap4d_command *command, char *arg) 266 imap4d_search (struct imap4d_command *command, imap4d_tokbuf_t tok)
254 { 267 {
255 int rc; 268 int rc;
256 char buffer[64]; 269 char *err_text= "";
257 270
258 rc = imap4d_search0 (arg, 0, buffer, sizeof buffer); 271 rc = imap4d_search0 (tok, 0, &err_text);
259 return util_finish (command, rc, "%s", buffer); 272 return util_finish (command, rc, "%s", err_text);
260 } 273 }
261 274
262 int 275 int
263 imap4d_search0 (char *arg, int isuid, char *replybuf, size_t replysize) 276 imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
264 { 277 {
265 struct parsebuf parsebuf; 278 struct parsebuf parsebuf;
266 279
267 memset (&parsebuf, 0, sizeof(parsebuf)); 280 memset (&parsebuf, 0, sizeof(parsebuf));
268 parsebuf.arg = arg; 281 parsebuf.tok = tok;
282 parsebuf.arg = IMAP4_ARG_1 + !!isuid;
269 parsebuf.err_mesg = NULL; 283 parsebuf.err_mesg = NULL;
270 parsebuf.alloc = NULL; 284 parsebuf.alloc = NULL;
271 parsebuf.isuid = isuid; 285 parsebuf.isuid = isuid;
272 286
273 if (!parse_gettoken (&parsebuf, 0)) 287 if (!parse_gettoken (&parsebuf, 0))
274 { 288 {
275 snprintf (replybuf, replysize, "Too few args"); 289 *err_text = "Too few args";
276 return RESP_BAD; 290 return RESP_BAD;
277 } 291 }
278 292
...@@ -280,20 +294,20 @@ imap4d_search0 (char *arg, int isuid, char *replybuf, size_t replysize) ...@@ -280,20 +294,20 @@ imap4d_search0 (char *arg, int isuid, char *replybuf, size_t replysize)
280 { 294 {
281 if (!parse_gettoken (&parsebuf, 0)) 295 if (!parse_gettoken (&parsebuf, 0))
282 { 296 {
283 snprintf (replybuf, replysize, "Too few args"); 297 *err_text = "Too few args";
284 return RESP_BAD; 298 return RESP_BAD;
285 } 299 }
286 300
287 /* Currently only ASCII is supported */ 301 /* Currently only ASCII is supported */
288 if (strcasecmp (parsebuf.token, "US-ASCII")) 302 if (strcasecmp (parsebuf.token, "US-ASCII"))
289 { 303 {
290 snprintf (replybuf, replysize, "Charset not supported"); 304 *err_text = "Charset not supported";
291 return RESP_NO; 305 return RESP_NO;
292 } 306 }
293 307
294 if (!parse_gettoken (&parsebuf, 0)) 308 if (!parse_gettoken (&parsebuf, 0))
295 { 309 {
296 snprintf (replybuf, replysize, "Too few args"); 310 *err_text = "Too few args";
297 return RESP_BAD; 311 return RESP_BAD;
298 } 312 }
299 313
...@@ -304,16 +318,14 @@ imap4d_search0 (char *arg, int isuid, char *replybuf, size_t replysize) ...@@ -304,16 +318,14 @@ imap4d_search0 (char *arg, int isuid, char *replybuf, size_t replysize)
304 if (!parsebuf.tree) 318 if (!parsebuf.tree)
305 { 319 {
306 parse_free_mem (&parsebuf); 320 parse_free_mem (&parsebuf);
307 snprintf (replybuf, replysize, "%s (near %s)", 321 *err_text = "Parse error";
308 parsebuf.err_mesg,
309 *parsebuf.arg ? parsebuf.arg : "end");
310 return RESP_BAD; 322 return RESP_BAD;
311 } 323 }
312 324
313 if (parsebuf.token[0] != 0) 325 if (parsebuf.token)
314 { 326 {
315 parse_free_mem (&parsebuf); 327 parse_free_mem (&parsebuf);
316 snprintf (replybuf, replysize, "Junk at the end of statement"); 328 *err_text = "Junk at the end of statement";
317 return RESP_BAD; 329 return RESP_BAD;
318 } 330 }
319 331
...@@ -322,7 +334,7 @@ imap4d_search0 (char *arg, int isuid, char *replybuf, size_t replysize) ...@@ -322,7 +334,7 @@ imap4d_search0 (char *arg, int isuid, char *replybuf, size_t replysize)
322 334
323 parse_free_mem (&parsebuf); 335 parse_free_mem (&parsebuf);
324 336
325 snprintf (replybuf, replysize, "Completed"); 337 *err_text = "Completed";
326 return RESP_OK; 338 return RESP_OK;
327 } 339 }
328 340
...@@ -359,41 +371,13 @@ do_search (struct parsebuf *pb) ...@@ -359,41 +371,13 @@ do_search (struct parsebuf *pb)
359 int 371 int
360 parse_gettoken (struct parsebuf *pb, int req) 372 parse_gettoken (struct parsebuf *pb, int req)
361 { 373 {
362 int rc; 374 if (req && pb->arg >= imap4d_tokbuf_argc (pb->tok))
363 char *s;
364
365 pb->token = pb->tokbuf;
366 while (*pb->arg && *pb->arg == ' ')
367 pb->arg++;
368 switch (*pb->arg)
369 { 375 {
370 case '(':
371 case ')':
372 pb->token[0] = *pb->arg++;
373 pb->token[1] = 0;
374 rc = 1;
375 break;
376 case '"':
377 s = ++pb->arg;
378 while (*pb->arg && *pb->arg != '"')
379 pb->arg++;
380 rc = pb->arg - s;
381 if (*pb->arg)
382 pb->arg++;
383
384 if (rc >= sizeof(pb->tokbuf))
385 pb->token = parse_alloc (pb, rc+1);
386 memcpy (pb->token, s, rc);
387 pb->token[rc] = 0;
388 break;
389
390 default:
391 rc = util_token (pb->token, sizeof(pb->tokbuf), &pb->arg);
392 break;
393 }
394 if (req && rc == 0)
395 pb->err_mesg = "Unexpected end of statement"; 376 pb->err_mesg = "Unexpected end of statement";
396 return rc; 377 return 0;
378 }
379 pb->token = imap4d_tokbuf_getarg (pb->tok, pb->arg++);
380 return 1;
397 } 381 }
398 382
399 /* Memory handling */ 383 /* Memory handling */
...@@ -468,7 +452,7 @@ parse_search_key_list (struct parsebuf *pb) ...@@ -468,7 +452,7 @@ parse_search_key_list (struct parsebuf *pb)
468 { 452 {
469 struct search_node *leftarg = NULL; 453 struct search_node *leftarg = NULL;
470 454
471 while (pb->token[0] && pb->token[0] != ')') 455 while (pb->token && pb->token[0] != ')')
472 { 456 {
473 struct search_node *rightarg = parse_search_key (pb); 457 struct search_node *rightarg = parse_search_key (pb);
474 if (!rightarg) 458 if (!rightarg)
...@@ -563,8 +547,8 @@ parse_equiv_key (struct parsebuf *pb) ...@@ -563,8 +547,8 @@ parse_equiv_key (struct parsebuf *pb)
563 { 547 {
564 struct search_node *node; 548 struct search_node *node;
565 struct cond_equiv *condp; 549 struct cond_equiv *condp;
566 char *arg; 550 int save_arg;
567 char *save_arg; 551 imap4d_tokbuf_t save_tok;
568 552
569 for (condp = equiv_list; condp->name && strcasecmp (condp->name, pb->token); 553 for (condp = equiv_list; condp->name && strcasecmp (condp->name, pb->token);
570 condp++) 554 condp++)
...@@ -574,8 +558,9 @@ parse_equiv_key (struct parsebuf *pb) ...@@ -574,8 +558,9 @@ parse_equiv_key (struct parsebuf *pb)
574 return parse_simple_key (pb); 558 return parse_simple_key (pb);
575 559
576 save_arg = pb->arg; 560 save_arg = pb->arg;
577 arg = parse_strdup (pb, condp->equiv); 561 save_tok = pb->tok;
578 pb->arg = arg; 562 pb->tok = imap4d_tokbuf_from_string (condp->equiv);
563 pb->arg = 0;
579 564
580 parse_gettoken (pb, 0); 565 parse_gettoken (pb, 0);
581 566
...@@ -587,8 +572,10 @@ parse_equiv_key (struct parsebuf *pb) ...@@ -587,8 +572,10 @@ parse_equiv_key (struct parsebuf *pb)
587 __FILE__, __LINE__); 572 __FILE__, __LINE__);
588 abort (); 573 abort ();
589 } 574 }
575 imap4d_tokbuf_destroy (&pb->tok);
590 576
591 pb->arg = save_arg; 577 pb->arg = save_arg;
578 pb->tok = save_tok;
592 parse_gettoken (pb, 0); 579 parse_gettoken (pb, 0);
593 return node; 580 return node;
594 } 581 }
...@@ -658,7 +645,7 @@ parse_simple_key (struct parsebuf *pb) ...@@ -658,7 +645,7 @@ parse_simple_key (struct parsebuf *pb)
658 return NULL; 645 return NULL;
659 } 646 }
660 647
661 if (!pb->token[0]) 648 if (!pb->token)
662 { 649 {
663 pb->err_mesg = "Not enough arguments for criterion"; 650 pb->err_mesg = "Not enough arguments for criterion";
664 return NULL; 651 return NULL;
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2003, 2005, 2006, 2 Copyright (C) 1999, 2001, 2003, 2005, 2006,
3 2007 Free Software Foundation, Inc. 3 2007, 2008 Free Software Foundation, Inc.
4 4
5 GNU Mailutils is free software; you can redistribute it and/or modify 5 GNU Mailutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
...@@ -24,25 +24,22 @@ static int select_flags; ...@@ -24,25 +24,22 @@ static int select_flags;
24 /* select ::= "SELECT" SPACE mailbox */ 24 /* select ::= "SELECT" SPACE mailbox */
25 25
26 int 26 int
27 imap4d_select (struct imap4d_command *command, char *arg) 27 imap4d_select (struct imap4d_command *command, imap4d_tokbuf_t tok)
28 { 28 {
29 return imap4d_select0 (command, arg, MU_STREAM_RDWR); 29 if (imap4d_tokbuf_argc (tok) != 3)
30 return util_finish (command, RESP_BAD, "Invalid arguments");
31 return imap4d_select0 (command, imap4d_tokbuf_getarg (tok, IMAP4_ARG_1),
32 MU_STREAM_RDWR);
30 } 33 }
31 34
32 /* This code is share with EXAMINE. */ 35 /* This code is share with EXAMINE. */
33 int 36 int
34 imap4d_select0 (struct imap4d_command *command, char *arg, int flags) 37 imap4d_select0 (struct imap4d_command *command, char *mailbox_name, int flags)
35 { 38 {
36 char *mailbox_name, *sp = NULL;
37 int status; 39 int status;
38 40
39 /* FIXME: Check state. */ 41 /* FIXME: Check state. */
40 42
41 mailbox_name = util_getword (arg, &sp);
42 util_unquote (&mailbox_name);
43 if (mailbox_name == NULL || *mailbox_name == '\0')
44 return util_finish (command, RESP_BAD, "Too few arguments");
45
46 /* Even if a mailbox is selected, a SELECT EXAMINE or LOGOUT 43 /* Even if a mailbox is selected, a SELECT EXAMINE or LOGOUT
47 command MAY be issued without previously issuing a CLOSE command. 44 command MAY be issued without previously issuing a CLOSE command.
48 The SELECT, EXAMINE, and LOGUT commands implictly close the 45 The SELECT, EXAMINE, and LOGUT commands implictly close the
......
...@@ -23,17 +23,26 @@ ...@@ -23,17 +23,26 @@
23 static int tls_available; 23 static int tls_available;
24 static int tls_done; 24 static int tls_done;
25 25
26 /*
27 6.2.1. STARTTLS Command
28
29 Arguments: none
30
31 Responses: no specific response for this command
32
33 Result: OK - starttls completed, begin TLS negotiation
34 BAD - command unknown or arguments invalid
35 */
26 int 36 int
27 imap4d_starttls (struct imap4d_command *command, char *arg) 37 imap4d_starttls (struct imap4d_command *command, imap4d_tokbuf_t tok)
28 { 38 {
29 int status; 39 int status;
30 char *sp = NULL;
31 40
32 if (!tls_available || tls_done) 41 if (!tls_available || tls_done)
33 return util_finish (command, RESP_BAD, "Invalid command"); 42 return util_finish (command, RESP_BAD, "Invalid command");
34 43
35 if (util_getword (arg, &sp)) 44 if (imap4d_tokbuf_argc (tok) != 2)
36 return util_finish (command, RESP_BAD, "Too many args"); 45 return util_finish (command, RESP_BAD, "Invalid arguments");
37 46
38 util_atexit (mu_deinit_tls_libs); 47 util_atexit (mu_deinit_tls_libs);
39 48
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2005, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -53,10 +53,21 @@ status_get_handler (const char *name) ...@@ -53,10 +53,21 @@ status_get_handler (const char *name)
53 return NULL; 53 return NULL;
54 } 54 }
55 55
56 /*
57 6.3.10. STATUS Command
58
59 Arguments: mailbox name
60 status data item names
61
62 Responses: untagged responses: STATUS
63
64 Result: OK - status completed
65 NO - status failure: no status for that name
66 BAD - command unknown or arguments invalid
67 */
56 int 68 int
57 imap4d_status (struct imap4d_command *command, char *arg) 69 imap4d_status (struct imap4d_command *command, imap4d_tokbuf_t tok)
58 { 70 {
59 char *sp = NULL;
60 char *name; 71 char *name;
61 char *mailbox_name; 72 char *mailbox_name;
62 const char *delim = "/"; 73 const char *delim = "/";
...@@ -64,11 +75,12 @@ imap4d_status (struct imap4d_command *command, char *arg) ...@@ -64,11 +75,12 @@ imap4d_status (struct imap4d_command *command, char *arg)
64 int status; 75 int status;
65 int count = 0; 76 int count = 0;
66 char *err_msg = NULL; 77 char *err_msg = NULL;
78 int argc = imap4d_tokbuf_argc (tok);
79
80 if (argc < 4)
81 return util_finish (command, RESP_BAD, "Invalid arguments");
67 82
68 name = util_getword (arg, &sp); 83 name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
69 util_unquote (&name);
70 if (!name || *name == '\0' || !sp || *sp == '\0')
71 return util_finish (command, RESP_BAD, "Too few args");
72 84
73 mailbox_name = namespace_getfullpath (name, delim); 85 mailbox_name = namespace_getfullpath (name, delim);
74 86
...@@ -85,20 +97,22 @@ imap4d_status (struct imap4d_command *command, char *arg) ...@@ -85,20 +97,22 @@ imap4d_status (struct imap4d_command *command, char *arg)
85 status = mu_mailbox_open (smbox, MU_STREAM_READ); 97 status = mu_mailbox_open (smbox, MU_STREAM_READ);
86 if (status == 0) 98 if (status == 0)
87 { 99 {
88 char item[32]; 100 int i = IMAP4_ARG_2;
89 item[0] = '\0'; 101 char *item = imap4d_tokbuf_getarg (tok, i);
90 102
91 if (*sp == '(') 103 if (item[0] == '(')
92 sp++; 104 {
93 else 105 if (imap4d_tokbuf_getarg (tok, argc - 1)[0] != ')')
94 *sp = 0; 106 return util_finish (command, RESP_BAD, "Invalid arguments");
107 argc--;
108 i++;
109 }
95 110
96 /* Get the status item names. */ 111 for (; i < argc; i++)
97 while (*sp && *sp != ')')
98 { 112 {
99 status_funcp fun; 113 status_funcp fun;
100 114
101 util_token (item, sizeof (item), &sp); 115 item = imap4d_tokbuf_getarg (tok, i);
102 fun = status_get_handler (item); 116 fun = status_get_handler (item);
103 if (!fun) 117 if (!fun)
104 { 118 {
...@@ -112,6 +126,8 @@ imap4d_status (struct imap4d_command *command, char *arg) ...@@ -112,6 +126,8 @@ imap4d_status (struct imap4d_command *command, char *arg)
112 if (!fun (smbox)) 126 if (!fun (smbox))
113 util_send (" "); 127 util_send (" ");
114 } 128 }
129
130
115 if (count > 0) 131 if (count > 0)
116 util_send (")\r\n"); 132 util_send (")\r\n");
117 mu_mailbox_close (smbox); 133 mu_mailbox_close (smbox);
...@@ -193,5 +209,4 @@ status_unseen (mu_mailbox_t smbox) ...@@ -193,5 +209,4 @@ status_unseen (mu_mailbox_t smbox)
193 } 209 }
194 util_send ("UNSEEN %d", unseen); 210 util_send ("UNSEEN %d", unseen);
195 return 0; 211 return 0;
196
197 } 212 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2005, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -23,134 +23,155 @@ ...@@ -23,134 +23,155 @@
23 */ 23 */
24 24
25 int 25 int
26 imap4d_store (struct imap4d_command *command, char *arg) 26 imap4d_store (struct imap4d_command *command, imap4d_tokbuf_t tok)
27 { 27 {
28 int rc; 28 int rc;
29 char buffer[64]; 29 char *err_text;
30 30
31 rc = imap4d_store0 (arg, 0, buffer, sizeof buffer); 31 rc = imap4d_store0 (tok, 0, &err_text);
32 return util_finish (command, rc, "%s", buffer); 32 return util_finish (command, rc, "%s", err_text);
33 }
34
35 struct parsebuf
36 {
37 char *token;
38 imap4d_tokbuf_t tok;
39 int arg;
40 jmp_buf errjmp;
41 char *err_text;
42 };
43
44 static void
45 parsebuf_exit (struct parsebuf *p, char *text)
46 {
47 p->err_text = text;
48 longjmp (p->errjmp, 1);
49 }
50
51 static char *
52 parsebuf_next (struct parsebuf *p, int req)
53 {
54 p->token = imap4d_tokbuf_getarg (p->tok, p->arg++);
55 if (!p->token && req)
56 parsebuf_exit (p, "Too few arguments");
57 return p->token;
33 } 58 }
34 59
35 int 60 int
36 imap4d_store0 (char *arg, int isuid, char *resp, size_t resplen) 61 imap4d_store0 (imap4d_tokbuf_t tok, int isuid, char **ptext)
37 { 62 {
38 char *msgset; 63 char *msgset;
39 char *data;
40 char *sp = NULL;
41 int status; 64 int status;
42 int ack = 0; 65 int ack = 1;
43 size_t i; 66 size_t i;
44 int n = 0; 67 int n = 0;
45 size_t *set = NULL; 68 size_t *set = NULL;
46 enum value_type { STORE_SET, STORE_ADD, STORE_UNSET } how; 69 enum value_type { STORE_SET, STORE_ADD, STORE_UNSET } how;
70 struct parsebuf pb;
71 char *data;
72 int type = 0;
47 73
48 msgset = util_getword (arg, &sp); 74 pb.tok = tok;
49 data = util_getword (NULL, &sp); 75 pb.arg = IMAP4_ARG_1;
50 76 pb.err_text = NULL;
51 if (!msgset || !data || !sp || *sp == '\0') 77 if (setjmp (pb.errjmp))
52 { 78 {
53 snprintf (resp, resplen, "Too few args"); 79 *ptext = pb.err_text;
80 free (set);
54 return RESP_BAD; 81 return RESP_BAD;
55 } 82 }
56 83
57 /* The parsing of the data-item is a little slugish. */ 84 msgset = parsebuf_next (&pb, 1);
58 if (strcasecmp (data, "FLAGS") == 0) 85 data = parsebuf_next (&pb, 1);
59 { 86
60 ack = 1; 87 if (*data == '+')
61 how = STORE_SET;
62 }
63 else if (strcasecmp (data, "+FLAGS") == 0)
64 { 88 {
65 ack = 1;
66 how = STORE_ADD; 89 how = STORE_ADD;
90 data++;
67 } 91 }
68 else if (strcasecmp (data, "-FLAGS") == 0) 92 else if (*data == '-')
69 { 93 {
70 ack = 1;
71 how = STORE_UNSET; 94 how = STORE_UNSET;
95 data++;
72 } 96 }
73 else if (strcasecmp (data, "FLAGS.SILENT") == 0) 97 else
74 {
75 ack = 0;
76 how = STORE_SET; 98 how = STORE_SET;
77 } 99
78 else if (strcasecmp (data, "+FLAGS.SILENT") == 0) 100 if (strcasecmp (data, "FLAGS"))
101 parsebuf_exit (&pb, "Bogus data item");
102 data = parsebuf_next (&pb, 1);
103
104 if (*data == '.')
79 { 105 {
80 ack = 0; 106 data = parsebuf_next (&pb, 1);
81 how = STORE_ADD; 107 if (strcasecmp (data, "SILENT") == 0)
82 }
83 else if (strcasecmp (data, "-FLAGS.SILENT") == 0)
84 { 108 {
85 ack = 0; 109 ack = 0;
86 how = STORE_UNSET; 110 parsebuf_next (&pb, 1);
87 } 111 }
88 else 112 else
89 { 113 parsebuf_exit (&pb, "Bogus data suffix");
90 snprintf (resp, resplen, "Bogus data item");
91 return RESP_BAD;
92 } 114 }
93 115
94 /* Get the message numbers in set[]. */ 116 /* Get the message numbers in set[]. */
95 status = util_msgset (msgset, &set, &n, isuid); 117 status = util_msgset (msgset, &set, &n, isuid);
96 if (status != 0) 118 if (status != 0)
119 parsebuf_exit (&pb, "Bogus number set");
120
121 if (pb.token[0] != '(')
122 parsebuf_exit (&pb, "Syntax error");
123 parsebuf_next (&pb, 1);
124
125 do
97 { 126 {
98 snprintf (resp, resplen, "Bogus number set"); 127 int t;
99 return RESP_BAD; 128 if (!util_attribute_to_type (pb.token, &t))
129 type |= t;
100 } 130 }
131 while (parsebuf_next (&pb, 1) && pb.token[0] != ')');
101 132
102 for (i = 0; i < n; i++) 133 for (i = 0; i < n; i++)
103 { 134 {
104 mu_message_t msg = NULL; 135 mu_message_t msg = NULL;
105 mu_attribute_t attr = NULL; 136 mu_attribute_t attr = NULL;
106 char *items = strdup (sp); /* Don't use the orignal list. */ 137 size_t msgno = isuid ? uid_to_msgno (set[i]) : set[i];
107 int first = 1;
108 size_t msgno;
109 char *p = items;
110 138
111 msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
112 if (msgno) 139 if (msgno)
113 { 140 {
114 mu_mailbox_get_message (mbox, msgno, &msg); 141 mu_mailbox_get_message (mbox, msgno, &msg);
115 mu_message_get_attribute (msg, &attr); 142 mu_message_get_attribute (msg, &attr);
116 143
117 /* Get the fetch command names. */ 144 switch (how)
118 while (*items && *items != ')')
119 { 145 {
120 int type = 0; 146 case STORE_ADD:
121 char item[64] = "";
122 util_token (item, sizeof (item), &items);
123 if (!util_attribute_to_type (item, &type))
124 {
125 if (how == STORE_ADD )
126 mu_attribute_set_flags (attr, type); 147 mu_attribute_set_flags (attr, type);
127 else if (how == STORE_UNSET ) 148 break;
149
150 case STORE_UNSET:
128 mu_attribute_unset_flags (attr, type); 151 mu_attribute_unset_flags (attr, type);
129 else if (how == STORE_SET ) 152 break;
130 { 153
131 if (first) 154 case STORE_SET:
132 { 155 mu_attribute_unset_flags (attr, 0xffffffff); /* FIXME */
133 mu_attribute_set_flags (attr, 0);
134 first = 0;
135 }
136 mu_attribute_set_flags (attr, type); 156 mu_attribute_set_flags (attr, type);
137 } 157 }
138 mu_attribute_set_flags (attr, MU_ATTRIBUTE_MODIFIED);
139 }
140 }
141 } 158 }
159
142 if (ack) 160 if (ack)
143 { 161 {
144 util_send ("* %d FETCH (", msgno); 162 util_send ("* %d FETCH (", msgno);
145 fetch_flags0 ("FLAGS", msg, isuid); 163
146 util_send (")\r\n"); 164 if (isuid)
165 util_send ("UID %lu ", (unsigned long) msgno);
166 util_send ("FLAGS (");
167 util_print_flags (attr);
168 util_send ("))\r\n");
147 } 169 }
148 free (p);
149 /* Update the flags of uid table. */ 170 /* Update the flags of uid table. */
150 imap4d_sync_flags (set[i]); 171 imap4d_sync_flags (set[i]);
151 } 172 }
152 free (set); 173 free (set);
153 snprintf (resp, resplen, "Completed"); 174 *ptext = "Completed";
154 return RESP_OK; 175 return RESP_OK;
155 } 176 }
156 177
......
...@@ -19,21 +19,27 @@ ...@@ -19,21 +19,27 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 /* 21 /*
22 FIXME: We need to lock the file to prevent simultaneous access. 22 6.3.6. SUBSCRIBE Command
23 */
24 23
24 Arguments: mailbox
25
26 Responses: no specific responses for this command
27
28 Result: OK - subscribe completed
29 NO - subscribe failure: can't subscribe to that name
30 BAD - command unknown or arguments invalid
31 */
25 int 32 int
26 imap4d_subscribe (struct imap4d_command *command, char *arg) 33 imap4d_subscribe (struct imap4d_command *command, imap4d_tokbuf_t tok)
27 { 34 {
28 char *sp = NULL;
29 char *name; 35 char *name;
30 char *file; 36 char *file;
31 FILE *fp; 37 FILE *fp;
32 38
33 name = util_getword (arg, &sp); 39 if (imap4d_tokbuf_argc (tok) != 3)
34 util_unquote (&name); 40 return util_finish (command, RESP_BAD, "Invalid arguments");
35 if (!name || *name == '\0') 41
36 return util_finish (command, RESP_BAD, "Too few arguments"); 42 name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
37 43
38 asprintf (&file, "%s/.mailboxlist", homedir); 44 asprintf (&file, "%s/.mailboxlist", homedir);
39 fp = fopen (file, "a"); 45 fp = fopen (file, "a");
......
1 # -*- tcl -*- 1 # -*- tcl -*-
2 # This file is part of Mailutils testsuite. 2 # This file is part of Mailutils testsuite.
3 # Copyright (C) 2002, 2007 Free Software Foundation 3 # Copyright (C) 2002, 2007, 2008 Free Software Foundation
4 # 4 #
5 # This program is free software; you can redistribute it and/or modify 5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by 6 # it under the terms of the GNU General Public License as published by
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
20 imap4d_start 20 imap4d_start
21 21
22 imap4d_test "CAPABILITY" \ 22 imap4d_test "CAPABILITY" \
23 "CAPABILITY IMAP4rev1 NAMESPACE IDLE X-VERSION" \ 23 "CAPABILITY IMAP4rev1 NAMESPACE IDLE LITERAL+ X-VERSION" \
24 "OK" 24 "OK"
25 imap4d_test "NOOP" 25 imap4d_test "NOOP"
26 26
......
...@@ -48,7 +48,7 @@ Hello Joe, do you think we can meet at 3:30 tomorrow? ...@@ -48,7 +48,7 @@ Hello Joe, do you think we can meet at 3:30 tomorrow?
48 48
49 " 49 "
50 50
51 imap4d_test -long "APPEND mbox 25-Aug-2002 18:00:00 +0200"\ 51 imap4d_test -long "APPEND mbox \"25-Aug-2002 18:00:00 +0200\""\
52 "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) 52 "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
53 From: Fred Foobar <foobar@Blurdybloop.COM> 53 From: Fred Foobar <foobar@Blurdybloop.COM>
54 Subject: afternoon meeting again 54 Subject: afternoon meeting again
...@@ -72,7 +72,7 @@ imap4d_test "SELECT mbox"\ ...@@ -72,7 +72,7 @@ imap4d_test "SELECT mbox"\
72 "OK" 72 "OK"
73 73
74 imap4d_test "FETCH 2:3 BODY\[\]"\ 74 imap4d_test "FETCH 2:3 BODY\[\]"\
75 "2 FETCH (FLAGS (\\Seen) BODY\[\] {310}"\ 75 "2 FETCH (FLAGS (\\Seen) BODY\[\] {312}"\
76 -literal\ 76 -literal\
77 "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)"\ 77 "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)"\
78 "From: Fred Foobar <foobar@Blurdybloop.COM>"\ 78 "From: Fred Foobar <foobar@Blurdybloop.COM>"\
...@@ -83,9 +83,10 @@ imap4d_test "FETCH 2:3 BODY\[\]"\ ...@@ -83,9 +83,10 @@ imap4d_test "FETCH 2:3 BODY\[\]"\
83 "Content-Type: TEXT/PLAIN; CHARSET=US-ASCII"\ 83 "Content-Type: TEXT/PLAIN; CHARSET=US-ASCII"\
84 ""\ 84 ""\
85 "Hello Joe, do you think we can meet at 3:30 tomorrow?"\ 85 "Hello Joe, do you think we can meet at 3:30 tomorrow?"\
86 ""\
86 ")"\ 87 ")"\
87 -noliteral\ 88 -noliteral\
88 "3 FETCH (FLAGS (\\Seen) BODY\[\] {283}"\ 89 "3 FETCH (FLAGS (\\Seen) BODY\[\] {285}"\
89 -literal\ 90 -literal\
90 "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)"\ 91 "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)"\
91 "From: Fred Foobar <foobar@Blurdybloop.COM>"\ 92 "From: Fred Foobar <foobar@Blurdybloop.COM>"\
......
...@@ -37,7 +37,7 @@ imap4d_test "CREATE flat" ...@@ -37,7 +37,7 @@ imap4d_test "CREATE flat"
37 37
38 imap4d_test "CREATE en/to/tre" 38 imap4d_test "CREATE en/to/tre"
39 39
40 imap4d_test -long "APPEND en/to/tre 25-Aug-2002 18:00:00 +0200"\ 40 imap4d_test -long "APPEND en/to/tre \"25-Aug-2002 18:00:00 +0200\""\
41 "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) 41 "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
42 From: Fred Foobar <foobar@Blurdybloop.COM> 42 From: Fred Foobar <foobar@Blurdybloop.COM>
43 Subject: afternoon meeting again 43 Subject: afternoon meeting again
...@@ -65,7 +65,7 @@ imap4d_test "SELECT en/to/tre"\ ...@@ -65,7 +65,7 @@ imap4d_test "SELECT en/to/tre"\
65 "OK \[READ-WRITE\] SELECT Completed" 65 "OK \[READ-WRITE\] SELECT Completed"
66 66
67 imap4d_test "FETCH 1 ALL"\ 67 imap4d_test "FETCH 1 ALL"\
68 "1 FETCH (FLAGS (\\Recent) INTERNALDATE \"25-Aug-2002 16:00:00 +0000\" RFC822.SIZE 283 ENVELOPE (\"Mon, 7 Feb 1994 21:52:25 -0800 (PST)\" \"afternoon meeting again\" ((\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\")) ((\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\")) ((\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\")) ((NIL NIL \"mooch\" \"owatagu.siam.edu\")) NIL NIL NIL \"<B27397-0200000@Blurdybloop.COM>\"))"\ 68 "1 FETCH (FLAGS (\\Recent) INTERNALDATE \"25-Aug-2002 16:00:00 +0000\" RFC822.SIZE 285 ENVELOPE (\"Mon, 7 Feb 1994 21:52:25 -0800 (PST)\" \"afternoon meeting again\" ((\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\")) ((\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\")) ((\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\")) ((NIL NIL \"mooch\" \"owatagu.siam.edu\")) NIL NIL NIL \"<B27397-0200000@Blurdybloop.COM>\"))"\
69 "OK" 69 "OK"
70 70
71 71
......
...@@ -165,7 +165,7 @@ imap4d_test "FETCH 1 BODY\[HEADER\]"\ ...@@ -165,7 +165,7 @@ imap4d_test "FETCH 1 BODY\[HEADER\]"\
165 # The subset returned by HEADER.FIELDS contains only those header fields 165 # The subset returned by HEADER.FIELDS contains only those header fields
166 # with a field-name that matches one of the names in the list; 166 # with a field-name that matches one of the names in the list;
167 167
168 imap4d_test "FETCH 1 BODY\[HEADER.FIELDS FROM TO SUBJECT\]"\ 168 imap4d_test "FETCH 1 BODY\[HEADER.FIELDS (FROM TO SUBJECT)\]"\
169 "1 FETCH (BODY\[HEADER.FIELDS (\"FROM\" \"TO\" \"SUBJECT\")\] {94}"\ 169 "1 FETCH (BODY\[HEADER.FIELDS (\"FROM\" \"TO\" \"SUBJECT\")\] {94}"\
170 -literal\ 170 -literal\
171 "FROM: Foo Bar <foobar@nonexistent.net>"\ 171 "FROM: Foo Bar <foobar@nonexistent.net>"\
...@@ -178,7 +178,7 @@ imap4d_test "FETCH 1 BODY\[HEADER.FIELDS FROM TO SUBJECT\]"\ ...@@ -178,7 +178,7 @@ imap4d_test "FETCH 1 BODY\[HEADER.FIELDS FROM TO SUBJECT\]"\
178 # similarly, the subset returned by HEADER.FIELDS.NOT contains only 178 # similarly, the subset returned by HEADER.FIELDS.NOT contains only
179 # the header fields with a non-matching field-name. 179 # the header fields with a non-matching field-name.
180 180
181 imap4d_test "FETCH 1 BODY\[HEADER.FIELDS.NOT FROM TO SUBJECT\]"\ 181 imap4d_test "FETCH 1 BODY\[HEADER.FIELDS.NOT (FROM TO SUBJECT)\]"\
182 "1 FETCH (BODY\[HEADER.FIELDS.NOT (\"FROM\" \"TO\" \"SUBJECT\")\] {235}"\ 182 "1 FETCH (BODY\[HEADER.FIELDS.NOT (\"FROM\" \"TO\" \"SUBJECT\")\] {235}"\
183 -literal\ 183 -literal\
184 "Received: (from foobar@nonexistent.net) "\ 184 "Received: (from foobar@nonexistent.net) "\
...@@ -330,8 +330,13 @@ imap4d_test "FETCH 3 BODY\[1.MIME\]"\ ...@@ -330,8 +330,13 @@ imap4d_test "FETCH 3 BODY\[1.MIME\]"\
330 "OK" 330 "OK"
331 331
332 imap4d_test "FETCH 4 BODY\[2.2.1\]"\ 332 imap4d_test "FETCH 4 BODY\[2.2.1\]"\
333 "4 FETCH (FLAGS (\\Seen) BODY\[2.2.1\] {490}"\ 333 "4 FETCH (FLAGS (\\Seen) BODY\[2.2.1\] {680}"\
334 -literal\ 334 -literal\
335 "Content-Type: application/octet-stream; name=\"msg.23\""\
336 "Content-ID: <5122.1026510654.6@Mirddin.farlep.net>"\
337 "Content-Description: Father William Part III"\
338 "Content-Transfer-Encoding: base64"\
339 ""\
335 "YFlvdSBhcmUgb2xkLCcgc2FpZCB0aGUgeW91dGgsIGBhbmQgeW91ciBqYXdzIGFyZSB0b28gd2Vh"\ 340 "YFlvdSBhcmUgb2xkLCcgc2FpZCB0aGUgeW91dGgsIGBhbmQgeW91ciBqYXdzIGFyZSB0b28gd2Vh"\
336 "awpGb3IgYW55dGhpbmcgdG91Z2hlciB0aGFuIHN1ZXQ7CllldCB5b3UgZmluaXNoZWQgdGhlIGdv"\ 341 "awpGb3IgYW55dGhpbmcgdG91Z2hlciB0aGFuIHN1ZXQ7CllldCB5b3UgZmluaXNoZWQgdGhlIGdv"\
337 "b3NlLCB3aXRoIHRoZSBib25lcyBhbmQgdGhlIGJlYWstLQpQcmF5IGhvdyBkaWQgeW91IG1hbmFn"\ 342 "b3NlLCB3aXRoIHRoZSBib25lcyBhbmQgdGhlIGJlYWstLQpQcmF5IGhvdyBkaWQgeW91IG1hbmFn"\
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -24,36 +24,29 @@ ...@@ -24,36 +24,29 @@
24 */ 24 */
25 25
26 int 26 int
27 imap4d_uid (struct imap4d_command *command, char *arg) 27 imap4d_uid (struct imap4d_command *command, imap4d_tokbuf_t tok)
28 { 28 {
29 char *cmd; 29 char *cmd;
30 char *sp = NULL;
31 int rc = RESP_NO; 30 int rc = RESP_NO;
32 char buffer[64]; 31 char *err_text = "Completed";
32
33 if (imap4d_tokbuf_argc (tok) < 3)
34 return util_finish (command, RESP_BAD, "Invalid arguments");
35
36 cmd = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
33 37
34 cmd = util_getword (arg, &sp);
35 if (!cmd)
36 util_finish (command, RESP_BAD, "Too few args");
37 if (strcasecmp (cmd, "FETCH") == 0) 38 if (strcasecmp (cmd, "FETCH") == 0)
38 { 39 rc = imap4d_fetch0 (tok, 1, &err_text);
39 rc = imap4d_fetch0 (sp, 1, buffer, sizeof buffer);
40 }
41 else if (strcasecmp (cmd, "COPY") == 0) 40 else if (strcasecmp (cmd, "COPY") == 0)
42 { 41 rc = imap4d_copy0 (tok, 1, &err_text);
43 rc = imap4d_copy0 (sp, 1, buffer, sizeof buffer);
44 }
45 else if (strcasecmp (cmd, "STORE") == 0) 42 else if (strcasecmp (cmd, "STORE") == 0)
46 { 43 rc = imap4d_store0 (tok, 1, &err_text);
47 rc = imap4d_store0 (sp, 1, buffer, sizeof buffer);
48 }
49 else if (strcasecmp (cmd, "SEARCH") == 0) 44 else if (strcasecmp (cmd, "SEARCH") == 0)
50 { 45 rc = imap4d_search0 (tok, 1, &err_text);
51 rc = imap4d_search0 (sp, 1, buffer, sizeof buffer);
52 }
53 else 46 else
54 { 47 {
55 snprintf (buffer, sizeof buffer, "Error uknown uid command"); 48 err_text = "Uknown uid command";
56 rc = RESP_BAD; 49 rc = RESP_BAD;
57 } 50 }
58 return util_finish (command, rc, "%s %s", cmd, buffer); 51 return util_finish (command, rc, "%s %s", cmd, err_text);
59 } 52 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -71,19 +71,34 @@ unsubscribe (struct scan_data *data, char *name) ...@@ -71,19 +71,34 @@ unsubscribe (struct scan_data *data, char *name)
71 return 0; 71 return 0;
72 } 72 }
73 73
74 /*
75 6.3.7. UNSUBSCRIBE Command
76
77 Arguments: mailbox name
78
79 Responses: no specific responses for this command
80
81 Result: OK - unsubscribe completed
82 NO - unsubscribe failure: can't unsubscribe that name
83 BAD - command unknown or arguments invalid
84
85 The UNSUBSCRIBE command removes the specified mailbox name from
86 the server's set of "active" or "subscribed" mailboxes as returned
87 by the LSUB command. This command returns a tagged OK response
88 only if the unsubscription is successful.
89 */
74 int 90 int
75 imap4d_unsubscribe (struct imap4d_command *command, char *arg) 91 imap4d_unsubscribe (struct imap4d_command *command, imap4d_tokbuf_t tok)
76 { 92 {
77 char *sp = NULL;
78 char *name; 93 char *name;
79 char *file; 94 char *file;
80 struct scan_data sd; 95 struct scan_data sd;
81 int rc; 96 int rc;
82 97
83 name = util_getword (arg, &sp); 98 if (imap4d_tokbuf_argc (tok) != 3)
84 util_unquote (&name); 99 return util_finish (command, RESP_BAD, "Invalid arguments");
85 if (!name || *name == '\0') 100
86 return util_finish (command, RESP_BAD, "Too few arguments"); 101 name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
87 102
88 asprintf (&file, "%s/.mailboxlist", homedir); 103 asprintf (&file, "%s/.mailboxlist", homedir);
89 sd.result = 0; 104 sd.result = 0;
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2007, 2008 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -19,8 +19,10 @@ ...@@ -19,8 +19,10 @@
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 int 21 int
22 imap4d_version (struct imap4d_command *command, char *arg) 22 imap4d_version (struct imap4d_command *command, imap4d_tokbuf_t tok)
23 { 23 {
24 if (imap4d_tokbuf_argc (tok) != 2)
25 return util_finish (command, RESP_BAD, "Invalid arguments");
24 util_send ("* %s GNU %s\r\n", command->name, program_version); 26 util_send ("* %s GNU %s\r\n", command->name, program_version);
25 return util_finish (command, RESP_OK, "Completed"); 27 return util_finish (command, RESP_OK, "Completed");
26 } 28 }
......
...@@ -145,7 +145,7 @@ mail_tmp_finish (struct mail_tmp *mtmp, mu_mailbox_t *mbox) ...@@ -145,7 +145,7 @@ mail_tmp_finish (struct mail_tmp *mtmp, mu_mailbox_t *mbox)
145 } 145 }
146 146
147 mu_stream_flush (mtmp->stream); 147 mu_stream_flush (mtmp->stream);
148 if ((status = mu_mailbox_create (mbox, "/dev/null")) 148 if ((status = mu_mailbox_create (mbox, "mbox:/dev/null"))
149 || (status = mu_mailbox_open (*mbox, MU_STREAM_READ)) 149 || (status = mu_mailbox_open (*mbox, MU_STREAM_READ))
150 || (status = mu_mailbox_set_stream (*mbox, mtmp->stream))) 150 || (status = mu_mailbox_set_stream (*mbox, mtmp->stream)))
151 { 151 {
......
...@@ -51,7 +51,7 @@ _memory_destroy (mu_stream_t stream) ...@@ -51,7 +51,7 @@ _memory_destroy (mu_stream_t stream)
51 struct _memory_stream *mfs = mu_stream_get_owner (stream); 51 struct _memory_stream *mfs = mu_stream_get_owner (stream);
52 if (mfs && mfs->ptr != NULL) 52 if (mfs && mfs->ptr != NULL)
53 free (mfs->ptr); 53 free (mfs->ptr);
54 if(mfs->filename) 54 if (mfs->filename)
55 free (mfs->filename); 55 free (mfs->filename);
56 free (mfs); 56 free (mfs);
57 } 57 }
......