Commit 7ca75462 7ca7546248a32a53049e1d59889013925c01ed85 by Sergey Poznyakoff

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.
1 parent 48fb45e6
......@@ -22,8 +22,11 @@ extern "C" {
#endif
# include <mailutils/types.h>
int mu_imapio_create (mu_imapio_t *iop, mu_stream_t str);
#define MU_IMAPIO_CLIENT 0
#define MU_IMAPIO_SERVER 1
int mu_imapio_create (mu_imapio_t *iop, mu_stream_t str, int server);
void mu_imapio_free (mu_imapio_t io);
void mu_imapio_destroy (mu_imapio_t *pio);
......@@ -41,6 +44,8 @@ int mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer,
int mu_imapio_trace_enable (mu_imapio_t io);
int mu_imapio_trace_disable (mu_imapio_t io);
int mu_imapio_get_trace (mu_imapio_t io);
void mu_imapio_trace_payload (mu_imapio_t io, int val);
int mu_imapio_get_trace_payload (mu_imapio_t io);
int mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t *psize);
......
......@@ -28,7 +28,9 @@ struct _mu_imapio
size_t _imap_buf_level;
struct mu_wordsplit _imap_ws;
int _imap_ws_flags;
int _imap_server:1;
int _imap_transcript:1;
int _imap_trace_payload:1;
int _imap_reply_ready:1;
};
......
......@@ -21,7 +21,7 @@
#include <mailutils/sys/imapio.h>
int
mu_imapio_create (mu_imapio_t *iop, mu_stream_t str)
mu_imapio_create (mu_imapio_t *iop, mu_stream_t str, int server)
{
struct _mu_imapio *io = calloc (1, sizeof (*io));
if (!io)
......@@ -38,6 +38,7 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str)
MU_WRDSF_RETURN_DELIMS |
MU_WRDSF_WS |
MU_WRDSF_APPEND;
io->_imap_server = server;
*iop = io;
return 0;
}
......
......@@ -104,31 +104,42 @@ static int
initial_parse (struct _mu_imapio *io)
{
int rc, type;
int eat_rest = 0;
if ((rc = mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level,
&io->_imap_ws,
io->_imap_ws_flags | MU_WRDSF_INCREMENTAL)))
io->_imap_ws_flags |
(io->_imap_server ? 0 : MU_WRDSF_INCREMENTAL))))
{
if (rc == MU_WRDSE_NOINPUT)
return IMAPIO_OK;
return IMAPIO_ERR;
}
io->_imap_ws_flags |= MU_WRDSF_REUSE;
if (io->_imap_server)
return IMAPIO_OK;
if ((rc = mu_wordsplit (NULL, &io->_imap_ws, MU_WRDSF_INCREMENTAL)))
{
if (rc == MU_WRDSE_NOINPUT)
return IMAPIO_OK;
return IMAPIO_ERR;
}
if ((type = is_status_response (io->_imap_ws.ws_wordv[1]))
if (strcmp (io->_imap_ws.ws_wordv[0], "+") == 0)
eat_rest = 1;
else if ((type = is_status_response (io->_imap_ws.ws_wordv[1]))
&& (type == STATUS_RESPONSE ||
strcmp (io->_imap_ws.ws_wordv[0], "*") == 0))
{
rc = get_response_code (io);
if (rc)
return IMAPIO_ERR;
eat_rest = 1;
}
if (eat_rest)
{
while (io->_imap_ws.ws_endp < io->_imap_ws.ws_len &&
mu_isblank (io->_imap_ws.ws_input[io->_imap_ws.ws_endp]))
io->_imap_ws.ws_endp++;
......@@ -150,6 +161,7 @@ mu_imapio_getline (struct _mu_imapio *io)
{
int rc;
char *last_arg;
int xlev = MU_XSCRIPT_NORMAL;
if (io->_imap_reply_ready)
{
......@@ -163,7 +175,7 @@ mu_imapio_getline (struct _mu_imapio *io)
&io->_imap_buf_base, &io->_imap_buf_size,
&io->_imap_buf_level);
if (rc)
return rc;
break;
if (io->_imap_buf_level == 0)
break;
io->_imap_buf_level = mu_rtrim_class (io->_imap_buf_base,
......@@ -185,8 +197,11 @@ mu_imapio_getline (struct _mu_imapio *io)
io->_imap_buf_level - io->_imap_ws.ws_endp,
&io->_imap_ws, io->_imap_ws_flags);
if (rc)
return MU_ERR_PARSE;
{
rc = MU_ERR_PARSE;
break;
}
if (io->_imap_ws.ws_wordc == 0)
break;
......@@ -196,13 +211,18 @@ mu_imapio_getline (struct _mu_imapio *io)
int rc;
unsigned long number;
char *sp = NULL;
int xlev = mu_imapio_set_xscript_level (io, MU_XSCRIPT_PAYLOAD);
if (!io->_imap_trace_payload)
xlev = mu_imapio_set_xscript_level (io, MU_XSCRIPT_PAYLOAD);
number = strtoul (last_arg + 1, &sp, 10);
/* Client can ask for non-synchronised literal,
if a '+' is appended to the octet count. */
if (*sp == '}')
mu_stream_printf (io->_imap_stream, "+ GO AHEAD\n");
{
if (io->_imap_server)
mu_stream_printf (io->_imap_stream, "+ GO AHEAD\n");
}
else if (*sp != '+')
break;
......@@ -211,7 +231,10 @@ mu_imapio_getline (struct _mu_imapio *io)
size_t newsize = number + 1;
void *newp = realloc (io->_imap_buf_base, newsize);
if (!newp)
return ENOMEM;
{
rc = ENOMEM;
break;
}
io->_imap_buf_base = newp;
io->_imap_buf_size = newsize;
}
......@@ -229,7 +252,7 @@ mu_imapio_getline (struct _mu_imapio *io)
}
mu_imapio_set_xscript_level (io, xlev);
if (rc)
return rc;
break;
io->_imap_buf_base[io->_imap_buf_level++] = 0;
free (last_arg);
......@@ -237,12 +260,18 @@ mu_imapio_getline (struct _mu_imapio *io)
if (mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level,
&io->_imap_ws,
io->_imap_ws_flags|MU_WRDSF_NOSPLIT))
return MU_ERR_PARSE;
{
rc = MU_ERR_PARSE;
break;
}
}
else
break;
}
if (!io->_imap_trace_payload)
mu_imapio_set_xscript_level (io, xlev);
io->_imap_reply_ready = 1;
return 0;
return rc;
}
......
......@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <string.h>
#include <mailutils/types.h>
#include <mailutils/errno.h>
#include <mailutils/imapio.h>
#include <mailutils/sys/imapio.h>
#include <mailutils/stream.h>
......@@ -25,7 +26,18 @@
int
mu_imapio_send_literal (struct _mu_imapio *io, const char *buffer)
{
return mu_stream_printf (io->_imap_stream,
"{%lu}\n%s", (unsigned long) strlen (buffer),
buffer);
size_t len = strlen (buffer);
mu_stream_printf (io->_imap_stream, "{%lu}\n", (unsigned long) len);
if (!io->_imap_server)
{
int rc = mu_imapio_getline (io);
if (rc)
return rc;
if (!(io->_imap_reply_ready && io->_imap_ws.ws_wordv[0][0] == '+'))
return MU_ERR_BADREPLY;
}
return mu_stream_write (io->_imap_stream, buffer, len, NULL);
}
......
......@@ -84,3 +84,15 @@ mu_imapio_get_trace (mu_imapio_t io)
{
return io ? io->_imap_transcript : 0;
}
void
mu_imapio_trace_payload (mu_imapio_t io, int val)
{
io->_imap_trace_payload = !!val;
}
int
mu_imapio_get_trace_payload (mu_imapio_t io)
{
return io ? io->_imap_trace_payload : 0;
}
......
......@@ -16,6 +16,8 @@
AT_BANNER(IMAP IO)
m4_pushdef([IMAPIO_FLAGS])
dnl ------------------------------------------------------------
dnl IMAPIO([NAME], [KW = `'], [INPUT], [STDOUT = `'],
dnl [STDERR = `'])
......@@ -23,7 +25,7 @@ dnl
m4_pushdef([IMAPIO],[
m4_pushdef([MU_TEST_GROUP],[imapio])
m4_pushdef([MU_TEST_KEYWORDS],[imapio])
m4_pushdef([MU_TEST_COMMAND],[imapio])
m4_pushdef([MU_TEST_COMMAND],[imapio IMAPIO_FLAGS])
MU_GENERIC_TEST([$1],[$2],[$3],[],[$4],[$5])
m4_popdef([MU_TEST_COMMAND])
m4_popdef([MU_TEST_KEYWORDS])
......@@ -78,7 +80,21 @@ IMAPIO([server response with code],[],
6: 'Predicted next uid'
])
IMAPIO([literals],[literal],
IMAPIO([literals (client)],[literal],
[A001 LOGIN {11}
FRED FOOBAR {7}
fat man
],
[],
[4
0: 'A001'
1: 'LOGIN'
2: 'FRED FOOBAR'
3: 'fat man'
])
m4_pushdef([IMAPIO_FLAGS],[-server])
IMAPIO([literals (server)],[literal],
[A001 LOGIN {11}
FRED FOOBAR {7}
fat man
......@@ -93,7 +109,7 @@ fat man
3: 'fat man'
])
IMAPIO([non-synch literals],[literal],
IMAPIO([non-synchronized literals (server)],[literal],
[A001 LOGIN {11+}
FRED FOOBAR {7+}
fat man
......@@ -105,6 +121,9 @@ fat man
2: 'FRED FOOBAR'
3: 'fat man'
])
m4_popdef([IMAPIO_FLAGS])
dnl ------------------------------------------------------------
m4_popdef([IMAPIO])
m4_pushdef([IMAPIO_FLAGS])
......
......@@ -29,7 +29,7 @@
void
usage ()
{
mu_stream_printf (mu_strout, "usage: %s [debug=SPEC] [-transcript]\n",
mu_stream_printf (mu_strout, "usage: %s [debug=SPEC] [-transcript] [-server]\n",
mu_program_name);
exit (0);
}
......@@ -41,6 +41,7 @@ main (int argc, char **argv)
int transcript = 0;
mu_imapio_t io;
mu_stream_t str;
int imapio_mode = MU_IMAPIO_CLIENT;
mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
......@@ -52,6 +53,8 @@ main (int argc, char **argv)
mu_debug_parse_spec (opt + 6);
else if (strcmp (opt, "-transcript") == 0)
transcript = 1;
else if (strcmp (opt, "-server") == 0)
imapio_mode = MU_IMAPIO_SERVER;
else if (strcmp (opt, "-h") == 0)
usage ();
else
......@@ -64,7 +67,7 @@ main (int argc, char **argv)
MU_ASSERT (mu_iostream_create (&str, mu_strin, mu_strout));
MU_ASSERT (mu_imapio_create (&io, str));
MU_ASSERT (mu_imapio_create (&io, str, imapio_mode));
if (transcript)
mu_imapio_trace_enable (io);
......