Commit b12c4638 b12c4638805b9528800f319283536b3e0bb2fb13 by Sergey Poznyakoff

imap4d: CLOSE should not send EXPUNGE responses. Fix error checking in STORE.

* imap4d/imap4d.h (silent_expunge): New global.
* imap4d/sync.c (silent_expunge): New variable.
(action): Suppress EXPUNGE responses if silent_expunge is set.
* imap4d/close.c (imap4d_close0): Set silent_expunge before calling
mu_mailbox_flush.

* imap4d/tests/close-expunge.at: New test.
* imap4d/tests/testsuite.at: Include close-expunge.at.
* imap4d/tests/Makefile.am (TESTSUITE_AT): Add close-expunge.at.

* imap4d/fetch.c (fetch_thunk): Emit BAD response if failed to parse
message set.
* imap4d/store.c (store_thunk): Emit BAD response if failed to parse
flags.
1 parent ea8772cd
...@@ -30,9 +30,11 @@ imap4d_close0 (struct imap4d_command *command, imap4d_tokbuf_t tok, ...@@ -30,9 +30,11 @@ imap4d_close0 (struct imap4d_command *command, imap4d_tokbuf_t tok,
30 mu_mailbox_get_flags (mbox, &flags); 30 mu_mailbox_get_flags (mbox, &flags);
31 if (flags & MU_STREAM_WRITE) 31 if (flags & MU_STREAM_WRITE)
32 { 32 {
33 silent_expunge = expunge;
33 imap4d_enter_critical (); 34 imap4d_enter_critical ();
34 status = mu_mailbox_flush (mbox, expunge); 35 status = mu_mailbox_flush (mbox, expunge);
35 imap4d_leave_critical (); 36 imap4d_leave_critical ();
37 silent_expunge = 0;
36 if (status) 38 if (status)
37 { 39 {
38 mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_flush", NULL, status); 40 mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_flush", NULL, status);
...@@ -69,9 +71,11 @@ imap4d_close0 (struct imap4d_command *command, imap4d_tokbuf_t tok, ...@@ -69,9 +71,11 @@ imap4d_close0 (struct imap4d_command *command, imap4d_tokbuf_t tok,
69 NO - close failure: no mailbox selected 71 NO - close failure: no mailbox selected
70 BAD - command unknown or arguments invalid 72 BAD - command unknown or arguments invalid
71 73
72 The CLOSE command permanently removes from the currently selected 74 The CLOSE command permanently removes all messages that have the
73 mailbox all messages that have the \\Deleted flag set, and returns 75 \Deleted flag set from the currently selected mailbox, and returns
74 to authenticated state from selected state. */ 76 to the authenticated state from the selected state. No untagged
77 EXPUNGE responses are sent. */
78
75 int 79 int
76 imap4d_close (struct imap4d_command *command, imap4d_tokbuf_t tok) 80 imap4d_close (struct imap4d_command *command, imap4d_tokbuf_t tok)
77 { 81 {
......
...@@ -1778,13 +1778,10 @@ fetch_thunk (imap4d_parsebuf_t pb) ...@@ -1778,13 +1778,10 @@ fetch_thunk (imap4d_parsebuf_t pb)
1778 FIXME: This code also causes imap4d to silently ignore erroneous 1778 FIXME: This code also causes imap4d to silently ignore erroneous
1779 msgset specifications (e.g. FETCH foobar (FLAGS)), which should 1779 msgset specifications (e.g. FETCH foobar (FLAGS)), which should
1780 be fixed. */ 1780 be fixed. */
1781
1782 pb->err_text = "Completed";
1783 return RESP_OK; 1781 return RESP_OK;
1784 1782
1785 default: 1783 default:
1786 pb->err_text = "Failed to parse message set"; 1784 imap4d_parsebuf_exit (pb, "Failed to parse message set");
1787 return RESP_NO;
1788 } 1785 }
1789 1786
1790 /* Compile the expression */ 1787 /* Compile the expression */
......
...@@ -205,6 +205,7 @@ extern char **imap4d_argv; ...@@ -205,6 +205,7 @@ extern char **imap4d_argv;
205 extern jmp_buf child_jmp; 205 extern jmp_buf child_jmp;
206 206
207 extern int test_mode; 207 extern int test_mode;
208 extern int silent_expunge;
208 209
209 /* Input functions */ 210 /* Input functions */
210 extern mu_stream_t iostream; 211 extern mu_stream_t iostream;
......
...@@ -79,12 +79,10 @@ store_thunk (imap4d_parsebuf_t p) ...@@ -79,12 +79,10 @@ store_thunk (imap4d_parsebuf_t p)
79 case EINVAL: 79 case EINVAL:
80 /* See RFC 3501, section 6.4.8, and a comment to the equivalent code 80 /* See RFC 3501, section 6.4.8, and a comment to the equivalent code
81 in fetch.c */ 81 in fetch.c */
82 p->err_text = "Completed";
83 return RESP_OK; 82 return RESP_OK;
84 83
85 default: 84 default:
86 p->err_text = "Failed to parse message set"; 85 imap4d_parsebuf_exit (p, "Failed to parse message set");
87 return RESP_NO;
88 } 86 }
89 87
90 if (p->token[0] != '(') 88 if (p->token[0] != '(')
...@@ -94,7 +92,9 @@ store_thunk (imap4d_parsebuf_t p) ...@@ -94,7 +92,9 @@ store_thunk (imap4d_parsebuf_t p)
94 do 92 do
95 { 93 {
96 int t; 94 int t;
97 if (!util_attribute_to_type (p->token, &t)) 95 if (util_attribute_to_type (p->token, &t))
96 imap4d_parsebuf_exit (p, "Failed to parse flags");
97 else
98 pclos->type |= t; 98 pclos->type |= t;
99 } 99 }
100 while (imap4d_parsebuf_next (p, 1) && p->token[0] != ')'); 100 while (imap4d_parsebuf_next (p, 1) && p->token[0] != ')');
...@@ -173,9 +173,9 @@ int ...@@ -173,9 +173,9 @@ int
173 imap4d_store (struct imap4d_command *command, imap4d_tokbuf_t tok) 173 imap4d_store (struct imap4d_command *command, imap4d_tokbuf_t tok)
174 { 174 {
175 int rc; 175 int rc;
176 char *err_text; 176 char *err_text = NULL;
177 177
178 rc = imap4d_store0 (tok, 0, &err_text); 178 rc = imap4d_store0 (tok, 0, &err_text);
179 return io_completion_response (command, rc, "%s", err_text); 179 return io_completion_response (command, rc, "%s", err_text ? err_text : "");
180 } 180 }
181 181
......
...@@ -136,7 +136,11 @@ imap4d_sync_flags (size_t msgno) ...@@ -136,7 +136,11 @@ imap4d_sync_flags (size_t msgno)
136 return 0; 136 return 0;
137 } 137 }
138 138
139 int silent_expunge;
140 /* When true, non-tagged EXPUNGE responses are suppressed. */
141
139 static int mailbox_corrupt; 142 static int mailbox_corrupt;
143 /* When true, mailbox has been altered by another party. */
140 144
141 static int 145 static int
142 action (mu_observer_t observer, size_t type, void *data, void *action_data) 146 action (mu_observer_t observer, size_t type, void *data, void *action_data)
...@@ -158,6 +162,7 @@ action (mu_observer_t observer, size_t type, void *data, void *action_data) ...@@ -158,6 +162,7 @@ action (mu_observer_t observer, size_t type, void *data, void *action_data)
158 immediately decremented by 1, and this decrement is reflected in 162 immediately decremented by 1, and this decrement is reflected in
159 message sequence numbers in subsequent responses (including other 163 message sequence numbers in subsequent responses (including other
160 untagged EXPUNGE responses). */ 164 untagged EXPUNGE responses). */
165 if (!silent_expunge)
161 { 166 {
162 size_t *exp = data; 167 size_t *exp = data;
163 io_untagged_response (RESP_NONE, "%lu EXPUNGED", 168 io_untagged_response (RESP_NONE, "%lu EXPUNGED",
......
...@@ -42,6 +42,7 @@ TESTSUITE_AT = \ ...@@ -42,6 +42,7 @@ TESTSUITE_AT = \
42 anystate.at\ 42 anystate.at\
43 append00.at\ 43 append00.at\
44 append01.at\ 44 append01.at\
45 close-expunge.at\
45 create01.at\ 46 create01.at\
46 create02.at\ 47 create02.at\
47 examine.at\ 48 examine.at\
......
1 # This file is part of GNU Mailutils. -*- Autotest -*-
2 # Copyright (C) 2011 Free Software Foundation, Inc.
3 #
4 # GNU Mailutils is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3, or (at
7 # your option) any later version.
8 #
9 # GNU Mailutils is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
16
17 AT_SETUP([Close with expunge])
18 AT_KEYWORDS([close close-expunge])
19
20 # According to RFC3501, CLOSE command should not send untagged EXPUNGE
21 # responses even if expunge actually took place.
22
23 IMAP4D_CHECK([
24 MUT_MBCOPY($abs_top_srcdir/testsuite/spool/search.mbox,temp)
25 sed 's/^\(Status: .*\)/\1D/' temp > INBOX
26 ],
27 [1 SELECT INBOX
28 2 CLOSE
29 3 EXAMINE INBOX
30 X LOGOUT
31 ],
32 [* PREAUTH IMAP4rev1 Test mode
33 * 8 EXISTS
34 * 5 RECENT
35 * OK [[UIDNEXT 9]] Predicted next uid
36 * OK [[UNSEEN 4]] first unseen messsage
37 * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
38 * OK [[PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft)]] Permanent flags
39 1 OK [[READ-WRITE]] SELECT Completed
40 2 OK CLOSE Completed
41 * 5 EXISTS
42 * 0 RECENT
43 * OK [[UIDNEXT 9]] Predicted next uid
44 * OK [[UNSEEN 1]] first unseen messsage
45 * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
46 * OK [[PERMANENTFLAGS ()]] No permanent flags
47 3 OK [[READ-ONLY]] EXAMINE Completed
48 * BYE Session terminating.
49 X OK LOGOUT Completed
50 ])
51
52 AT_CLEANUP
...@@ -70,6 +70,7 @@ m4_include([select.at]) ...@@ -70,6 +70,7 @@ m4_include([select.at])
70 m4_include([examine.at]) 70 m4_include([examine.at])
71 m4_include([status.at]) 71 m4_include([status.at])
72 m4_include([expunge.at]) 72 m4_include([expunge.at])
73 m4_include([close-expunge.at])
73 m4_include([create01.at]) 74 m4_include([create01.at])
74 m4_include([create02.at]) 75 m4_include([create02.at])
75 76
......