Commit f675ddc7 f675ddc76948a39c4b6dd4a47460a63e731e927a by Sergey Poznyakoff

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.
1 parent bc02e5c2
...@@ -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\
......
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
......
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"),
......