Imap client: implement LSUB.
LSUB is pretty similar to LIST, therefore it is implemented as a wrapper over the latter. * include/mailutils/imap.h (mu_imap_genlist,mu_imap_genlist_new) (mu_imap_lsub,mu_imap_lsub_new): New protos. * include/mailutils/sys/imap.h (MU_IMAP_CLIENT_LSUB_RX): New state. * libproto/imap/Makefile.am (libmu_imap_la_SOURCES): Add new files. * libproto/imap/genlist.c: New file. * libproto/imap/list.c: Rewrite using generalized list functions. * libproto/imap/lsub.c: New file. * mu/imap.c: Implement lsub.
Showing
7 changed files
with
258 additions
and
140 deletions
... | @@ -87,11 +87,23 @@ int mu_imap_append_message (mu_imap_t imap, const char *mailbox, int flags, | ... | @@ -87,11 +87,23 @@ int mu_imap_append_message (mu_imap_t imap, const char *mailbox, int flags, |
87 | struct tm *tm, struct mu_timezone *tz, | 87 | struct tm *tm, struct mu_timezone *tz, |
88 | mu_message_t msg); | 88 | mu_message_t msg); |
89 | 89 | ||
90 | int mu_imap_list (mu_imap_t imap, const char *refname, const char *mboxname, | 90 | int mu_imap_genlist (mu_imap_t imap, int lsub, |
91 | const char *refname, const char *mboxname, | ||
91 | mu_list_t retlist); | 92 | mu_list_t retlist); |
92 | int mu_imap_list_new (mu_imap_t imap, const char *refname, const char *mboxname, | 93 | int mu_imap_genlist_new (mu_imap_t imap, int lsub, |
94 | const char *refname, const char *mboxname, | ||
93 | mu_list_t *plist); | 95 | mu_list_t *plist); |
94 | 96 | ||
97 | int mu_imap_list (mu_imap_t imap, const char *refname, const char *mboxname, | ||
98 | mu_list_t retlist); | ||
99 | int mu_imap_list_new (mu_imap_t imap, const char *refname, | ||
100 | const char *mboxname, mu_list_t *plist); | ||
101 | |||
102 | int mu_imap_lsub (mu_imap_t imap, const char *refname, const char *mboxname, | ||
103 | mu_list_t retlist); | ||
104 | int mu_imap_lsub_new (mu_imap_t imap, const char *refname, | ||
105 | const char *mboxname, mu_list_t *plist); | ||
106 | |||
95 | int mu_imap_subscribe (mu_imap_t imap, const char *mailbox); | 107 | int mu_imap_subscribe (mu_imap_t imap, const char *mailbox); |
96 | int mu_imap_unsubscribe (mu_imap_t imap, const char *mailbox); | 108 | int mu_imap_unsubscribe (mu_imap_t imap, const char *mailbox); |
97 | 109 | ... | ... |
... | @@ -69,6 +69,7 @@ enum mu_imap_client_state | ... | @@ -69,6 +69,7 @@ enum mu_imap_client_state |
69 | MU_IMAP_CLIENT_LIST_RX, | 69 | MU_IMAP_CLIENT_LIST_RX, |
70 | MU_IMAP_CLIENT_SUBSCRIBE_RX, | 70 | MU_IMAP_CLIENT_SUBSCRIBE_RX, |
71 | MU_IMAP_CLIENT_UNSUBSCRIBE_RX, | 71 | MU_IMAP_CLIENT_UNSUBSCRIBE_RX, |
72 | MU_IMAP_CLIENT_LSUB_RX, | ||
72 | MU_IMAP_CLIENT_CLOSING | 73 | MU_IMAP_CLIENT_CLOSING |
73 | }; | 74 | }; |
74 | 75 | ... | ... |
... | @@ -33,6 +33,7 @@ libmu_imap_la_SOURCES = \ | ... | @@ -33,6 +33,7 @@ libmu_imap_la_SOURCES = \ |
33 | fake-folder.c\ | 33 | fake-folder.c\ |
34 | fetch.c\ | 34 | fetch.c\ |
35 | gencom.c\ | 35 | gencom.c\ |
36 | genlist.c\ | ||
36 | callback.c\ | 37 | callback.c\ |
37 | capability.c\ | 38 | capability.c\ |
38 | capatst.c\ | 39 | capatst.c\ |
... | @@ -51,6 +52,7 @@ libmu_imap_la_SOURCES = \ | ... | @@ -51,6 +52,7 @@ libmu_imap_la_SOURCES = \ |
51 | list.c\ | 52 | list.c\ |
52 | login.c\ | 53 | login.c\ |
53 | logout.c\ | 54 | logout.c\ |
55 | lsub.c\ | ||
54 | mbcreate.c\ | 56 | mbcreate.c\ |
55 | noop.c\ | 57 | noop.c\ |
56 | rename.c\ | 58 | rename.c\ | ... | ... |
libproto/imap/genlist.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 | const char *command; | ||
37 | }; | ||
38 | |||
39 | static int | ||
40 | count_level (const char *name, int delim) | ||
41 | { | ||
42 | int level = 0; | ||
43 | |||
44 | while (*name) | ||
45 | if (*name++ == delim) | ||
46 | level++; | ||
47 | return level; | ||
48 | } | ||
49 | |||
50 | static int | ||
51 | list_attr_conv (void *item, void *data) | ||
52 | { | ||
53 | struct imap_list_element *elt = item; | ||
54 | struct mu_list_response *rp = data; | ||
55 | |||
56 | if (elt->type != imap_eltype_string) | ||
57 | return 0; | ||
58 | if (mu_c_strcasecmp (elt->v.string, "\\Noinferiors")) | ||
59 | rp->type |= MU_FOLDER_ATTRIBUTE_DIRECTORY; | ||
60 | if (mu_c_strcasecmp (elt->v.string, "\\Noselect")) | ||
61 | rp->type |= MU_FOLDER_ATTRIBUTE_FILE; | ||
62 | /* FIXME: \Marked nad \Unmarked have no correspondence in flags. */ | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static void | ||
67 | list_untagged_handler (mu_imap_t imap, mu_list_t resp, void *data) | ||
68 | { | ||
69 | struct list_closure *clos = data; | ||
70 | struct imap_list_element *elt; | ||
71 | size_t count; | ||
72 | |||
73 | if (clos->error_code) | ||
74 | return; | ||
75 | |||
76 | mu_list_count (resp, &count); | ||
77 | if (count == 4 && | ||
78 | _mu_imap_list_nth_element_is_string (resp, 0, clos->command)) | ||
79 | { | ||
80 | struct mu_list_response *rp; | ||
81 | |||
82 | rp = calloc (1, sizeof (*rp)); | ||
83 | if (!rp) | ||
84 | { | ||
85 | clos->error_code = ENOMEM; | ||
86 | return; | ||
87 | } | ||
88 | |||
89 | elt = _mu_imap_list_at (resp, 1); | ||
90 | if (!(elt && elt->type == imap_eltype_list)) | ||
91 | return; | ||
92 | rp->type = 0; | ||
93 | mu_list_foreach (elt->v.list, list_attr_conv, rp); | ||
94 | |||
95 | elt = _mu_imap_list_at (resp, 3); | ||
96 | if (!(elt && elt->type == imap_eltype_string)) | ||
97 | return; | ||
98 | rp->name = strdup (elt->v.string); | ||
99 | if (!rp->name) | ||
100 | { | ||
101 | free (rp); | ||
102 | clos->error_code = ENOMEM; | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | elt = _mu_imap_list_at (resp, 2); | ||
107 | if (!(elt && elt->type == imap_eltype_string)) | ||
108 | return; | ||
109 | if (mu_c_strcasecmp (elt->v.string, "NIL") == 0) | ||
110 | { | ||
111 | rp->separator = 0; | ||
112 | rp->level = 0; | ||
113 | } | ||
114 | else | ||
115 | { | ||
116 | rp->separator = elt->v.string[0]; | ||
117 | rp->level = count_level (rp->name, rp->separator); | ||
118 | } | ||
119 | if ((clos->error_code = mu_list_append (clos->retlist, rp))) | ||
120 | mu_list_response_free (rp); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | int | ||
125 | mu_imap_genlist (mu_imap_t imap, int lsub, | ||
126 | const char *refname, const char *mboxname, | ||
127 | mu_list_t retlist) | ||
128 | { | ||
129 | char const *argv[3]; | ||
130 | static struct imap_command com; | ||
131 | struct list_closure clos; | ||
132 | int rc; | ||
133 | |||
134 | argv[0] = lsub ? "LSUB" : "LIST"; | ||
135 | argv[1] = refname; | ||
136 | argv[2] = mboxname; | ||
137 | |||
138 | clos.error_code = 0; | ||
139 | clos.retlist = retlist; | ||
140 | clos.command = argv[0]; | ||
141 | |||
142 | com.session_state = MU_IMAP_SESSION_AUTH; | ||
143 | com.capa = NULL; | ||
144 | com.rx_state = lsub ? MU_IMAP_CLIENT_LSUB_RX : MU_IMAP_CLIENT_LIST_RX; | ||
145 | com.argc = 3; | ||
146 | com.argv = argv; | ||
147 | com.extra = NULL; | ||
148 | com.tagged_handler = NULL; | ||
149 | com.untagged_handler = list_untagged_handler; | ||
150 | com.untagged_handler_data = &clos; | ||
151 | |||
152 | rc = mu_imap_gencom (imap, &com); | ||
153 | if (rc == 0) | ||
154 | rc = clos.error_code; | ||
155 | |||
156 | return rc; | ||
157 | } | ||
158 | |||
159 | int | ||
160 | mu_imap_genlist_new (mu_imap_t imap, int lsub, | ||
161 | const char *refname, const char *mboxname, | ||
162 | mu_list_t *plist) | ||
163 | { | ||
164 | mu_list_t list; | ||
165 | int rc = mu_list_create (&list); | ||
166 | if (rc == 0) | ||
167 | { | ||
168 | mu_list_set_destroy_item (list, mu_list_response_free); | ||
169 | rc = mu_imap_genlist (imap, lsub, refname, mboxname, list); | ||
170 | if (rc) | ||
171 | mu_list_destroy (&list); | ||
172 | else | ||
173 | *plist = list; | ||
174 | } | ||
175 | return rc; | ||
176 | } |
... | @@ -19,154 +19,20 @@ | ... | @@ -19,154 +19,20 @@ |
19 | # include <config.h> | 19 | # include <config.h> |
20 | #endif | 20 | #endif |
21 | 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> | 22 | #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 | 23 | ||
123 | int | 24 | int |
124 | mu_imap_list (mu_imap_t imap, const char *refname, const char *mboxname, | 25 | mu_imap_list (mu_imap_t imap, const char *refname, const char *mboxname, |
125 | mu_list_t retlist) | 26 | mu_list_t retlist) |
126 | { | 27 | { |
127 | char const *argv[3]; | 28 | return mu_imap_genlist (imap, 0, refname, mboxname, retlist); |
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.argc = 3; | ||
143 | com.argv = argv; | ||
144 | com.extra = NULL; | ||
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 | } | 29 | } |
155 | 30 | ||
156 | int | 31 | int |
157 | mu_imap_list_new (mu_imap_t imap, const char *refname, const char *mboxname, | 32 | mu_imap_list_new (mu_imap_t imap, const char *refname, const char *mboxname, |
158 | mu_list_t *plist) | 33 | mu_list_t *plist) |
159 | { | 34 | { |
160 | mu_list_t list; | 35 | return mu_imap_genlist_new (imap, 0, refname, mboxname, plist); |
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 | } | 36 | } |
37 | |||
38 | ... | ... |
libproto/imap/lsub.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 <mailutils/imap.h> | ||
23 | |||
24 | int | ||
25 | mu_imap_lsub (mu_imap_t imap, const char *refname, const char *mboxname, | ||
26 | mu_list_t retlist) | ||
27 | { | ||
28 | return mu_imap_genlist (imap, 1, refname, mboxname, retlist); | ||
29 | } | ||
30 | |||
31 | int | ||
32 | mu_imap_lsub_new (mu_imap_t imap, const char *refname, const char *mboxname, | ||
33 | mu_list_t *plist) | ||
34 | { | ||
35 | return mu_imap_genlist_new (imap, 1, refname, mboxname, plist); | ||
36 | } | ||
37 | |||
38 |
... | @@ -949,6 +949,25 @@ com_list (int argc, char **argv) | ... | @@ -949,6 +949,25 @@ com_list (int argc, char **argv) |
949 | return 0; | 949 | return 0; |
950 | } | 950 | } |
951 | 951 | ||
952 | static int | ||
953 | com_lsub (int argc, char **argv) | ||
954 | { | ||
955 | mu_list_t list; | ||
956 | int rc; | ||
957 | mu_stream_t out; | ||
958 | |||
959 | rc = mu_imap_lsub_new (imap, argv[1], argv[2], &list); | ||
960 | if (rc) | ||
961 | { | ||
962 | report_failure ("lsub", rc); | ||
963 | return 0; | ||
964 | } | ||
965 | |||
966 | out = mutool_open_pager (); | ||
967 | mu_list_foreach (list, print_list_item, out); | ||
968 | mu_stream_unref (out); | ||
969 | return 0; | ||
970 | } | ||
952 | 971 | ||
953 | struct mutool_command imap_comtab[] = { | 972 | struct mutool_command imap_comtab[] = { |
954 | { "capability", 1, -1, 0, | 973 | { "capability", 1, -1, 0, |
... | @@ -1041,6 +1060,10 @@ struct mutool_command imap_comtab[] = { | ... | @@ -1041,6 +1060,10 @@ struct mutool_command imap_comtab[] = { |
1041 | com_list, | 1060 | com_list, |
1042 | N_("REF MBOX"), | 1061 | N_("REF MBOX"), |
1043 | N_("List matching mailboxes") }, | 1062 | N_("List matching mailboxes") }, |
1063 | { "lsub", 3, 3, 0, | ||
1064 | com_lsub, | ||
1065 | N_("REF MBOX"), | ||
1066 | N_("List subscribed mailboxes") }, | ||
1044 | { "subscribe", 2, 2, 0, | 1067 | { "subscribe", 2, 2, 0, |
1045 | com_subscribe, | 1068 | com_subscribe, |
1046 | N_("MBOX"), | 1069 | N_("MBOX"), | ... | ... |
-
Please register or sign in to post a comment