Imap client: implement list.
* libmailutils/stdstream/basestr.c (mu_strout): Bugfix: initialize destroy function. * include/mailutils/imap.h (imap_command) (mu_imap_gencom): Move to sys/imap.h (mu_imap_list,mu_imap_list_new): New protos. * include/mailutils/sys/imap.h (imap_command): New struct (from ../imap.h). <handler>: Rename to tagged_handler. (untagged_handler,untagged_handler_data): New members. All uses changed. (mu_imap_gencom): New proto. * libproto/imap/list.c: New file. * libproto/imap/Makefile.am: Add list.c * libproto/imap/gencom.c: Use supplied untagged_handler to analize untagged response. * mu/imap.c: Implement list command.
Showing
13 changed files
with
255 additions
and
25 deletions
... | @@ -44,19 +44,6 @@ enum mu_imap_session_state | ... | @@ -44,19 +44,6 @@ enum mu_imap_session_state |
44 | int mu_imap_create (mu_imap_t *pimap); | 44 | int mu_imap_create (mu_imap_t *pimap); |
45 | void mu_imap_destroy (mu_imap_t *pimap); | 45 | void mu_imap_destroy (mu_imap_t *pimap); |
46 | 46 | ||
47 | struct imap_command | ||
48 | { | ||
49 | int session_state; | ||
50 | char *capa; | ||
51 | int rx_state; | ||
52 | int uid; | ||
53 | int argc; | ||
54 | char const **argv; | ||
55 | void (*handler) (mu_imap_t); | ||
56 | }; | ||
57 | |||
58 | int mu_imap_gencom (mu_imap_t imap, struct imap_command *cmd); | ||
59 | |||
60 | int mu_imap_connect (mu_imap_t imap); | 47 | int mu_imap_connect (mu_imap_t imap); |
61 | int mu_imap_disconnect (mu_imap_t imap); | 48 | int mu_imap_disconnect (mu_imap_t imap); |
62 | 49 | ||
... | @@ -100,6 +87,11 @@ int mu_imap_append_message (mu_imap_t imap, const char *mailbox, int flags, | ... | @@ -100,6 +87,11 @@ int mu_imap_append_message (mu_imap_t imap, const char *mailbox, int flags, |
100 | struct tm *tm, struct mu_timezone *tz, | 87 | struct tm *tm, struct mu_timezone *tz, |
101 | mu_message_t msg); | 88 | mu_message_t msg); |
102 | 89 | ||
90 | int mu_imap_list (mu_imap_t imap, const char *refname, const char *mboxname, | ||
91 | mu_list_t retlist); | ||
92 | int mu_imap_list_new (mu_imap_t imap, const char *refname, const char *mboxname, | ||
93 | mu_list_t *plist); | ||
94 | |||
103 | int mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier); | 95 | int mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier); |
104 | int mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier); | 96 | int mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier); |
105 | 97 | ... | ... |
... | @@ -66,6 +66,7 @@ enum mu_imap_client_state | ... | @@ -66,6 +66,7 @@ enum mu_imap_client_state |
66 | MU_IMAP_CLIENT_COPY_RX, | 66 | MU_IMAP_CLIENT_COPY_RX, |
67 | MU_IMAP_CLIENT_EXPUNGE_RX, | 67 | MU_IMAP_CLIENT_EXPUNGE_RX, |
68 | MU_IMAP_CLIENT_APPEND_RX, | 68 | MU_IMAP_CLIENT_APPEND_RX, |
69 | MU_IMAP_CLIENT_LIST_RX, | ||
69 | MU_IMAP_CLIENT_CLOSING | 70 | MU_IMAP_CLIENT_CLOSING |
70 | }; | 71 | }; |
71 | 72 | ||
... | @@ -135,6 +136,24 @@ int _mu_imap_trace_enable (mu_imap_t imap); | ... | @@ -135,6 +136,24 @@ int _mu_imap_trace_enable (mu_imap_t imap); |
135 | int _mu_imap_trace_disable (mu_imap_t imap); | 136 | int _mu_imap_trace_disable (mu_imap_t imap); |
136 | int _mu_imap_xscript_level (mu_imap_t imap, int xlev); | 137 | int _mu_imap_xscript_level (mu_imap_t imap, int xlev); |
137 | 138 | ||
139 | typedef void (*mu_imap_response_action_t) (mu_imap_t imap, mu_list_t resp, | ||
140 | void *data); | ||
141 | |||
142 | struct imap_command | ||
143 | { | ||
144 | int session_state; | ||
145 | char *capa; | ||
146 | int rx_state; | ||
147 | int uid; | ||
148 | int argc; | ||
149 | char const **argv; | ||
150 | void (*tagged_handler) (mu_imap_t); | ||
151 | mu_imap_response_action_t untagged_handler; | ||
152 | void *untagged_handler_data; | ||
153 | }; | ||
154 | |||
155 | int mu_imap_gencom (mu_imap_t imap, struct imap_command *cmd); | ||
156 | |||
138 | /* If status indicates an error, return. | 157 | /* If status indicates an error, return. |
139 | */ | 158 | */ |
140 | #define MU_IMAP_CHECK_ERROR(imap, status) \ | 159 | #define MU_IMAP_CHECK_ERROR(imap, status) \ |
... | @@ -182,9 +201,6 @@ int _mu_imap_tag_next (mu_imap_t imap); | ... | @@ -182,9 +201,6 @@ int _mu_imap_tag_next (mu_imap_t imap); |
182 | int _mu_imap_tag_clr (mu_imap_t imap); | 201 | int _mu_imap_tag_clr (mu_imap_t imap); |
183 | 202 | ||
184 | 203 | ||
185 | typedef void (*mu_imap_response_action_t) (mu_imap_t imap, mu_list_t resp, | ||
186 | void *data); | ||
187 | |||
188 | int _mu_imap_untagged_response_to_list (mu_imap_t imap, mu_list_t *plist); | 204 | int _mu_imap_untagged_response_to_list (mu_imap_t imap, mu_list_t *plist); |
189 | int _mu_imap_process_untagged_response (mu_imap_t imap, mu_list_t list, | 205 | int _mu_imap_process_untagged_response (mu_imap_t imap, mu_list_t list, |
190 | mu_imap_response_action_t fun, | 206 | mu_imap_response_action_t fun, | ... | ... |
... | @@ -128,6 +128,7 @@ static struct _mu_file_stream stdstream[2] = { | ... | @@ -128,6 +128,7 @@ static struct _mu_file_stream stdstream[2] = { |
128 | { { ref_count: 1, | 128 | { { ref_count: 1, |
129 | buftype: mu_buffer_none, | 129 | buftype: mu_buffer_none, |
130 | flags: MU_STREAM_WRITE, | 130 | flags: MU_STREAM_WRITE, |
131 | destroy: bootstrap_destroy, | ||
131 | event_cb: std_bootstrap, | 132 | event_cb: std_bootstrap, |
132 | event_mask: _MU_STR_EVMASK (_MU_STR_EVENT_BOOTSTRAP) | 133 | event_mask: _MU_STR_EVMASK (_MU_STR_EVENT_BOOTSTRAP) |
133 | }, fd: MU_STDOUT_FD, filename: "<stdout>", | 134 | }, fd: MU_STDOUT_FD, filename: "<stdout>", | ... | ... |
... | @@ -39,7 +39,8 @@ mu_imap_copy (mu_imap_t imap, int uid, const char *msgset, const char *mailbox) | ... | @@ -39,7 +39,8 @@ mu_imap_copy (mu_imap_t imap, int uid, const char *msgset, const char *mailbox) |
39 | com.uid = 0; | 39 | com.uid = 0; |
40 | com.argc = 3; | 40 | com.argc = 3; |
41 | com.argv = argv; | 41 | com.argv = argv; |
42 | com.handler = NULL; | 42 | com.tagged_handler = NULL; |
43 | com.untagged_handler = NULL; | ||
43 | 44 | ||
44 | return mu_imap_gencom (imap, &com); | 45 | return mu_imap_gencom (imap, &com); |
45 | } | 46 | } | ... | ... |
... | @@ -40,7 +40,8 @@ mu_imap_delete (mu_imap_t imap, const char *mailbox) | ... | @@ -40,7 +40,8 @@ mu_imap_delete (mu_imap_t imap, const char *mailbox) |
40 | com.uid = 0; | 40 | com.uid = 0; |
41 | com.argc = 2; | 41 | com.argc = 2; |
42 | com.argv = argv; | 42 | com.argv = argv; |
43 | com.handler = NULL; | 43 | com.tagged_handler = NULL; |
44 | com.untagged_handler = NULL; | ||
44 | 45 | ||
45 | return mu_imap_gencom (imap, &com); | 46 | return mu_imap_gencom (imap, &com); |
46 | } | 47 | } | ... | ... |
... | @@ -44,7 +44,8 @@ mu_imap_fetch (mu_imap_t imap, int uid, const char *msgset, const char *items) | ... | @@ -44,7 +44,8 @@ mu_imap_fetch (mu_imap_t imap, int uid, const char *msgset, const char *items) |
44 | com.uid = uid; | 44 | com.uid = uid; |
45 | com.argc = 3; | 45 | com.argc = 3; |
46 | com.argv = argv; | 46 | com.argv = argv; |
47 | com.handler = NULL; | 47 | com.tagged_handler = NULL; |
48 | com.untagged_handler = NULL; | ||
48 | 49 | ||
49 | return mu_imap_gencom (imap, &com); | 50 | return mu_imap_gencom (imap, &com); |
50 | } | 51 | } | ... | ... |
... | @@ -74,10 +74,11 @@ mu_imap_gencom (mu_imap_t imap, struct imap_command *cmd) | ... | @@ -74,10 +74,11 @@ mu_imap_gencom (mu_imap_t imap, struct imap_command *cmd) |
74 | 74 | ||
75 | if (imap->client_state == cmd->rx_state) | 75 | if (imap->client_state == cmd->rx_state) |
76 | { | 76 | { |
77 | status = _mu_imap_response (imap, NULL, NULL); | 77 | status = _mu_imap_response (imap, cmd->untagged_handler, |
78 | cmd->untagged_handler_data); | ||
78 | MU_IMAP_CHECK_EAGAIN (imap, status); | 79 | MU_IMAP_CHECK_EAGAIN (imap, status); |
79 | if (cmd->handler) | 80 | if (cmd->tagged_handler) |
80 | cmd->handler (imap); | 81 | cmd->tagged_handler (imap); |
81 | switch (imap->resp_code) | 82 | switch (imap->resp_code) |
82 | { | 83 | { |
83 | case MU_IMAP_OK: | 84 | case MU_IMAP_OK: | ... | ... |
libproto/imap/list.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2011 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library. If not, see | ||
16 | <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | #include <mailutils/errno.h> | ||
25 | #include <mailutils/address.h> | ||
26 | #include <mailutils/cstr.h> | ||
27 | #include <mailutils/cctype.h> | ||
28 | #include <mailutils/list.h> | ||
29 | #include <mailutils/imap.h> | ||
30 | #include <mailutils/sys/imap.h> | ||
31 | |||
32 | struct list_closure | ||
33 | { | ||
34 | int error_code; | ||
35 | mu_list_t retlist; | ||
36 | }; | ||
37 | |||
38 | static int | ||
39 | count_level (const char *name, int delim) | ||
40 | { | ||
41 | int level = 0; | ||
42 | |||
43 | while (*name) | ||
44 | if (*name++ == delim) | ||
45 | level++; | ||
46 | return level; | ||
47 | } | ||
48 | |||
49 | static int | ||
50 | list_attr_conv (void *item, void *data) | ||
51 | { | ||
52 | struct imap_list_element *elt = item; | ||
53 | struct mu_list_response *rp = data; | ||
54 | |||
55 | if (elt->type != imap_eltype_string) | ||
56 | return 0; | ||
57 | if (mu_c_strcasecmp (elt->v.string, "\\Noinferiors")) | ||
58 | rp->type |= MU_FOLDER_ATTRIBUTE_DIRECTORY; | ||
59 | if (mu_c_strcasecmp (elt->v.string, "\\Noselect")) | ||
60 | rp->type |= MU_FOLDER_ATTRIBUTE_FILE; | ||
61 | /* FIXME: \Marked nad \Unmarked have no correspondence in flags. */ | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static void | ||
66 | list_untagged_handler (mu_imap_t imap, mu_list_t resp, void *data) | ||
67 | { | ||
68 | struct list_closure *clos = data; | ||
69 | struct imap_list_element *elt; | ||
70 | size_t count; | ||
71 | |||
72 | if (clos->error_code) | ||
73 | return; | ||
74 | |||
75 | mu_list_count (resp, &count); | ||
76 | if (count == 4 && | ||
77 | _mu_imap_list_nth_element_is_string (resp, 0, "LIST")) | ||
78 | { | ||
79 | struct mu_list_response *rp; | ||
80 | |||
81 | rp = calloc (1, sizeof (*rp)); | ||
82 | if (!rp) | ||
83 | { | ||
84 | clos->error_code = ENOMEM; | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | elt = _mu_imap_list_at (resp, 1); | ||
89 | if (!(elt && elt->type == imap_eltype_list)) | ||
90 | return; | ||
91 | rp->type = 0; | ||
92 | mu_list_foreach (elt->v.list, list_attr_conv, rp); | ||
93 | |||
94 | elt = _mu_imap_list_at (resp, 3); | ||
95 | if (!(elt && elt->type == imap_eltype_string)) | ||
96 | return; | ||
97 | rp->name = strdup (elt->v.string); | ||
98 | if (!rp->name) | ||
99 | { | ||
100 | free (rp); | ||
101 | clos->error_code = ENOMEM; | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | elt = _mu_imap_list_at (resp, 2); | ||
106 | if (!(elt && elt->type == imap_eltype_string)) | ||
107 | return; | ||
108 | if (mu_c_strcasecmp (elt->v.string, "NIL") == 0) | ||
109 | { | ||
110 | rp->separator = 0; | ||
111 | rp->level = 0; | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | rp->separator = elt->v.string[0]; | ||
116 | rp->level = count_level (rp->name, rp->separator); | ||
117 | } | ||
118 | if ((clos->error_code = mu_list_append (clos->retlist, rp))) | ||
119 | mu_list_response_free (rp); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | int | ||
124 | mu_imap_list (mu_imap_t imap, const char *refname, const char *mboxname, | ||
125 | mu_list_t retlist) | ||
126 | { | ||
127 | char const *argv[3]; | ||
128 | static struct imap_command com; | ||
129 | struct list_closure clos; | ||
130 | int rc; | ||
131 | |||
132 | argv[0] = "LIST"; | ||
133 | argv[1] = refname; | ||
134 | argv[2] = mboxname; | ||
135 | |||
136 | clos.error_code = 0; | ||
137 | clos.retlist = retlist; | ||
138 | |||
139 | com.session_state = MU_IMAP_SESSION_AUTH; | ||
140 | com.capa = NULL; | ||
141 | com.rx_state = MU_IMAP_CLIENT_LIST_RX; | ||
142 | com.uid = 0; | ||
143 | com.argc = 3; | ||
144 | com.argv = argv; | ||
145 | com.tagged_handler = NULL; | ||
146 | com.untagged_handler = list_untagged_handler; | ||
147 | com.untagged_handler_data = &clos; | ||
148 | |||
149 | rc = mu_imap_gencom (imap, &com); | ||
150 | if (rc == 0) | ||
151 | rc = clos.error_code; | ||
152 | |||
153 | return rc; | ||
154 | } | ||
155 | |||
156 | int | ||
157 | mu_imap_list_new (mu_imap_t imap, const char *refname, const char *mboxname, | ||
158 | mu_list_t *plist) | ||
159 | { | ||
160 | mu_list_t list; | ||
161 | int rc = mu_list_create (&list); | ||
162 | if (rc == 0) | ||
163 | { | ||
164 | mu_list_set_destroy_item (list, mu_list_response_free); | ||
165 | rc = mu_imap_list (imap, refname, mboxname, list); | ||
166 | if (rc) | ||
167 | mu_list_destroy (&list); | ||
168 | else | ||
169 | *plist = list; | ||
170 | } | ||
171 | return rc; | ||
172 | } |
... | @@ -40,7 +40,8 @@ mu_imap_mailbox_create (mu_imap_t imap, const char *mailbox) | ... | @@ -40,7 +40,8 @@ mu_imap_mailbox_create (mu_imap_t imap, const char *mailbox) |
40 | com.uid = 0; | 40 | com.uid = 0; |
41 | com.argc = 2; | 41 | com.argc = 2; |
42 | com.argv = argv; | 42 | com.argv = argv; |
43 | com.handler = NULL; | 43 | com.tagged_handler = NULL; |
44 | com.untagged_handler = NULL; | ||
44 | 45 | ||
45 | return mu_imap_gencom (imap, &com); | 46 | return mu_imap_gencom (imap, &com); |
46 | } | 47 | } | ... | ... |
... | @@ -39,7 +39,8 @@ mu_imap_rename (mu_imap_t imap, const char *mailbox, const char *new_mailbox) | ... | @@ -39,7 +39,8 @@ mu_imap_rename (mu_imap_t imap, const char *mailbox, const char *new_mailbox) |
39 | com.uid = 0; | 39 | com.uid = 0; |
40 | com.argc = 3; | 40 | com.argc = 3; |
41 | com.argv = argv; | 41 | com.argv = argv; |
42 | com.handler = NULL; | 42 | com.tagged_handler = NULL; |
43 | com.untagged_handler = NULL; | ||
43 | 44 | ||
44 | return mu_imap_gencom (imap, &com); | 45 | return mu_imap_gencom (imap, &com); |
45 | } | 46 | } | ... | ... |
... | @@ -41,7 +41,8 @@ mu_imap_store (mu_imap_t imap, int uid, const char *msgset, const char *items) | ... | @@ -41,7 +41,8 @@ mu_imap_store (mu_imap_t imap, int uid, const char *msgset, const char *items) |
41 | com.uid = uid; | 41 | com.uid = uid; |
42 | com.argc = 3; | 42 | com.argc = 3; |
43 | com.argv = argv; | 43 | com.argv = argv; |
44 | com.handler = NULL; | 44 | com.tagged_handler = NULL; |
45 | com.untagged_handler = NULL; | ||
45 | 46 | ||
46 | return mu_imap_gencom (imap, &com); | 47 | return mu_imap_gencom (imap, &com); |
47 | } | 48 | } | ... | ... |
... | @@ -895,6 +895,43 @@ com_append (int argc, char **argv) | ... | @@ -895,6 +895,43 @@ com_append (int argc, char **argv) |
895 | return 0; | 895 | return 0; |
896 | } | 896 | } |
897 | 897 | ||
898 | static int | ||
899 | print_list_item (void *item, void *data) | ||
900 | { | ||
901 | struct mu_list_response *resp = item; | ||
902 | mu_stream_t out = data; | ||
903 | |||
904 | mu_stream_printf (out, | ||
905 | "%c%c %c %4d %s\n", | ||
906 | (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY) ? 'd' : '-', | ||
907 | (resp->type & MU_FOLDER_ATTRIBUTE_FILE) ? 'f' : '-', | ||
908 | resp->separator, | ||
909 | resp->level, | ||
910 | resp->name); | ||
911 | return 0; | ||
912 | } | ||
913 | |||
914 | static int | ||
915 | com_list (int argc, char **argv) | ||
916 | { | ||
917 | mu_list_t list; | ||
918 | int rc; | ||
919 | mu_stream_t out; | ||
920 | |||
921 | rc = mu_imap_list_new (imap, argv[1], argv[2], &list); | ||
922 | if (rc) | ||
923 | { | ||
924 | report_failure ("list", rc); | ||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | out = mutool_open_pager (); | ||
929 | mu_list_foreach (list, print_list_item, out); | ||
930 | mu_stream_unref (out); | ||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | |||
898 | struct mutool_command imap_comtab[] = { | 935 | struct mutool_command imap_comtab[] = { |
899 | { "capability", 1, -1, 0, | 936 | { "capability", 1, -1, 0, |
900 | com_capability, | 937 | com_capability, |
... | @@ -982,6 +1019,10 @@ struct mutool_command imap_comtab[] = { | ... | @@ -982,6 +1019,10 @@ struct mutool_command imap_comtab[] = { |
982 | com_append, | 1019 | com_append, |
983 | N_("[-time DATETIME] [-flag FLAG] MAILBOX FILE"), | 1020 | N_("[-time DATETIME] [-flag FLAG] MAILBOX FILE"), |
984 | N_("append message text from FILE to MAILBOX") }, | 1021 | N_("append message text from FILE to MAILBOX") }, |
1022 | { "list", 3, 3, 0, | ||
1023 | com_list, | ||
1024 | N_("REF MBOX"), | ||
1025 | N_("List matching mailboxes") }, | ||
985 | { "quit", 1, 1, 0, | 1026 | { "quit", 1, 1, 0, |
986 | com_logout, | 1027 | com_logout, |
987 | NULL, | 1028 | NULL, | ... | ... |
-
Please register or sign in to post a comment