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,
mu_mailbox_get_flags (mbox, &flags);
if (flags & MU_STREAM_WRITE)
{
silent_expunge = expunge;
imap4d_enter_critical ();
status = mu_mailbox_flush (mbox, expunge);
imap4d_leave_critical ();
silent_expunge = 0;
if (status)
{
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,
NO - close failure: no mailbox selected
BAD - command unknown or arguments invalid
The CLOSE command permanently removes from the currently selected
mailbox all messages that have the \\Deleted flag set, and returns
to authenticated state from selected state. */
The CLOSE command permanently removes all messages that have the
\Deleted flag set from the currently selected mailbox, and returns
to the authenticated state from the selected state. No untagged
EXPUNGE responses are sent. */
int
imap4d_close (struct imap4d_command *command, imap4d_tokbuf_t tok)
{
......
......@@ -1778,13 +1778,10 @@ fetch_thunk (imap4d_parsebuf_t pb)
FIXME: This code also causes imap4d to silently ignore erroneous
msgset specifications (e.g. FETCH foobar (FLAGS)), which should
be fixed. */
pb->err_text = "Completed";
return RESP_OK;
default:
pb->err_text = "Failed to parse message set";
return RESP_NO;
imap4d_parsebuf_exit (pb, "Failed to parse message set");
}
/* Compile the expression */
......
......@@ -205,6 +205,7 @@ extern char **imap4d_argv;
extern jmp_buf child_jmp;
extern int test_mode;
extern int silent_expunge;
/* Input functions */
extern mu_stream_t iostream;
......
......@@ -79,12 +79,10 @@ store_thunk (imap4d_parsebuf_t p)
case EINVAL:
/* See RFC 3501, section 6.4.8, and a comment to the equivalent code
in fetch.c */
p->err_text = "Completed";
return RESP_OK;
default:
p->err_text = "Failed to parse message set";
return RESP_NO;
imap4d_parsebuf_exit (p, "Failed to parse message set");
}
if (p->token[0] != '(')
......@@ -94,7 +92,9 @@ store_thunk (imap4d_parsebuf_t p)
do
{
int t;
if (!util_attribute_to_type (p->token, &t))
if (util_attribute_to_type (p->token, &t))
imap4d_parsebuf_exit (p, "Failed to parse flags");
else
pclos->type |= t;
}
while (imap4d_parsebuf_next (p, 1) && p->token[0] != ')');
......@@ -173,9 +173,9 @@ int
imap4d_store (struct imap4d_command *command, imap4d_tokbuf_t tok)
{
int rc;
char *err_text;
char *err_text = NULL;
rc = imap4d_store0 (tok, 0, &err_text);
return io_completion_response (command, rc, "%s", err_text);
return io_completion_response (command, rc, "%s", err_text ? err_text : "");
}
......
......@@ -136,7 +136,11 @@ imap4d_sync_flags (size_t msgno)
return 0;
}
int silent_expunge;
/* When true, non-tagged EXPUNGE responses are suppressed. */
static int mailbox_corrupt;
/* When true, mailbox has been altered by another party. */
static int
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)
immediately decremented by 1, and this decrement is reflected in
message sequence numbers in subsequent responses (including other
untagged EXPUNGE responses). */
if (!silent_expunge)
{
size_t *exp = data;
io_untagged_response (RESP_NONE, "%lu EXPUNGED",
......
......@@ -42,6 +42,7 @@ TESTSUITE_AT = \
anystate.at\
append00.at\
append01.at\
close-expunge.at\
create01.at\
create02.at\
examine.at\
......
# This file is part of GNU Mailutils. -*- Autotest -*-
# Copyright (C) 2011 Free Software Foundation, Inc.
#
# GNU Mailutils is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3, or (at
# your option) any later version.
#
# GNU Mailutils is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([Close with expunge])
AT_KEYWORDS([close close-expunge])
# According to RFC3501, CLOSE command should not send untagged EXPUNGE
# responses even if expunge actually took place.
IMAP4D_CHECK([
MUT_MBCOPY($abs_top_srcdir/testsuite/spool/search.mbox,temp)
sed 's/^\(Status: .*\)/\1D/' temp > INBOX
],
[1 SELECT INBOX
2 CLOSE
3 EXAMINE INBOX
X LOGOUT
],
[* PREAUTH IMAP4rev1 Test mode
* 8 EXISTS
* 5 RECENT
* OK [[UIDNEXT 9]] Predicted next uid
* OK [[UNSEEN 4]] first unseen messsage
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [[PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft)]] Permanent flags
1 OK [[READ-WRITE]] SELECT Completed
2 OK CLOSE Completed
* 5 EXISTS
* 0 RECENT
* OK [[UIDNEXT 9]] Predicted next uid
* OK [[UNSEEN 1]] first unseen messsage
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [[PERMANENTFLAGS ()]] No permanent flags
3 OK [[READ-ONLY]] EXAMINE Completed
* BYE Session terminating.
X OK LOGOUT Completed
])
AT_CLEANUP
......@@ -70,6 +70,7 @@ m4_include([select.at])
m4_include([examine.at])
m4_include([status.at])
m4_include([expunge.at])
m4_include([close-expunge.at])
m4_include([create01.at])
m4_include([create02.at])
......