diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-04-29 22:06:49 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-04-29 22:30:48 +0300 |
commit | e6ae2852edb142fcf84dc489715f8984843dfe0c (patch) | |
tree | 3f1ee3b8e88c17740452b257cf6a344066deac9e | |
parent | 1cf13b32d876b2f7ef0faf8f074142c376aeba1d (diff) | |
download | mailutils-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-- | NEWS | 19 | ||||
-rw-r--r-- | include/mailutils/folder.h | 3 | ||||
-rw-r--r-- | include/mailutils/imap.h | 23 | ||||
-rw-r--r-- | include/mailutils/mailbox.h | 10 | ||||
-rw-r--r-- | include/mailutils/sys/imap.h | 7 | ||||
-rw-r--r-- | include/mailutils/sys/mailbox.h | 1 | ||||
-rw-r--r-- | libmailutils/mailbox/Makefile.am | 1 | ||||
-rw-r--r-- | libmailutils/mailbox/copy.c | 62 | ||||
-rw-r--r-- | libmailutils/mailbox/folder.c | 13 | ||||
-rw-r--r-- | libproto/imap/appstrsiz.c | 2 | ||||
-rw-r--r-- | libproto/imap/capability.c | 2 | ||||
-rw-r--r-- | libproto/imap/close.c | 2 | ||||
-rw-r--r-- | libproto/imap/err.c | 18 | ||||
-rw-r--r-- | libproto/imap/gencom.c | 2 | ||||
-rw-r--r-- | libproto/imap/id.c | 2 | ||||
-rw-r--r-- | libproto/imap/login.c | 2 | ||||
-rw-r--r-- | libproto/imap/mbox.c | 36 | ||||
-rw-r--r-- | libproto/imap/resplist.c | 4 | ||||
-rw-r--r-- | libproto/imap/response.c | 37 | ||||
-rw-r--r-- | libproto/imap/resproc.c | 75 | ||||
-rw-r--r-- | libproto/imap/select.c | 2 | ||||
-rw-r--r-- | libproto/imap/starttls.c | 2 | ||||
-rw-r--r-- | libproto/imap/status.c | 2 | ||||
-rw-r--r-- | libproto/imap/storeflg.c | 2 | ||||
-rw-r--r-- | mh/inc.c | 38 | ||||
-rw-r--r-- | mh/mh_getopt.h | 3 |
26 files changed, 307 insertions, 63 deletions
@@ -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; @@ -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 |