Commit f7942ced f7942ced21d97774e678be261cc5b9094e47e8da by Sergey Poznyakoff

Rewrite existing imap client support using imapio.

1 parent a4a3755e
...@@ -53,7 +53,7 @@ int mu_imap_capability_test (mu_imap_t imap, const char *name, ...@@ -53,7 +53,7 @@ int mu_imap_capability_test (mu_imap_t imap, const char *name,
53 int mu_imap_login (mu_imap_t imap, const char *user, const char *pass); 53 int mu_imap_login (mu_imap_t imap, const char *user, const char *pass);
54 int mu_imap_logout (mu_imap_t imap); 54 int mu_imap_logout (mu_imap_t imap);
55 55
56 int mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist); 56 int mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc);
57 57
58 int mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier); 58 int mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier);
59 int mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier); 59 int mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 # include <mailutils/sys/mailbox.h> 22 # include <mailutils/sys/mailbox.h>
23 # include <mailutils/sys/registrar.h> 23 # include <mailutils/sys/registrar.h>
24 # include <mailutils/sys/auth.h> 24 # include <mailutils/sys/auth.h>
25 # include <mailutils/imapio.h>
25 # include <mailutils/imap.h> 26 # include <mailutils/imap.h>
26 27
27 # ifdef __cplusplus 28 # ifdef __cplusplus
...@@ -29,7 +30,7 @@ extern "C" { ...@@ -29,7 +30,7 @@ extern "C" {
29 # endif 30 # endif
30 31
31 #define MU_IMAP_RESP 0x01 32 #define MU_IMAP_RESP 0x01
32 #define MU_IMAP_TRACE 0x02 33 #define MU_IMAP_TRACE 0x02
33 #define MU_IMAP_XSCRIPT_MASK(n) (1<<((n)+1)) 34 #define MU_IMAP_XSCRIPT_MASK(n) (1<<((n)+1))
34 35
35 enum mu_imap_client_state 36 enum mu_imap_client_state
...@@ -56,9 +57,7 @@ struct _mu_imap ...@@ -56,9 +57,7 @@ struct _mu_imap
56 { 57 {
57 int flags; 58 int flags;
58 59
59 /* Holds the tagged response to the last command */ 60 /* Holds the recect response code */
60 char *tagbuf;
61 size_t tagsize;
62 enum mu_imap_response resp_code; 61 enum mu_imap_response resp_code;
63 62
64 /* Untagged responses */ 63 /* Untagged responses */
...@@ -68,10 +67,6 @@ struct _mu_imap ...@@ -68,10 +67,6 @@ struct _mu_imap
68 char *errstr; 67 char *errstr;
69 size_t errsize; 68 size_t errsize;
70 69
71 /* Input line buffer */
72 char *rdbuf;
73 size_t rdsize;
74
75 enum mu_imap_state state; 70 enum mu_imap_state state;
76 enum mu_imap_state imap_state; 71 enum mu_imap_state imap_state;
77 72
...@@ -81,7 +76,23 @@ struct _mu_imap ...@@ -81,7 +76,23 @@ struct _mu_imap
81 char *tag_str; /* String representation (tag_len + 1 bytes, asciiz) */ 76 char *tag_str; /* String representation (tag_len + 1 bytes, asciiz) */
82 77
83 mu_list_t capa; 78 mu_list_t capa;
84 mu_stream_t carrier; 79 mu_imapio_t io;
80 };
81
82 enum imap_eltype
83 {
84 imap_eltype_string,
85 imap_eltype_list
86 };
87
88 struct imap_list_element
89 {
90 enum imap_eltype type;
91 union
92 {
93 mu_list_t list;
94 char *string;
95 } v;
85 }; 96 };
86 97
87 #define MU_IMAP_FSET(p,f) ((p)->flags |= (f)) 98 #define MU_IMAP_FSET(p,f) ((p)->flags |= (f))
...@@ -137,6 +148,9 @@ int _mu_imap_tag_next (mu_imap_t imap); ...@@ -137,6 +148,9 @@ int _mu_imap_tag_next (mu_imap_t imap);
137 int _mu_imap_tag_clr (mu_imap_t imap); 148 int _mu_imap_tag_clr (mu_imap_t imap);
138 149
139 int _mu_imap_response (mu_imap_t imap); 150 int _mu_imap_response (mu_imap_t imap);
151
152 int _mu_imap_untagged_response_clear (mu_imap_t imap);
153 int _mu_imap_untagged_response_add (mu_imap_t imap);
140 154
141 # ifdef __cplusplus 155 # ifdef __cplusplus
142 } 156 }
......
...@@ -39,6 +39,7 @@ libmu_imap_la_SOURCES = \ ...@@ -39,6 +39,7 @@ libmu_imap_la_SOURCES = \
39 id.c\ 39 id.c\
40 login.c\ 40 login.c\
41 logout.c\ 41 logout.c\
42 resplist.c\
42 response.c\ 43 response.c\
43 state.c\ 44 state.c\
44 tag.c\ 45 tag.c\
......
...@@ -19,13 +19,14 @@ ...@@ -19,13 +19,14 @@
19 # include <config.h> 19 # include <config.h>
20 #endif 20 #endif
21 21
22 #include <string.h>
22 #include <mailutils/types.h> 23 #include <mailutils/types.h>
23 #include <mailutils/cctype.h> 24 #include <mailutils/cctype.h>
24 #include <mailutils/cstr.h> 25 #include <mailutils/cstr.h>
25 #include <mailutils/errno.h> 26 #include <mailutils/errno.h>
26 #include <mailutils/stream.h> 27 #include <mailutils/stream.h>
27 #include <mailutils/list.h> 28 #include <mailutils/list.h>
28 #include <mailutils/wordsplit.h> 29 #include <mailutils/iterator.h>
29 #include <mailutils/sys/imap.h> 30 #include <mailutils/sys/imap.h>
30 31
31 static int 32 static int
...@@ -50,7 +51,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter) ...@@ -50,7 +51,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
50 51
51 if (imap == NULL) 52 if (imap == NULL)
52 return EINVAL; 53 return EINVAL;
53 if (!imap->carrier) 54 if (!imap->io)
54 return MU_ERR_NO_TRANSPORT; 55 return MU_ERR_NO_TRANSPORT;
55 if (imap->state != MU_IMAP_CONNECTED) 56 if (imap->state != MU_IMAP_CONNECTED)
56 return MU_ERR_SEQ; 57 return MU_ERR_SEQ;
...@@ -78,7 +79,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter) ...@@ -78,7 +79,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
78 case MU_IMAP_CONNECTED: 79 case MU_IMAP_CONNECTED:
79 status = _mu_imap_tag_next (imap); 80 status = _mu_imap_tag_next (imap);
80 MU_IMAP_CHECK_EAGAIN (imap, status); 81 MU_IMAP_CHECK_EAGAIN (imap, status);
81 status = mu_stream_printf (imap->carrier, "%s CAPABILITY\r\n", 82 status = mu_imapio_printf (imap->io, "%s CAPABILITY\r\n",
82 imap->tag_str); 83 imap->tag_str);
83 MU_IMAP_CHECK_EAGAIN (imap, status); 84 MU_IMAP_CHECK_EAGAIN (imap, status);
84 MU_IMAP_FCLR (imap, MU_IMAP_RESP); 85 MU_IMAP_FCLR (imap, MU_IMAP_RESP);
...@@ -92,35 +93,35 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter) ...@@ -92,35 +93,35 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
92 else 93 else
93 { 94 {
94 size_t count; 95 size_t count;
95 char *str; 96 struct imap_list_element *elt;
96 97
97 imap->state = MU_IMAP_CONNECTED; 98 imap->state = MU_IMAP_CONNECTED;
98 mu_list_count (imap->untagged_resp, &count); 99 mu_list_count (imap->untagged_resp, &count);
99 if (mu_list_get (imap->untagged_resp, 0, (void*)&str) == 0) 100 if (mu_list_get (imap->untagged_resp, 0, (void*)&elt) == 0)
100 { 101 {
101 size_t i; 102 /* Top-level elements are always of imap_eltype_list type. */
103 mu_iterator_t itr;
102 104
103 struct mu_wordsplit ws; 105 mu_list_get_iterator (elt->v.list, &itr);
104 106 mu_iterator_first (itr);
105 if (mu_wordsplit (str, &ws, 107 if (mu_iterator_is_done (itr))
106 MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | 108 return MU_ERR_PARSE;
107 MU_WRDSF_QUOTE | MU_WRDSF_SQUEEZE_DELIMS)) 109 mu_iterator_current (itr, (void **) &elt);
108 { 110 if (elt->type == imap_eltype_string &&
109 int ec = errno; 111 strcmp (elt->v.string, "CAPABILITY") == 0)
110 mu_error ("mu_imap_capability: cannot split line: %s",
111 mu_wordsplit_strerror (&ws));
112 return ec;
113 }
114 if (ws.ws_wordc > 1 &&
115 mu_c_strcasecmp (ws.ws_wordv[0], "CAPABILITY") == 0)
116 { 112 {
117 for (i = 1; i < ws.ws_wordc; i++) 113 for (mu_iterator_next (itr); !mu_iterator_is_done (itr);
114 mu_iterator_next (itr))
118 { 115 {
119 mu_list_append (imap->capa, ws.ws_wordv[i]); 116 mu_iterator_current (itr, (void **) &elt);
120 ws.ws_wordv[i] = NULL; 117 if (elt->type == imap_eltype_string)
118 {
119 mu_list_append (imap->capa, elt->v.string);
120 elt->v.string = NULL;
121 }
121 } 122 }
122 } 123 }
123 mu_wordsplit_free (&ws); 124 mu_iterator_destroy (&itr);
124 } 125 }
125 if (piter) 126 if (piter)
126 status = mu_list_get_iterator (imap->capa, piter); 127 status = mu_list_get_iterator (imap->capa, piter);
......
...@@ -23,23 +23,30 @@ ...@@ -23,23 +23,30 @@
23 #include <stdlib.h> 23 #include <stdlib.h>
24 #include <errno.h> 24 #include <errno.h>
25 #include <mailutils/errno.h> 25 #include <mailutils/errno.h>
26 #include <mailutils/imapio.h>
26 #include <mailutils/sys/imap.h> 27 #include <mailutils/sys/imap.h>
28 #include <mailutils/sys/imapio.h>
27 29
28 int 30 int
29 mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier) 31 mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier)
30 { 32 {
33 int rc;
34 mu_imapio_t io;
35
31 /* Sanity checks. */ 36 /* Sanity checks. */
32 if (imap == NULL) 37 if (imap == NULL)
33 return EINVAL; 38 return EINVAL;
34 39
35 if (imap->carrier) 40 rc = mu_imapio_create (&io, carrier);
41 if (rc)
42 return rc;
43 if (imap->io)
36 { 44 {
37 /* Close any old carrier. */ 45 /* Close any old carrier. */
38 mu_imap_disconnect (imap); 46 mu_imap_disconnect (imap);
39 mu_stream_destroy (&imap->carrier); 47 mu_imapio_free (imap->io);
40 } 48 }
41 mu_stream_ref (carrier); 49 imap->io = io;
42 imap->carrier = carrier;
43 if (MU_IMAP_FISSET (imap, MU_IMAP_TRACE)) 50 if (MU_IMAP_FISSET (imap, MU_IMAP_TRACE))
44 _mu_imap_trace_enable (imap); 51 _mu_imap_trace_enable (imap);
45 imap->state = MU_IMAP_CONNECT; 52 imap->state = MU_IMAP_CONNECT;
...@@ -55,8 +62,8 @@ mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier) ...@@ -55,8 +62,8 @@ mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier)
55 if (pcarrier == NULL) 62 if (pcarrier == NULL)
56 return MU_ERR_OUT_PTR_NULL; 63 return MU_ERR_OUT_PTR_NULL;
57 64
58 mu_stream_ref (imap->carrier); 65 mu_stream_ref (imap->io->_imap_stream);
59 *pcarrier = imap->carrier; 66 *pcarrier = imap->io->_imap_stream;
60 return 0; 67 return 0;
61 } 68 }
62 69
......
...@@ -24,18 +24,23 @@ ...@@ -24,18 +24,23 @@
24 #include <sys/select.h> 24 #include <sys/select.h>
25 #include <sys/time.h> 25 #include <sys/time.h>
26 #include <mailutils/errno.h> 26 #include <mailutils/errno.h>
27 #include <mailutils/wordsplit.h> 27 #include <mailutils/imapio.h>
28 #include <mailutils/sys/imap.h> 28 #include <mailutils/sys/imap.h>
29 #include <mailutils/sys/imapio.h>
29 30
30 31
31 int 32 int
32 mu_imap_connect (mu_imap_t imap) 33 mu_imap_connect (mu_imap_t imap)
33 { 34 {
34 int status; 35 int status;
35 36 size_t wc;
37 char **wv;
38 char *bufptr;
39 size_t bufsize;
40
36 if (imap == NULL) 41 if (imap == NULL)
37 return EINVAL; 42 return EINVAL;
38 if (imap->carrier == NULL) 43 if (imap->io == NULL)
39 return EINVAL; 44 return EINVAL;
40 switch (imap->state) 45 switch (imap->state)
41 { 46 {
...@@ -54,66 +59,48 @@ mu_imap_connect (mu_imap_t imap) ...@@ -54,66 +59,48 @@ mu_imap_connect (mu_imap_t imap)
54 59
55 case MU_IMAP_CONNECT: 60 case MU_IMAP_CONNECT:
56 /* Establish the connection. */ 61 /* Establish the connection. */
57 if (!mu_stream_is_open (imap->carrier)) 62 if (!mu_stream_is_open (imap->io->_imap_stream))
58 { 63 {
59 status = mu_stream_open (imap->carrier); 64 status = mu_stream_open (imap->io->_imap_stream);
60 MU_IMAP_CHECK_EAGAIN (imap, status); 65 MU_IMAP_CHECK_EAGAIN (imap, status);
61 MU_IMAP_FCLR (imap, MU_IMAP_RESP); 66 MU_IMAP_FCLR (imap, MU_IMAP_RESP);
62 } 67 }
63 imap->state = MU_IMAP_GREETINGS; 68 imap->state = MU_IMAP_GREETINGS;
64 69
65 case MU_IMAP_GREETINGS: 70 case MU_IMAP_GREETINGS:
66 status = mu_stream_getline (imap->carrier, &imap->rdbuf, 71 status = mu_imapio_getline (imap->io);
67 &imap->rdsize, NULL);
68 MU_IMAP_CHECK_EAGAIN (imap, status); 72 MU_IMAP_CHECK_EAGAIN (imap, status);
69 if (imap->rdsize < 2 || 73 mu_imapio_get_words (imap->io, &wc, &wv);
70 !(imap->rdbuf[0] == '*' && imap->rdbuf[1] == ' ')) 74 if (wc < 2 || strcmp (wv[0], "*"))
71 { 75 {
76 mu_imapio_getbuf (imap->io, &bufptr, &bufsize);
72 mu_error ("mu_imap_connect: invalid server response: %s", 77 mu_error ("mu_imap_connect: invalid server response: %s",
73 imap->rdbuf); 78 bufptr);
74 imap->state = MU_IMAP_ERROR; 79 imap->state = MU_IMAP_ERROR;
75 return MU_ERR_BADREPLY; 80 return MU_ERR_BADREPLY;
76 } 81 }
82 else if (strcmp (wv[1], "BYE") == 0)
83 {
84 status = EACCES;
85 mu_imapio_getbuf (imap->io, &bufptr, &bufsize);
86 _mu_imap_seterrstr (imap, bufptr + 2, bufsize - 2);
87 }
88 else if (strcmp (wv[1], "PREAUTH") == 0)
89 {
90 status = 0;
91 imap->state = MU_IMAP_CONNECTED;
92 imap->imap_state = MU_IMAP_STATE_AUTH;
93 }
94 else if (strcmp (wv[1], "OK") == 0)
95 {
96 status = 0;
97 imap->state = MU_IMAP_CONNECTED;
98 imap->imap_state = MU_IMAP_STATE_NONAUTH;
99 }
77 else 100 else
78 { 101 {
79 struct mu_wordsplit ws; 102 status = MU_ERR_BADREPLY;
80 103 imap->state = MU_IMAP_ERROR;
81 if (mu_wordsplit (imap->rdbuf, &ws,
82 MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
83 MU_WRDSF_SQUEEZE_DELIMS))
84 {
85 int ec = errno;
86 mu_error ("mu_imap_connect: cannot split line: %s",
87 mu_wordsplit_strerror (&ws));
88 imap->state = MU_IMAP_ERROR;
89 return ec;
90 }
91 if (ws.ws_wordc < 2)
92 status = MU_ERR_BADREPLY;
93 else if (strcmp (ws.ws_wordv[1], "BYE") == 0)
94 {
95 status = EACCES;
96 _mu_imap_seterrstr (imap, imap->rdbuf + 2,
97 strlen (imap->rdbuf + 2));
98 }
99 else if (strcmp (ws.ws_wordv[1], "PREAUTH") == 0)
100 {
101 status = 0;
102 imap->state = MU_IMAP_CONNECTED;
103 imap->imap_state = MU_IMAP_STATE_AUTH;
104 }
105 else if (strcmp (ws.ws_wordv[1], "OK") == 0)
106 {
107 status = 0;
108 imap->state = MU_IMAP_CONNECTED;
109 imap->imap_state = MU_IMAP_STATE_NONAUTH;
110 }
111 else
112 {
113 status = MU_ERR_BADREPLY;
114 imap->state = MU_IMAP_ERROR;
115 }
116 mu_wordsplit_free (&ws);
117 } 104 }
118 } 105 }
119 106
......
...@@ -49,7 +49,7 @@ _mu_imap_init (mu_imap_t imap) ...@@ -49,7 +49,7 @@ _mu_imap_init (mu_imap_t imap)
49 { 49 {
50 if (imap == NULL) 50 if (imap == NULL)
51 return EINVAL; 51 return EINVAL;
52 if (imap->carrier == 0) 52 if (!imap->io)
53 { 53 {
54 int rc; 54 int rc;
55 55
......
...@@ -31,13 +31,6 @@ mu_imap_destroy (mu_imap_t *pimap) ...@@ -31,13 +31,6 @@ mu_imap_destroy (mu_imap_t *pimap)
31 { 31 {
32 mu_imap_t imap = *pimap; 32 mu_imap_t imap = *pimap;
33 33
34 /* Free the response buffer. */
35 if (imap->tagbuf)
36 free (imap->tagbuf);
37 /* Free the read buffer. */
38 if (imap->rdbuf)
39 free (imap->rdbuf);
40
41 if (imap->errstr) 34 if (imap->errstr)
42 free (imap->errstr); 35 free (imap->errstr);
43 36
...@@ -49,7 +42,7 @@ mu_imap_destroy (mu_imap_t *pimap) ...@@ -49,7 +42,7 @@ mu_imap_destroy (mu_imap_t *pimap)
49 mu_list_destroy (&imap->untagged_resp); 42 mu_list_destroy (&imap->untagged_resp);
50 mu_list_destroy (&imap->capa); 43 mu_list_destroy (&imap->capa);
51 44
52 mu_stream_destroy (&imap->carrier); 45 mu_imapio_destroy (&imap->io);
53 46
54 free (imap); 47 free (imap);
55 48
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 #include <stdlib.h> 22 #include <stdlib.h>
23 #include <string.h> 23 #include <string.h>
24 #include <errno.h> 24 #include <errno.h>
25 #include <mailutils/imapio.h>
25 #include <mailutils/sys/imap.h> 26 #include <mailutils/sys/imap.h>
26 27
27 int 28 int
...@@ -34,14 +35,11 @@ mu_imap_disconnect (mu_imap_t imap) ...@@ -34,14 +35,11 @@ mu_imap_disconnect (mu_imap_t imap)
34 imap->state = MU_IMAP_NO_STATE; 35 imap->state = MU_IMAP_NO_STATE;
35 MU_IMAP_FCLR (imap, MU_IMAP_RESP); 36 MU_IMAP_FCLR (imap, MU_IMAP_RESP);
36 37
37 if (imap->rdbuf)
38 imap->rdbuf[0] = 0;
39
40 mu_list_clear (imap->untagged_resp); 38 mu_list_clear (imap->untagged_resp);
41 mu_list_clear (imap->capa); 39 mu_list_clear (imap->capa);
42 40
43 /* Close the stream. */ 41 /* Close the stream. */
44 if (mu_stream_is_open (imap->carrier)) 42 mu_imapio_destroy (&imap->io);
45 return mu_stream_close (imap->carrier); 43
46 return 0; 44 return 0;
47 } 45 }
......
...@@ -22,93 +22,109 @@ ...@@ -22,93 +22,109 @@
22 #include <stdlib.h> 22 #include <stdlib.h>
23 #include <string.h> 23 #include <string.h>
24 #include <mailutils/errno.h> 24 #include <mailutils/errno.h>
25 #include <mailutils/cstr.h> 25 #include <mailutils/assoc.h>
26 #include <mailutils/wordsplit.h>
27 #include <mailutils/stream.h> 26 #include <mailutils/stream.h>
27 #include <mailutils/imap.h>
28 #include <mailutils/sys/imap.h> 28 #include <mailutils/sys/imap.h>
29 29
30 static int 30 void
31 id_comp (const void *item, const void *value) 31 _id_free (void *data)
32 { 32 {
33 const char *id = item; 33 char *s = *(char**)data;
34 const char *needle = value; 34 free (s);
35 return mu_c_strcasecmp (id, needle);
36 } 35 }
37 36
37 struct id_convert_state
38 {
39 int item;
40 mu_assoc_t assoc;
41 int ret;
42 };
43
38 static int 44 static int
39 parse_id_reply (mu_imap_t imap, mu_list_t *plist) 45 _id_convert (void *item, void *data)
46 {
47 struct imap_list_element *elt = item;
48 struct id_convert_state *stp = data;
49
50 switch (stp->item)
51 {
52 case 0:
53 if (!(elt->type == imap_eltype_string &&
54 strcmp (elt->v.string, "ID") == 0))
55 {
56 stp->ret = MU_ERR_PARSE;
57 return 1;
58 }
59 stp->item++;
60 return 0;
61
62 case 1:
63 if (elt->type == imap_eltype_list)
64 {
65 mu_iterator_t itr;
66
67 mu_list_get_iterator (elt->v.list, &itr);
68 for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
69 mu_iterator_next (itr))
70 {
71 char *key, *val;
72 mu_iterator_current (itr, (void **) &elt);
73
74 if (elt->type != imap_eltype_string)
75 break;
76 key = elt->v.string;
77 elt->v.string = NULL;
78
79 mu_iterator_next (itr);
80 if (mu_iterator_is_done (itr))
81 break;
82 mu_iterator_current (itr, (void **) &elt);
83 if (elt->type != imap_eltype_string)
84 break;
85 val = elt->v.string;
86 elt->v.string = NULL;
87 mu_assoc_install (stp->assoc, key, &val);
88 }
89 }
90 }
91 return 1;
92 }
93
94 static int
95 parse_id_reply (mu_imap_t imap, mu_assoc_t *passoc)
40 { 96 {
41 mu_list_t list;
42 int rc; 97 int rc;
43 const char *response; 98 struct imap_list_element const *response;
44 struct mu_wordsplit ws; 99 struct id_convert_state st;
45 size_t i; 100 mu_assoc_t assoc;
46 101
47 rc = mu_list_create (&list); 102 rc = mu_assoc_create (&assoc, sizeof (char**), MU_ASSOC_ICASE);
48 if (rc) 103 if (rc)
49 return rc; 104 return rc;
50 mu_list_set_comparator (list, id_comp); 105 mu_assoc_set_free (assoc, _id_free);
51 mu_list_set_destroy_item (list, mu_list_free_item);
52 106
53 rc = mu_list_get (imap->untagged_resp, 0, (void*) &response); 107 rc = mu_list_get (imap->untagged_resp, 0, (void*) &response);
108 *passoc = assoc;
54 if (rc == MU_ERR_NOENT) 109 if (rc == MU_ERR_NOENT)
55 { 110 return 0;
56 *plist = list;
57 return 0;
58 }
59 else if (rc)
60 {
61 mu_list_destroy (&list);
62 return rc;
63 }
64
65 ws.ws_delim = "() \t";
66 if (mu_wordsplit (response, &ws,
67 MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
68 MU_WRDSF_QUOTE | MU_WRDSF_DELIM |
69 MU_WRDSF_SQUEEZE_DELIMS |
70 MU_WRDSF_WS))
71 {
72 int ec = errno;
73 mu_error ("mu_imap_id: cannot split line: %s",
74 mu_wordsplit_strerror (&ws));
75 mu_list_destroy (&list);
76 return ec;
77 }
78 111
79 for (i = 1; i < ws.ws_wordc; i += 2) 112 st.item = 0;
80 { 113 st.assoc = assoc;
81 size_t len, l1, l2; 114 st.ret = 0;
82 char *elt; 115 mu_list_do (response->v.list, _id_convert, &st);
83 116 return st.ret;
84 if (i + 1 == ws.ws_wordc)
85 break;
86 l1 = strlen (ws.ws_wordv[i]);
87 l2 = strlen (ws.ws_wordv[i+1]);
88 len = l1 + l2 + 1;
89 elt = malloc (len + 1);
90 if (!elt)
91 break;
92
93 memcpy (elt, ws.ws_wordv[i], l1);
94 elt[l1] = 0;
95 memcpy (elt + l1 + 1, ws.ws_wordv[i+1], l2);
96 elt[len] = 0;
97 mu_list_append (list, elt);
98 }
99 mu_wordsplit_free (&ws);
100 *plist = list;
101 return 0;
102 } 117 }
103 118
119
104 int 120 int
105 mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist) 121 mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc)
106 { 122 {
107 int status; 123 int status;
108 124
109 if (imap == NULL) 125 if (imap == NULL)
110 return EINVAL; 126 return EINVAL;
111 if (!imap->carrier) 127 if (!imap->io)
112 return MU_ERR_NO_TRANSPORT; 128 return MU_ERR_NO_TRANSPORT;
113 if (imap->state != MU_IMAP_CONNECTED) 129 if (imap->state != MU_IMAP_CONNECTED)
114 return MU_ERR_SEQ; 130 return MU_ERR_SEQ;
...@@ -118,11 +134,10 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist) ...@@ -118,11 +134,10 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist)
118 case MU_IMAP_CONNECTED: 134 case MU_IMAP_CONNECTED:
119 status = _mu_imap_tag_next (imap); 135 status = _mu_imap_tag_next (imap);
120 MU_IMAP_CHECK_EAGAIN (imap, status); 136 MU_IMAP_CHECK_EAGAIN (imap, status);
121 status = mu_stream_printf (imap->carrier, "%s ID ", 137 status = mu_imapio_printf (imap->io, "%s ID ", imap->tag_str);
122 imap->tag_str);
123 MU_IMAP_CHECK_ERROR (imap, status); 138 MU_IMAP_CHECK_ERROR (imap, status);
124 if (!idenv) 139 if (!idenv)
125 status = mu_stream_printf (imap->carrier, "NIL"); 140 status = mu_imapio_printf (imap->io, "NIL");
126 else 141 else
127 { 142 {
128 if (idenv[0]) 143 if (idenv[0])
...@@ -131,7 +146,7 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist) ...@@ -131,7 +146,7 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist)
131 char *delim = "("; 146 char *delim = "(";
132 for (i = 0; idenv[i]; i++) 147 for (i = 0; idenv[i]; i++)
133 { 148 {
134 status = mu_stream_printf (imap->carrier, "%s\"%s\"", 149 status = mu_imapio_printf (imap->io, "%s\"%s\"",
135 delim, idenv[i]); 150 delim, idenv[i]);
136 MU_IMAP_CHECK_ERROR (imap, status); 151 MU_IMAP_CHECK_ERROR (imap, status);
137 152
...@@ -139,13 +154,13 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist) ...@@ -139,13 +154,13 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist)
139 if (status) 154 if (status)
140 break; 155 break;
141 } 156 }
142 status = mu_stream_printf (imap->carrier, ")"); 157 status = mu_imapio_printf (imap->io, ")");
143 } 158 }
144 else 159 else
145 status = mu_stream_printf (imap->carrier, "()"); 160 status = mu_imapio_printf (imap->io, "()");
146 } 161 }
147 MU_IMAP_CHECK_ERROR (imap, status); 162 MU_IMAP_CHECK_ERROR (imap, status);
148 status = mu_stream_printf (imap->carrier, "\r\n"); 163 status = mu_imapio_printf (imap->io, "\r\n");
149 MU_IMAP_CHECK_ERROR (imap, status); 164 MU_IMAP_CHECK_ERROR (imap, status);
150 MU_IMAP_FCLR (imap, MU_IMAP_RESP); 165 MU_IMAP_FCLR (imap, MU_IMAP_RESP);
151 imap->state = MU_IMAP_ID_RX; 166 imap->state = MU_IMAP_ID_RX;
...@@ -157,8 +172,8 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist) ...@@ -157,8 +172,8 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist)
157 { 172 {
158 case MU_IMAP_OK: 173 case MU_IMAP_OK:
159 imap->imap_state = MU_IMAP_STATE_AUTH; 174 imap->imap_state = MU_IMAP_STATE_AUTH;
160 if (plist) 175 if (passoc)
161 status = parse_id_reply (imap, plist); 176 status = parse_id_reply (imap, passoc);
162 break; 177 break;
163 178
164 case MU_IMAP_NO: 179 case MU_IMAP_NO:
......
...@@ -30,7 +30,7 @@ mu_imap_login (mu_imap_t imap, const char *user, const char *pass) ...@@ -30,7 +30,7 @@ mu_imap_login (mu_imap_t imap, const char *user, const char *pass)
30 30
31 if (imap == NULL) 31 if (imap == NULL)
32 return EINVAL; 32 return EINVAL;
33 if (!imap->carrier) 33 if (!imap->io)
34 return MU_ERR_NO_TRANSPORT; 34 return MU_ERR_NO_TRANSPORT;
35 if (imap->state != MU_IMAP_CONNECTED) 35 if (imap->state != MU_IMAP_CONNECTED)
36 return MU_ERR_SEQ; 36 return MU_ERR_SEQ;
...@@ -44,7 +44,7 @@ mu_imap_login (mu_imap_t imap, const char *user, const char *pass) ...@@ -44,7 +44,7 @@ mu_imap_login (mu_imap_t imap, const char *user, const char *pass)
44 _mu_imap_xscript_level (imap, MU_XSCRIPT_SECURE); 44 _mu_imap_xscript_level (imap, MU_XSCRIPT_SECURE);
45 status = _mu_imap_tag_next (imap); 45 status = _mu_imap_tag_next (imap);
46 MU_IMAP_CHECK_EAGAIN (imap, status); 46 MU_IMAP_CHECK_EAGAIN (imap, status);
47 status = mu_stream_printf (imap->carrier, "%s LOGIN \"%s\" \"%s\"\r\n", 47 status = mu_imapio_printf (imap->io, "%s LOGIN \"%s\" \"%s\"\r\n",
48 imap->tag_str, user, pass); 48 imap->tag_str, user, pass);
49 _mu_imap_xscript_level (imap, MU_XSCRIPT_NORMAL); 49 _mu_imap_xscript_level (imap, MU_XSCRIPT_NORMAL);
50 /* FIXME: how to obscure the passwd in the stream buffer? */ 50 /* FIXME: how to obscure the passwd in the stream buffer? */
......
...@@ -30,7 +30,7 @@ mu_imap_logout (mu_imap_t imap) ...@@ -30,7 +30,7 @@ mu_imap_logout (mu_imap_t imap)
30 30
31 if (imap == NULL) 31 if (imap == NULL)
32 return EINVAL; 32 return EINVAL;
33 if (!imap->carrier) 33 if (!imap->io)
34 return MU_ERR_NO_TRANSPORT; 34 return MU_ERR_NO_TRANSPORT;
35 if (imap->state != MU_IMAP_CONNECTED) 35 if (imap->state != MU_IMAP_CONNECTED)
36 return MU_ERR_SEQ; 36 return MU_ERR_SEQ;
...@@ -40,7 +40,7 @@ mu_imap_logout (mu_imap_t imap) ...@@ -40,7 +40,7 @@ mu_imap_logout (mu_imap_t imap)
40 case MU_IMAP_CONNECTED: 40 case MU_IMAP_CONNECTED:
41 status = _mu_imap_tag_next (imap); 41 status = _mu_imap_tag_next (imap);
42 MU_IMAP_CHECK_EAGAIN (imap, status); 42 MU_IMAP_CHECK_EAGAIN (imap, status);
43 status = mu_stream_printf (imap->carrier, "%s LOGOUT\r\n", 43 status = mu_imapio_printf (imap->io, "%s LOGOUT\r\n",
44 imap->tag_str); 44 imap->tag_str);
45 MU_IMAP_CHECK_EAGAIN (imap, status); 45 MU_IMAP_CHECK_EAGAIN (imap, status);
46 MU_IMAP_FCLR (imap, MU_IMAP_RESP); 46 MU_IMAP_FCLR (imap, MU_IMAP_RESP);
......
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 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <mailutils/cctype.h>
25 #include <mailutils/cstr.h>
26 #include <mailutils/stream.h>
27 #include <mailutils/errno.h>
28 #include <mailutils/sys/imap.h>
29
30 static void
31 _imap_list_free (void *ptr)
32 {
33 struct imap_list_element *elt = ptr;
34
35 switch (elt->type)
36 {
37 case imap_eltype_string:
38 free (elt->v.string);
39 break;
40
41 case imap_eltype_list:
42 mu_list_destroy (&elt->v.list);
43 }
44 free (ptr);
45 }
46
47 static int
48 _mu_imap_response_list_create (mu_imap_t imap, mu_list_t *plist)
49 {
50 mu_list_t list;
51 int status = mu_list_create (&list);
52 MU_IMAP_CHECK_ERROR (imap, status);
53 mu_list_set_destroy_item (list, _imap_list_free);
54 *plist = list;
55 return 0;
56 }
57
58 int
59 _mu_imap_untagged_response_clear (mu_imap_t imap)
60 {
61 if (imap->untagged_resp)
62 mu_list_clear (imap->untagged_resp);
63 else
64 return _mu_imap_response_list_create (imap, &imap->untagged_resp);
65 return 0;
66 }
67
68 #define IS_LBRACE(p) ((p)[0] == '(')
69 #define IS_RBRACE(p) ((p)[0] == ')')
70
71 static struct imap_list_element *
72 _new_imap_list_element (mu_imap_t imap, enum imap_eltype type)
73 {
74 struct imap_list_element *elt = calloc (1, sizeof (*elt));
75 if (!elt)
76 {
77 imap->state = MU_IMAP_ERROR;
78 }
79 else
80 elt->type = type;
81 return elt;
82 }
83
84 struct parsebuf
85 {
86 mu_imap_t pb_imap;
87 size_t pb_count;
88 char **pb_arr;
89 int pb_err;
90 int pb_inlist;
91 };
92
93 static void
94 parsebuf_init (struct parsebuf *pb, mu_imap_t imap)
95 {
96 memset (pb, 0, sizeof *pb);
97 pb->pb_imap = imap;
98 }
99
100 static int
101 parsebuf_advance (struct parsebuf *pb)
102 {
103 if (pb->pb_count == 0)
104 return MU_ERR_NOENT;
105 pb->pb_count--;
106 pb->pb_arr++;
107 return 0;
108 }
109
110 static char *
111 parsebuf_gettok (struct parsebuf *pb)
112 {
113 char *p;
114
115 if (pb->pb_count == 0)
116 return NULL;
117 p = *pb->pb_arr;
118 parsebuf_advance (pb);
119 return p;
120 }
121
122 static char *
123 parsebuf_peek (struct parsebuf *pb)
124 {
125 if (pb->pb_count == 0)
126 return NULL;
127 return *pb->pb_arr;
128 }
129
130 static void
131 parsebuf_seterr (struct parsebuf *pb, int err)
132 {
133 pb->pb_err = err;
134 }
135
136 static struct imap_list_element *_parse_element (struct parsebuf *pb);
137
138 static struct imap_list_element *
139 _parse_list (struct parsebuf *pb)
140 {
141 int rc;
142 struct imap_list_element *elt, *list_elt;
143
144 elt = _new_imap_list_element (pb->pb_imap, imap_eltype_list);
145 if (!elt)
146 {
147 parsebuf_seterr (pb, ENOMEM);
148 return NULL;
149 }
150
151 rc = _mu_imap_response_list_create (pb->pb_imap, &elt->v.list);
152 if (rc)
153 {
154 free (elt);
155 parsebuf_seterr (pb, rc);
156 return NULL;
157 }
158
159 while ((list_elt = _parse_element (pb)))
160 mu_list_append (elt->v.list, list_elt);
161
162 return elt;
163 }
164
165 static struct imap_list_element *
166 _parse_element (struct parsebuf *pb)
167 {
168 struct imap_list_element *elt;
169 char *tok;
170
171 if (pb->pb_err)
172 return NULL;
173
174 tok = parsebuf_gettok (pb);
175
176 if (!tok)
177 {
178 if (pb->pb_inlist)
179 parsebuf_seterr (pb, MU_ERR_PARSE);
180 return NULL;
181 }
182
183 if (IS_LBRACE (tok))
184 {
185 tok = parsebuf_peek (pb);
186 if (!tok)
187 {
188 parsebuf_seterr (pb, MU_ERR_PARSE);
189 return NULL;
190 }
191
192 if (IS_RBRACE (tok))
193 {
194 elt = _new_imap_list_element (pb->pb_imap, imap_eltype_list);
195 if (!elt)
196 {
197 parsebuf_seterr (pb, ENOMEM);
198 return NULL;
199 }
200 elt->v.list = NULL;
201 }
202 else
203 {
204 pb->pb_inlist++;
205 elt = _parse_list (pb);
206 }
207 }
208 else if (IS_RBRACE (tok))
209 {
210 if (pb->pb_inlist)
211 pb->pb_inlist--;
212 else
213 parsebuf_seterr (pb, MU_ERR_PARSE);
214 return NULL;
215 }
216 else
217 {
218 char *s;
219 elt = _new_imap_list_element (pb->pb_imap, imap_eltype_string);
220 if (!elt)
221 {
222 parsebuf_seterr (pb, ENOMEM);
223 return NULL;
224 }
225 s = strdup (tok);
226 if (!s)
227 {
228 free (elt);
229 parsebuf_seterr (pb, ENOMEM);
230 return NULL;
231 }
232 elt->v.string = s;
233 }
234 return elt;
235 }
236
237 int
238 _mu_imap_untagged_response_add (mu_imap_t imap)
239 {
240 struct imap_list_element *elt;
241 struct parsebuf pb;
242
243 parsebuf_init (&pb, imap);
244 mu_imapio_get_words (imap->io, &pb.pb_count, &pb.pb_arr);
245 parsebuf_advance (&pb); /* Skip initial '*' */
246 elt = _parse_list (&pb);
247 if (pb.pb_err)
248 {
249 if (elt)
250 _imap_list_free (elt);
251 imap->state = MU_IMAP_ERROR;
252 return pb.pb_err;
253 }
254 mu_list_append (imap->untagged_resp, elt);
255 return 0;
256 }
...@@ -27,15 +27,9 @@ ...@@ -27,15 +27,9 @@
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 #define IS_PREFIX(s, len, pfx) \
31 ((len) >= sizeof (pfx) - 1 && \
32 memcmp ((s), (pfx), sizeof (pfx) - 1) == 0 && \
33 s[sizeof (pfx) - 1] == ' ')
34
35 int 30 int
36 _mu_imap_response (mu_imap_t imap) 31 _mu_imap_response (mu_imap_t imap)
37 { 32 {
38 size_t n = 0;
39 int status = 0; 33 int status = 0;
40 34
41 if (imap == NULL) 35 if (imap == NULL)
...@@ -45,81 +39,74 @@ _mu_imap_response (mu_imap_t imap) ...@@ -45,81 +39,74 @@ _mu_imap_response (mu_imap_t imap)
45 return 0; 39 return 0;
46 40
47 _mu_imap_clrerrstr (imap); 41 _mu_imap_clrerrstr (imap);
48 if (imap->untagged_resp) 42 status = _mu_imap_untagged_response_clear (imap);
49 mu_list_clear (imap->untagged_resp); 43 if (status)
50 else 44 return status;
51 { 45
52 status = mu_list_create (&imap->untagged_resp);
53 MU_IMAP_CHECK_ERROR (imap, status);
54 mu_list_set_destroy_item (imap->untagged_resp, mu_list_free_item);
55 }
56
57 while (1) 46 while (1)
58 { 47 {
59 status = mu_stream_getline (imap->carrier, &imap->rdbuf, 48 status = mu_imapio_getline (imap->io);
60 &imap->rdsize, NULL);
61 if (status == 0) 49 if (status == 0)
62 { 50 {
63 n = mu_rtrim_class (imap->rdbuf, MU_CTYPE_SPACE); 51 char **wv;
64 if (imap->rdbuf[0] == '*' && imap->rdbuf[1] == ' ') 52 size_t wc;
53 char *p;
54
55 mu_imapio_get_words (imap->io, &wc, &wv);
56 if (strcmp (wv[0], "*") == 0)
65 { 57 {
66 char *p = mu_str_skip_cset (imap->rdbuf + 2, " "); 58 _mu_imap_untagged_response_add (imap);/* FIXME: error checking */
67 mu_list_append (imap->untagged_resp, strdup (p)); 59 continue;
68 } 60 }
69 else if (n > imap->tag_len + 3 && 61 else if (strlen (wv[0]) == imap->tag_len &&
70 memcmp (imap->rdbuf, imap->tag_str, imap->tag_len) == 0 62 memcmp (wv[0], imap->tag_str, imap->tag_len) == 0)
71 && imap->rdbuf[imap->tag_len] == ' ')
72 { 63 {
73 char *p = mu_str_skip_cset (imap->rdbuf + imap->tag_len, " "); 64 /* Handle the tagged response */
74 size_t len = strlen (p); 65 if (wc < 2)
75
76 if (len >= imap->tagsize)
77 { 66 {
78 char *np = realloc (imap->tagbuf, len + 1); 67 /*imap->state = MU_IMAP_ERROR;*/
79 if (!np) 68 status = MU_ERR_BADREPLY;
80 {
81 imap->state = MU_IMAP_ERROR;
82 return ENOMEM;
83 }
84 imap->tagsize = len + 1;
85 imap->tagbuf = np;
86 } 69 }
87 strcpy (imap->tagbuf, p); 70 else if (strcmp (wv[1], "OK") == 0)
88 if (IS_PREFIX (p, len, "OK"))
89 { 71 {
90 imap->resp_code = MU_IMAP_OK; 72 imap->resp_code = MU_IMAP_OK;
91 p = mu_str_skip_cset (p + 2, " "); 73 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
92 _mu_imap_seterrstr (imap, p, strlen (p)); 74 {
75 _mu_imap_seterrstr (imap, p, strlen (p));
76 free (p);
77 }
93 } 78 }
94 else if (IS_PREFIX (p, len, "NO")) 79 else if (strcmp (wv[1], "NO") == 0)
95 { 80 {
96 imap->resp_code = MU_IMAP_NO; 81 imap->resp_code = MU_IMAP_NO;
97 p = mu_str_skip_cset (p + 2, " "); 82 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
98 _mu_imap_seterrstr (imap, p, strlen (p)); 83 {
84 _mu_imap_seterrstr (imap, p, strlen (p));
85 free (p);
86 }
99 } 87 }
100 else if (IS_PREFIX (p, len, "BAD")) 88 else if (strcmp (wv[1], "BAD") == 0)
101 { 89 {
102 imap->resp_code = MU_IMAP_BAD; 90 imap->resp_code = MU_IMAP_BAD;
103 p = mu_str_skip_cset (p + 2, " "); 91 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
104 _mu_imap_seterrstr (imap, p, strlen (p)); 92 {
93 _mu_imap_seterrstr (imap, p, strlen (p));
94 free (p);
95 }
105 } 96 }
106 else 97 else
107 status = MU_ERR_BADREPLY; 98 status = MU_ERR_BADREPLY;
108 MU_IMAP_FSET (imap, MU_IMAP_RESP); 99 MU_IMAP_FSET (imap, MU_IMAP_RESP);
109 break;
110 } 100 }
111 else 101 else
112 { 102 {
113 imap->state = MU_IMAP_ERROR; 103 imap->state = MU_IMAP_ERROR;
114 return MU_ERR_BADREPLY; 104 status = MU_ERR_BADREPLY;
115 } 105 }
116 } 106 }
117 else 107 else
118 { 108 imap->state = MU_IMAP_ERROR;
119 imap->state = MU_IMAP_ERROR; 109 break;
120 return status;
121 }
122 } 110 }
123 return status; 111 return status;
124 } 112 }
125
......
...@@ -19,78 +19,50 @@ ...@@ -19,78 +19,50 @@
19 # include <config.h> 19 # include <config.h>
20 #endif 20 #endif
21 21
22 #include <string.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <mailutils/error.h>
26 #include <mailutils/errno.h> 22 #include <mailutils/errno.h>
27 #include <mailutils/nls.h> 23 #include <mailutils/imapio.h>
28 #include <mailutils/stream.h>
29 #include <mailutils/sys/imap.h> 24 #include <mailutils/sys/imap.h>
30 25
31 static const char *imap_prefix[] = {
32 "S: ", "C: "
33 };
34
35 int 26 int
36 _mu_imap_trace_enable (mu_imap_t imap) 27 _mu_imap_trace_enable (mu_imap_t imap)
37 { 28 {
38 int rc = 0; 29 int rc;
39 mu_stream_t dstr, xstr; 30 if (!imap->io)
40 31 return 0;
41 if (!imap->carrier) 32 rc = mu_imapio_trace_enable (imap->io);
33 switch (rc)
42 { 34 {
35 case 0:
36 case MU_ERR_OPEN:
43 MU_IMAP_FSET (imap, MU_IMAP_TRACE); 37 MU_IMAP_FSET (imap, MU_IMAP_TRACE);
44 return 0; 38 break;
45 }
46
47 rc = mu_dbgstream_create (&dstr, MU_DIAG_DEBUG);
48 if (rc)
49 mu_error (_("cannot create debug stream; transcript disabled: %s"),
50 mu_strerror (rc));
51 else
52 {
53 rc = mu_xscript_stream_create (&xstr, imap->carrier, dstr,
54 imap_prefix);
55 if (rc)
56 mu_error (_("cannot create transcript stream: %s"),
57 mu_strerror (rc));
58 else
59 {
60 mu_stream_unref (imap->carrier);
61 imap->carrier = xstr;
62 MU_IMAP_FSET (imap, MU_IMAP_TRACE);
63 }
64 } 39 }
65
66 return rc; 40 return rc;
67 } 41 }
68 42
69 int 43 int
70 _mu_imap_trace_disable (mu_imap_t imap) 44 _mu_imap_trace_disable (mu_imap_t imap)
71 { 45 {
72 mu_stream_t xstr = imap->carrier;
73 mu_stream_t stream[2];
74 int rc; 46 int rc;
75 47 if (!imap->io)
76 if (!xstr)
77 return 0; 48 return 0;
78 49 rc = mu_imapio_trace_disable (imap->io);
79 rc = mu_stream_ioctl (xstr, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, stream); 50 switch (rc)
80 if (rc) 51 {
81 return rc; 52 case 0:
53 case MU_ERR_NOT_OPEN:
54 MU_IMAP_FCLR (imap, MU_IMAP_TRACE);
55 break;
56 }
57 return rc;
82 58
83 imap->carrier = stream[0];
84 mu_stream_destroy (&xstr);
85 MU_IMAP_FCLR (imap, MU_IMAP_TRACE);
86 return 0;
87 } 59 }
88 60
89 int 61 int
90 mu_imap_trace (mu_imap_t imap, int op) 62 mu_imap_trace (mu_imap_t imap, int op)
91 { 63 {
92 int trace_on = MU_IMAP_FISSET (imap, MU_IMAP_TRACE); 64 int trace_on = mu_imapio_get_trace (imap->io);
93 65
94 switch (op) 66 switch (op)
95 { 67 {
96 case MU_IMAP_TRACE_SET: 68 case MU_IMAP_TRACE_SET:
...@@ -117,15 +89,15 @@ mu_imap_trace_mask (mu_imap_t imap, int op, int lev) ...@@ -117,15 +89,15 @@ mu_imap_trace_mask (mu_imap_t imap, int op, int lev)
117 switch (op) 89 switch (op)
118 { 90 {
119 case MU_IMAP_TRACE_SET: 91 case MU_IMAP_TRACE_SET:
120 imap->flags |= MU_IMAP_XSCRIPT_MASK(lev); 92 imap->flags |= MU_IMAP_XSCRIPT_MASK (lev);
121 break; 93 break;
122 94
123 case MU_IMAP_TRACE_CLR: 95 case MU_IMAP_TRACE_CLR:
124 imap->flags &= ~MU_IMAP_XSCRIPT_MASK(lev); 96 imap->flags &= ~MU_IMAP_XSCRIPT_MASK (lev);
125 break; 97 break;
126 98
127 case MU_IMAP_TRACE_QRY: 99 case MU_IMAP_TRACE_QRY:
128 if (imap->flags & MU_IMAP_XSCRIPT_MASK(lev)) 100 if (imap->flags & MU_IMAP_XSCRIPT_MASK (lev))
129 break; 101 break;
130 return MU_ERR_NOENT; 102 return MU_ERR_NOENT;
131 103
...@@ -138,8 +110,5 @@ mu_imap_trace_mask (mu_imap_t imap, int op, int lev) ...@@ -138,8 +110,5 @@ mu_imap_trace_mask (mu_imap_t imap, int op, int lev)
138 int 110 int
139 _mu_imap_xscript_level (mu_imap_t imap, int xlev) 111 _mu_imap_xscript_level (mu_imap_t imap, int xlev)
140 { 112 {
141 if (mu_stream_ioctl (imap->carrier, MU_IOCTL_XSCRIPTSTREAM, 113 return mu_imapio_set_xscript_level (imap->io, xlev);
142 MU_IOCTL_XSCRIPTSTREAM_LEVEL, &xlev) == 0)
143 return xlev;
144 return MU_XSCRIPT_NORMAL;
145 } 114 }
......
...@@ -364,6 +364,12 @@ com_login (int argc, char **argv) ...@@ -364,6 +364,12 @@ com_login (int argc, char **argv)
364 int status; 364 int status;
365 char *pwd, *passbuf = NULL; 365 char *pwd, *passbuf = NULL;
366 366
367 if (!imap)
368 {
369 mu_error (_("you need to connect first"));
370 return 0;
371 }
372
367 if (argc == 2) 373 if (argc == 2)
368 { 374 {
369 if (!mutool_shell_interactive) 375 if (!mutool_shell_interactive)
...@@ -395,22 +401,13 @@ com_login (int argc, char **argv) ...@@ -395,22 +401,13 @@ com_login (int argc, char **argv)
395 return 0; 401 return 0;
396 } 402 }
397 403
398
399 static int
400 _print_id (void *item, void *data)
401 {
402 const char *id = item;
403 mu_printf ("ID: %s %s\n", id, id + strlen (id) + 1);
404 return 0;
405 }
406
407 static int 404 static int
408 com_id (int argc, char **argv) 405 com_id (int argc, char **argv)
409 { 406 {
410 mu_list_t list; 407 mu_assoc_t assoc;
411 char *test = NULL; 408 char *test = NULL;
412 int status; 409 int status;
413 410
414 argv++; 411 argv++;
415 if (argv[0] && strcmp (argv[0], "-test") == 0) 412 if (argv[0] && strcmp (argv[0], "-test") == 0)
416 { 413 {
...@@ -424,31 +421,36 @@ com_id (int argc, char **argv) ...@@ -424,31 +421,36 @@ com_id (int argc, char **argv)
424 argv++; 421 argv++;
425 } 422 }
426 423
427 status = mu_imap_id (imap, argv + 1, &list); 424 status = mu_imap_id (imap, argv + 1, &assoc);
428 if (status == 0) 425 if (status == 0)
429 { 426 {
430 if (test) 427 if (test)
431 { 428 {
432 const char *res; 429 void *res = mu_assoc_ref (assoc, test);
433 int rc = mu_list_locate (list, test, (void*)&res); 430 if (res)
434
435 switch (rc)
436 { 431 {
437 case 0: 432 mu_printf ("%s: %s\n", test, *(char **)res);
438 mu_printf ("%s: %s\n", test, res + strlen (res) + 1);
439 break;
440
441 case MU_ERR_NOENT:
442 mu_printf ("%s is not set\n", test);
443 break;
444
445 default:
446 return rc;
447 } 433 }
434 else
435 mu_printf ("%s is not set\n", test);
448 } 436 }
449 else 437 else
450 mu_list_do (list, _print_id, NULL); 438 {
451 mu_list_destroy (&list); 439 mu_iterator_t itr;
440
441 mu_assoc_get_iterator (assoc, &itr);
442 for (mu_iterator_first (itr);
443 !mu_iterator_is_done (itr); mu_iterator_next (itr))
444 {
445 char *key;
446 void *val;
447
448 mu_iterator_current_kv (itr, (const void**)&key, &val);
449 mu_printf ("ID: %s %s\n", key, *(char**)val);
450 }
451 mu_iterator_destroy (&itr);
452 }
453 mu_assoc_destroy (&assoc);
452 } 454 }
453 return status; 455 return status;
454 } 456 }
......