Rewrite existing imap client support using imapio.
Showing
16 changed files
with
546 additions
and
316 deletions
... | @@ -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 | } | ... | ... |
... | @@ -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 | ... | ... |
... | @@ -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); | ... | ... |
libproto/imap/resplist.c
0 → 100644
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 | } | ... | ... |
-
Please register or sign in to post a comment