imapio: fix payload tracing and handling of continuation responses
* include/mailutils/imapio.h (mu_imapio_create): Change signature. All uses updated. (mu_imapio_trace_payload,mu_imapio_get_trace_payload): New protos. * include/mailutils/sys/imapio.h (_mu_imapio) <_imap_server> <_imap_trace_payload>: New bits. * libmailutils/imapio/create.c (mu_imapio_create): Take three arguments, the third one specifying whether the imapio object is intended for server or client. * libmailutils/imapio/getline.c (initial_parse): In server mode, parse everything at once. Handle continuation responses in client mode. (mu_imapio_getline): Toggle MU_XSCRIPT_PAYLOAD only if requested. * libmailutils/imapio/literal.c: Wait for continuation response (in client mode). * libmailutils/imapio/trace.c (mu_imapio_trace_payload) (mu_imapio_get_trace_payload): New functions. * libmailutils/tests/imapio.c: New option -server. * libmailutils/tests/imapio.at: Update literal tests.
Showing
8 changed files
with
102 additions
and
19 deletions
... | @@ -23,7 +23,10 @@ extern "C" { | ... | @@ -23,7 +23,10 @@ extern "C" { |
23 | 23 | ||
24 | # include <mailutils/types.h> | 24 | # include <mailutils/types.h> |
25 | 25 | ||
26 | int mu_imapio_create (mu_imapio_t *iop, mu_stream_t str); | 26 | #define MU_IMAPIO_CLIENT 0 |
27 | #define MU_IMAPIO_SERVER 1 | ||
28 | |||
29 | int mu_imapio_create (mu_imapio_t *iop, mu_stream_t str, int server); | ||
27 | void mu_imapio_free (mu_imapio_t io); | 30 | void mu_imapio_free (mu_imapio_t io); |
28 | void mu_imapio_destroy (mu_imapio_t *pio); | 31 | void mu_imapio_destroy (mu_imapio_t *pio); |
29 | 32 | ||
... | @@ -41,6 +44,8 @@ int mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer, | ... | @@ -41,6 +44,8 @@ int mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer, |
41 | int mu_imapio_trace_enable (mu_imapio_t io); | 44 | int mu_imapio_trace_enable (mu_imapio_t io); |
42 | int mu_imapio_trace_disable (mu_imapio_t io); | 45 | int mu_imapio_trace_disable (mu_imapio_t io); |
43 | int mu_imapio_get_trace (mu_imapio_t io); | 46 | int mu_imapio_get_trace (mu_imapio_t io); |
47 | void mu_imapio_trace_payload (mu_imapio_t io, int val); | ||
48 | int mu_imapio_get_trace_payload (mu_imapio_t io); | ||
44 | 49 | ||
45 | int mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t *psize); | 50 | int mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t *psize); |
46 | 51 | ... | ... |
... | @@ -28,7 +28,9 @@ struct _mu_imapio | ... | @@ -28,7 +28,9 @@ struct _mu_imapio |
28 | size_t _imap_buf_level; | 28 | size_t _imap_buf_level; |
29 | struct mu_wordsplit _imap_ws; | 29 | struct mu_wordsplit _imap_ws; |
30 | int _imap_ws_flags; | 30 | int _imap_ws_flags; |
31 | int _imap_server:1; | ||
31 | int _imap_transcript:1; | 32 | int _imap_transcript:1; |
33 | int _imap_trace_payload:1; | ||
32 | int _imap_reply_ready:1; | 34 | int _imap_reply_ready:1; |
33 | }; | 35 | }; |
34 | 36 | ... | ... |
... | @@ -21,7 +21,7 @@ | ... | @@ -21,7 +21,7 @@ |
21 | #include <mailutils/sys/imapio.h> | 21 | #include <mailutils/sys/imapio.h> |
22 | 22 | ||
23 | int | 23 | int |
24 | mu_imapio_create (mu_imapio_t *iop, mu_stream_t str) | 24 | mu_imapio_create (mu_imapio_t *iop, mu_stream_t str, int server) |
25 | { | 25 | { |
26 | struct _mu_imapio *io = calloc (1, sizeof (*io)); | 26 | struct _mu_imapio *io = calloc (1, sizeof (*io)); |
27 | if (!io) | 27 | if (!io) |
... | @@ -38,6 +38,7 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str) | ... | @@ -38,6 +38,7 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str) |
38 | MU_WRDSF_RETURN_DELIMS | | 38 | MU_WRDSF_RETURN_DELIMS | |
39 | MU_WRDSF_WS | | 39 | MU_WRDSF_WS | |
40 | MU_WRDSF_APPEND; | 40 | MU_WRDSF_APPEND; |
41 | io->_imap_server = server; | ||
41 | *iop = io; | 42 | *iop = io; |
42 | return 0; | 43 | return 0; |
43 | } | 44 | } | ... | ... |
... | @@ -104,16 +104,20 @@ static int | ... | @@ -104,16 +104,20 @@ static int |
104 | initial_parse (struct _mu_imapio *io) | 104 | initial_parse (struct _mu_imapio *io) |
105 | { | 105 | { |
106 | int rc, type; | 106 | int rc, type; |
107 | int eat_rest = 0; | ||
107 | 108 | ||
108 | if ((rc = mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level, | 109 | if ((rc = mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level, |
109 | &io->_imap_ws, | 110 | &io->_imap_ws, |
110 | io->_imap_ws_flags | MU_WRDSF_INCREMENTAL))) | 111 | io->_imap_ws_flags | |
112 | (io->_imap_server ? 0 : MU_WRDSF_INCREMENTAL)))) | ||
111 | { | 113 | { |
112 | if (rc == MU_WRDSE_NOINPUT) | 114 | if (rc == MU_WRDSE_NOINPUT) |
113 | return IMAPIO_OK; | 115 | return IMAPIO_OK; |
114 | return IMAPIO_ERR; | 116 | return IMAPIO_ERR; |
115 | } | 117 | } |
116 | io->_imap_ws_flags |= MU_WRDSF_REUSE; | 118 | io->_imap_ws_flags |= MU_WRDSF_REUSE; |
119 | if (io->_imap_server) | ||
120 | return IMAPIO_OK; | ||
117 | 121 | ||
118 | if ((rc = mu_wordsplit (NULL, &io->_imap_ws, MU_WRDSF_INCREMENTAL))) | 122 | if ((rc = mu_wordsplit (NULL, &io->_imap_ws, MU_WRDSF_INCREMENTAL))) |
119 | { | 123 | { |
... | @@ -122,13 +126,20 @@ initial_parse (struct _mu_imapio *io) | ... | @@ -122,13 +126,20 @@ initial_parse (struct _mu_imapio *io) |
122 | return IMAPIO_ERR; | 126 | return IMAPIO_ERR; |
123 | } | 127 | } |
124 | 128 | ||
125 | if ((type = is_status_response (io->_imap_ws.ws_wordv[1])) | 129 | if (strcmp (io->_imap_ws.ws_wordv[0], "+") == 0) |
130 | eat_rest = 1; | ||
131 | else if ((type = is_status_response (io->_imap_ws.ws_wordv[1])) | ||
126 | && (type == STATUS_RESPONSE || | 132 | && (type == STATUS_RESPONSE || |
127 | strcmp (io->_imap_ws.ws_wordv[0], "*") == 0)) | 133 | strcmp (io->_imap_ws.ws_wordv[0], "*") == 0)) |
128 | { | 134 | { |
129 | rc = get_response_code (io); | 135 | rc = get_response_code (io); |
130 | if (rc) | 136 | if (rc) |
131 | return IMAPIO_ERR; | 137 | return IMAPIO_ERR; |
138 | eat_rest = 1; | ||
139 | } | ||
140 | |||
141 | if (eat_rest) | ||
142 | { | ||
132 | while (io->_imap_ws.ws_endp < io->_imap_ws.ws_len && | 143 | while (io->_imap_ws.ws_endp < io->_imap_ws.ws_len && |
133 | mu_isblank (io->_imap_ws.ws_input[io->_imap_ws.ws_endp])) | 144 | mu_isblank (io->_imap_ws.ws_input[io->_imap_ws.ws_endp])) |
134 | io->_imap_ws.ws_endp++; | 145 | io->_imap_ws.ws_endp++; |
... | @@ -150,6 +161,7 @@ mu_imapio_getline (struct _mu_imapio *io) | ... | @@ -150,6 +161,7 @@ mu_imapio_getline (struct _mu_imapio *io) |
150 | { | 161 | { |
151 | int rc; | 162 | int rc; |
152 | char *last_arg; | 163 | char *last_arg; |
164 | int xlev = MU_XSCRIPT_NORMAL; | ||
153 | 165 | ||
154 | if (io->_imap_reply_ready) | 166 | if (io->_imap_reply_ready) |
155 | { | 167 | { |
... | @@ -163,7 +175,7 @@ mu_imapio_getline (struct _mu_imapio *io) | ... | @@ -163,7 +175,7 @@ mu_imapio_getline (struct _mu_imapio *io) |
163 | &io->_imap_buf_base, &io->_imap_buf_size, | 175 | &io->_imap_buf_base, &io->_imap_buf_size, |
164 | &io->_imap_buf_level); | 176 | &io->_imap_buf_level); |
165 | if (rc) | 177 | if (rc) |
166 | return rc; | 178 | break; |
167 | if (io->_imap_buf_level == 0) | 179 | if (io->_imap_buf_level == 0) |
168 | break; | 180 | break; |
169 | io->_imap_buf_level = mu_rtrim_class (io->_imap_buf_base, | 181 | io->_imap_buf_level = mu_rtrim_class (io->_imap_buf_base, |
... | @@ -185,7 +197,10 @@ mu_imapio_getline (struct _mu_imapio *io) | ... | @@ -185,7 +197,10 @@ mu_imapio_getline (struct _mu_imapio *io) |
185 | io->_imap_buf_level - io->_imap_ws.ws_endp, | 197 | io->_imap_buf_level - io->_imap_ws.ws_endp, |
186 | &io->_imap_ws, io->_imap_ws_flags); | 198 | &io->_imap_ws, io->_imap_ws_flags); |
187 | if (rc) | 199 | if (rc) |
188 | return MU_ERR_PARSE; | 200 | { |
201 | rc = MU_ERR_PARSE; | ||
202 | break; | ||
203 | } | ||
189 | 204 | ||
190 | if (io->_imap_ws.ws_wordc == 0) | 205 | if (io->_imap_ws.ws_wordc == 0) |
191 | break; | 206 | break; |
... | @@ -196,13 +211,18 @@ mu_imapio_getline (struct _mu_imapio *io) | ... | @@ -196,13 +211,18 @@ mu_imapio_getline (struct _mu_imapio *io) |
196 | int rc; | 211 | int rc; |
197 | unsigned long number; | 212 | unsigned long number; |
198 | char *sp = NULL; | 213 | char *sp = NULL; |
199 | int xlev = mu_imapio_set_xscript_level (io, MU_XSCRIPT_PAYLOAD); | 214 | |
215 | if (!io->_imap_trace_payload) | ||
216 | xlev = mu_imapio_set_xscript_level (io, MU_XSCRIPT_PAYLOAD); | ||
200 | 217 | ||
201 | number = strtoul (last_arg + 1, &sp, 10); | 218 | number = strtoul (last_arg + 1, &sp, 10); |
202 | /* Client can ask for non-synchronised literal, | 219 | /* Client can ask for non-synchronised literal, |
203 | if a '+' is appended to the octet count. */ | 220 | if a '+' is appended to the octet count. */ |
204 | if (*sp == '}') | 221 | if (*sp == '}') |
222 | { | ||
223 | if (io->_imap_server) | ||
205 | mu_stream_printf (io->_imap_stream, "+ GO AHEAD\n"); | 224 | mu_stream_printf (io->_imap_stream, "+ GO AHEAD\n"); |
225 | } | ||
206 | else if (*sp != '+') | 226 | else if (*sp != '+') |
207 | break; | 227 | break; |
208 | 228 | ||
... | @@ -211,7 +231,10 @@ mu_imapio_getline (struct _mu_imapio *io) | ... | @@ -211,7 +231,10 @@ mu_imapio_getline (struct _mu_imapio *io) |
211 | size_t newsize = number + 1; | 231 | size_t newsize = number + 1; |
212 | void *newp = realloc (io->_imap_buf_base, newsize); | 232 | void *newp = realloc (io->_imap_buf_base, newsize); |
213 | if (!newp) | 233 | if (!newp) |
214 | return ENOMEM; | 234 | { |
235 | rc = ENOMEM; | ||
236 | break; | ||
237 | } | ||
215 | io->_imap_buf_base = newp; | 238 | io->_imap_buf_base = newp; |
216 | io->_imap_buf_size = newsize; | 239 | io->_imap_buf_size = newsize; |
217 | } | 240 | } |
... | @@ -229,7 +252,7 @@ mu_imapio_getline (struct _mu_imapio *io) | ... | @@ -229,7 +252,7 @@ mu_imapio_getline (struct _mu_imapio *io) |
229 | } | 252 | } |
230 | mu_imapio_set_xscript_level (io, xlev); | 253 | mu_imapio_set_xscript_level (io, xlev); |
231 | if (rc) | 254 | if (rc) |
232 | return rc; | 255 | break; |
233 | io->_imap_buf_base[io->_imap_buf_level++] = 0; | 256 | io->_imap_buf_base[io->_imap_buf_level++] = 0; |
234 | 257 | ||
235 | free (last_arg); | 258 | free (last_arg); |
... | @@ -237,12 +260,18 @@ mu_imapio_getline (struct _mu_imapio *io) | ... | @@ -237,12 +260,18 @@ mu_imapio_getline (struct _mu_imapio *io) |
237 | if (mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level, | 260 | if (mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level, |
238 | &io->_imap_ws, | 261 | &io->_imap_ws, |
239 | io->_imap_ws_flags|MU_WRDSF_NOSPLIT)) | 262 | io->_imap_ws_flags|MU_WRDSF_NOSPLIT)) |
240 | return MU_ERR_PARSE; | 263 | { |
264 | rc = MU_ERR_PARSE; | ||
265 | break; | ||
266 | } | ||
241 | } | 267 | } |
242 | else | 268 | else |
243 | break; | 269 | break; |
244 | } | 270 | } |
245 | 271 | ||
272 | if (!io->_imap_trace_payload) | ||
273 | mu_imapio_set_xscript_level (io, xlev); | ||
274 | |||
246 | io->_imap_reply_ready = 1; | 275 | io->_imap_reply_ready = 1; |
247 | return 0; | 276 | return rc; |
248 | } | 277 | } | ... | ... |
... | @@ -18,6 +18,7 @@ | ... | @@ -18,6 +18,7 @@ |
18 | #include <stdlib.h> | 18 | #include <stdlib.h> |
19 | #include <string.h> | 19 | #include <string.h> |
20 | #include <mailutils/types.h> | 20 | #include <mailutils/types.h> |
21 | #include <mailutils/errno.h> | ||
21 | #include <mailutils/imapio.h> | 22 | #include <mailutils/imapio.h> |
22 | #include <mailutils/sys/imapio.h> | 23 | #include <mailutils/sys/imapio.h> |
23 | #include <mailutils/stream.h> | 24 | #include <mailutils/stream.h> |
... | @@ -25,7 +26,18 @@ | ... | @@ -25,7 +26,18 @@ |
25 | int | 26 | int |
26 | mu_imapio_send_literal (struct _mu_imapio *io, const char *buffer) | 27 | mu_imapio_send_literal (struct _mu_imapio *io, const char *buffer) |
27 | { | 28 | { |
28 | return mu_stream_printf (io->_imap_stream, | 29 | size_t len = strlen (buffer); |
29 | "{%lu}\n%s", (unsigned long) strlen (buffer), | 30 | |
30 | buffer); | 31 | mu_stream_printf (io->_imap_stream, "{%lu}\n", (unsigned long) len); |
32 | |||
33 | if (!io->_imap_server) | ||
34 | { | ||
35 | int rc = mu_imapio_getline (io); | ||
36 | if (rc) | ||
37 | return rc; | ||
38 | if (!(io->_imap_reply_ready && io->_imap_ws.ws_wordv[0][0] == '+')) | ||
39 | return MU_ERR_BADREPLY; | ||
40 | } | ||
41 | |||
42 | return mu_stream_write (io->_imap_stream, buffer, len, NULL); | ||
31 | } | 43 | } | ... | ... |
... | @@ -84,3 +84,15 @@ mu_imapio_get_trace (mu_imapio_t io) | ... | @@ -84,3 +84,15 @@ mu_imapio_get_trace (mu_imapio_t io) |
84 | { | 84 | { |
85 | return io ? io->_imap_transcript : 0; | 85 | return io ? io->_imap_transcript : 0; |
86 | } | 86 | } |
87 | |||
88 | void | ||
89 | mu_imapio_trace_payload (mu_imapio_t io, int val) | ||
90 | { | ||
91 | io->_imap_trace_payload = !!val; | ||
92 | } | ||
93 | |||
94 | int | ||
95 | mu_imapio_get_trace_payload (mu_imapio_t io) | ||
96 | { | ||
97 | return io ? io->_imap_trace_payload : 0; | ||
98 | } | ... | ... |
... | @@ -16,6 +16,8 @@ | ... | @@ -16,6 +16,8 @@ |
16 | 16 | ||
17 | AT_BANNER(IMAP IO) | 17 | AT_BANNER(IMAP IO) |
18 | 18 | ||
19 | m4_pushdef([IMAPIO_FLAGS]) | ||
20 | |||
19 | dnl ------------------------------------------------------------ | 21 | dnl ------------------------------------------------------------ |
20 | dnl IMAPIO([NAME], [KW = `'], [INPUT], [STDOUT = `'], | 22 | dnl IMAPIO([NAME], [KW = `'], [INPUT], [STDOUT = `'], |
21 | dnl [STDERR = `']) | 23 | dnl [STDERR = `']) |
... | @@ -23,7 +25,7 @@ dnl | ... | @@ -23,7 +25,7 @@ dnl |
23 | m4_pushdef([IMAPIO],[ | 25 | m4_pushdef([IMAPIO],[ |
24 | m4_pushdef([MU_TEST_GROUP],[imapio]) | 26 | m4_pushdef([MU_TEST_GROUP],[imapio]) |
25 | m4_pushdef([MU_TEST_KEYWORDS],[imapio]) | 27 | m4_pushdef([MU_TEST_KEYWORDS],[imapio]) |
26 | m4_pushdef([MU_TEST_COMMAND],[imapio]) | 28 | m4_pushdef([MU_TEST_COMMAND],[imapio IMAPIO_FLAGS]) |
27 | MU_GENERIC_TEST([$1],[$2],[$3],[],[$4],[$5]) | 29 | MU_GENERIC_TEST([$1],[$2],[$3],[],[$4],[$5]) |
28 | m4_popdef([MU_TEST_COMMAND]) | 30 | m4_popdef([MU_TEST_COMMAND]) |
29 | m4_popdef([MU_TEST_KEYWORDS]) | 31 | m4_popdef([MU_TEST_KEYWORDS]) |
... | @@ -78,7 +80,21 @@ IMAPIO([server response with code],[], | ... | @@ -78,7 +80,21 @@ IMAPIO([server response with code],[], |
78 | 6: 'Predicted next uid' | 80 | 6: 'Predicted next uid' |
79 | ]) | 81 | ]) |
80 | 82 | ||
81 | IMAPIO([literals],[literal], | 83 | IMAPIO([literals (client)],[literal], |
84 | [A001 LOGIN {11} | ||
85 | FRED FOOBAR {7} | ||
86 | fat man | ||
87 | ], | ||
88 | [], | ||
89 | [4 | ||
90 | 0: 'A001' | ||
91 | 1: 'LOGIN' | ||
92 | 2: 'FRED FOOBAR' | ||
93 | 3: 'fat man' | ||
94 | ]) | ||
95 | |||
96 | m4_pushdef([IMAPIO_FLAGS],[-server]) | ||
97 | IMAPIO([literals (server)],[literal], | ||
82 | [A001 LOGIN {11} | 98 | [A001 LOGIN {11} |
83 | FRED FOOBAR {7} | 99 | FRED FOOBAR {7} |
84 | fat man | 100 | fat man |
... | @@ -93,7 +109,7 @@ fat man | ... | @@ -93,7 +109,7 @@ fat man |
93 | 3: 'fat man' | 109 | 3: 'fat man' |
94 | ]) | 110 | ]) |
95 | 111 | ||
96 | IMAPIO([non-synch literals],[literal], | 112 | IMAPIO([non-synchronized literals (server)],[literal], |
97 | [A001 LOGIN {11+} | 113 | [A001 LOGIN {11+} |
98 | FRED FOOBAR {7+} | 114 | FRED FOOBAR {7+} |
99 | fat man | 115 | fat man |
... | @@ -105,6 +121,9 @@ fat man | ... | @@ -105,6 +121,9 @@ fat man |
105 | 2: 'FRED FOOBAR' | 121 | 2: 'FRED FOOBAR' |
106 | 3: 'fat man' | 122 | 3: 'fat man' |
107 | ]) | 123 | ]) |
124 | m4_popdef([IMAPIO_FLAGS]) | ||
108 | 125 | ||
109 | dnl ------------------------------------------------------------ | 126 | dnl ------------------------------------------------------------ |
110 | m4_popdef([IMAPIO]) | 127 | m4_popdef([IMAPIO]) |
128 | m4_pushdef([IMAPIO_FLAGS]) | ||
129 | ... | ... |
... | @@ -29,7 +29,7 @@ | ... | @@ -29,7 +29,7 @@ |
29 | void | 29 | void |
30 | usage () | 30 | usage () |
31 | { | 31 | { |
32 | mu_stream_printf (mu_strout, "usage: %s [debug=SPEC] [-transcript]\n", | 32 | mu_stream_printf (mu_strout, "usage: %s [debug=SPEC] [-transcript] [-server]\n", |
33 | mu_program_name); | 33 | mu_program_name); |
34 | exit (0); | 34 | exit (0); |
35 | } | 35 | } |
... | @@ -41,6 +41,7 @@ main (int argc, char **argv) | ... | @@ -41,6 +41,7 @@ main (int argc, char **argv) |
41 | int transcript = 0; | 41 | int transcript = 0; |
42 | mu_imapio_t io; | 42 | mu_imapio_t io; |
43 | mu_stream_t str; | 43 | mu_stream_t str; |
44 | int imapio_mode = MU_IMAPIO_CLIENT; | ||
44 | 45 | ||
45 | mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); | 46 | mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); |
46 | 47 | ||
... | @@ -52,6 +53,8 @@ main (int argc, char **argv) | ... | @@ -52,6 +53,8 @@ main (int argc, char **argv) |
52 | mu_debug_parse_spec (opt + 6); | 53 | mu_debug_parse_spec (opt + 6); |
53 | else if (strcmp (opt, "-transcript") == 0) | 54 | else if (strcmp (opt, "-transcript") == 0) |
54 | transcript = 1; | 55 | transcript = 1; |
56 | else if (strcmp (opt, "-server") == 0) | ||
57 | imapio_mode = MU_IMAPIO_SERVER; | ||
55 | else if (strcmp (opt, "-h") == 0) | 58 | else if (strcmp (opt, "-h") == 0) |
56 | usage (); | 59 | usage (); |
57 | else | 60 | else |
... | @@ -64,7 +67,7 @@ main (int argc, char **argv) | ... | @@ -64,7 +67,7 @@ main (int argc, char **argv) |
64 | MU_ASSERT (mu_iostream_create (&str, mu_strin, mu_strout)); | 67 | MU_ASSERT (mu_iostream_create (&str, mu_strin, mu_strout)); |
65 | 68 | ||
66 | 69 | ||
67 | MU_ASSERT (mu_imapio_create (&io, str)); | 70 | MU_ASSERT (mu_imapio_create (&io, str, imapio_mode)); |
68 | 71 | ||
69 | if (transcript) | 72 | if (transcript) |
70 | mu_imapio_trace_enable (io); | 73 | mu_imapio_trace_enable (io); | ... | ... |
-
Please register or sign in to post a comment