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.
Showing
26 changed files
with
307 additions
and
63 deletions
1 | GNU mailutils NEWS -- history of user-visible changes. 2012-02-26 | 1 | GNU mailutils NEWS -- history of user-visible changes. 2012-04-29 |
2 | Copyright (C) 2002-2012 Free Software Foundation, Inc. | 2 | Copyright (C) 2002-2012 Free Software Foundation, Inc. |
3 | See the end of file for copying conditions. | 3 | See the end of file for copying conditions. |
4 | 4 | ||
... | @@ -116,6 +116,16 @@ See <http://mailutils.org/wiki/Timestamp_(Sieve_test)>. | ... | @@ -116,6 +116,16 @@ See <http://mailutils.org/wiki/Timestamp_(Sieve_test)>. |
116 | 116 | ||
117 | ** MH: improved compatibility with other implementations | 117 | ** MH: improved compatibility with other implementations |
118 | 118 | ||
119 | ** MH inc: new option --moveto | ||
120 | |||
121 | This option instructs the utility to move incorporated messages into | ||
122 | another folder instead of deleting them. It is implemented only for | ||
123 | input folders of type IMAP or IMAPS. A sample usage is: | ||
124 | |||
125 | inc -truncate -moveto Read -file imaps://imap.gmail.com | ||
126 | |||
127 | Note the `-truncate' option. | ||
128 | |||
119 | ** mailutils-config is deprecated. | 129 | ** mailutils-config is deprecated. |
120 | 130 | ||
121 | Use `mu cflags' and `mu ldflags' instead. The mailutils-config is | 131 | Use `mu cflags' and `mu ldflags' instead. The mailutils-config is |
... | @@ -202,6 +212,13 @@ transaction. | ... | @@ -202,6 +212,13 @@ transaction. |
202 | 212 | ||
203 | ** Support for Maildir and MH formats considerably improved. | 213 | ** Support for Maildir and MH formats considerably improved. |
204 | 214 | ||
215 | ** The mailbox object contains a `copy' method. | ||
216 | |||
217 | This method copies the requested set of messages into another | ||
218 | mailbox. It is accessed using the `mu_mailbox_msgset_copy' or | ||
219 | `mu_mailbox_message_copy' functions. So far it is implememented | ||
220 | only for IMAP and IMAPS mailboxes. | ||
221 | |||
205 | ** MIME support improved. | 222 | ** MIME support improved. |
206 | 223 | ||
207 | ** Debugging support considerably improved. | 224 | ** Debugging support considerably improved. | ... | ... |
... | @@ -61,7 +61,8 @@ extern int mu_folder_enumerate (mu_folder_t, const char *, | ... | @@ -61,7 +61,8 @@ extern int mu_folder_enumerate (mu_folder_t, const char *, |
61 | extern int mu_folder_lsub (mu_folder_t, const char *, const char *, | 61 | extern int mu_folder_lsub (mu_folder_t, const char *, const char *, |
62 | mu_list_t *); | 62 | mu_list_t *); |
63 | 63 | ||
64 | /* Stream settings. */ | 64 | /* Stream settings. Don't use these functions. |
65 | FIXME: To be removed. */ | ||
65 | extern int mu_folder_get_stream (mu_folder_t, mu_stream_t *) | 66 | extern int mu_folder_get_stream (mu_folder_t, mu_stream_t *) |
66 | __attribute__ ((deprecated)); | 67 | __attribute__ ((deprecated)); |
67 | extern int mu_folder_get_streamref (mu_folder_t, mu_stream_t *); | 68 | extern int mu_folder_get_streamref (mu_folder_t, mu_stream_t *); | ... | ... |
... | @@ -133,6 +133,9 @@ int mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier); | ... | @@ -133,6 +133,9 @@ int mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier); |
133 | int mu_imap_trace (mu_imap_t imap, int op); | 133 | int mu_imap_trace (mu_imap_t imap, int op); |
134 | int mu_imap_trace_mask (mu_imap_t imap, int op, int lev); | 134 | int mu_imap_trace_mask (mu_imap_t imap, int op, int lev); |
135 | 135 | ||
136 | enum mu_imap_response mu_imap_response (mu_imap_t imap); | ||
137 | int mu_imap_response_code (mu_imap_t imap); | ||
138 | |||
136 | int mu_imap_strerror (mu_imap_t imap, const char **pstr); | 139 | int mu_imap_strerror (mu_imap_t imap, const char **pstr); |
137 | 140 | ||
138 | int mu_imap_session_state (mu_imap_t imap); | 141 | int mu_imap_session_state (mu_imap_t imap); |
... | @@ -178,21 +181,27 @@ extern struct mu_kwd _mu_imap_status_name_table[]; | ... | @@ -178,21 +181,27 @@ extern struct mu_kwd _mu_imap_status_name_table[]; |
178 | #define MU_IMAP_CB_UIDNEXT 4 | 181 | #define MU_IMAP_CB_UIDNEXT 4 |
179 | #define MU_IMAP_CB_UIDVALIDITY 5 | 182 | #define MU_IMAP_CB_UIDVALIDITY 5 |
180 | 183 | ||
181 | /* The following callbacks correspond to server responses and take two | 184 | /* The following callbacks correspond to unsolicited server responses and |
182 | arguments: a response code (see MU_IMAP_RESPONSE, below) in SDAT, and | 185 | take two arguments: a response code (see MU_IMAP_RESPONSE, below) in |
183 | human-readable text string as returned by the server in PDAT. The | 186 | SDAT, and human-readable text string as returned by the server in PDAT. |
184 | latter can be NULL. */ | 187 | The latter can be NULL. */ |
185 | #define MU_IMAP_CB_OK 6 | 188 | #define MU_IMAP_CB_OK 6 |
186 | #define MU_IMAP_CB_NO 7 | 189 | #define MU_IMAP_CB_NO 7 |
187 | #define MU_IMAP_CB_BAD 8 | 190 | #define MU_IMAP_CB_BAD 8 |
188 | #define MU_IMAP_CB_BYE 9 | 191 | #define MU_IMAP_CB_BYE 9 |
189 | #define MU_IMAP_CB_PREAUTH 10 | 192 | #define MU_IMAP_CB_PREAUTH 10 |
190 | 193 | ||
194 | /* These corresponde to the tagged server responses. The calling convention | ||
195 | is the same as above. */ | ||
196 | #define MU_IMAP_CB_TAGGED_OK 11 | ||
197 | #define MU_IMAP_CB_TAGGED_NO 12 | ||
198 | #define MU_IMAP_CB_TAGGED_BAD 13 | ||
199 | |||
191 | /* FETCH callback. Arguments: SDAT - message sequence number, PDAT - a | 200 | /* FETCH callback. Arguments: SDAT - message sequence number, PDAT - a |
192 | list (mu_list_t) of union mu_imap_fetch_response (see below). */ | 201 | list (mu_list_t) of union mu_imap_fetch_response (see below). */ |
193 | #define MU_IMAP_CB_FETCH 11 | 202 | #define MU_IMAP_CB_FETCH 14 |
194 | 203 | ||
195 | #define _MU_IMAP_CB_MAX 12 | 204 | #define _MU_IMAP_CB_MAX 15 |
196 | 205 | ||
197 | typedef void (*mu_imap_callback_t) (void *, int code, size_t sdat, void *pdat); | 206 | typedef void (*mu_imap_callback_t) (void *, int code, size_t sdat, void *pdat); |
198 | 207 | ||
... | @@ -202,8 +211,6 @@ void mu_imap_register_callback_function (mu_imap_t imap, int code, | ... | @@ -202,8 +211,6 @@ void mu_imap_register_callback_function (mu_imap_t imap, int code, |
202 | mu_imap_callback_t callback, | 211 | mu_imap_callback_t callback, |
203 | void *data); | 212 | void *data); |
204 | 213 | ||
205 | #define MU_IMAP_RESPONSE_TAGGED 0x10 | ||
206 | |||
207 | #define MU_IMAP_RESPONSE_UNKNOWN 0 | 214 | #define MU_IMAP_RESPONSE_UNKNOWN 0 |
208 | #define MU_IMAP_RESPONSE_ALERT 1 | 215 | #define MU_IMAP_RESPONSE_ALERT 1 |
209 | #define MU_IMAP_RESPONSE_BADCHARSET 2 | 216 | #define MU_IMAP_RESPONSE_BADCHARSET 2 | ... | ... |
... | @@ -42,7 +42,7 @@ extern int mu_mailbox_create_from_url (mu_mailbox_t *, mu_url_t); | ... | @@ -42,7 +42,7 @@ extern int mu_mailbox_create_from_url (mu_mailbox_t *, mu_url_t); |
42 | extern int mu_mailbox_create_from_record (mu_mailbox_t *pmbox, | 42 | extern int mu_mailbox_create_from_record (mu_mailbox_t *pmbox, |
43 | mu_record_t record, | 43 | mu_record_t record, |
44 | const char *name); | 44 | const char *name); |
45 | extern int mu_mailbox_create_default (mu_mailbox_t *, const char *); | 45 | extern int mu_mailbox_create_default (mu_mailbox_t *, const char *); |
46 | extern int mu_mailbox_create_at (mu_mailbox_t *pmbox, mu_folder_t folder, | 46 | extern int mu_mailbox_create_at (mu_mailbox_t *pmbox, mu_folder_t folder, |
47 | const char *name); | 47 | const char *name); |
48 | 48 | ||
... | @@ -119,6 +119,14 @@ extern int mu_mailbox_get_iterator (mu_mailbox_t mbx, | ... | @@ -119,6 +119,14 @@ extern int mu_mailbox_get_iterator (mu_mailbox_t mbx, |
119 | #define MU_MAILBOX_MSGNO_TO_UID 1 | 119 | #define MU_MAILBOX_MSGNO_TO_UID 1 |
120 | 120 | ||
121 | extern int mu_mailbox_translate (mu_mailbox_t, int, size_t, size_t *); | 121 | extern int mu_mailbox_translate (mu_mailbox_t, int, size_t, size_t *); |
122 | |||
123 | /* Copy message into a folder */ | ||
124 | #define MU_MAILBOX_COPY_UID 0x01 | ||
125 | #define MU_MAILBOX_COPY_CREAT 0x02 | ||
126 | |||
127 | extern int mu_mailbox_msgset_copy (mu_mailbox_t, mu_msgset_t, const char *, | ||
128 | int); | ||
129 | extern int mu_mailbox_message_copy (mu_mailbox_t, size_t, const char *, int); | ||
122 | 130 | ||
123 | #ifdef __cplusplus | 131 | #ifdef __cplusplus |
124 | } | 132 | } | ... | ... |
... | @@ -85,8 +85,10 @@ struct _mu_imap | ... | @@ -85,8 +85,10 @@ struct _mu_imap |
85 | { | 85 | { |
86 | int flags; | 86 | int flags; |
87 | 87 | ||
88 | /* Holds the recect response code */ | 88 | /* Holds the recent response */ |
89 | enum mu_imap_response resp_code; | 89 | enum mu_imap_response response; |
90 | /* The recent response code */ | ||
91 | int response_code; | ||
90 | 92 | ||
91 | /* Error string (if any) */ | 93 | /* Error string (if any) */ |
92 | char *errstr; | 94 | char *errstr; |
... | @@ -210,6 +212,7 @@ int _mu_imap_untagged_response_to_list (mu_imap_t imap, mu_list_t *plist); | ... | @@ -210,6 +212,7 @@ int _mu_imap_untagged_response_to_list (mu_imap_t imap, mu_list_t *plist); |
210 | int _mu_imap_process_untagged_response (mu_imap_t imap, mu_list_t list, | 212 | int _mu_imap_process_untagged_response (mu_imap_t imap, mu_list_t list, |
211 | mu_imap_response_action_t fun, | 213 | mu_imap_response_action_t fun, |
212 | void *data); | 214 | void *data); |
215 | int _mu_imap_process_tagged_response (mu_imap_t imap, mu_list_t resp); | ||
213 | 216 | ||
214 | int _mu_imap_response (mu_imap_t imap, mu_imap_response_action_t fun, | 217 | int _mu_imap_response (mu_imap_t imap, mu_imap_response_action_t fun, |
215 | void *data); | 218 | void *data); | ... | ... |
... | @@ -75,6 +75,7 @@ struct _mu_mailbox | ... | @@ -75,6 +75,7 @@ struct _mu_mailbox |
75 | int (*_get_uidls) (mu_mailbox_t, mu_list_t); | 75 | int (*_get_uidls) (mu_mailbox_t, mu_list_t); |
76 | 76 | ||
77 | int (*_translate) (mu_mailbox_t, int cmd, size_t, size_t *); | 77 | int (*_translate) (mu_mailbox_t, int cmd, size_t, size_t *); |
78 | int (*_copy) (mu_mailbox_t, mu_msgset_t, const char *, int); | ||
78 | }; | 79 | }; |
79 | 80 | ||
80 | # ifdef __cplusplus | 81 | # ifdef __cplusplus | ... | ... |
libmailutils/mailbox/copy.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999-2001, 2004-2005, 2007, 2009-2012 Free Software | ||
3 | Foundation, Inc. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 3 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General | ||
16 | Public License along with this library. If not, see | ||
17 | <http://www.gnu.org/licenses/>. */ | ||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | #include <mailutils/types.h> | ||
23 | #include <mailutils/mailbox.h> | ||
24 | #include <mailutils/stream.h> | ||
25 | #include <mailutils/errno.h> | ||
26 | #include <mailutils/msgset.h> | ||
27 | #include <mailutils/sys/mailbox.h> | ||
28 | |||
29 | int | ||
30 | mu_mailbox_msgset_copy (mu_mailbox_t mbox, mu_msgset_t msgset, | ||
31 | const char *dest, int flags) | ||
32 | { | ||
33 | if (!mbox) | ||
34 | return EINVAL; | ||
35 | if (!mbox->_copy) | ||
36 | return ENOSYS; | ||
37 | return mbox->_copy (mbox, msgset, dest, flags); | ||
38 | } | ||
39 | |||
40 | int | ||
41 | mu_mailbox_message_copy (mu_mailbox_t mbox, size_t msgno, | ||
42 | const char *dest, int flags) | ||
43 | { | ||
44 | int rc; | ||
45 | mu_msgset_t msgset; | ||
46 | int mode; | ||
47 | |||
48 | if (!mbox) | ||
49 | return EINVAL; | ||
50 | if (!mbox->_copy) | ||
51 | return ENOSYS; | ||
52 | |||
53 | mode = flags & MU_MAILBOX_COPY_UID ? MU_MSGSET_UID : MU_MSGSET_NUM; | ||
54 | rc = mu_msgset_create (&msgset, mbox, mode); | ||
55 | if (rc) | ||
56 | return rc; | ||
57 | rc = mu_msgset_add_range (msgset, 1, 1, mode); | ||
58 | if (rc == 0) | ||
59 | rc = mbox->_copy (mbox, msgset, dest, flags); | ||
60 | mu_msgset_destroy (&msgset); | ||
61 | return rc; | ||
62 | } |
... | @@ -475,12 +475,13 @@ mu_folder_delete (mu_folder_t folder, const char *name) | ... | @@ -475,12 +475,13 @@ mu_folder_delete (mu_folder_t folder, const char *name) |
475 | mailbox and call mailbox delete (remove) method. This is necessary | 475 | mailbox and call mailbox delete (remove) method. This is necessary |
476 | because certain types of mailboxes share a common folder (e.g. mbox, | 476 | because certain types of mailboxes share a common folder (e.g. mbox, |
477 | maildir and mh all use filesystem folder), but have a different | 477 | maildir and mh all use filesystem folder), but have a different |
478 | internal structure. Supplying mu_folder_t with a knowledge of mailbox | 478 | internal structure. Supplying mu_folder_t with knowledge about |
479 | internals will harm separation of concerns. On the other hand, | 479 | mailbox internals will harm separation of concerns. On the other |
480 | removing something without looking into it may well yield undesired | 480 | hand, removing something without looking into it may well yield |
481 | results. For example, a MH mailbox can hold another mailboxes, i.e. | 481 | undesired results. For example, a MH mailbox can hold another |
482 | be a folder itself. Removing it blindly would result in removing | 482 | mailboxes, i.e. be a folder itself. Removing it blindly would |
483 | these mailboxes as well, which is clearly not indended. | 483 | result in removing these mailboxes as well, which is clearly not |
484 | indended. | ||
484 | 485 | ||
485 | To solve this folder and mailbox delete methods are tightly paired, | 486 | To solve this folder and mailbox delete methods are tightly paired, |
486 | but without looking into each-others internal mechanisms. */ | 487 | but without looking into each-others internal mechanisms. */ | ... | ... |
... | @@ -121,7 +121,7 @@ mu_imap_append_stream_size (mu_imap_t imap, const char *mailbox, int flags, | ... | @@ -121,7 +121,7 @@ mu_imap_append_stream_size (mu_imap_t imap, const char *mailbox, int flags, |
121 | case MU_IMAP_CLIENT_APPEND_RX: | 121 | case MU_IMAP_CLIENT_APPEND_RX: |
122 | status = _mu_imap_response (imap, NULL, NULL); | 122 | status = _mu_imap_response (imap, NULL, NULL); |
123 | MU_IMAP_CHECK_EAGAIN (imap, status); | 123 | MU_IMAP_CHECK_EAGAIN (imap, status); |
124 | switch (imap->resp_code) | 124 | switch (imap->response) |
125 | { | 125 | { |
126 | case MU_IMAP_OK: | 126 | case MU_IMAP_OK: |
127 | status = 0; | 127 | status = 0; | ... | ... |
... | @@ -113,7 +113,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter) | ... | @@ -113,7 +113,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter) |
113 | NULL); | 113 | NULL); |
114 | imap->client_state = MU_IMAP_CLIENT_READY; | 114 | imap->client_state = MU_IMAP_CLIENT_READY; |
115 | MU_IMAP_CHECK_EAGAIN (imap, status); | 115 | MU_IMAP_CHECK_EAGAIN (imap, status); |
116 | if (imap->resp_code != MU_IMAP_OK) | 116 | if (imap->response != MU_IMAP_OK) |
117 | return MU_ERR_REPLY; | 117 | return MU_ERR_REPLY; |
118 | else | 118 | else |
119 | { | 119 | { | ... | ... |
... | @@ -25,7 +25,7 @@ | ... | @@ -25,7 +25,7 @@ |
25 | void | 25 | void |
26 | _mu_close_handler (mu_imap_t imap) | 26 | _mu_close_handler (mu_imap_t imap) |
27 | { | 27 | { |
28 | if (imap->resp_code == MU_IMAP_OK) | 28 | if (imap->response == MU_IMAP_OK) |
29 | imap->session_state = MU_IMAP_SESSION_AUTH; | 29 | imap->session_state = MU_IMAP_SESSION_AUTH; |
30 | } | 30 | } |
31 | 31 | ... | ... |
... | @@ -71,3 +71,21 @@ mu_imap_strerror (mu_imap_t imap, const char **pstr) | ... | @@ -71,3 +71,21 @@ mu_imap_strerror (mu_imap_t imap, const char **pstr) |
71 | *pstr = "(no recent reply)"; | 71 | *pstr = "(no recent reply)"; |
72 | return MU_ERR_NOENT; | 72 | return MU_ERR_NOENT; |
73 | } | 73 | } |
74 | |||
75 | enum mu_imap_response | ||
76 | mu_imap_response (mu_imap_t imap) | ||
77 | { | ||
78 | if (!imap) | ||
79 | return MU_IMAP_BAD; | ||
80 | return imap->response; | ||
81 | } | ||
82 | |||
83 | int | ||
84 | mu_imap_response_code (mu_imap_t imap) | ||
85 | { | ||
86 | if (!imap) | ||
87 | return -1; | ||
88 | return imap->response_code; | ||
89 | } | ||
90 | |||
91 | ... | ... |
... | @@ -71,7 +71,7 @@ mu_imap_gencom (mu_imap_t imap, struct imap_command *cmd) | ... | @@ -71,7 +71,7 @@ mu_imap_gencom (mu_imap_t imap, struct imap_command *cmd) |
71 | MU_IMAP_CHECK_EAGAIN (imap, status); | 71 | MU_IMAP_CHECK_EAGAIN (imap, status); |
72 | if (cmd->tagged_handler) | 72 | if (cmd->tagged_handler) |
73 | cmd->tagged_handler (imap); | 73 | cmd->tagged_handler (imap); |
74 | switch (imap->resp_code) | 74 | switch (imap->response) |
75 | { | 75 | { |
76 | case MU_IMAP_OK: | 76 | case MU_IMAP_OK: |
77 | status = 0; | 77 | status = 0; | ... | ... |
... | @@ -126,7 +126,7 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc) | ... | @@ -126,7 +126,7 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc) |
126 | case MU_IMAP_CLIENT_ID_RX: | 126 | case MU_IMAP_CLIENT_ID_RX: |
127 | status = _mu_imap_response (imap, parse_id_reply, passoc); | 127 | status = _mu_imap_response (imap, parse_id_reply, passoc); |
128 | MU_IMAP_CHECK_EAGAIN (imap, status); | 128 | MU_IMAP_CHECK_EAGAIN (imap, status); |
129 | switch (imap->resp_code) | 129 | switch (imap->response) |
130 | { | 130 | { |
131 | case MU_IMAP_OK: | 131 | case MU_IMAP_OK: |
132 | status = 0; | 132 | status = 0; | ... | ... |
... | @@ -56,7 +56,7 @@ mu_imap_login (mu_imap_t imap, const char *user, const char *pass) | ... | @@ -56,7 +56,7 @@ mu_imap_login (mu_imap_t imap, const char *user, const char *pass) |
56 | status = _mu_imap_response (imap, NULL, NULL); | 56 | status = _mu_imap_response (imap, NULL, NULL); |
57 | imap->client_state = MU_IMAP_CLIENT_READY; | 57 | imap->client_state = MU_IMAP_CLIENT_READY; |
58 | MU_IMAP_CHECK_EAGAIN (imap, status); | 58 | MU_IMAP_CHECK_EAGAIN (imap, status); |
59 | switch (imap->resp_code) | 59 | switch (imap->response) |
60 | { | 60 | { |
61 | case MU_IMAP_OK: | 61 | case MU_IMAP_OK: |
62 | imap->session_state = MU_IMAP_SESSION_AUTH; | 62 | imap->session_state = MU_IMAP_SESSION_AUTH; | ... | ... |
... | @@ -1252,6 +1252,41 @@ _imap_mbx_is_updated (mu_mailbox_t mbox) | ... | @@ -1252,6 +1252,41 @@ _imap_mbx_is_updated (mu_mailbox_t mbox) |
1252 | return imbx->flags & _MU_IMAP_MBX_UPTODATE; | 1252 | return imbx->flags & _MU_IMAP_MBX_UPTODATE; |
1253 | } | 1253 | } |
1254 | 1254 | ||
1255 | static int | ||
1256 | _imap_copy_to_mailbox (mu_mailbox_t mbox, mu_msgset_t msgset, | ||
1257 | const char *mailbox, int flags) | ||
1258 | { | ||
1259 | struct _mu_imap_mailbox *imbx = mbox->data; | ||
1260 | mu_folder_t folder = mbox->folder; | ||
1261 | mu_imap_t imap = folder->data; | ||
1262 | int rc; | ||
1263 | |||
1264 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1, | ||
1265 | (_("copying messages to mailbox %s"), mailbox)); | ||
1266 | _imap_mbx_clrerr (imbx); | ||
1267 | |||
1268 | rc = mu_imap_copy (imap, flags & MU_MAILBOX_COPY_UID, msgset, mailbox); | ||
1269 | if (rc) | ||
1270 | { | ||
1271 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, | ||
1272 | (_("mu_imap_copy: %s"), mu_strerror (rc))); | ||
1273 | if (rc) | ||
1274 | { | ||
1275 | if (mu_imap_response_code (imap) == MU_IMAP_RESPONSE_TRYCREATE) | ||
1276 | { | ||
1277 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1, | ||
1278 | (_("creating mailbox %s"), mailbox)); | ||
1279 | rc = mu_imap_mailbox_create (imap, mailbox); | ||
1280 | if (rc == 0) | ||
1281 | rc = mu_imap_copy (imap, flags & MU_MAILBOX_COPY_UID, | ||
1282 | msgset, mailbox); | ||
1283 | } | ||
1284 | } | ||
1285 | imbx->last_error = rc; | ||
1286 | } | ||
1287 | return rc; | ||
1288 | } | ||
1289 | |||
1255 | int | 1290 | int |
1256 | _mu_imap_mailbox_init (mu_mailbox_t mailbox) | 1291 | _mu_imap_mailbox_init (mu_mailbox_t mailbox) |
1257 | { | 1292 | { |
... | @@ -1279,6 +1314,7 @@ _mu_imap_mailbox_init (mu_mailbox_t mailbox) | ... | @@ -1279,6 +1314,7 @@ _mu_imap_mailbox_init (mu_mailbox_t mailbox) |
1279 | mailbox->_sync = _imap_mbx_sync; | 1314 | mailbox->_sync = _imap_mbx_sync; |
1280 | 1315 | ||
1281 | mailbox->_append_message = _imap_mbx_append_message; | 1316 | mailbox->_append_message = _imap_mbx_append_message; |
1317 | mailbox->_copy = _imap_copy_to_mailbox; | ||
1282 | 1318 | ||
1283 | return 0; | 1319 | return 0; |
1284 | } | 1320 | } | ... | ... |
... | @@ -55,8 +55,8 @@ _mu_imap_response_list_create (mu_imap_t imap, mu_list_t *plist) | ... | @@ -55,8 +55,8 @@ _mu_imap_response_list_create (mu_imap_t imap, mu_list_t *plist) |
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
58 | #define IS_LBRACE(p) ((p)[0] == '(') | 58 | #define IS_LBRACE(p) ((p)[0] == '(' && !(p)[1]) |
59 | #define IS_RBRACE(p) ((p)[0] == ')') | 59 | #define IS_RBRACE(p) ((p)[0] == ')' && !(p)[1]) |
60 | #define IS_NIL(p) (strcmp (p, "NIL") == 0) | 60 | #define IS_NIL(p) (strcmp (p, "NIL") == 0) |
61 | 61 | ||
62 | static struct imap_list_element * | 62 | static struct imap_list_element * | ... | ... |
... | @@ -27,13 +27,6 @@ | ... | @@ -27,13 +27,6 @@ |
27 | #include <mailutils/errno.h> | 27 | #include <mailutils/errno.h> |
28 | #include <mailutils/sys/imap.h> | 28 | #include <mailutils/sys/imap.h> |
29 | 29 | ||
30 | static void | ||
31 | response_to_errstr (mu_imap_t imap, size_t argc, char **argv) | ||
32 | { | ||
33 | if (argc && strcmp (argv[argc-1], "]")) | ||
34 | _mu_imap_seterrstrz (imap, argv[argc-1]); | ||
35 | } | ||
36 | |||
37 | int | 30 | int |
38 | _mu_imap_response (mu_imap_t imap, mu_imap_response_action_t fun, | 31 | _mu_imap_response (mu_imap_t imap, mu_imap_response_action_t fun, |
39 | void *data) | 32 | void *data) |
... | @@ -83,29 +76,17 @@ _mu_imap_response (mu_imap_t imap, mu_imap_response_action_t fun, | ... | @@ -83,29 +76,17 @@ _mu_imap_response (mu_imap_t imap, mu_imap_response_action_t fun, |
83 | /*imap->client_state = MU_IMAP_CLIENT_ERROR;*/ | 76 | /*imap->client_state = MU_IMAP_CLIENT_ERROR;*/ |
84 | status = MU_ERR_BADREPLY; | 77 | status = MU_ERR_BADREPLY; |
85 | } | 78 | } |
86 | else if (strcmp (wv[1], "OK") == 0) | 79 | else |
87 | { | ||
88 | imap->resp_code = MU_IMAP_OK; | ||
89 | response_to_errstr (imap, wc, wv); | ||
90 | } | ||
91 | else if (strcmp (wv[1], "NO") == 0) | ||
92 | { | ||
93 | imap->resp_code = MU_IMAP_NO; | ||
94 | response_to_errstr (imap, wc, wv); | ||
95 | } | ||
96 | else if (strcmp (wv[1], "BAD") == 0) | ||
97 | { | 80 | { |
98 | imap->resp_code = MU_IMAP_BAD; | 81 | mu_list_t list; |
99 | response_to_errstr (imap, wc, wv); | 82 | status = _mu_imap_untagged_response_to_list (imap, &list); |
100 | /* This may be so important that CB_BAD callback is | 83 | if (status == 0) |
101 | * overloaded to handle this case as well. | 84 | { |
102 | */ | 85 | if (_mu_imap_process_tagged_response (imap, list)) |
103 | mu_imap_callback (imap, MU_IMAP_CB_BAD, | 86 | status = MU_ERR_BADREPLY; |
104 | MU_IMAP_RESPONSE_TAGGED, | 87 | mu_list_destroy (&list); |
105 | wc >= 1 ? wv[wc-1] : NULL); | 88 | } |
106 | } | 89 | } |
107 | else | ||
108 | status = MU_ERR_BADREPLY; | ||
109 | MU_IMAP_FSET (imap, MU_IMAP_RESP); | 90 | MU_IMAP_FSET (imap, MU_IMAP_RESP); |
110 | } | 91 | } |
111 | else | 92 | else | ... | ... |
... | @@ -72,7 +72,7 @@ parse_response_code (mu_imap_t imap, mu_list_t resp) | ... | @@ -72,7 +72,7 @@ parse_response_code (mu_imap_t imap, mu_list_t resp) |
72 | if (mu_kwd_xlat_name (mu_imap_response_codes, arg->v.string, &rcode)) | 72 | if (mu_kwd_xlat_name (mu_imap_response_codes, arg->v.string, &rcode)) |
73 | return -1; | 73 | return -1; |
74 | 74 | ||
75 | arg = _mu_imap_list_at (resp, 4); | 75 | arg = _mu_imap_list_at (resp, 3); |
76 | if (!arg || !_mu_imap_list_element_is_string (arg, "]")) | 76 | if (!arg || !_mu_imap_list_element_is_string (arg, "]")) |
77 | return -1; | 77 | return -1; |
78 | } | 78 | } |
... | @@ -217,6 +217,7 @@ struct resptab | ... | @@ -217,6 +217,7 @@ struct resptab |
217 | { | 217 | { |
218 | char *name; | 218 | char *name; |
219 | mu_imap_response_action_t action; | 219 | mu_imap_response_action_t action; |
220 | int code; | ||
220 | }; | 221 | }; |
221 | 222 | ||
222 | static struct resptab resptab[] = { | 223 | static struct resptab resptab[] = { |
... | @@ -350,5 +351,75 @@ _mu_imap_process_untagged_response (mu_imap_t imap, mu_list_t list, | ... | @@ -350,5 +351,75 @@ _mu_imap_process_untagged_response (mu_imap_t imap, mu_list_t list, |
350 | } | 351 | } |
351 | return 0; | 352 | return 0; |
352 | } | 353 | } |
354 | |||
355 | static void | ||
356 | default_tagged_response (mu_imap_t imap, int code, mu_list_t resp, void *data) | ||
357 | { | ||
358 | struct imap_list_element *arg; | ||
359 | |||
360 | if (mu_list_tail (resp, (void*) &arg) == 0 && | ||
361 | arg->type == imap_eltype_string) | ||
362 | _mu_imap_seterrstrz (imap, arg->v.string); | ||
363 | imap->response_code = parse_response_code (imap, resp); | ||
364 | mu_imap_callback (imap, code, imap->response_code, | ||
365 | arg ? arg->v.string : NULL); | ||
366 | } | ||
367 | |||
368 | static void | ||
369 | ok_tagged_response (mu_imap_t imap, mu_list_t resp, void *data) | ||
370 | { | ||
371 | default_tagged_response (imap, MU_IMAP_CB_TAGGED_OK, resp, data); | ||
372 | } | ||
373 | |||
374 | static void | ||
375 | no_tagged_response (mu_imap_t imap, mu_list_t resp, void *data) | ||
376 | { | ||
377 | default_tagged_response (imap, MU_IMAP_CB_TAGGED_NO, resp, data); | ||
378 | } | ||
379 | |||
380 | static void | ||
381 | bad_tagged_response (mu_imap_t imap, mu_list_t resp, void *data) | ||
382 | { | ||
383 | default_tagged_response (imap, MU_IMAP_CB_TAGGED_BAD, resp, data); | ||
384 | } | ||
385 | |||
386 | static struct resptab tagged_resptab[] = { | ||
387 | { "OK", ok_tagged_response, MU_IMAP_OK }, | ||
388 | { "NO", no_tagged_response, MU_IMAP_NO }, | ||
389 | { "BAD", bad_tagged_response, MU_IMAP_BAD }, | ||
390 | { NULL } | ||
391 | }; | ||
392 | |||
393 | static int | ||
394 | _std_tagged_response (mu_imap_t imap, size_t count, mu_list_t resp) | ||
395 | { | ||
396 | struct resptab *rp; | ||
397 | struct imap_list_element *arg = _mu_imap_list_at (resp, 0); | ||
398 | |||
399 | if (!arg) | ||
400 | return 1; | ||
401 | |||
402 | if (arg->type == imap_eltype_string) | ||
403 | for (rp = tagged_resptab; rp->name; rp++) | ||
404 | { | ||
405 | if (mu_c_strcasecmp (rp->name, arg->v.string) == 0) | ||
406 | { | ||
407 | imap->response = rp->code; | ||
408 | rp->action (imap, resp, NULL); | ||
409 | return 0; | ||
410 | } | ||
411 | } | ||
412 | return 1; | ||
413 | } | ||
414 | |||
415 | int | ||
416 | _mu_imap_process_tagged_response (mu_imap_t imap, mu_list_t resp) | ||
417 | { | ||
418 | size_t count; | ||
419 | |||
420 | if (mu_list_count (resp, &count)) | ||
421 | return 1; | ||
422 | |||
423 | return _std_tagged_response (imap, count, resp); | ||
424 | } | ||
353 | 425 | ||
354 | ... | ... |
... | @@ -113,7 +113,7 @@ mu_imap_select (mu_imap_t imap, const char *mbox, int writable, | ... | @@ -113,7 +113,7 @@ mu_imap_select (mu_imap_t imap, const char *mbox, int writable, |
113 | memset (&imap->mbox_stat, 0, sizeof (imap->mbox_stat)); | 113 | memset (&imap->mbox_stat, 0, sizeof (imap->mbox_stat)); |
114 | status = _mu_imap_response (imap, _select_response_action, NULL); | 114 | status = _mu_imap_response (imap, _select_response_action, NULL); |
115 | MU_IMAP_CHECK_EAGAIN (imap, status); | 115 | MU_IMAP_CHECK_EAGAIN (imap, status); |
116 | switch (imap->resp_code) | 116 | switch (imap->response) |
117 | { | 117 | { |
118 | case MU_IMAP_OK: | 118 | case MU_IMAP_OK: |
119 | imap->session_state = MU_IMAP_SESSION_SELECTED; | 119 | imap->session_state = MU_IMAP_SESSION_SELECTED; | ... | ... |
... | @@ -60,7 +60,7 @@ mu_imap_starttls (mu_imap_t imap) | ... | @@ -60,7 +60,7 @@ mu_imap_starttls (mu_imap_t imap) |
60 | case MU_IMAP_CLIENT_STARTTLS_RX: | 60 | case MU_IMAP_CLIENT_STARTTLS_RX: |
61 | status = _mu_imap_response (imap, NULL, NULL); | 61 | status = _mu_imap_response (imap, NULL, NULL); |
62 | MU_IMAP_CHECK_EAGAIN (imap, status); | 62 | MU_IMAP_CHECK_EAGAIN (imap, status); |
63 | switch (imap->resp_code) | 63 | switch (imap->response) |
64 | { | 64 | { |
65 | case MU_IMAP_OK: | 65 | case MU_IMAP_OK: |
66 | status = mu_imapio_get_streams (imap->io, streams); | 66 | status = mu_imapio_get_streams (imap->io, streams); | ... | ... |
... | @@ -185,7 +185,7 @@ mu_imap_status (mu_imap_t imap, const char *mboxname, struct mu_imap_stat *ps) | ... | @@ -185,7 +185,7 @@ mu_imap_status (mu_imap_t imap, const char *mboxname, struct mu_imap_stat *ps) |
185 | 185 | ||
186 | status = _mu_imap_response (imap, _status_response_action, &sd); | 186 | status = _mu_imap_response (imap, _status_response_action, &sd); |
187 | MU_IMAP_CHECK_EAGAIN (imap, status); | 187 | MU_IMAP_CHECK_EAGAIN (imap, status); |
188 | switch (imap->resp_code) | 188 | switch (imap->response) |
189 | { | 189 | { |
190 | case MU_IMAP_OK: | 190 | case MU_IMAP_OK: |
191 | break; | 191 | break; | ... | ... |
... | @@ -67,7 +67,7 @@ mu_imap_store_flags (mu_imap_t imap, int uid, mu_msgset_t msgset, | ... | @@ -67,7 +67,7 @@ mu_imap_store_flags (mu_imap_t imap, int uid, mu_msgset_t msgset, |
67 | /* FIXME: Handle unsolicited responses */ | 67 | /* FIXME: Handle unsolicited responses */ |
68 | status = _mu_imap_response (imap, NULL, NULL); | 68 | status = _mu_imap_response (imap, NULL, NULL); |
69 | MU_IMAP_CHECK_EAGAIN (imap, status); | 69 | MU_IMAP_CHECK_EAGAIN (imap, status); |
70 | switch (imap->resp_code) | 70 | switch (imap->response) |
71 | { | 71 | { |
72 | case MU_IMAP_OK: | 72 | case MU_IMAP_OK: |
73 | status = 0; | 73 | status = 0; | ... | ... |
... | @@ -42,6 +42,8 @@ static struct argp_option options[] = { | ... | @@ -42,6 +42,8 @@ static struct argp_option options[] = { |
42 | {"truncate", ARG_TRUNCATE, N_("BOOL"), OPTION_ARG_OPTIONAL, | 42 | {"truncate", ARG_TRUNCATE, N_("BOOL"), OPTION_ARG_OPTIONAL, |
43 | N_("truncate source mailbox after incorporating (default)")}, | 43 | N_("truncate source mailbox after incorporating (default)")}, |
44 | {"notruncate", ARG_NOTRUNCATE, NULL, OPTION_HIDDEN, ""}, | 44 | {"notruncate", ARG_NOTRUNCATE, NULL, OPTION_HIDDEN, ""}, |
45 | {"moveto", ARG_MOVETO, N_("MAILBOX"), 0, | ||
46 | N_("move incorporated messages to MAILBOX instead of deleting them") }, | ||
45 | {"width", ARG_WIDTH, N_("NUMBER"), 0, | 47 | {"width", ARG_WIDTH, N_("NUMBER"), 0, |
46 | N_("set output width")}, | 48 | N_("set output width")}, |
47 | {"quiet", ARG_QUIET, 0, 0, | 49 | {"quiet", ARG_QUIET, 0, 0, |
... | @@ -58,6 +60,7 @@ struct mh_option mh_option[] = { | ... | @@ -58,6 +60,7 @@ struct mh_option mh_option[] = { |
58 | { "form", MH_OPT_ARG, "format-file" }, | 60 | { "form", MH_OPT_ARG, "format-file" }, |
59 | { "format", MH_OPT_ARG, "string" }, | 61 | { "format", MH_OPT_ARG, "string" }, |
60 | { "truncate", MH_OPT_BOOL }, | 62 | { "truncate", MH_OPT_BOOL }, |
63 | { "moveto", MH_OPT_ARG, "folder" }, | ||
61 | { "width", MH_OPT_ARG, "number" }, | 64 | { "width", MH_OPT_ARG, "number" }, |
62 | { "quiet" }, | 65 | { "quiet" }, |
63 | { NULL } | 66 | { NULL } |
... | @@ -72,6 +75,7 @@ static int changecur = -1; | ... | @@ -72,6 +75,7 @@ static int changecur = -1; |
72 | static int truncate_source = -1; | 75 | static int truncate_source = -1; |
73 | static int quiet = 0; | 76 | static int quiet = 0; |
74 | static const char *append_folder; | 77 | static const char *append_folder; |
78 | static const char *move_to_mailbox; | ||
75 | 79 | ||
76 | static error_t | 80 | static error_t |
77 | opt_handler (int key, char *arg, struct argp_state *state) | 81 | opt_handler (int key, char *arg, struct argp_state *state) |
... | @@ -122,6 +126,10 @@ opt_handler (int key, char *arg, struct argp_state *state) | ... | @@ -122,6 +126,10 @@ opt_handler (int key, char *arg, struct argp_state *state) |
122 | case ARG_NOTRUNCATE: | 126 | case ARG_NOTRUNCATE: |
123 | truncate_source = 0; | 127 | truncate_source = 0; |
124 | break; | 128 | break; |
129 | |||
130 | case ARG_MOVETO: | ||
131 | move_to_mailbox = arg; | ||
132 | break; | ||
125 | 133 | ||
126 | case ARG_WIDTH: | 134 | case ARG_WIDTH: |
127 | width = strtoul (arg, NULL, 0); | 135 | width = strtoul (arg, NULL, 0); |
... | @@ -143,7 +151,8 @@ opt_handler (int key, char *arg, struct argp_state *state) | ... | @@ -143,7 +151,8 @@ opt_handler (int key, char *arg, struct argp_state *state) |
143 | } | 151 | } |
144 | 152 | ||
145 | void | 153 | void |
146 | list_message (mh_format_t *format, mu_mailbox_t mbox, size_t msgno, size_t width) | 154 | list_message (mh_format_t *format, mu_mailbox_t mbox, size_t msgno, |
155 | size_t width) | ||
147 | { | 156 | { |
148 | mu_message_t msg; | 157 | mu_message_t msg; |
149 | char *buf = NULL; | 158 | char *buf = NULL; |
... | @@ -275,6 +284,33 @@ main (int argc, char **argv) | ... | @@ -275,6 +284,33 @@ main (int argc, char **argv) |
275 | } | 284 | } |
276 | } | 285 | } |
277 | 286 | ||
287 | if (truncate_source && move_to_mailbox) | ||
288 | { | ||
289 | mu_msgset_t msgset; | ||
290 | |||
291 | rc = mu_msgset_create (&msgset, input, MU_MSGSET_NUM); | ||
292 | if (rc) | ||
293 | mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_create", NULL, rc); | ||
294 | else | ||
295 | { | ||
296 | rc = mu_msgset_add_range (msgset, 1, total, MU_MSGSET_NUM); | ||
297 | if (rc) | ||
298 | mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_add_range", NULL, rc); | ||
299 | else | ||
300 | { | ||
301 | rc = mu_mailbox_msgset_copy (input, msgset, move_to_mailbox, | ||
302 | MU_MAILBOX_COPY_CREAT); | ||
303 | if (rc) | ||
304 | { | ||
305 | mu_error (_("failed to move messages to %s: %s"), | ||
306 | move_to_mailbox, mu_strerror (rc)); | ||
307 | truncate_source = 0; | ||
308 | } | ||
309 | } | ||
310 | mu_msgset_destroy (&msgset); | ||
311 | } | ||
312 | } | ||
313 | |||
278 | if (!changecur) | 314 | if (!changecur) |
279 | { | 315 | { |
280 | mu_property_t prop = mh_mailbox_get_property (output); | 316 | mu_property_t prop = mh_mailbox_get_property (output); | ... | ... |
-
Please register or sign in to post a comment