Commit 4290bdcd 4290bdcd312193ffedb77bcd9811b584db2a2529 by Alain Magloire

mbx_mbox.c mbx_mboxscan.c : I need to clean the expunge code

I realise that MBOX format means that we also have to escapes lines
that starting with "From " --> ">From ". So much for speed since
this will imply reading line by line.

mbx_pop.c : Some bug fixes, connection is close down if the client
is trying to seek() backward.

folder_imap.c mbx_imap.c : Unfinish business, but getting better.

stream.c : Don't force a flush on close, let the underlying implementatio
do that.
1 parent fb62000f
......@@ -23,6 +23,7 @@
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <mailutils/address.h>
#include <mailbox0.h>
......@@ -83,6 +84,13 @@ static int message_operation (f_imap_t, msg_imap_t, enum imap_state, char *,
size_t, size_t *);
static void free_subparts (msg_imap_t);
static const char *MONTHS[] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
/* Initialize the concrete object mailbox_t by overloading the function of the
structure. */
int
......@@ -890,6 +898,12 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen,
msg_imap_t msg_imap = message_get_owner (msg);
m_imap_t m_imap = msg_imap->m_imap;
f_imap_t f_imap = m_imap->f_imap;
int year, mon, day, hour, min, sec;
int offt;
int i;
struct tm tm;
time_t now;
char month[5];
int status;
if (f_imap->state == IMAP_NO_STATE)
{
......@@ -904,7 +918,44 @@ 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;
}
return message_operation (f_imap, msg_imap, 0, buffer, buflen, plen);
status = message_operation (f_imap, msg_imap, 0, buffer, buflen, plen);
if (status != 0)
return status;
day = mon = year = hour = min = sec = offt = 0;
month[0] = '\0';
sscanf (buffer, "%2d-%3s-%4d %2d:%2d:%2d %d", &day, month, &year,
&hour, &min, &sec, &offt);
tm.tm_sec = sec;
tm.tm_min = min;
tm.tm_hour = hour;
tm.tm_mday = day;
for (i = 0; i < 12; i++)
{
if (strncasecmp(month, MONTHS[i], 3) == 0)
{
mon = i;
break;
}
}
tm.tm_mon = mon;
tm.tm_year = (year > 1900) ? year - 1900 : year;
tm.tm_yday = 0; /* unknown. */
tm.tm_wday = 0; /* unknown. */
tm.tm_isdst = -1; /* unknown. */
/* What to do the timezone? */
now = mktime (&tm);
if (now == (time_t)-1)
{
/* Fall back to localtime. */
now = time (NULL);
snprintf (buffer, buflen, "%s", ctime(&now));
}
else
{
strftime (buffer, buflen, " %a %b %d %H:%M:%S %Y", &tm);
}
return 0;
}
/* Attributes. */
......@@ -1131,6 +1182,7 @@ imap_body_lines (body_t body, size_t *plines)
return 0;
}
/* FIXME: Send EISPIPE if trying to seek back. */
static int
imap_body_read (stream_t stream, char *buffer, size_t buflen, off_t offset,
size_t *plen)
......@@ -1144,11 +1196,12 @@ imap_body_read (stream_t stream, char *buffer, size_t buflen, off_t offset,
char newbuf[2];
int status = 0;
/* This so F*$&#g annoying, a buffer len of 1 is a killer.
If you have for example "\n", IMAP servers will transform
this to "\r\n" and since you ask for only 1 sends '\r' only.
'\r' will be stripped and the number of char read will be 0
which means we're done. So we guard to at least ask for 2 chars. */
/* This is so annoying, a buffer len of 1 is a killer. If you have for
example "\n" to retrieve from the server, IMAP will transform this to
"\r\n" and since you ask for only 1, the server will send '\r' only.
And ... '\r' will be stripped by (imap_readline()) the number of char
read will be 0 which means we're done .... sigh ... So we guard to at
least ask for 2 chars. */
if (buflen == 1)
{
oldbuf = buffer;
......@@ -1161,8 +1214,8 @@ imap_body_read (stream_t stream, char *buffer, size_t buflen, off_t offset,
status = imap_messages_count (m_imap->mailbox, NULL);
if (status != 0)
return status;
/* We strip the \r, but the offset/size on the imap server is with that
octet so add it in the offset, since it's the number of lines. */
/* We strip the \r, but the offset/size on the imap server is with the
octet, so add it since it's the number of lines. */
if (msg_imap->part)
{
char *section = section_name (msg_imap);
......
......@@ -1255,7 +1255,7 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg)
if (pmsg == NULL || mud == NULL)
return EINVAL;
/* We did not start a scanning yet do it now. */
/* If we did not start a scanning yet do it now. */
if (mud->messages_count == 0)
{
status = mbox_scan0 (mailbox, 1, NULL, 0);
......@@ -1397,8 +1397,8 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
return 0;
}
/* FIXME: We need to escape line body line that begins with "From ", this
will required to read the body by line instead of by chuncks hearting
/* FIXME: We need to escape body line that begins with "From ", this
will required to read the body by line instead of by chuncks hurting
perfomance big time when expunging. But should not this be the
responsability of the client ? */
static int
......@@ -1734,6 +1734,13 @@ mbox_messages_recent (mailbox_t mailbox, size_t *pcount)
mbox_message_t mum;
size_t j, recent;
/* If we did not start a scanning yet do it now. */
if (mud->messages_count == 0)
{
int status = mbox_scan0 (mailbox, 1, NULL, 0);
if (status != 0)
return status;
}
for (recent = j = 0; j < mud->messages_count; j++)
{
mum = mud->umessages[j];
......@@ -1753,6 +1760,13 @@ mbox_message_unseen (mailbox_t mailbox, size_t *pmsgno)
mbox_message_t mum;
size_t j, unseen;
/* If we did not start a scanning yet do it now. */
if (mud->messages_count == 0)
{
int status = mbox_scan0 (mailbox, 1, NULL, 0);
if (status != 0)
return status;
}
for (unseen = j = 0; j < mud->messages_count; j++)
{
mum = mud->umessages[j];
......@@ -1775,6 +1789,13 @@ mbox_uidvalidity (mailbox_t mailbox, unsigned long *puidvalidity)
int status = mbox_messages_count (mailbox, NULL);
if (status != 0)
return status;
/* If we did not start a scanning yet do it now. */
if (mud->messages_count == 0)
{
status = mbox_scan0 (mailbox, 1, NULL, 0);
if (status != 0)
return status;
}
if (puidvalidity)
*puidvalidity = mud->uidvalidity;
return 0;
......@@ -1787,6 +1808,13 @@ mbox_uidnext (mailbox_t mailbox, size_t *puidnext)
int status = mbox_messages_count (mailbox, NULL);
if (status != 0)
return status;
/* If we did not start a scanning yet do it now. */
if (mud->messages_count == 0)
{
status = mbox_scan0 (mailbox, 1, NULL, 0);
if (status != 0)
return status;
}
if (puidnext)
*puidnext = mud->uidnext;
return 0;
......
......@@ -643,7 +643,8 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif)
mum->mud = mud;
mum->header_from = total - n;
mum->header_from_end = total;
//mum->body_end = mum->body = 0;
mum->body_end = mum->body = 0;
mum->attr_flags = 0;
lines = 0;
sfield = NULL;
for (j = 0; j < HDRSIZE; j++)
......
......@@ -395,12 +395,13 @@ pop_user (authority_t auth)
CHECK_ERROR_CLOSE (mbox, mpd, EINVAL);
}
status = pop_writeline (mpd, "PASS %s\r\n", mpd->passwd);
MAILBOX_DEBUG0 (mbox, MU_DEBUG_PROT, mpd->buffer);
/* We have to nuke the passwd. */
memset (mpd->passwd, '\0', strlen (mpd->passwd));
free (mpd->passwd);
mpd->passwd = NULL;
CHECK_ERROR_CLOSE (mbox, mpd, status);
MAILBOX_DEBUG0 (mbox, MU_DEBUG_PROT, "PASS *\n");
//MAILBOX_DEBUG0 (mbox, MU_DEBUG_PROT, "PASS *\n");
mpd->state = POP_AUTH_PASS;
case POP_AUTH_PASS:
......@@ -908,8 +909,14 @@ pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount)
if (mbox->observable == NULL)
return 0;
for (i = msgno; i <= count; i++)
if (observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD) != 0)
break;
{
if (observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD) != 0)
break;
if (((i +1) % 10) == 0)
{
observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS);
}
}
return 0;
}
......@@ -1306,6 +1313,9 @@ pop_top (header_t header, char *buffer, size_t buflen,
mpd = mpm->mpd;
/* Busy ? */
CHECK_BUSY (mpd->mbox, mpd, func, msg);
/* We start fresh then reset the sizes. */
if (mpd->state == POP_NO_STATE)
mpm->header_size = 0;
......@@ -1314,9 +1324,6 @@ pop_top (header_t header, char *buffer, size_t buflen,
if ((size_t)offset < mpm->header_size)
return ESPIPE;
/* Busy ? */
CHECK_BUSY (mpd->mbox, mpd, func, msg);
/* Get the header. */
switch (mpd->state)
{
......@@ -1408,17 +1415,17 @@ pop_header_read (header_t header, char *buffer, size_t buflen, off_t offset,
mpd = mpm->mpd;
/* Busy ? */
CHECK_BUSY (mpd->mbox, mpd, func, msg);
/* We start fresh then reset the sizes. */
if (mpd->state == POP_NO_STATE)
mpm->header_size = 0;
mpm->header_size = mpm->inbody = 0;
/* Throw an error if trying to seek back. */
if ((size_t)offset < mpm->header_size)
return ESPIPE;
/* Busy ? */
CHECK_BUSY (mpd->mbox, mpd, func, msg);
mpm->skip_header = 0;
mpm->skip_body = 1;
return pop_retr (mpm, buffer, buflen, offset, pnread);
......@@ -1441,17 +1448,17 @@ pop_body_read (stream_t is, char *buffer, size_t buflen, off_t offset,
mpd = mpm->mpd;
/* Busy ? */
CHECK_BUSY (mpd->mbox, mpd, func, msg);
/* We start fresh then reset the sizes. */
if (mpd->state == POP_NO_STATE)
mpm->body_size = 0;
mpm->body_size = mpm->inbody = 0;
/* Can not seek back this a stream socket. */
if ((size_t)offset < mpm->body_size)
return ESPIPE;
/* Busy ? */
CHECK_BUSY (mpd->mbox, mpd, func, msg);
mpm->skip_header = 1;
mpm->skip_body = 0;
return pop_retr (mpm, buffer, buflen, offset, pnread);
......@@ -1472,17 +1479,17 @@ pop_message_read (stream_t is, char *buffer, size_t buflen, off_t offset,
mpd = mpm->mpd;
/* Busy ? */
CHECK_BUSY (mpd->mbox, mpd, func, msg);
/* We start fresh then reset the sizes. */
if (mpd->state == POP_NO_STATE)
mpm->header_size = mpm->body_size = 0;
mpm->header_size = mpm->body_size = mpm->inbody = 0;
/* Can not seek back this is a stream socket. */
if ((size_t)offset < (mpm->body_size + mpm->header_size))
return ESPIPE;
/* Busy ? */
CHECK_BUSY (mpd->mbox, mpd, func, msg);
mpm->skip_header = mpm->skip_body = 0;
return pop_retr (mpm, buffer, buflen, offset, pnread);
}
......
......@@ -102,8 +102,6 @@ stream_close (stream_t stream)
{
if (stream == NULL)
return EINVAL;
/* Make sure the writes were flush. */
stream_flush (stream);
stream->state = MU_STREAM_STATE_CLOSE;
/* Clear the buffer of any residue left. */
if (stream->rbuffer.base)
......