Commit 30f0097c 30f0097c4c2a9b552323733cbc436b91d32fbce6 by Sergey Poznyakoff

Bugfixes.

* imap4d/fetch.c (fetch_send_section_part): Make sure the item tag
always reflects peek status.  All callers updated.
(fetch_io): Try to allocate as large a buffer as possible.
Use util_send_bytes where fit.
* imap4d/imap4d.h (imap4d_auth_handler_fp): Remove unused argument.
* imap4d/store.c (imap4d_store0): Take into account eventual UID
prefix.
* imap4d/util.c (util_send_bytes): New function.
(util_send): Comment out transcript.
(util_do_command): Fix coredump on invalid commands.
(imap4d_readline): Transcript only first line of the input.
Ensure entire literal is read.
1 parent 927c27f8
2008-08-11 Sergey Poznyakoff <gray@gnu.org.ua>
* imap4d/fetch.c (fetch_send_section_part): Make sure the item tag
always reflects peek status. All callers updated.
(fetch_io): Try to allocate as large a buffer as possible.
Use util_send_bytes where fit.
* imap4d/imap4d.h (imap4d_auth_handler_fp): Remove unused argument.
* imap4d/store.c (imap4d_store0): Take into account eventual UID
prefix.
* imap4d/util.c (util_send_bytes): New function.
(util_send): Comment out transcript.
(util_do_command): Fix coredump on invalid commands.
(imap4d_readline): Transcript only first line of the input.
Ensure entire literal is read.
Fix input operations and RFC-compliance in imap4d.
* imap4d/util.c (util_getword, util_getitem, util_token)
......
......@@ -656,20 +656,24 @@ fetch_get_part (struct fetch_function_closure *ffc,
static void
fetch_send_section_part (struct fetch_function_closure *ffc,
const char *prefix, const char *suffix)
const char *suffix)
{
int i;
util_send ("%s", prefix);
util_send ("BODY%s[", ffc->peek ? ".PEEK" : "");
for (i = 0; i < ffc->nset; i++)
{
if (i)
util_send (".");
util_send ("%lu", (unsigned long) ffc->section_part[i]);
}
if (i && suffix[0] != ']')
util_send (".");
util_send ("%s", suffix);
if (suffix)
{
if (i)
util_send (".");
util_send ("%s", suffix);
}
util_send ("]");
}
static int
......@@ -683,19 +687,25 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
if (start == 0 && size == (size_t) -1)
{
char buffer[512];
char *buffer;
size_t bufsize;
for (bufsize = max; (buffer = malloc (bufsize)) == NULL; bufsize /= 2)
if (bufsize < 512)
imap4d_bye (ERR_NO_MEM);
offset = 0;
if (max)
{
util_send (" {%lu}\r\n", (unsigned long) max);
while (mu_stream_read (rfc, buffer, sizeof (buffer) - 1, offset,
while (mu_stream_read (rfc, buffer, bufsize, offset,
&n) == 0 && n > 0)
{
buffer[n] = '\0';
util_send ("%s", buffer);
util_send_bytes (buffer, n);
offset += n;
}
/* FIXME: Make sure exactly max bytes were sent */
free (buffer);
}
else
util_send (" \"\"");
......@@ -726,7 +736,7 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
if (total)
{
util_send (" {%lu}\r\n", (unsigned long) total);
util_send ("%s", buffer);
util_send_bytes (buffer, total);
}
else
util_send (" \"\"");
......@@ -858,7 +868,7 @@ _frt_body (struct fetch_function_closure *ffc,
if (ffc->name)
util_send ("%s", ffc->name);
else
fetch_send_section_part (ffc, "BODY[", "]");
fetch_send_section_part (ffc, NULL);
msg = fetch_get_part (ffc, frt);
if (!msg)
{
......@@ -884,7 +894,7 @@ _frt_body_text (struct fetch_function_closure *ffc,
if (ffc->name)
util_send ("%s", ffc->name);
else
fetch_send_section_part (ffc, "BODY[", "TEXT]");
fetch_send_section_part (ffc, "TEXT");
msg = fetch_get_part (ffc, frt);
if (!msg)
{
......@@ -926,7 +936,7 @@ _frt_header0 (struct fetch_function_closure *ffc,
if (ffc->name)
util_send ("%s", ffc->name);
else
fetch_send_section_part (ffc, "BODY[", suffix);
fetch_send_section_part (ffc, suffix);
msg = fetch_get_part (ffc, frt);
if (!msg)
......@@ -945,14 +955,14 @@ static int
_frt_header (struct fetch_function_closure *ffc,
struct fetch_runtime_closure *frt)
{
return _frt_header0 (ffc, frt, "HEADER]");
return _frt_header0 (ffc, frt, "HEADER");
}
static int
_frt_mime (struct fetch_function_closure *ffc,
struct fetch_runtime_closure *frt)
{
return _frt_header0 (ffc, frt, "MIME]");
return _frt_header0 (ffc, frt, "MIME");
}
static int
......@@ -990,7 +1000,7 @@ _frt_header_fields (struct fetch_function_closure *ffc,
set_seen (ffc, frt);
fetch_send_section_part (ffc, "BODY[", "HEADER.FIELDS");
fetch_send_section_part (ffc, "HEADER.FIELDS");
if (ffc->not)
util_send (".NOT");
util_send (" (");
......
......@@ -347,7 +347,7 @@ int imap4d_init_tls_server (void);
#endif /* WITH_TLS */
typedef int (*imap4d_auth_handler_fp) (struct imap4d_command *,
char *, char *, char **);
char *, char **);
extern void auth_add (char *name, imap4d_auth_handler_fp handler);
extern void auth_remove (char *name);
......
......@@ -72,7 +72,7 @@ imap4d_store0 (imap4d_tokbuf_t tok, int isuid, char **ptext)
int type = 0;
pb.tok = tok;
pb.arg = IMAP4_ARG_1;
pb.arg = IMAP4_ARG_1 + !!isuid;
pb.err_text = NULL;
if (setjmp (pb.errjmp))
{
......
......@@ -262,6 +262,12 @@ util_msgset (char *s, size_t ** set, int *n, int isuid)
}
int
util_send_bytes (const char *buf, size_t size)
{
return mu_stream_sequential_write (ostream, buf, size);
}
int
util_send (const char *format, ...)
{
char *buf = NULL;
......@@ -274,8 +280,10 @@ util_send (const char *format, ...)
if (!buf)
imap4d_bye (ERR_NO_MEM);
#if 0
if (imap4d_transcript)
mu_diag_output (MU_DIAG_DEBUG, "sent: %s", buf);
#endif
status = mu_stream_sequential_write (ostream, buf, strlen (buf));
free (buf);
......@@ -410,7 +418,7 @@ util_do_command (imap4d_tokbuf_t tok)
else if (argc == 1)
{
nullcommand.name = "";
nullcommand.tag = tag;
nullcommand.tag = imap4d_tokbuf_getarg (tok, 0);
return util_finish (&nullcommand, RESP_BAD, "Missing command");
}
......@@ -1339,11 +1347,15 @@ imap4d_tokbuf_getline (struct imap4d_tokbuf *tok)
void
imap4d_readline (struct imap4d_tokbuf *tok)
{
int transcript = imap4d_transcript;
tok->argc = 0;
tok->level = 0;
for (;;)
{
char *last_arg;
size_t off = imap4d_tokbuf_getline (tok);
if (transcript)
mu_diag_output (MU_DIAG_DEBUG, "recv: %s", tok->buffer);
imap4d_tokbuf_tokenize (tok, off);
last_arg = tok->buffer + tok->argp[tok->argc - 1];
if (last_arg[0] == '{' && last_arg[strlen(last_arg)-1] == '}')
......@@ -1354,6 +1366,9 @@ imap4d_readline (struct imap4d_tokbuf *tok)
char *buf;
size_t len;
if (transcript)
mu_diag_output (MU_DIAG_DEBUG, "(literal follows)");
transcript = 0;
number = strtoul (last_arg + 1, &sp, 10);
/* Client can ask for non-synchronised literal,
if a '+' is appended to the octet count. */
......@@ -1364,7 +1379,16 @@ imap4d_readline (struct imap4d_tokbuf *tok)
imap4d_tokbuf_expand (tok, number + 1);
off = tok->level;
buf = tok->buffer + off;
rc = mu_stream_sequential_read (istream, buf, number, &len);
len = 0;
while (len < number)
{
size_t sz;
rc = mu_stream_sequential_read (istream,
buf + len, number - len, &sz);
if (rc || sz == 0)
break;
len += sz;
}
check_input_err (rc, len);
len = remove_cr (buf, len);
imap4d_tokbuf_unquote (tok, &off, &len);
......@@ -1403,6 +1427,8 @@ imap4d_getline (char **pbuf, size_t *psize, size_t *pnbytes)
s[--len] = 0;
if (s && len > 0 && s[len - 1] == '\r')
s[--len] = 0;
if (imap4d_transcript)
mu_diag_output (MU_DIAG_DEBUG, "recv: %s", s);
if (pnbytes)
*pnbytes = len;
}
......
......@@ -102,8 +102,8 @@ rfc822_readline (mu_filter_t filter, char *buffer, size_t buflen,
}
/* RFC 822 converter "\n" --> "\r\n"
We maintain to offset, the rfc822 offset (r_offset) and the offset of
the stream (s_offset). If they do not match we go back as for as possible
We maintain two offsets, the rfc822 offset (r_offset) and the offset of
the stream (s_offset). If they do not match we go back as far as possible
and start to read by 1 'till we reach the current offset. */
static int
......@@ -118,7 +118,7 @@ rfc822_read0 (mu_filter_t filter, char *buffer, size_t buflen,
if (rfc822->r_offset != off)
{
rfc822->residue = 0;
/* Try to find a starting point. */
if (rfc822->lines)
{
......@@ -162,7 +162,7 @@ rfc822_read0 (mu_filter_t filter, char *buffer, size_t buflen,
{
size_t nread = 0;
status = mu_stream_readline (filter->stream, buffer, buflen,
rfc822->s_offset, &nread);
rfc822->s_offset, &nread);
if (status != 0)
return status;
if (nread == 0)
......