Commit ebbbc397 ebbbc397fba86fd32fb2cccb377a59f8e38d03e9 by Sergey Poznyakoff

imap client: implement select/examine.

* include/mailutils/imap.h (mu_imap_stat): New structs.
(MU_IMAP_STAT_DEFINED_FLAGS,MU_IMAP_STAT_PERMANENT_FLAGS)
(MU_IMAP_STAT_MESSAGE_COUNT,MU_IMAP_STAT_RECENT_COUNT)
(MU_IMAP_STAT_FIRST_UNSEEN,MU_IMAP_STAT_UIDNEXT)
(MU_IMAP_STAT_UIDVALIDITY):  New flags.
(mu_imap_select): New proto.
* include/mailutils/imapio.h (mu_imap_flag_to_attribute)
(mu_imap_format_flags): New protos.
* include/mailutils/sys/imap.h (mu_imap_client_state)
<MU_IMAP_SELECT_RX>: New state.
(_mu_imap) <mbox_name,mbox_writable,mbox_stat>: New members.
* libmailutils/imapio/flags.c: New file.
* libmailutils/imapio/Makefile.am: Add flags.c
* libproto/imap/select.c: New file.
* libproto/imap/Makefile.am: Add select.c
* libproto/imap/err.c (_mu_imap_seterrstr)
(_mu_imap_clrerrstr, mu_imap_strerror): Allow for imap==NULL.
* libproto/imap/id.c (mu_imap_id): Set errstr on MU_ERR_BADREPLY
* libproto/imap/login.c (mu_imap_login): Likewise.
* libproto/imap/resplist.c (_mu_imap_list_element_is_string): New function.
* mu/imap.c: Implement examine and select.
1 parent a736b7a9
...@@ -37,7 +37,7 @@ enum mu_imap_state ...@@ -37,7 +37,7 @@ enum mu_imap_state
37 MU_IMAP_STATE_NONAUTH, /* Non-Authenticated State */ 37 MU_IMAP_STATE_NONAUTH, /* Non-Authenticated State */
38 MU_IMAP_STATE_AUTH, /* Authenticated State */ 38 MU_IMAP_STATE_AUTH, /* Authenticated State */
39 MU_IMAP_STATE_SELECTED, /* Selected State */ 39 MU_IMAP_STATE_SELECTED, /* Selected State */
40 MU_IMAP_STATE_LOGOUT /* Logout State */ 40 MU_IMAP_STATE_LOGOUT, /* Logout State */
41 }; 41 };
42 42
43 int mu_imap_create (mu_imap_t *pimap); 43 int mu_imap_create (mu_imap_t *pimap);
...@@ -70,7 +70,31 @@ int mu_imap_state (mu_imap_t imap, int *pstate); ...@@ -70,7 +70,31 @@ int mu_imap_state (mu_imap_t imap, int *pstate);
70 int mu_imap_state_str (int state, const char **pstr); 70 int mu_imap_state_str (int state, const char **pstr);
71 71
72 int mu_imap_tag (mu_imap_t imap, const char **pseq); 72 int mu_imap_tag (mu_imap_t imap, const char **pseq);
73 73
74
75 #define MU_IMAP_STAT_DEFINED_FLAGS 0x01
76 #define MU_IMAP_STAT_PERMANENT_FLAGS 0x02
77 #define MU_IMAP_STAT_MESSAGE_COUNT 0x04
78 #define MU_IMAP_STAT_RECENT_COUNT 0x08
79 #define MU_IMAP_STAT_FIRST_UNSEEN 0x10
80 #define MU_IMAP_STAT_UIDNEXT 0x20
81 #define MU_IMAP_STAT_UIDVALIDITY 0x40
82
83 struct mu_imap_stat
84 {
85 int flags; /* Bitmap of what fields are filled */
86 int defined_flags; /* Flags defined for this mailbox */
87 int permanent_flags; /* Flags that can be changed permanently */
88 size_t message_count; /* Number of messages */
89 size_t recent_count; /* Number of recent messages */
90 size_t first_unseen; /* Sequence number of the first unseen message */
91 size_t uidnext; /* The next unique identifier value. */
92 unsigned long uidvalidity; /* The unique identifier validity value. */
93 };
94
95 int mu_imap_select (mu_imap_t imap, const char *mbox, int writable,
96 struct mu_imap_stat *ps);
97
74 #ifdef __cplusplus 98 #ifdef __cplusplus
75 } 99 }
76 #endif 100 #endif
......
...@@ -45,6 +45,9 @@ int mu_imapio_get_trace (mu_imapio_t io); ...@@ -45,6 +45,9 @@ int mu_imapio_get_trace (mu_imapio_t io);
45 int mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t *psize); 45 int mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t *psize);
46 46
47 int mu_imapio_reply_string (struct _mu_imapio *io, size_t start, char **pbuf); 47 int mu_imapio_reply_string (struct _mu_imapio *io, size_t start, char **pbuf);
48
49 int mu_imap_flag_to_attribute (const char *item, int *attr);
50 int mu_imap_format_flags (mu_stream_t str, int flags);
48 51
49 #ifdef __cplusplus 52 #ifdef __cplusplus
50 } 53 }
......
...@@ -44,6 +44,7 @@ enum mu_imap_client_state ...@@ -44,6 +44,7 @@ enum mu_imap_client_state
44 MU_IMAP_LOGIN_RX, 44 MU_IMAP_LOGIN_RX,
45 MU_IMAP_LOGOUT_RX, 45 MU_IMAP_LOGOUT_RX,
46 MU_IMAP_ID_RX, 46 MU_IMAP_ID_RX,
47 MU_IMAP_SELECT_RX
47 }; 48 };
48 49
49 enum mu_imap_response 50 enum mu_imap_response
...@@ -77,6 +78,10 @@ struct _mu_imap ...@@ -77,6 +78,10 @@ struct _mu_imap
77 78
78 mu_list_t capa; 79 mu_list_t capa;
79 mu_imapio_t io; 80 mu_imapio_t io;
81
82 char *mbox_name; /* Name of the currently opened mailbox */
83 int mbox_writable:1; /* Is it open read/write? */
84 struct mu_imap_stat mbox_stat; /* Stats obtained from it */
80 }; 85 };
81 86
82 enum imap_eltype 87 enum imap_eltype
...@@ -151,6 +156,9 @@ int _mu_imap_response (mu_imap_t imap); ...@@ -151,6 +156,9 @@ int _mu_imap_response (mu_imap_t imap);
151 156
152 int _mu_imap_untagged_response_clear (mu_imap_t imap); 157 int _mu_imap_untagged_response_clear (mu_imap_t imap);
153 int _mu_imap_untagged_response_add (mu_imap_t imap); 158 int _mu_imap_untagged_response_add (mu_imap_t imap);
159
160 int _mu_imap_list_element_is_string (struct imap_list_element *elt,
161 const char *str);
154 162
155 # ifdef __cplusplus 163 # ifdef __cplusplus
156 } 164 }
......
...@@ -19,6 +19,7 @@ noinst_LTLIBRARIES = libimapio.la ...@@ -19,6 +19,7 @@ noinst_LTLIBRARIES = libimapio.la
19 19
20 libimapio_la_SOURCES = \ 20 libimapio_la_SOURCES = \
21 create.c\ 21 create.c\
22 flags.c\
22 getline.c\ 23 getline.c\
23 literal.c\ 24 literal.c\
24 printf.c\ 25 printf.c\
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils 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
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <mailutils/types.h>
19 #include <mailutils/imapio.h>
20 #include <mailutils/attribute.h>
21 #include <mailutils/stream.h>
22 #include <mailutils/errno.h>
23 #include <mailutils/cstr.h>
24 #include <mailutils/sys/imapio.h>
25
26 static struct
27 {
28 char *name;
29 int flag;
30 }
31 _imap4_attrlist[] =
32 {
33 { "\\Answered", MU_ATTRIBUTE_ANSWERED },
34 { "\\Flagged", MU_ATTRIBUTE_FLAGGED },
35 { "\\Deleted", MU_ATTRIBUTE_DELETED },
36 { "\\Draft", MU_ATTRIBUTE_DRAFT },
37 { "\\Seen", MU_ATTRIBUTE_SEEN|MU_ATTRIBUTE_READ },
38 };
39
40 static int _imap4_nattr = MU_ARRAY_SIZE (_imap4_attrlist);
41
42 int
43 mu_imap_flag_to_attribute (const char *item, int *attr)
44 {
45 int i;
46
47 if (mu_c_strcasecmp (item, "\\Recent") == 0)
48 {
49 *attr |= MU_ATTRIBUTE_RECENT;
50 return 0;
51 }
52
53 for (i = 0; i < _imap4_nattr; i++)
54 if (mu_c_strcasecmp (item, _imap4_attrlist[i].name) == 0)
55 {
56 *attr |= _imap4_attrlist[i].flag;
57 return 0;
58 }
59 return MU_ERR_NOENT;
60 }
61
62 int
63 mu_imap_format_flags (mu_stream_t str, int flags)
64 {
65 int i;
66 int delim = 0;
67
68 for (i = 0; i < _imap4_nattr; i++)
69 if ((flags & _imap4_attrlist[i].flag) == _imap4_attrlist[i].flag)
70 {
71 if (delim)
72 mu_stream_printf (str, " ");
73 mu_stream_printf (str, "%s", _imap4_attrlist[i].name);
74 delim = 1;
75 }
76
77 if (MU_ATTRIBUTE_IS_UNSEEN (flags))
78 {
79 if (delim)
80 mu_stream_printf (str, " ");
81 mu_stream_printf (str, "\\Recent");
82 }
83
84 return 0;
85 }
...@@ -41,6 +41,7 @@ libmu_imap_la_SOURCES = \ ...@@ -41,6 +41,7 @@ libmu_imap_la_SOURCES = \
41 logout.c\ 41 logout.c\
42 resplist.c\ 42 resplist.c\
43 response.c\ 43 response.c\
44 select.c\
44 state.c\ 45 state.c\
45 tag.c\ 46 tag.c\
46 trace.c 47 trace.c
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
26 int 26 int
27 _mu_imap_seterrstr (mu_imap_t imap, const char *str, size_t len) 27 _mu_imap_seterrstr (mu_imap_t imap, const char *str, size_t len)
28 { 28 {
29 if (!imap)
30 return EINVAL;
29 if (len + 1 > imap->errsize) 31 if (len + 1 > imap->errsize)
30 { 32 {
31 char *p = realloc (imap->errstr, len + 1); 33 char *p = realloc (imap->errstr, len + 1);
...@@ -42,13 +44,18 @@ _mu_imap_seterrstr (mu_imap_t imap, const char *str, size_t len) ...@@ -42,13 +44,18 @@ _mu_imap_seterrstr (mu_imap_t imap, const char *str, size_t len)
42 void 44 void
43 _mu_imap_clrerrstr (mu_imap_t imap) 45 _mu_imap_clrerrstr (mu_imap_t imap)
44 { 46 {
45 if (imap->errstr) 47 if (imap && imap->errstr)
46 imap->errstr[0] = 0; 48 imap->errstr[0] = 0;
47 } 49 }
48 50
49 int 51 int
50 mu_imap_strerror (mu_imap_t imap, const char **pstr) 52 mu_imap_strerror (mu_imap_t imap, const char **pstr)
51 { 53 {
54 if (!imap)
55 {
56 *pstr = "(imap not initialized)";
57 return EINVAL;
58 }
52 if (imap->errstr) 59 if (imap->errstr)
53 { 60 {
54 *pstr = imap->errstr; 61 *pstr = imap->errstr;
......
...@@ -105,11 +105,11 @@ parse_id_reply (mu_imap_t imap, mu_assoc_t *passoc) ...@@ -105,11 +105,11 @@ parse_id_reply (mu_imap_t imap, mu_assoc_t *passoc)
105 return st.ret; 105 return st.ret;
106 } 106 }
107 107
108
109 int 108 int
110 mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc) 109 mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc)
111 { 110 {
112 int status; 111 int status;
112 char *p;
113 113
114 if (imap == NULL) 114 if (imap == NULL)
115 return EINVAL; 115 return EINVAL;
...@@ -171,6 +171,11 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc) ...@@ -171,6 +171,11 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc)
171 171
172 case MU_IMAP_BAD: 172 case MU_IMAP_BAD:
173 status = MU_ERR_BADREPLY; 173 status = MU_ERR_BADREPLY;
174 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
175 {
176 _mu_imap_seterrstr (imap, p, strlen (p));
177 free (p);
178 }
174 break; 179 break;
175 } 180 }
176 imap->state = MU_IMAP_CONNECTED; 181 imap->state = MU_IMAP_CONNECTED;
......
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
18 #ifdef HAVE_CONFIG_H 18 #ifdef HAVE_CONFIG_H
19 # include <config.h> 19 # include <config.h>
20 #endif 20 #endif
21 21 #include <stdlib.h>
22 #include <string.h>
22 #include <mailutils/errno.h> 23 #include <mailutils/errno.h>
23 #include <mailutils/stream.h> 24 #include <mailutils/stream.h>
24 #include <mailutils/sys/imap.h> 25 #include <mailutils/sys/imap.h>
...@@ -27,6 +28,7 @@ int ...@@ -27,6 +28,7 @@ int
27 mu_imap_login (mu_imap_t imap, const char *user, const char *pass) 28 mu_imap_login (mu_imap_t imap, const char *user, const char *pass)
28 { 29 {
29 int status; 30 int status;
31 char *p;
30 32
31 if (imap == NULL) 33 if (imap == NULL)
32 return EINVAL; 34 return EINVAL;
...@@ -67,6 +69,11 @@ mu_imap_login (mu_imap_t imap, const char *user, const char *pass) ...@@ -67,6 +69,11 @@ mu_imap_login (mu_imap_t imap, const char *user, const char *pass)
67 69
68 case MU_IMAP_BAD: 70 case MU_IMAP_BAD:
69 status = MU_ERR_BADREPLY; 71 status = MU_ERR_BADREPLY;
72 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
73 {
74 _mu_imap_seterrstr (imap, p, strlen (p));
75 free (p);
76 }
70 break; 77 break;
71 } 78 }
72 imap->state = MU_IMAP_CONNECTED; 79 imap->state = MU_IMAP_CONNECTED;
......
...@@ -254,3 +254,13 @@ _mu_imap_untagged_response_add (mu_imap_t imap) ...@@ -254,3 +254,13 @@ _mu_imap_untagged_response_add (mu_imap_t imap)
254 mu_list_append (imap->untagged_resp, elt); 254 mu_list_append (imap->untagged_resp, elt);
255 return 0; 255 return 0;
256 } 256 }
257
258 int
259 _mu_imap_list_element_is_string (struct imap_list_element *elt,
260 const char *str)
261 {
262 if (elt->type != imap_eltype_string)
263 return 0;
264 return strcmp (elt->v.string, str) == 0;
265 }
266
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010, 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/assoc.h>
26 #include <mailutils/stream.h>
27 #include <mailutils/imap.h>
28 #include <mailutils/sys/imap.h>
29
30 static int
31 _collect_flags (void *item, void *data)
32 {
33 struct imap_list_element *elt = item;
34 int *args = data;
35
36 if (elt->type == imap_eltype_string)
37 mu_imap_flag_to_attribute (elt->v.string, args);
38 return 0;
39 }
40
41 static int
42 _parse_stat (void *item, void *data)
43 {
44 struct imap_list_element *response = item;
45 mu_imap_t imap = data;
46 struct imap_list_element *elt;
47 size_t count;
48 int rc;
49 char *p;
50
51 if (response->type != imap_eltype_list)
52 return 0;
53
54 mu_list_count (response->v.list, &count);
55
56 rc = mu_list_get (response->v.list, 0, (void*) &elt);
57 if (rc)
58 return rc;
59
60 if (_mu_imap_list_element_is_string (elt, "OK"))
61 {
62 struct imap_list_element *arg;
63
64 if (count < 3)
65 return 0; /* ignore the line */
66 rc = mu_list_get (response->v.list, 1, (void*) &elt);
67 if (rc)
68 return rc;
69 rc = mu_list_get (response->v.list, 2, (void*) &arg);
70 if (rc)
71 return rc;
72
73 if (_mu_imap_list_element_is_string (elt, "[UIDVALIDITY"))
74 {
75 if (arg->type != imap_eltype_string)
76 return 0;
77 imap->mbox_stat.uidvalidity = strtoul (arg->v.string, &p, 10);
78 if (*p == ']')
79 imap->mbox_stat.flags |= MU_IMAP_STAT_UIDVALIDITY;
80 }
81 else if (_mu_imap_list_element_is_string (elt, "[UIDNEXT"))
82 {
83 if (arg->type != imap_eltype_string)
84 return 0;
85 imap->mbox_stat.uidnext = strtoul (arg->v.string, &p, 10);
86 if (*p == ']')
87 imap->mbox_stat.flags |= MU_IMAP_STAT_UIDNEXT;
88 }
89 else if (_mu_imap_list_element_is_string (elt, "[UNSEEN"))
90 {
91 if (arg->type != imap_eltype_string)
92 return 0;
93 imap->mbox_stat.first_unseen = strtoul (arg->v.string, &p, 10);
94 if (*p == ']')
95 imap->mbox_stat.flags |= MU_IMAP_STAT_FIRST_UNSEEN;
96 }
97 else if (_mu_imap_list_element_is_string (elt, "[PERMANENTFLAGS"))
98 {
99 if (arg->type != imap_eltype_list)
100 return 0;
101 mu_list_do (arg->v.list, _collect_flags,
102 &imap->mbox_stat.permanent_flags);
103 imap->mbox_stat.flags |= MU_IMAP_STAT_PERMANENT_FLAGS;
104 }
105 }
106 else if (_mu_imap_list_element_is_string (elt, "FLAGS"))
107 {
108 struct imap_list_element *arg;
109 rc = mu_list_get (response->v.list, 1, (void*) &arg);
110 if (rc)
111 return 0;
112 if (arg->type != imap_eltype_list)
113 return 0;
114 mu_list_do (arg->v.list, _collect_flags, &imap->mbox_stat.defined_flags);
115 imap->mbox_stat.flags |= MU_IMAP_STAT_DEFINED_FLAGS;
116 }
117 else if (count == 2)
118 {
119 struct imap_list_element *arg;
120 rc = mu_list_get (response->v.list, 1, (void*) &arg);
121 if (rc)
122 return rc;
123 if (_mu_imap_list_element_is_string (arg, "EXISTS"))
124 {
125 imap->mbox_stat.message_count = strtoul (elt->v.string, &p, 10);
126 if (*p == 0)
127 imap->mbox_stat.flags |= MU_IMAP_STAT_MESSAGE_COUNT;
128 }
129 else if (_mu_imap_list_element_is_string (arg, "RECENT"))
130 {
131 imap->mbox_stat.recent_count = strtoul (elt->v.string, &p, 10);
132 if (*p == 0)
133 imap->mbox_stat.flags |= MU_IMAP_STAT_RECENT_COUNT;
134 }
135 }
136
137 return 0;
138 }
139
140 int
141 mu_imap_select (mu_imap_t imap, const char *mbox, int writable,
142 struct mu_imap_stat *ps)
143 {
144 int status;
145 char *p;
146
147 if (imap == NULL)
148 return EINVAL;
149 if (!imap->io)
150 return MU_ERR_NO_TRANSPORT;
151 if (imap->state != MU_IMAP_CONNECTED)
152 return MU_ERR_SEQ;
153 if (imap->imap_state != MU_IMAP_STATE_AUTH &&
154 imap->imap_state != MU_IMAP_STATE_SELECTED)
155 return MU_ERR_SEQ;
156
157 if (!mbox)
158 {
159 if (imap->imap_state == MU_IMAP_STATE_SELECTED)
160 {
161 if (ps)
162 *ps = imap->mbox_stat;
163 return 0;
164 }
165 return MU_ERR_INFO_UNAVAILABLE;
166 }
167
168 if (imap->mbox_name && strcmp (imap->mbox_name, mbox) == 0
169 && writable == imap->mbox_writable)
170 {
171 if (ps)
172 *ps = imap->mbox_stat;
173 return 0;
174 }
175
176 switch (imap->state)
177 {
178 case MU_IMAP_CONNECTED:
179 status = _mu_imap_tag_next (imap);
180 MU_IMAP_CHECK_EAGAIN (imap, status);
181 status = mu_imapio_printf (imap->io, "%s %s %s\r\n",
182 imap->tag_str,
183 writable ? "SELECT" : "EXAMINE",
184 mbox);
185 MU_IMAP_CHECK_ERROR (imap, status);
186 MU_IMAP_FCLR (imap, MU_IMAP_RESP);
187 imap->state = MU_IMAP_SELECT_RX;
188
189 case MU_IMAP_SELECT_RX:
190 status = _mu_imap_response (imap);
191 MU_IMAP_CHECK_EAGAIN (imap, status);
192 switch (imap->resp_code)
193 {
194 case MU_IMAP_OK:
195 imap->imap_state = MU_IMAP_STATE_SELECTED;
196 free (imap->mbox_name);
197 imap->mbox_name = strdup (mbox);
198 if (!imap->mbox_name)
199 {
200 imap->state = MU_IMAP_ERROR;
201 return errno;
202 }
203 imap->mbox_writable = writable;
204 memset (&imap->mbox_stat, 0, sizeof (imap->mbox_stat));
205 mu_list_do (imap->untagged_resp, _parse_stat, imap);
206 if (ps)
207 *ps = imap->mbox_stat;
208 break;
209
210 case MU_IMAP_NO:
211 status = EACCES;
212 break;
213
214 case MU_IMAP_BAD:
215 status = MU_ERR_BADREPLY;
216 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
217 {
218 _mu_imap_seterrstr (imap, p, strlen (p));
219 free (p);
220 }
221 break;
222 }
223 imap->state = MU_IMAP_CONNECTED;
224 break;
225
226 default:
227 status = EINPROGRESS;
228 }
229 return status;
230 }
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
25 #include <netinet/in.h> 25 #include <netinet/in.h>
26 #include <mailutils/mailutils.h> 26 #include <mailutils/mailutils.h>
27 #include <mailutils/imap.h> 27 #include <mailutils/imap.h>
28 #include <mailutils/imapio.h>
28 #include "mu.h" 29 #include "mu.h"
29 #include "argp.h" 30 #include "argp.h"
30 #include "xalloc.h" 31 #include "xalloc.h"
...@@ -454,6 +455,71 @@ com_id (int argc, char **argv) ...@@ -454,6 +455,71 @@ com_id (int argc, char **argv)
454 } 455 }
455 return status; 456 return status;
456 } 457 }
458
459 static void
460 print_imap_stats (struct mu_imap_stat *st)
461 {
462 if (st->flags & MU_IMAP_STAT_DEFINED_FLAGS)
463 {
464 mu_printf (_("Flags defined: "));
465 mu_imap_format_flags (mu_strout, st->defined_flags);
466 mu_printf ("\n");
467 }
468 if (st->flags & MU_IMAP_STAT_PERMANENT_FLAGS)
469 {
470 mu_printf (_("Flags permanent: "));
471 mu_imap_format_flags (mu_strout, st->permanent_flags);
472 mu_printf ("\n");
473 }
474
475 if (st->flags & MU_IMAP_STAT_MESSAGE_COUNT)
476 mu_printf (_("Total messages: %lu\n"), (unsigned long) st->message_count);
477 if (st->flags & MU_IMAP_STAT_RECENT_COUNT)
478 mu_printf (_("Recent messages: %lu\n"), (unsigned long) st->recent_count);
479 if (st->flags & MU_IMAP_STAT_FIRST_UNSEEN)
480 mu_printf (_("First unseen message: %lu\n"),
481 (unsigned long) st->first_unseen);
482 if (st->flags & MU_IMAP_STAT_UIDNEXT)
483 mu_printf (_("Next UID: %lu\n"), (unsigned long) st->uidnext);
484 if (st->flags & MU_IMAP_STAT_UIDVALIDITY)
485 mu_printf (_("UID validity: %lu\n"), st->uidvalidity);
486 }
487
488
489 static int
490 select_mbox (int argc, char **argv, int writable)
491 {
492 int status;
493 struct mu_imap_stat st;
494
495 status = mu_imap_select (imap, argv[1], writable, &st);
496 if (status == 0)
497 {
498 print_imap_stats (&st);
499 imap_prompt_env ();
500 }
501 else
502 {
503 const char *str;
504
505 mu_error ("select failed: %s", mu_strerror (status));
506 if (mu_imap_strerror (imap, &str) == 0)
507 mu_error ("server reply: %s", str);
508 }
509 return 0;
510 }
511
512 static int
513 com_select (int argc, char **argv)
514 {
515 return select_mbox (argc, argv, 1);
516 }
517
518 static int
519 com_examine (int argc, char **argv)
520 {
521 return select_mbox (argc, argv, 0);
522 }
457 523
458 524
459 struct mutool_command imap_comtab[] = { 525 struct mutool_command imap_comtab[] = {
...@@ -481,6 +547,12 @@ struct mutool_command imap_comtab[] = { ...@@ -481,6 +547,12 @@ struct mutool_command imap_comtab[] = {
481 { "id", 1, -1, com_id, 547 { "id", 1, -1, com_id,
482 N_("[-test KW] [ARG [ARG...]]"), 548 N_("[-test KW] [ARG [ARG...]]"),
483 N_("send ID command") }, 549 N_("send ID command") },
550 { "select", 1, 2, com_select,
551 N_("MBOX"),
552 N_("select a mailbox") },
553 { "examine", 1, 2, com_examine,
554 N_("MBOX"),
555 N_("examine a mailbox") },
484 { "quit", 1, 1, com_logout, 556 { "quit", 1, 1, com_logout,
485 NULL, 557 NULL,
486 N_("same as `logout'") }, 558 N_("same as `logout'") },
......