Commit ed1175f9 ed1175f91d78846077062af5cf8a969dbaff80a6 by Alain Magloire

* mail/mail.c: Possibility to enable debuging output.

	It should probably be a runtime option via set debug=1 or something
	for now it is disable between if (0) {...}.

	More cleanup in the IMAP code.  A memory stream buffer is
	use to save the string literal sended by the IMAP server.
	The allocation is handle by the memory_stream which simplifies
	the code.

	* folder_imap.c (folder_imap.c): Create a memory stream to
	hold the literal or quoted string send by the IMAP server.
	(folder_imap_list folder_imap_lsub): There is no callback
	field the struct folder_list is in struct _f_imap now.
	(imap_literal_string imap_quoted_string imap_string):  Use the
	memory string stream to save the result.
	(imap_body): Still need to be clean, but creates the cache
	header when doing the scan.
	(imap_parse): Do not use alloca().
1 parent a59f00d4
2001-10-13 Jeff Bailey <jbailey@outpost.dnsalias.org>
2001-10-13 Alain Malgoire
* mail/mail.c: Possibility to enable debuging output.
It should probably be a runtime option via set debug=1 or something
for now it is disable between if (0) {...}.
More cleanup in the IMAP code. A memory stream buffer is
use to save the string literal sended by the IMAP server.
The allocation is handle by the memory_stream which simplifies
the code.
* folder_imap.c (folder_imap.c): Create a memory stream to
hold the literal or quoted string send by the IMAP server.
(folder_imap_list folder_imap_lsub): There is no callback
field the struct folder_list is in struct _f_imap now.
(imap_literal_string imap_quoted_string imap_string): Use the
memory string stream to save the result.
(imap_body): Still need to be clean, but creates the cache
header when doing the scan.
(imap_parse): Do not use alloca().
2001-10-13 Jeff Bailey
* guimb/Makefile.am: Remove GNU Makeism.
* libmu_scm/Makefile.am: Remove GNU Makeism.
2001-10-12 Jeff Bailey <jbailey@outpost.dnsalias.org>
2001-10-12 Jeff Bailey
* libmu_scm/Makefile.am: Fixes for RO srcdir.
......
......@@ -345,6 +345,14 @@ main (int argc, char **argv)
exit (EXIT_FAILURE);
}
/* Could we enable this at runtime, via the a set environment? */
if (0)
{
mu_debug_t debug = NULL;
mailbox_get_debug (mbox, &debug);
mu_debug_set_level (debug, MU_DEBUG_TRACE|MU_DEBUG_PROT);
}
if (mailbox_open (mbox, MU_STREAM_RDWR) != 0)
{
util_error ("Can not open mailbox");
......
......@@ -140,10 +140,24 @@ struct _f_imap
size_t seq; /* Sequence number to build a tag. */
char *capa; /* Cabilities of the server. */
size_t flags;
struct literal_string callback;
/* IO use to hold the literal and quoted strings send by
the IMAP server. */
struct
{
stream_t stream;
off_t offset;
size_t nleft; /* nleft to read in the literal. */
msg_imap_t msg_imap;
enum imap_state type;
} string;
/* Use for LIST and LSUB. */
struct folder_list flist;
int isopen;
/* Buffer I/O */
/* Server channel buffer I/O */
size_t buflen;
char *buffer;
char *ptr;
......@@ -155,7 +169,6 @@ struct _f_imap
/* Login */
char *user;
char *passwd;
};
struct _m_imap
......@@ -187,6 +200,7 @@ struct _msg_imap
size_t uid;
header_t fheader;
char *internal_date;
size_t message_size;
size_t message_lines;
......
......@@ -174,6 +174,8 @@ free_subparts (msg_imap_t msg_imap)
free (msg_imap->parts);
if (msg_imap->fheader)
header_destroy (&msg_imap->fheader, NULL);
if (msg_imap->internal_date)
free (msg_imap->internal_date);
free(msg_imap);
}
......@@ -672,9 +674,15 @@ imap_expunge (mailbox_t mailbox)
{
case IMAP_NO_STATE:
{
char *set;
char *set = NULL;
status = delete_to_string (m_imap, &set);
CHECK_ERROR (f_imap, status);
if (set == NULL || *set == '\0')
{
if (set)
free (set);
return 0;
}
status = imap_writeline (f_imap,
"g%d STORE %s +FLAGS.SILENT (\\Deleted)\r\n",
f_imap->seq++, set);
......@@ -1224,6 +1232,9 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen,
const char** datep = &date;
/* reserve as much space as we need for internal-date */
int status;
if (msg_imap->internal_date == NULL)
{
if (f_imap->state == IMAP_NO_STATE)
{
/* Select first. */
......@@ -1237,9 +1248,17 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen,
MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer);
f_imap->state = IMAP_FETCH;
}
status = fetch_operation (f_imap, msg_imap, datebuf, sizeof datebuf, NULL);
status = fetch_operation (f_imap, msg_imap, datebuf,
sizeof datebuf, NULL);
if (status != 0)
return status;
msg_imap->internal_date = strdup (datebuf);
}
else
{
date = msg_imap->internal_date;
datep = &date;
}
if (mu_parse_imap_date_time(datep, &tm, &tz) != 0)
now = (time_t)-1;
......@@ -1323,6 +1342,10 @@ imap_attr_set_flags (attribute_t attribute, int flag)
f_imap_t f_imap = m_imap->f_imap;
int status = 0;
/* If already set don't bother. */
if (msg_imap->flags & flag)
return 0;
/* The delete FLAG is not pass yet but only on the expunge. */
if (flag & MU_ATTRIBUTE_DELETED)
{
......@@ -1705,13 +1728,11 @@ fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer,
case IMAP_FETCH:
status = imap_send (f_imap);
CHECK_EAGAIN (f_imap, status);
if (f_imap->callback.buffer)
free (f_imap->callback.buffer);
f_imap->callback.buffer = NULL;
f_imap->callback.buflen = 0;
f_imap->callback.total = 0;
f_imap->callback.nleft = 0;
f_imap->callback.msg_imap = msg_imap;
stream_truncate (f_imap->string.stream, 0);
f_imap->string.offset = 0;
f_imap->string.nleft = 0;
f_imap->string.type = IMAP_NO_STATE;
f_imap->string.msg_imap = msg_imap;
f_imap->state = IMAP_FETCH_ACK;
case IMAP_FETCH_ACK:
......@@ -1725,25 +1746,21 @@ fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer,
break;
}
if (status == 0 && f_imap->isopen == 0 && f_imap->callback.total == 0)
f_imap->state = IMAP_NO_STATE;
/* The server may have timeout any case connection is gone away. */
if (status == 0 && f_imap->isopen == 0 && f_imap->string.offset == 0)
status = EBADF;
buflen = min (buflen, f_imap->callback.total);
if (f_imap->callback.buffer)
{
if (buffer)
memcpy (buffer, f_imap->callback.buffer, buflen);
free (f_imap->callback.buffer);
}
if (plen)
*plen = buflen;
f_imap->callback.buffer = NULL;
f_imap->callback.buflen = 0;
f_imap->callback.total = 0;
f_imap->callback.nleft = 0;
f_imap->callback.type = 0;
f_imap->callback.msg_imap = NULL;
f_imap->state = IMAP_NO_STATE;
stream_read (f_imap->string.stream, buffer, buflen, 0, plen);
else if (plen)
*plen = 0;
stream_truncate (f_imap->string.stream, 0);
f_imap->string.offset = 0;
f_imap->string.nleft = 0;
f_imap->string.type = IMAP_NO_STATE;
f_imap->string.msg_imap = NULL;
return status;
}
......
......@@ -22,15 +22,24 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <mailutils/stream.h>
#undef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#define MU_STREAM_MEMORY_BLOCKSIZE 128
struct _memory_stream
{
char *ptr;
size_t size;
size_t capacity;
};
static void
......@@ -71,7 +80,7 @@ _memory_readline (stream_t stream, char *optr, size_t osize,
osize--;
nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset);
n = (nl) ? (size_t)(nl - (mfs->ptr + offset) + 1) : mfs->size - offset;
n = (n > osize) ? osize : n;
n = min (n, osize);
memcpy (optr, mfs->ptr + offset, n);
optr[n] = '\0';
}
......@@ -87,13 +96,17 @@ _memory_write (stream_t stream, const char *iptr, size_t isize,
struct _memory_stream *mfs = stream_get_owner (stream);
/* Bigger we have to realloc. */
if (mfs->size < (offset + isize))
if (mfs->capacity < (offset + isize))
{
char *tmp = realloc (mfs->ptr, offset + isize);
/* Realloc by fixed blocks of 128. */
int newsize = MU_STREAM_MEMORY_BLOCKSIZE *
(((offset + isize)/MU_STREAM_MEMORY_BLOCKSIZE) + 1);
char *tmp = realloc (mfs->ptr, newsize);
if (tmp == NULL)
return ENOMEM;
mfs->ptr = tmp;
mfs->size = offset + isize;
mfs->capacity = newsize;
}
memcpy (mfs->ptr + offset, iptr, isize);
......@@ -109,6 +122,7 @@ _memory_truncate (stream_t stream, off_t len)
if (len == 0)
{
if (mfs->ptr)
free (mfs->ptr);
mfs->ptr = NULL;
}
......@@ -120,6 +134,7 @@ _memory_truncate (stream_t stream, off_t len)
mfs->ptr = tmp;
}
mfs->size = len;
mfs->capacity = len;
return 0;
}
......@@ -137,11 +152,10 @@ _memory_close (stream_t stream)
{
struct _memory_stream *mfs = stream_get_owner (stream);
if (mfs->ptr)
{
free (mfs->ptr);
mfs->ptr = NULL;
mfs->size = 0;
}
mfs->capacity = 0;
return 0;
}
......@@ -149,6 +163,7 @@ static int
_memory_open (stream_t stream, const char *filename, int port, int flags)
{
struct _memory_stream *mfs = stream_get_owner (stream);
int status = 0;
(void)port; /* Ignored. */
(void)filename; /* Ignored. */
......@@ -156,13 +171,47 @@ _memory_open (stream_t stream, const char *filename, int port, int flags)
/* Close any previous file. */
if (mfs->ptr)
free (mfs->ptr);
mfs->ptr = NULL;
mfs->size = 0;
mfs->capacity = 0;
stream_set_flags (stream, flags |MU_STREAM_NO_CHECK);
if (filename)
{
struct stat statbuf;
if (stat (filename, &statbuf) == 0)
{
mfs->ptr = calloc (statbuf.st_size, 1);
if (mfs->ptr)
{
FILE *fp;
mfs->capacity = statbuf.st_size;
mfs->size = statbuf.st_size;
fp = fopen (filename, "r");
if (fp)
{
size_t r = fread (mfs->ptr, mfs->size, 1, fp);
if (r != mfs->size)
status = EIO;
fclose (fp);
}
else
status = errno;
if (status != 0)
{
free (mfs->ptr);
mfs->ptr = NULL;
mfs->capacity = 0;
mfs->size = 0;
}
stream_set_flags (stream, flags |MU_STREAM_NO_CHECK);
return 0;
}
else
status = ENOMEM;
}
else
status = EIO;
}
return status;
}
int
......
......@@ -60,8 +60,7 @@ _stream_memory_read (stream_t stream, void *optr, size_t osize,
mu_refcount_lock (mem->refcount);
if (mem->ptr != NULL && (offset < (off_t)mem->size))
{
n = ((offset + osize) > mem->size) ?
mem->size - offset : osize;
n = ((offset + osize) > mem->size) ? mem->size - offset : osize;
memcpy (optr, mem->ptr + offset, n);
}
mu_refcount_unlock (mem->refcount);
......@@ -130,6 +129,7 @@ _stream_memory_truncate (stream_t stream, off_t len)
mu_refcount_lock (mem->refcount);
if (len == 0)
{
if (mem->ptr)
free (mem->ptr);
mem->ptr = NULL;
}
......