summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-04-29 22:06:49 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2012-04-29 22:30:48 +0300
commite6ae2852edb142fcf84dc489715f8984843dfe0c (patch)
tree3f1ee3b8e88c17740452b257cf6a344066deac9e
parent1cf13b32d876b2f7ef0faf8f074142c376aeba1d (diff)
downloadmailutils-e6ae2852edb142fcf84dc489715f8984843dfe0c.tar.gz
mailutils-e6ae2852edb142fcf84dc489715f8984843dfe0c.tar.bz2
Implement a copy method in mailbox.
This method copies given messages (ificated by their sequence or UID numbers) to the given mailbox. So far this is implemented only in IMAP[S] folders. The mh/inc utility uses this method to optionally move incorporated messages to other folder (mailbox) instead of simply deleting them. * include/mailutils/imap.h (mu_imap_response) (mu_imap_response_code): New protos. (MU_IMAP_CB_TAGGED_OK,MU_IMAP_CB_TAGGED_NO) (MU_IMAP_CB_TAGGED_BAD): New callback codes. * include/mailutils/mailbox.h (MU_MAILBOX_COPY_UID) (MU_MAILBOX_COPY_CREAT): New constants. (mu_mailbox_msgset_copy) (mu_mailbox_message_copy): New protos. * include/mailutils/sys/imap.h (resp_code): Rename to response to avoid confusion. All uses updated. (response_code): New member. (_mu_imap_process_tagged_response): New proto. * include/mailutils/sys/mailbox.h (_mu_mailbox) <_copy>: New member. * libmailutils/mailbox/Makefile.am (libmailbox_la_SOURCES): Add copy.c * libmailutils/mailbox/copy.c: New file. * libproto/imap/err.c (mu_imap_response): New function. (mu_imap_response_code): New function. * libproto/imap/mbox.c (_imap_copy_to_mailbox) (_mu_imap_mailbox_init): Implement _copy method. * libproto/imap/resplist.c (IS_LBRACE,IS_RBRACE): Fix macros. * libproto/imap/response.c (_mu_imap_response): Call _mu_imap_process_tagged_response to process tagged responses. * libproto/imap/resproc.c (parse_response_code): Bugfix: expected ']' was set off by one. (resptab)<code>: New member. (_mu_imap_process_tagged_response): New function. * mh/inc.c (options, mh_option, opt_handler): New option --moveto. (move_to_mailbox): New variable. (main): If move_to_mailbox is set, move messages to that mailbox instead of deleting them. * mh/mh_getopt.h (mh_arg)<ARG_MOVETO>: New constant. * NEWS: Update. * include/mailutils/folder.h: Add a comment. * libmailutils/mailbox/folder.c: Minor formatting change.
-rw-r--r--NEWS19
-rw-r--r--include/mailutils/folder.h3
-rw-r--r--include/mailutils/imap.h23
-rw-r--r--include/mailutils/mailbox.h10
-rw-r--r--include/mailutils/sys/imap.h7
-rw-r--r--include/mailutils/sys/mailbox.h1
-rw-r--r--libmailutils/mailbox/Makefile.am1
-rw-r--r--libmailutils/mailbox/copy.c62
-rw-r--r--libmailutils/mailbox/folder.c13
-rw-r--r--libproto/imap/appstrsiz.c2
-rw-r--r--libproto/imap/capability.c2
-rw-r--r--libproto/imap/close.c2
-rw-r--r--libproto/imap/err.c18
-rw-r--r--libproto/imap/gencom.c2
-rw-r--r--libproto/imap/id.c2
-rw-r--r--libproto/imap/login.c2
-rw-r--r--libproto/imap/mbox.c36
-rw-r--r--libproto/imap/resplist.c4
-rw-r--r--libproto/imap/response.c37
-rw-r--r--libproto/imap/resproc.c75
-rw-r--r--libproto/imap/select.c2
-rw-r--r--libproto/imap/starttls.c2
-rw-r--r--libproto/imap/status.c2
-rw-r--r--libproto/imap/storeflg.c2
-rw-r--r--mh/inc.c38
-rw-r--r--mh/mh_getopt.h3
26 files changed, 307 insertions, 63 deletions
diff --git a/NEWS b/NEWS
index 90f044616..02291b47a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2012-02-26
+GNU mailutils NEWS -- history of user-visible changes. 2012-04-29
Copyright (C) 2002-2012 Free Software Foundation, Inc.
See the end of file for copying conditions.
@@ -116,6 +116,16 @@ See <http://mailutils.org/wiki/Timestamp_(Sieve_test)>.
** MH: improved compatibility with other implementations
+** MH inc: new option --moveto
+
+This option instructs the utility to move incorporated messages into
+another folder instead of deleting them. It is implemented only for
+input folders of type IMAP or IMAPS. A sample usage is:
+
+ inc -truncate -moveto Read -file imaps://imap.gmail.com
+
+Note the `-truncate' option.
+
** mailutils-config is deprecated.
Use `mu cflags' and `mu ldflags' instead. The mailutils-config is
@@ -202,6 +212,13 @@ transaction.
** Support for Maildir and MH formats considerably improved.
+** The mailbox object contains a `copy' method.
+
+This method copies the requested set of messages into another
+mailbox. It is accessed using the `mu_mailbox_msgset_copy' or
+`mu_mailbox_message_copy' functions. So far it is implememented
+only for IMAP and IMAPS mailboxes.
+
** MIME support improved.
** Debugging support considerably improved.
diff --git a/include/mailutils/folder.h b/include/mailutils/folder.h
index bbaafedc6..9036249f1 100644
--- a/include/mailutils/folder.h
+++ b/include/mailutils/folder.h
@@ -61,7 +61,8 @@ extern int mu_folder_enumerate (mu_folder_t, const char *,
extern int mu_folder_lsub (mu_folder_t, const char *, const char *,
mu_list_t *);
-/* Stream settings. */
+/* Stream settings. Don't use these functions.
+ FIXME: To be removed. */
extern int mu_folder_get_stream (mu_folder_t, mu_stream_t *)
__attribute__ ((deprecated));
extern int mu_folder_get_streamref (mu_folder_t, mu_stream_t *);
diff --git a/include/mailutils/imap.h b/include/mailutils/imap.h
index af47c05f0..300e59013 100644
--- a/include/mailutils/imap.h
+++ b/include/mailutils/imap.h
@@ -133,6 +133,9 @@ int mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier);
int mu_imap_trace (mu_imap_t imap, int op);
int mu_imap_trace_mask (mu_imap_t imap, int op, int lev);
+enum mu_imap_response mu_imap_response (mu_imap_t imap);
+int mu_imap_response_code (mu_imap_t imap);
+
int mu_imap_strerror (mu_imap_t imap, const char **pstr);
int mu_imap_session_state (mu_imap_t imap);
@@ -178,21 +181,27 @@ extern struct mu_kwd _mu_imap_status_name_table[];
#define MU_IMAP_CB_UIDNEXT 4
#define MU_IMAP_CB_UIDVALIDITY 5
- /* The following callbacks correspond to server responses and take two
- arguments: a response code (see MU_IMAP_RESPONSE, below) in SDAT, and
- human-readable text string as returned by the server in PDAT. The
- latter can be NULL. */
+ /* The following callbacks correspond to unsolicited server responses and
+ take two arguments: a response code (see MU_IMAP_RESPONSE, below) in
+ SDAT, and human-readable text string as returned by the server in PDAT.
+ The latter can be NULL. */
#define MU_IMAP_CB_OK 6
#define MU_IMAP_CB_NO 7
#define MU_IMAP_CB_BAD 8
#define MU_IMAP_CB_BYE 9
#define MU_IMAP_CB_PREAUTH 10
+ /* These corresponde to the tagged server responses. The calling convention
+ is the same as above. */
+#define MU_IMAP_CB_TAGGED_OK 11
+#define MU_IMAP_CB_TAGGED_NO 12
+#define MU_IMAP_CB_TAGGED_BAD 13
+
/* FETCH callback. Arguments: SDAT - message sequence number, PDAT - a
list (mu_list_t) of union mu_imap_fetch_response (see below). */
-#define MU_IMAP_CB_FETCH 11
+#define MU_IMAP_CB_FETCH 14
-#define _MU_IMAP_CB_MAX 12
+#define _MU_IMAP_CB_MAX 15
typedef void (*mu_imap_callback_t) (void *, int code, size_t sdat, void *pdat);
@@ -202,8 +211,6 @@ void mu_imap_register_callback_function (mu_imap_t imap, int code,
mu_imap_callback_t callback,
void *data);
-#define MU_IMAP_RESPONSE_TAGGED 0x10
-
#define MU_IMAP_RESPONSE_UNKNOWN 0
#define MU_IMAP_RESPONSE_ALERT 1
#define MU_IMAP_RESPONSE_BADCHARSET 2
diff --git a/include/mailutils/mailbox.h b/include/mailutils/mailbox.h
index 146824466..4a2d8c28b 100644
--- a/include/mailutils/mailbox.h
+++ b/include/mailutils/mailbox.h
@@ -42,7 +42,7 @@ extern int mu_mailbox_create_from_url (mu_mailbox_t *, mu_url_t);
extern int mu_mailbox_create_from_record (mu_mailbox_t *pmbox,
mu_record_t record,
const char *name);
-extern int mu_mailbox_create_default (mu_mailbox_t *, const char *);
+extern int mu_mailbox_create_default (mu_mailbox_t *, const char *);
extern int mu_mailbox_create_at (mu_mailbox_t *pmbox, mu_folder_t folder,
const char *name);
@@ -119,6 +119,14 @@ extern int mu_mailbox_get_iterator (mu_mailbox_t mbx,
#define MU_MAILBOX_MSGNO_TO_UID 1
extern int mu_mailbox_translate (mu_mailbox_t, int, size_t, size_t *);
+
+/* Copy message into a folder */
+#define MU_MAILBOX_COPY_UID 0x01
+#define MU_MAILBOX_COPY_CREAT 0x02
+
+extern int mu_mailbox_msgset_copy (mu_mailbox_t, mu_msgset_t, const char *,
+ int);
+extern int mu_mailbox_message_copy (mu_mailbox_t, size_t, const char *, int);
#ifdef __cplusplus
}
diff --git a/include/mailutils/sys/imap.h b/include/mailutils/sys/imap.h
index e8bc9a299..41f995b3d 100644
--- a/include/mailutils/sys/imap.h
+++ b/include/mailutils/sys/imap.h
@@ -85,8 +85,10 @@ struct _mu_imap
{
int flags;
- /* Holds the recect response code */
- enum mu_imap_response resp_code;
+ /* Holds the recent response */
+ enum mu_imap_response response;
+ /* The recent response code */
+ int response_code;
/* Error string (if any) */
char *errstr;
@@ -210,6 +212,7 @@ int _mu_imap_untagged_response_to_list (mu_imap_t imap, mu_list_t *plist);
int _mu_imap_process_untagged_response (mu_imap_t imap, mu_list_t list,
mu_imap_response_action_t fun,
void *data);
+int _mu_imap_process_tagged_response (mu_imap_t imap, mu_list_t resp);
int _mu_imap_response (mu_imap_t imap, mu_imap_response_action_t fun,
void *data);
diff --git a/include/mailutils/sys/mailbox.h b/include/mailutils/sys/mailbox.h
index ebae207f2..f1b8813ed 100644
--- a/include/mailutils/sys/mailbox.h
+++ b/include/mailutils/sys/mailbox.h
@@ -75,6 +75,7 @@ struct _mu_mailbox
int (*_get_uidls) (mu_mailbox_t, mu_list_t);
int (*_translate) (mu_mailbox_t, int cmd, size_t, size_t *);
+ int (*_copy) (mu_mailbox_t, mu_msgset_t, const char *, int);
};
# ifdef __cplusplus
diff --git a/libmailutils/mailbox/Makefile.am b/libmailutils/mailbox/Makefile.am
index dee4aa0c6..f2144e604 100644
--- a/libmailutils/mailbox/Makefile.am
+++ b/libmailutils/mailbox/Makefile.am
@@ -24,6 +24,7 @@ libmailbox_la_SOURCES = \
attribute.c\
body.c\
bodystruct.c\
+ copy.c\
envelope.c\
folder.c\
fsfolder.c\
diff --git a/libmailutils/mailbox/copy.c b/libmailutils/mailbox/copy.c
new file mode 100644
index 000000000..2c884c3d4
--- /dev/null
+++ b/libmailutils/mailbox/copy.c
@@ -0,0 +1,62 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2001, 2004-2005, 2007, 2009-2012 Free Software
+ Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <mailutils/types.h>
+#include <mailutils/mailbox.h>
+#include <mailutils/stream.h>
+#include <mailutils/errno.h>
+#include <mailutils/msgset.h>
+#include <mailutils/sys/mailbox.h>
+
+int
+mu_mailbox_msgset_copy (mu_mailbox_t mbox, mu_msgset_t msgset,
+ const char *dest, int flags)
+{
+ if (!mbox)
+ return EINVAL;
+ if (!mbox->_copy)
+ return ENOSYS;
+ return mbox->_copy (mbox, msgset, dest, flags);
+}
+
+int
+mu_mailbox_message_copy (mu_mailbox_t mbox, size_t msgno,
+ const char *dest, int flags)
+{
+ int rc;
+ mu_msgset_t msgset;
+ int mode;
+
+ if (!mbox)
+ return EINVAL;
+ if (!mbox->_copy)
+ return ENOSYS;
+
+ mode = flags & MU_MAILBOX_COPY_UID ? MU_MSGSET_UID : MU_MSGSET_NUM;
+ rc = mu_msgset_create (&msgset, mbox, mode);
+ if (rc)
+ return rc;
+ rc = mu_msgset_add_range (msgset, 1, 1, mode);
+ if (rc == 0)
+ rc = mbox->_copy (mbox, msgset, dest, flags);
+ mu_msgset_destroy (&msgset);
+ return rc;
+}
diff --git a/libmailutils/mailbox/folder.c b/libmailutils/mailbox/folder.c
index b6e86f4e6..a3fdb5495 100644
--- a/libmailutils/mailbox/folder.c
+++ b/libmailutils/mailbox/folder.c
@@ -475,12 +475,13 @@ mu_folder_delete (mu_folder_t folder, const char *name)
mailbox and call mailbox delete (remove) method. This is necessary
because certain types of mailboxes share a common folder (e.g. mbox,
maildir and mh all use filesystem folder), but have a different
- internal structure. Supplying mu_folder_t with a knowledge of mailbox
- internals will harm separation of concerns. On the other hand,
- removing something without looking into it may well yield undesired
- results. For example, a MH mailbox can hold another mailboxes, i.e.
- be a folder itself. Removing it blindly would result in removing
- these mailboxes as well, which is clearly not indended.
+ internal structure. Supplying mu_folder_t with knowledge about
+ mailbox internals will harm separation of concerns. On the other
+ hand, removing something without looking into it may well yield
+ undesired results. For example, a MH mailbox can hold another
+ mailboxes, i.e. be a folder itself. Removing it blindly would
+ result in removing these mailboxes as well, which is clearly not
+ indended.
To solve this folder and mailbox delete methods are tightly paired,
but without looking into each-others internal mechanisms. */
diff --git a/libproto/imap/appstrsiz.c b/libproto/imap/appstrsiz.c
index f9887f227..ee59dceb0 100644
--- a/libproto/imap/appstrsiz.c
+++ b/libproto/imap/appstrsiz.c
@@ -121,7 +121,7 @@ mu_imap_append_stream_size (mu_imap_t imap, const char *mailbox, int flags,
case MU_IMAP_CLIENT_APPEND_RX:
status = _mu_imap_response (imap, NULL, NULL);
MU_IMAP_CHECK_EAGAIN (imap, status);
- switch (imap->resp_code)
+ switch (imap->response)
{
case MU_IMAP_OK:
status = 0;
diff --git a/libproto/imap/capability.c b/libproto/imap/capability.c
index c301a6d29..ce1c46ba5 100644
--- a/libproto/imap/capability.c
+++ b/libproto/imap/capability.c
@@ -113,7 +113,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
NULL);
imap->client_state = MU_IMAP_CLIENT_READY;
MU_IMAP_CHECK_EAGAIN (imap, status);
- if (imap->resp_code != MU_IMAP_OK)
+ if (imap->response != MU_IMAP_OK)
return MU_ERR_REPLY;
else
{
diff --git a/libproto/imap/close.c b/libproto/imap/close.c
index a006f10f4..d2156b4c2 100644
--- a/libproto/imap/close.c
+++ b/libproto/imap/close.c
@@ -25,7 +25,7 @@
void
_mu_close_handler (mu_imap_t imap)
{
- if (imap->resp_code == MU_IMAP_OK)
+ if (imap->response == MU_IMAP_OK)
imap->session_state = MU_IMAP_SESSION_AUTH;
}
diff --git a/libproto/imap/err.c b/libproto/imap/err.c
index b0db47aaf..f28da512d 100644
--- a/libproto/imap/err.c
+++ b/libproto/imap/err.c
@@ -71,3 +71,21 @@ mu_imap_strerror (mu_imap_t imap, const char **pstr)
*pstr = "(no recent reply)";
return MU_ERR_NOENT;
}
+
+enum mu_imap_response
+mu_imap_response (mu_imap_t imap)
+{
+ if (!imap)
+ return MU_IMAP_BAD;
+ return imap->response;
+}
+
+int
+mu_imap_response_code (mu_imap_t imap)
+{
+ if (!imap)
+ return -1;
+ return imap->response_code;
+}
+
+
diff --git a/libproto/imap/gencom.c b/libproto/imap/gencom.c
index 119a53c13..908f033df 100644
--- a/libproto/imap/gencom.c
+++ b/libproto/imap/gencom.c
@@ -71,7 +71,7 @@ mu_imap_gencom (mu_imap_t imap, struct imap_command *cmd)
MU_IMAP_CHECK_EAGAIN (imap, status);
if (cmd->tagged_handler)
cmd->tagged_handler (imap);
- switch (imap->resp_code)
+ switch (imap->response)
{
case MU_IMAP_OK:
status = 0;
diff --git a/libproto/imap/id.c b/libproto/imap/id.c
index a2769a089..4132813cf 100644
--- a/libproto/imap/id.c
+++ b/libproto/imap/id.c
@@ -126,7 +126,7 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc)
case MU_IMAP_CLIENT_ID_RX:
status = _mu_imap_response (imap, parse_id_reply, passoc);
MU_IMAP_CHECK_EAGAIN (imap, status);
- switch (imap->resp_code)
+ switch (imap->response)
{
case MU_IMAP_OK:
status = 0;
diff --git a/libproto/imap/login.c b/libproto/imap/login.c
index 9a3a7faa5..60a2d4fc5 100644
--- a/libproto/imap/login.c
+++ b/libproto/imap/login.c
@@ -56,7 +56,7 @@ mu_imap_login (mu_imap_t imap, const char *user, const char *pass)
status = _mu_imap_response (imap, NULL, NULL);
imap->client_state = MU_IMAP_CLIENT_READY;
MU_IMAP_CHECK_EAGAIN (imap, status);
- switch (imap->resp_code)
+ switch (imap->response)
{
case MU_IMAP_OK:
imap->session_state = MU_IMAP_SESSION_AUTH;
diff --git a/libproto/imap/mbox.c b/libproto/imap/mbox.c
index ed53c5ff0..a7fd302c6 100644
--- a/libproto/imap/mbox.c
+++ b/libproto/imap/mbox.c
@@ -1252,6 +1252,41 @@ _imap_mbx_is_updated (mu_mailbox_t mbox)
return imbx->flags & _MU_IMAP_MBX_UPTODATE;
}
+static int
+_imap_copy_to_mailbox (mu_mailbox_t mbox, mu_msgset_t msgset,
+ const char *mailbox, int flags)
+{
+ struct _mu_imap_mailbox *imbx = mbox->data;
+ mu_folder_t folder = mbox->folder;
+ mu_imap_t imap = folder->data;
+ int rc;
+
+ mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1,
+ (_("copying messages to mailbox %s"), mailbox));
+ _imap_mbx_clrerr (imbx);
+
+ rc = mu_imap_copy (imap, flags & MU_MAILBOX_COPY_UID, msgset, mailbox);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
+ (_("mu_imap_copy: %s"), mu_strerror (rc)));
+ if (rc)
+ {
+ if (mu_imap_response_code (imap) == MU_IMAP_RESPONSE_TRYCREATE)
+ {
+ mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1,
+ (_("creating mailbox %s"), mailbox));
+ rc = mu_imap_mailbox_create (imap, mailbox);
+ if (rc == 0)
+ rc = mu_imap_copy (imap, flags & MU_MAILBOX_COPY_UID,
+ msgset, mailbox);
+ }
+ }
+ imbx->last_error = rc;
+ }
+ return rc;
+}
+
int
_mu_imap_mailbox_init (mu_mailbox_t mailbox)
{
@@ -1279,6 +1314,7 @@ _mu_imap_mailbox_init (mu_mailbox_t mailbox)
mailbox->_sync = _imap_mbx_sync;
mailbox->_append_message = _imap_mbx_append_message;
+ mailbox->_copy = _imap_copy_to_mailbox;
return 0;
}
diff --git a/libproto/imap/resplist.c b/libproto/imap/resplist.c
index d2d06b2c8..43f64c500 100644
--- a/libproto/imap/resplist.c
+++ b/libproto/imap/resplist.c
@@ -55,8 +55,8 @@ _mu_imap_response_list_create (mu_imap_t imap, mu_list_t *plist)
return 0;
}
-#define IS_LBRACE(p) ((p)[0] == '(')
-#define IS_RBRACE(p) ((p)[0] == ')')
+#define IS_LBRACE(p) ((p)[0] == '(' && !(p)[1])
+#define IS_RBRACE(p) ((p)[0] == ')' && !(p)[1])
#define IS_NIL(p) (strcmp (p, "NIL") == 0)
static struct imap_list_element *
diff --git a/libproto/imap/response.c b/libproto/imap/response.c
index 00d9f8d5c..5b92485b7 100644
--- a/libproto/imap/response.c
+++ b/libproto/imap/response.c
@@ -27,13 +27,6 @@
#include <mailutils/errno.h>
#include <mailutils/sys/imap.h>
-static void
-response_to_errstr (mu_imap_t imap, size_t argc, char **argv)
-{
- if (argc && strcmp (argv[argc-1], "]"))
- _mu_imap_seterrstrz (imap, argv[argc-1]);
-}
-
int
_mu_imap_response (mu_imap_t imap, mu_imap_response_action_t fun,
void *data)
@@ -83,29 +76,17 @@ _mu_imap_response (mu_imap_t imap, mu_imap_response_action_t fun,
/*imap->client_state = MU_IMAP_CLIENT_ERROR;*/
status = MU_ERR_BADREPLY;
}
- else if (strcmp (wv[1], "OK") == 0)
- {
- imap->resp_code = MU_IMAP_OK;
- response_to_errstr (imap, wc, wv);
- }
- else if (strcmp (wv[1], "NO") == 0)
- {
- imap->resp_code = MU_IMAP_NO;
- response_to_errstr (imap, wc, wv);
- }
- else if (strcmp (wv[1], "BAD") == 0)
+ else
{
- imap->resp_code = MU_IMAP_BAD;
- response_to_errstr (imap, wc, wv);
- /* This may be so important that CB_BAD callback is
- * overloaded to handle this case as well.
- */
- mu_imap_callback (imap, MU_IMAP_CB_BAD,
- MU_IMAP_RESPONSE_TAGGED,
- wc >= 1 ? wv[wc-1] : NULL);
+ mu_list_t list;
+ status = _mu_imap_untagged_response_to_list (imap, &list);
+ if (status == 0)
+ {
+ if (_mu_imap_process_tagged_response (imap, list))
+ status = MU_ERR_BADREPLY;
+ mu_list_destroy (&list);
+ }
}
- else
- status = MU_ERR_BADREPLY;
MU_IMAP_FSET (imap, MU_IMAP_RESP);
}
else
diff --git a/libproto/imap/resproc.c b/libproto/imap/resproc.c
index b1bc43c7a..7f6e1849b 100644
--- a/libproto/imap/resproc.c
+++ b/libproto/imap/resproc.c
@@ -72,7 +72,7 @@ parse_response_code (mu_imap_t imap, mu_list_t resp)
if (mu_kwd_xlat_name (mu_imap_response_codes, arg->v.string, &rcode))
return -1;
- arg = _mu_imap_list_at (resp, 4);
+ arg = _mu_imap_list_at (resp, 3);
if (!arg || !_mu_imap_list_element_is_string (arg, "]"))
return -1;
}
@@ -217,6 +217,7 @@ struct resptab
{
char *name;
mu_imap_response_action_t action;
+ int code;
};
static struct resptab resptab[] = {
@@ -350,5 +351,75 @@ _mu_imap_process_untagged_response (mu_imap_t imap, mu_list_t list,
}
return 0;
}
+
+static void
+default_tagged_response (mu_imap_t imap, int code, mu_list_t resp, void *data)
+{
+ struct imap_list_element *arg;
+
+ if (mu_list_tail (resp, (void*) &arg) == 0 &&
+ arg->type == imap_eltype_string)
+ _mu_imap_seterrstrz (imap, arg->v.string);
+ imap->response_code = parse_response_code (imap, resp);
+ mu_imap_callback (imap, code, imap->response_code,
+ arg ? arg->v.string : NULL);
+}
+
+static void
+ok_tagged_response (mu_imap_t imap, mu_list_t resp, void *data)
+{
+ default_tagged_response (imap, MU_IMAP_CB_TAGGED_OK, resp, data);
+}
+
+static void
+no_tagged_response (mu_imap_t imap, mu_list_t resp, void *data)
+{
+ default_tagged_response (imap, MU_IMAP_CB_TAGGED_NO, resp, data);
+}
+
+static void
+bad_tagged_response (mu_imap_t imap, mu_list_t resp, void *data)
+{
+ default_tagged_response (imap, MU_IMAP_CB_TAGGED_BAD, resp, data);
+}
+
+static struct resptab tagged_resptab[] = {
+ { "OK", ok_tagged_response, MU_IMAP_OK },
+ { "NO", no_tagged_response, MU_IMAP_NO },
+ { "BAD", bad_tagged_response, MU_IMAP_BAD },
+ { NULL }
+};
+
+static int
+_std_tagged_response (mu_imap_t imap, size_t count, mu_list_t resp)
+{
+ struct resptab *rp;
+ struct imap_list_element *arg = _mu_imap_list_at (resp, 0);
+
+ if (!arg)
+ return 1;
+
+ if (arg->type == imap_eltype_string)
+ for (rp = tagged_resptab; rp->name; rp++)
+ {
+ if (mu_c_strcasecmp (rp->name, arg->v.string) == 0)
+ {
+ imap->response = rp->code;
+ rp->action (imap, resp, NULL);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int
+_mu_imap_process_tagged_response (mu_imap_t imap, mu_list_t resp)
+{
+ size_t count;
+
+ if (mu_list_count (resp, &count))
+ return 1;
+
+ return _std_tagged_response (imap, count, resp);
+}
-
diff --git a/libproto/imap/select.c b/libproto/imap/select.c
index 72af1a7c8..6debee728 100644
--- a/libproto/imap/select.c
+++ b/libproto/imap/select.c
@@ -113,7 +113,7 @@ mu_imap_select (mu_imap_t imap, const char *mbox, int writable,
memset (&imap->mbox_stat, 0, sizeof (imap->mbox_stat));
status = _mu_imap_response (imap, _select_response_action, NULL);
MU_IMAP_CHECK_EAGAIN (imap, status);
- switch (imap->resp_code)
+ switch (imap->response)
{
case MU_IMAP_OK:
imap->session_state = MU_IMAP_SESSION_SELECTED;
diff --git a/libproto/imap/starttls.c b/libproto/imap/starttls.c
index 08cbce9ed..45498de47 100644
--- a/libproto/imap/starttls.c
+++ b/libproto/imap/starttls.c
@@ -60,7 +60,7 @@ mu_imap_starttls (mu_imap_t imap)
case MU_IMAP_CLIENT_STARTTLS_RX:
status = _mu_imap_response (imap, NULL, NULL);
MU_IMAP_CHECK_EAGAIN (imap, status);
- switch (imap->resp_code)
+ switch (imap->response)
{
case MU_IMAP_OK:
status = mu_imapio_get_streams (imap->io, streams);
diff --git a/libproto/imap/status.c b/libproto/imap/status.c
index 32dd9f12c..915225ae6 100644
--- a/libproto/imap/status.c
+++ b/libproto/imap/status.c
@@ -185,7 +185,7 @@ mu_imap_status (mu_imap_t imap, const char *mboxname, struct mu_imap_stat *ps)
status = _mu_imap_response (imap, _status_response_action, &sd);
MU_IMAP_CHECK_EAGAIN (imap, status);
- switch (imap->resp_code)
+ switch (imap->response)
{
case MU_IMAP_OK:
break;
diff --git a/libproto/imap/storeflg.c b/libproto/imap/storeflg.c
index 9eb7536b2..e265d1599 100644
--- a/libproto/imap/storeflg.c
+++ b/libproto/imap/storeflg.c
@@ -67,7 +67,7 @@ mu_imap_store_flags (mu_imap_t imap, int uid, mu_msgset_t msgset,
/* FIXME: Handle unsolicited responses */
status = _mu_imap_response (imap, NULL, NULL);
MU_IMAP_CHECK_EAGAIN (imap, status);
- switch (imap->resp_code)
+ switch (imap->response)
{
case MU_IMAP_OK:
status = 0;
diff --git a/mh/inc.c b/mh/inc.c
index a51511b24..790d5cf15 100644
--- a/mh/inc.c
+++ b/mh/inc.c
@@ -42,6 +42,8 @@ static struct argp_option options[] = {
{"truncate", ARG_TRUNCATE, N_("BOOL"), OPTION_ARG_OPTIONAL,
N_("truncate source mailbox after incorporating (default)")},
{"notruncate", ARG_NOTRUNCATE, NULL, OPTION_HIDDEN, ""},
+ {"moveto", ARG_MOVETO, N_("MAILBOX"), 0,
+ N_("move incorporated messages to MAILBOX instead of deleting them") },
{"width", ARG_WIDTH, N_("NUMBER"), 0,
N_("set output width")},
{"quiet", ARG_QUIET, 0, 0,
@@ -58,6 +60,7 @@ struct mh_option mh_option[] = {
{ "form", MH_OPT_ARG, "format-file" },
{ "format", MH_OPT_ARG, "string" },
{ "truncate", MH_OPT_BOOL },
+ { "moveto", MH_OPT_ARG, "folder" },
{ "width", MH_OPT_ARG, "number" },
{ "quiet" },
{ NULL }
@@ -72,6 +75,7 @@ static int changecur = -1;
static int truncate_source = -1;
static int quiet = 0;
static const char *append_folder;
+static const char *move_to_mailbox;
static error_t
opt_handler (int key, char *arg, struct argp_state *state)
@@ -122,6 +126,10 @@ opt_handler (int key, char *arg, struct argp_state *state)
case ARG_NOTRUNCATE:
truncate_source = 0;
break;
+
+ case ARG_MOVETO:
+ move_to_mailbox = arg;
+ break;
case ARG_WIDTH:
width = strtoul (arg, NULL, 0);
@@ -143,7 +151,8 @@ opt_handler (int key, char *arg, struct argp_state *state)
}
void
-list_message (mh_format_t *format, mu_mailbox_t mbox, size_t msgno, size_t width)
+list_message (mh_format_t *format, mu_mailbox_t mbox, size_t msgno,
+ size_t width)
{
mu_message_t msg;
char *buf = NULL;
@@ -275,6 +284,33 @@ main (int argc, char **argv)
}
}
+ if (truncate_source && move_to_mailbox)
+ {
+ mu_msgset_t msgset;
+
+ rc = mu_msgset_create (&msgset, input, MU_MSGSET_NUM);
+ if (rc)
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_create", NULL, rc);
+ else
+ {
+ rc = mu_msgset_add_range (msgset, 1, total, MU_MSGSET_NUM);
+ if (rc)
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_add_range", NULL, rc);
+ else
+ {
+ rc = mu_mailbox_msgset_copy (input, msgset, move_to_mailbox,
+ MU_MAILBOX_COPY_CREAT);
+ if (rc)
+ {
+ mu_error (_("failed to move messages to %s: %s"),
+ move_to_mailbox, mu_strerror (rc));
+ truncate_source = 0;
+ }
+ }
+ mu_msgset_destroy (&msgset);
+ }
+ }
+
if (!changecur)
{
mu_property_t prop = mh_mailbox_get_property (output);
diff --git a/mh/mh_getopt.h b/mh/mh_getopt.h
index e552103d2..a0fb7c859 100644
--- a/mh/mh_getopt.h
+++ b/mh/mh_getopt.h
@@ -91,7 +91,8 @@ enum mh_arg {
A