Commit 5188cb9d 5188cb9dcb8526f3b7d41ab88dca25b9b045743c by Alain Magloire

ChangeLog: Update.

doc/mailbox.texi: ?
imap4d/fetch.c: Cool!  Things are finally falling in place for the
fetch, pieces missing:  bodystructures, body[header.fields],
body[header.fields.not].  I need to find a way to cleanly check the
spacing, I got things like:
* FETCH 1 ( FLAGS ( \Read \Seen ))
Which is compliant but too many spaces at the compliant it should be
* FETCH 1 (FLAGS (\Read \Seen ))
imap4d/imap4d.h imap4d/util.c : New helper function util_token().
mailbox/mbx_imap.c : getting the size of the subparts from the bodystructure.
1 parent c9b8e345
2001-02-26 Alain Magloire
* mailbox/mbx_imap.c (imap_submessage_size) : New function to
retrieve message size of attachments.
* imap4d/fetch.c : More functionnality for the FETCH command.
(fetch_operation) : New operation.
* imap4d/util.c (util_token) : little helper function.
2001-02-25 Alain Magloire
* lib/strtok_r.c : If there are no delimiters left save the old string
......
......@@ -18,7 +18,7 @@
#include "imap4d.h"
/* This will suck, too.
Alain: Yest it does. */
Alain: Yes it does. */
/* Taken from RFC2060
fetch ::= "FETCH" SPACE set SPACE ("ALL" / "FULL" /
......@@ -46,6 +46,8 @@ static int fetch_body_peek (struct imap4d_command *, char*);
static int fetch_body (struct imap4d_command *, char*);
static int fetch_uid (struct imap4d_command *, char*);
static int fetch_operation (size_t, char *);
struct imap4d_command fetch_command_table [] =
{
#define F_ALL 0
......@@ -79,48 +81,44 @@ struct imap4d_command fetch_command_table [] =
{ 0, 0},
};
/* NOTE: the states field in the command structure is use to as a place
holder for the message number. */
int
imap4d_fetch (struct imap4d_command *command, char *arg)
{
char *sp = NULL;
char *msgset;
int *set = NULL;
char *item;
int i, n = 0;
int rc = RESP_OK;
int status;
const char *errmsg = "Completed";
struct imap4d_command *fcmd;
char item[32];
msgset = util_getword (arg, &sp);
if (!msgset)
return util_finish (command, RESP_BAD, "Too few args");
item = strchr (sp, '[');
if (item)
{
char *s = alloca (item - sp + 1);
memcpy (s, sp, item - sp);
s[item - sp] = '\0';
arg = item;
item = s;
}
else
arg = item = sp;
/* Get the command name. */
item[0] = '\0';
util_token (item, sizeof (item), &sp);
/* Search in the table. */
fcmd = util_getcommand (item, fetch_command_table);
if (!fcmd)
return util_finish (command, RESP_BAD, "Command unknown");
/* Get the message numbers in set[]. */
status = util_msgset (msgset, &set, &n, 0);
if (status != 0)
return util_finish (command, RESP_BAD, "Bogus number set");
/* We use the states to hold the msgno/uid. */
for (i = 0; i < n; i++)
{
/* We use the states field to hold the msgno/uid. */
fcmd->states = set[i];
util_send ("* FETCH %d (%s", set[i], command->name);
util_send ("* FETCH %d (", set[i]);
fcmd->func (fcmd, sp);
util_send (")\r\n");
}
......@@ -128,8 +126,7 @@ imap4d_fetch (struct imap4d_command *command, char *arg)
return util_finish (command, rc, errmsg);
}
/* --------------- Fetch commands definition ----- */
/* Combination of (FAST ENVELOPE). */
static int
fetch_all (struct imap4d_command *command, char *arg)
{
......@@ -140,6 +137,7 @@ fetch_all (struct imap4d_command *command, char *arg)
return 0;
}
/* Combination of (ALL BODY). */
static int
fetch_full (struct imap4d_command *command, char *arg)
{
......@@ -150,6 +148,7 @@ fetch_full (struct imap4d_command *command, char *arg)
return 0;
}
/* Combination of (FLAGS INTERNALDATE RFC822.SIZE). */
static int
fetch_fast (struct imap4d_command *command, char *arg)
{
......@@ -165,6 +164,8 @@ fetch_fast (struct imap4d_command *command, char *arg)
return 0;
}
/* Header: Date, Subject, From, Sender, Reply-To, To, Cc, Bcc, In-Reply-To,
and Message-Id. */
/* FIXME, FIXME:
- incorrect DATE
- address not the correct format
......@@ -183,6 +184,7 @@ fetch_envelope (struct imap4d_command *command, char *arg)
message_get_header (msg, &header);
util_send (" %s", command->name);
/* FIXME: Incorrect Date. */
status = header_get_value (header, "Date", buffer, sizeof (buffer), NULL);
if (status != 0)
util_send (" NIL");
......@@ -238,6 +240,8 @@ fetch_envelope (struct imap4d_command *command, char *arg)
return 0;
}
/* The flags that are set for this message. */
/* FIXME: User flags not done. */
static int
fetch_flags (struct imap4d_command *command, char *arg)
{
......@@ -259,6 +263,8 @@ fetch_flags (struct imap4d_command *command, char *arg)
return 0;
}
/* The internal date of the message. */
/* FIXME: Wrong format. */
static int
fetch_internaldate (struct imap4d_command *command, char *arg)
{
......@@ -276,17 +282,35 @@ fetch_internaldate (struct imap4d_command *command, char *arg)
return 0;
}
/* Equivalent to BODY.PEEK[HEADER]. */
static int
fetch_rfc822_header (struct imap4d_command *command, char *arg)
{
char buffer[64];
struct imap4d_command c_body_p = fetch_command_table[F_BODY_PEEK];
c_body_p.states = command->states;
char buffer[16];
util_send (" %s", command->name);
strcpy (buffer, "[HEADER]");
fetch_body_peek (&c_body_p, buffer);
fetch_operation (command->states, buffer);
return 0;
}
/* Equivalent to BODY[TEXT]. */
/* FIXME: send a Fetch flag if the mail was not set seen ? */
static int
fetch_rfc822_text (struct imap4d_command *command, char *arg)
{
char buffer[16];
attribute_t attr = NULL;
message_t msg = NULL;
mailbox_get_message (mbox, command->states, &msg);
message_get_attribute (msg, &attr);
attribute_set_read (attr);
util_send (" %s", command->name);
strcpy (buffer, "[TEXT]");
fetch_operation (command->states, buffer);
return 0;
}
/* The [RFC-822] size of the message. */
static int
fetch_rfc822_size (struct imap4d_command *command, char *arg)
{
......@@ -296,31 +320,60 @@ fetch_rfc822_size (struct imap4d_command *command, char *arg)
mailbox_get_message (mbox, command->states, &msg);
message_size (msg, &size);
message_lines (msg, &lines);
util_send (" %s", command->name);
util_send (" %u", size + lines);
util_send (" %s %u", command->name, size + lines);
return 0;
}
/* Equivalent to BODY[]. */
/* FIXME: send a Fetch flag if the mail was not set seen ? */
static int
fetch_rfc822_text (struct imap4d_command *command, char *arg)
fetch_rfc822 (struct imap4d_command *command, char *arg)
{
char buffer[64];
struct imap4d_command c_body = fetch_command_table[F_BODY];
c_body.states = command->states;
strcpy (buffer, "[TEXT]");
fetch_body (&c_body, buffer);
if (*arg == '.')
{
if (strcasecmp (arg, ".SIZE") == 0)
{
struct imap4d_command c_rfc= fetch_command_table[F_RFC822_SIZE];
c_rfc.states = command->states;
fetch_rfc822_size (&c_rfc, arg);
}
else if (strcasecmp (arg, ".TEXT") == 0)
{
struct imap4d_command c_rfc = fetch_command_table[F_RFC822_TEXT];
c_rfc.states = command->states;
fetch_rfc822_text (&c_rfc, arg);
}
else if (strcasecmp (arg, ".HEADER") == 0)
{
struct imap4d_command c_rfc = fetch_command_table[F_RFC822_HEADER];
c_rfc.states = command->states;
fetch_rfc822_header (&c_rfc, arg);
}
}
else
{
char buffer[16];
attribute_t attr = NULL;
message_t msg = NULL;
mailbox_get_message (mbox, command->states, &msg);
message_get_attribute (msg, &attr);
attribute_set_read (attr);
util_send (" %s", command->name);
strcpy (buffer, "[]");
fetch_operation (command->states, buffer);
}
return 0;
}
/* The unique identifier for the message. */
static int
fetch_rfc822 (struct imap4d_command *command, char *arg)
fetch_uid (struct imap4d_command *command, char *arg)
{
char buffer[64];
struct imap4d_command c_body = fetch_command_table[F_BODY];
c_body.states = command->states;
strcpy (buffer, "[]");
fetch_body (&c_body, buffer);
size_t uid = 0;
message_t msg = NULL;
mailbox_get_message (mbox, command->states, &msg);
message_get_uid (msg, &uid);
util_send (" %s %d", command->name, uid);
return 0;
}
......@@ -328,43 +381,57 @@ fetch_rfc822 (struct imap4d_command *command, char *arg)
static int
fetch_bodystructure (struct imap4d_command *command, char *arg)
{
util_send (" %s ()", command->name);
return 0;
}
/* An alternate form of BODY that does not implicitly set the \Seen flag. */
static int
fetch_body_peek (struct imap4d_command *command, char *arg)
{
struct imap4d_command c_body = fetch_command_table[F_BODY];
c_body.states = command->states;
return fetch_body (&c_body, arg);
}
/* FIXME: send notificaton if seen attribute is set? */
/* FIXME: partial offset not done. */
/* FIXME: HEADER.FIELDS not done. */
/* FIXME: HEADER.FIELDS.NOT not done. */
static int
fetch_body (struct imap4d_command *command, char *arg)
{
struct imap4d_command c_body_p = fetch_command_table[F_BODY_PEEK];
util_send (" %s", command->name);
if (strcasecmp (arg, ".PEEK") == 0)
{
arg += strlen (".PEEK");
}
else if (*arg == '[')
{
attribute_t attr = NULL;
message_t msg = NULL;
struct imap4d_command c_body_p = fetch_command_table[F_BODY_PEEK];
mailbox_get_message (mbox, command->states, &msg);
message_get_attribute (msg, &attr);
c_body_p.states = command->states;
fetch_body_peek (&c_body_p, arg);
attribute_set_seen (attr);
return 0;
}
}
else if (*arg != '[' && *arg != '.')
{
struct imap4d_command c_bs = fetch_command_table[F_BODYSTRUCTURE];
c_bs.states = command->states;
return fetch_bodystructure (&c_bs, arg);
}
static int
fetch_uid (struct imap4d_command *command, char *arg)
{
size_t uid = 0;
message_t msg = NULL;
mailbox_get_message (mbox, command->states, &msg);
message_get_uid (msg, &uid);
util_send (" %s %d", command->name, uid);
fetch_operation (command->states, arg);
return 0;
}
static int
fetch_body_peek (struct imap4d_command *command, char *arg)
fetch_operation (size_t msgno, char *arg)
{
message_t msg = NULL;
//char *partial = strchr (arg, '<');
mailbox_get_message (mbox, command->states, &msg);
util_send (" %s", command->name);
message_t msg = NULL;
mailbox_get_message (mbox, msgno, &msg);
if (strncasecmp (arg, "[]", 2) == 0)
{
......@@ -375,7 +442,7 @@ fetch_body_peek (struct imap4d_command *command, char *arg)
message_get_stream (msg, &stream);
message_size (msg, &size);
message_size (msg, &lines);
util_send (" BODY[] {%u}\r\n", size + lines);
util_send ("{%u}\r\n", size + lines);
while (stream_readline (stream, buffer, sizeof (buffer), off, &n) == 0
&& n > 0)
{
......@@ -396,7 +463,7 @@ fetch_body_peek (struct imap4d_command *command, char *arg)
message_get_header (msg, &header);
header_size (header, &size);
header_lines (header, &lines);
util_send (" BODY[HEADER] {%u}\r\n", size + lines);
util_send ("{%u}\r\n", size + lines);
header_get_stream (header, &stream);
while (stream_readline (stream, buffer, sizeof (buffer), off, &n) == 0
&& n > 0)
......@@ -408,6 +475,14 @@ fetch_body_peek (struct imap4d_command *command, char *arg)
off += n;
}
}
else if (strncasecmp (arg, "[HEADER.FIELDS.NOT", 19) == 0)
{
/* Not implemented. */
}
else if (strncasecmp (arg, "[HEADER.FIELDS", 15) == 0)
{
/* Not implemented. */
}
else if (strncasecmp (arg, "[TEXT]", 6) == 0)
{
body_t body = NULL;
......@@ -418,7 +493,7 @@ fetch_body_peek (struct imap4d_command *command, char *arg)
message_get_body (msg, &body);
body_size (body, &size);
body_lines (body, &lines);
util_send (" BODY[TEXT] {%u}\r\n", size + lines);
util_send ("{%u}\r\n", size + lines);
body_get_stream (body, &stream);
while (stream_readline (stream, buffer, sizeof (buffer), off, &n) == 0
&& n > 0)
......@@ -430,7 +505,6 @@ fetch_body_peek (struct imap4d_command *command, char *arg)
off += n;
}
}
else
util_send (" Not supported");
/* else util_send (" Not supported"); */
return 0;
}
......
......@@ -130,6 +130,7 @@ int util_do_command __P ((char *prompt));
char *imap4d_readline __P ((int fd));
void util_quit __P ((int));
char *util_getword __P ((char *s, char **save_ptr));
int util_token __P ((char *s, size_t, char **save_ptr));
int util_msgset __P ((char *s, int **set, int *n, int isuid));
struct imap4d_command *util_getcommand __P ((char *cmd,
struct imap4d_command []));
......
......@@ -28,6 +28,35 @@ util_getword (char *s, char **save)
return strtok_r (s, " \r\n", save);
}
int
util_token (char *buf, size_t len, char **ptr)
{
char *start = *ptr;
size_t i;
/* Skip leading space. */
while (**ptr && **ptr == ' ')
(*ptr)++;
for (i = 1; **ptr && i < len; (*ptr)++, buf++, i++)
{
if (**ptr == ' ' || **ptr == '.'
|| **ptr == '(' || **ptr == ')'
|| **ptr == '[' || **ptr == ']'
|| **ptr == '<' || **ptr == '>')
{
/* Advance. */
if (start == (*ptr))
(*ptr)++;
break;
}
*buf = **ptr;
}
*buf = '\0';
/* Skip trailing space. */
while (**ptr && **ptr == ' ')
(*ptr)++;
return *ptr - start;;
}
/* Return in set an allocated array contain (n) numbers, for imap messsage set
set ::= sequence_num / (sequence_num ":" sequence_num) / (set "," set)
......
......@@ -47,6 +47,7 @@ static int imap_append_message (mailbox_t, message_t);
/* Message API. */
static int imap_submessage_size (msg_imap_t, size_t *);
static int imap_message_size (message_t, size_t *);
static int imap_message_lines (message_t, size_t *);
static int imap_message_fd (stream_t, int *);
......@@ -698,6 +699,33 @@ imap_message_lines (message_t msg, size_t *plines)
return 0;
}
/* Sometimes a message is just a place container for other sub parts.
In those cases imap bodystructure does not set the message_size aka
the body_size. But we can calculate it since the message_size
is the sum of its subparts. */
static int
imap_submessage_size (msg_imap_t msg_imap, size_t *psize)
{
if (psize)
{
if (msg_imap->message_size == 0)
{
size_t i, size;
for (size = i = 0; i < msg_imap->num_parts; i++, size = 0)
{
if (msg_imap->parts[i])
imap_submessage_size (msg_imap->parts[i], &size);
*psize += size;
}
}
else
*psize = (msg_imap->message_size + msg_imap->header_size)
- msg_imap->message_lines;
}
return 0;
}
static int
imap_message_size (message_t msg, size_t *psize)
{
......@@ -707,16 +735,11 @@ imap_message_size (message_t msg, size_t *psize)
int status;
/* If there is a parent it means it is a sub message, IMAP does not give
the full size of mime messages, so the message_size was retrieve from
doing a bodystructure and represent rather the body_size. */
the full size of mime messages, so the message_size retrieved from
doing a bodystructure represents rather the body_size. */
if (msg_imap->parent)
{
if (psize)
{
*psize = (msg_imap->message_size + msg_imap->header_size)
- msg_imap->message_lines;
}
return 0;
return imap_submessage_size (msg_imap, psize);
}
/* Select first. */
......