summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlain Magloire <alainm@gnu.org>2001-05-07 04:36:40 +0000
committerAlain Magloire <alainm@gnu.org>2001-05-07 04:36:40 +0000
commit43ba0c68726d41135916aaaf9f4dfffdb56af872 (patch)
treeb629eebf2462a65f3481a8f344a8ebcdf7c55ef3
parent33825193d58de51f0d9fbe261180159d1f623d8f (diff)
downloadmailutils-43ba0c68726d41135916aaaf9f4dfffdb56af872.tar.gz
mailutils-43ba0c68726d41135916aaaf9f4dfffdb56af872.tar.bz2
Implemented UID fetch BODYSTRUCTURE and multiple access to mailbox via IMAP
-rw-r--r--ChangeLog44
-rw-r--r--doc/Makefile.am3
-rw-r--r--doc/address.texi73
-rw-r--r--examples/Addrs.good24
-rw-r--r--examples/addr.c10
-rw-r--r--imap4d/copy.c54
-rw-r--r--imap4d/fetch.c626
-rw-r--r--imap4d/imap4d.c18
-rw-r--r--imap4d/imap4d.h17
-rw-r--r--imap4d/login.c3
-rw-r--r--imap4d/select.c11
-rw-r--r--imap4d/status.c2
-rw-r--r--imap4d/store.c44
-rw-r--r--imap4d/sync.c250
-rw-r--r--imap4d/uid.c28
-rw-r--r--imap4d/util.c154
-rw-r--r--include/mailutils/header.h70
-rw-r--r--include/mailutils/parse822.h1
-rw-r--r--mailbox/attribute.c4
-rw-r--r--mailbox/file_stream.c43
-rw-r--r--mailbox/mailbox.c2
-rw-r--r--mailbox/parse822.c69
22 files changed, 1145 insertions, 405 deletions
diff --git a/ChangeLog b/ChangeLog
index b4eec651b..4e6f69bc8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,47 @@
+2001-05-07 Alain Magloire
+
+ Now we can have multiple access to the mailbox and the server
+ will update the mailbox and send the unsollicited responses.
+ This is implemented in imap4d/sync.c.
+
+ * imap4d/copy.c: Move the code into imap4d_copy0() to allow
+ the use of UID COPY.
+ (imaprd_copy0): New function.
+ * imap4d/fetch.c: Define a new structure command for FETCH.
+ (fetch_getcommand): New function.
+ (imap4d_fetch0): New function to allow the use of UID COPY.
+ (fetch_envelope0): New function to permit to reuse the function
+ in bodystructure.
+ (fetch_bodystructure): Implemented.
+ (fetch_bodystructure0): The implementation.
+ (bodystructure): The helper function for fetch_bodystructure.
+ * imap4d/imap4d.c (imap4d_mainloop): call imap4d_sync() in the
+ mainloop. Now use FILE *ifile.
+ * imap4d/imap4d.h: Update prototypes. Define ERR_NO_MEM and
+ ERR_NO_OFILE.
+ * imap4d/select.c (imap4d_select0): Call imap4d_sync() to update.
+ * imap4d/store.c (ima4d_store): Cal imap4d_sync_flags() to
+ update the flags in the uid_table.
+ * imap4d/uid.c: Implemented.
+ * imap4d/util.c (imap4d_readline): Use fgets() and deal
+ with literals send from the client.
+ * imap4d/sync.c: New file.
+
+ * include/mailutils/header.c: Added some new headers.
+ * mailbox/attribute.c (attribute_copy): Do a shalow copy.
+ * mailbox/file_stream.c: Check if FILE * is null in all functions.
+ * mailbox/mailbox.c (mailbox_is_updated): Should not return ENOSYS
+ but rather 1.
+
+2001-05-07 Sam Roberts
+
+ * mailbox/parse822.c: Now allow a unix mailbox in an address.
+ * include/mailutils/parse822.h: Declare the function to parse them.
+ * doc/address.texi: Document the fact.
+ * doc/Makefile.am: Automatically build the example code from addr.c.
+ * examples/addr.c: And update the parser test.
+ * examples/Addrs.good: Update the parser test.
+
2001-05-03 Sam Roberts
* mail/mail.c: Typo
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 92aca963d..0607918ff 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -23,3 +23,6 @@ EXTRA_DIST = \
url.texi \
version.texi
+ex-address.texi: ../examples/addr.c
+ sed -es/{/@{/g -e s/}/@}/g < $< > $@
+
diff --git a/doc/address.texi b/doc/address.texi
index 2a5b8398b..23ec93ee7 100644
--- a/doc/address.texi
+++ b/doc/address.texi
@@ -1,9 +1,9 @@
-@code{#include <mailutils/mailbox.h>}
+@code{#include <mailutils/address.h>}
-The internet address format is defined in RFC 822. RFC 822 is in the
-process of being updated, and will soon be superceeded by a new RFC
-that makes some corrections and clarifications. References to RFC 822
-here apply equally to the new RFC.
+The internet address format is defined in RFC 822. RFC 822 has been
+updated, and is now superceeded by RFC 2822, which
+makes some corrections and clarifications. References to RFC 822
+here apply equally to RFC 2822.
The RFC 822 format is more flexible than many people realize, here
is a quick summary of the syntax this parser implements, see
@@ -16,10 +16,15 @@ mailbox = addr-spec ["(" display-name ")"] /
[display-name] "<" [route] addr-spec ">"
mailbox-list = mailbox ["," mailbox-list]
group = display-name ":" [mailbox-list] ";"
-address = mailbox / group
+address = mailbox / group / unix-mbox
address-list = address ["," address-list]
@end example
+unix-mbox is a non-standard extention meant to deal with the common
+practice of using user names as addresses in mail utilities. It allows
+addresses such as "root" to be parsed correctly. These are NOT valid
+internet email addresses, they must be qualified before use.
+
Several address functions have a set of common arguments with consistent
semantics, these are described here to avoid repetition.
@@ -133,7 +138,8 @@ The return value is @code{0} on success and a code number on error conditions:
@deftypefun int address_get_email (address_t *@var{addr}, size_t @var{no}, char* @var{buf}, size_t @var{len}, size_t* @var{n})
Acesses the email addr-spec extracted while
-parsing the @var{no}th email address.
+parsing the @var{no}th email address. This will be @code{0}
+length for a unix-mbox.
The return value is @code{0} on success and a code number on error conditions:
@table @code
@@ -157,7 +163,8 @@ The return value is @code{0} on success and a code number on error conditions:
@deftypefun int address_get_domain (address_t *@var{addr}, size_t @var{no}, char* @var{buf}, size_t @var{len}, size_t* @var{n})
Acesses the domain of an email addr-spec extracted while
-parsing the @var{no}th email address.
+parsing the @var{no}th email address. This will be @code{0}
+length for a unix-mbox.
The return value is @code{0} on success and a code number on error conditions:
@table @code
@@ -223,54 +230,6 @@ The return value is @code{0}.
@section Example
@example
-#include <stdio.h>
-#include <mailutils/address.h>
-
-int
-main(int argc, const char *argv[])
-@{
- for(argc = 1; argv[argc]; argc++)
- @{
- const char* str = argv[argc];
- address_t address = NULL;
-
- address_create(&address, str);
-
- printf("'%s' ->\n", str);
- @{
- size_t no = 0;
- size_t pcount;
-
- address_get_count(address, &pcount);
-
- printf(" pcount %d\n", pcount);
-
- for(no = 1; no <= pcount; no++)
- @{
- char buf[BUFSIZ];
-
- address_get_personal(address, no, buf, sizeof(buf), 0);
-
- printf(" personal '%s'\n", buf);
-
- address_get_local_part(address, no, buf, sizeof(buf), 0);
-
- printf(" local_part '%s'\n", buf);
-
- address_get_domain(address, no, buf, sizeof(buf), 0);
-
- printf(" domain '%s'\n", buf);
-
- address_get_email(address, no, buf, sizeof(buf), 0);
-
- printf(" email '%s'\n", buf);
- @}
- @}
-
- address_destroy(&address);
- @}
-
- return 0;
-@}
+@include ex-address.texi
@end example
diff --git a/examples/Addrs.good b/examples/Addrs.good
index e15b45e42..17536398e 100644
--- a/examples/Addrs.good
+++ b/examples/Addrs.good
@@ -228,7 +228,7 @@ list-ietf-wg-apps-drums@faerber.muc.de (=?ISO-8859-1?Q?Claus_F=E4rber?=)=> pcoun
personal <'sroberts@certicom.ca'>
local-part <sroberts> domain <certicom.ca>
-"=?iso-8859-1?Q?Juan_Carlos_Marcos_Rodr=EDguez?=" <jcmarcos@datavoicees>=> pcount 1
+"=?iso-8859-1?Q?Juan_Carlos_Marcos_Rodr=EDguez?=" <jcmarcos@datavoice.es>=> pcount 1
1 email <jcmarcos@datavoice.es>
personal <=?iso-8859-1?Q?Juan_Carlos_Marcos_Rodr=EDguez?=>
local-part <jcmarcos> domain <datavoice.es>
@@ -432,17 +432,17 @@ list-ietf-wg-apps-drums@faerber.muc.de (=?ISO-8859-1?Q?Claus_F=E4rber?=)=> pcoun
personal <=?US-ASCII?Q?gary=5Fc?=>
local-part <gary_c> domain <cunningham-lee.com>
-=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidusnet>=> pcount 1
+=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidus.net>=> pcount 1
1 email <0@pervalidus.net>
personal <=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier>
local-part <0> domain <pervalidus.net>
-=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidusnet>,=> pcount 1
+=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidus.net>,=> pcount 1
1 email <0@pervalidus.net>
personal <=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier>
local-part <0> domain <pervalidus.net>
-=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E_Meunier?= <0@pervalidusnet>=> pcount 1
+=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E_Meunier?= <0@pervalidus.net>=> pcount 1
1 email <0@pervalidus.net>
personal <=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E_Meunier?=>
local-part <0> domain <pervalidus.net>
@@ -554,14 +554,22 @@ No_Reply-To@mapquest.com=> pcount 1
1 email <No_Reply-To@mapquest.com>
local-part <No_Reply-To> domain <mapquest.com>
-OSULLIE@rte.ie, skidswam@hotmail.com, boot=> error ENOENT
+OSULLIE@rte.ie, skidswam@hotmail.com, boot=> pcount 3
+1 email <OSULLIE@rte.ie>
+ local-part <OSULLIE> domain <rte.ie>
+2 email <skidswam@hotmail.com>
+ local-part <skidswam> domain <hotmail.com>
+3 email <>
+ local-part <boot>
Paul Hoffman / IMC <phoffman@imc.org>=> pcount 1
1 email <phoffman@imc.org>
personal <Paul Hoffman / IMC>
local-part <phoffman> domain <imc.org>
-Sam=> error ENOENT
+Sam=> pcount 1
+1 email <>
+ local-part <Sam>
Sam Roberts <sam@cogent.ca>=> pcount 1
1 email <sam@cogent.ca>
@@ -605,7 +613,9 @@ mcaustin@eudoramail.com, aposner@usaid.gov, Kieran.O'Leary@anpost.ie,=> pcount 3
rfunk@wks.uts.ohio-state.eduofflinemailer-bounce@dikke.penguin.nl=> error ENOENT
-root=> error ENOENT
+root=> pcount 1
+1 email <>
+ local-part <root>
srr <sam@localhost>=> error ENOENT
diff --git a/examples/addr.c b/examples/addr.c
index 5f495a052..e32b60766 100644
--- a/examples/addr.c
+++ b/examples/addr.c
@@ -78,11 +78,15 @@ static int parse(const char* str)
address_get_local_part(address, no, buf, sizeof(buf), &got);
- if(got) printf(" local-part <%s>", buf);
+ if(got) {
+ printf(" local-part <%s>", buf);
- address_get_domain(address, no, buf, sizeof(buf), &got);
+ address_get_domain(address, no, buf, sizeof(buf), &got);
- if(got) printf(" domain <%s>\n", buf);
+ if(got) printf(" domain <%s>", buf);
+
+ printf("\n");
+ }
address_get_route(address, no, buf, sizeof(buf), &got);
diff --git a/imap4d/copy.c b/imap4d/copy.c
index 2c688921d..56e9fc90a 100644
--- a/imap4d/copy.c
+++ b/imap4d/copy.c
@@ -21,34 +21,57 @@
* copy messages in argv[2] to mailbox in argv[3]
*/
-/* FIXME if the mailbox is the one selecte we should send notif. */
int
imap4d_copy (struct imap4d_command *command, char *arg)
{
+ int rc;
+ char buffer[64];
+
+ if (! (command->states & state))
+ return util_finish (command, RESP_BAD, "Wrong state");
+
+ rc = imap4d_copy0 (arg, 0, buffer, sizeof buffer);
+ if (rc == RESP_NONE)
+ {
+ /* Reset the state ourself. */
+ int new_state = (rc == RESP_OK) ? command->success : command->failure;
+ if (new_state != STATE_NONE)
+ state = new_state;
+ return util_send ("%s %s\r\n", command->tag, buffer);
+ }
+ return util_finish (command, rc, buffer);
+}
+
+int
+imap4d_copy0 (char *arg, int isuid, char *resp, size_t resplen)
+{
int status;
char *msgset;
char *name;
char *mailbox_name;
const char *delim = "/";
char *sp = NULL;
- int *set = NULL;
+ size_t *set = NULL;
size_t n = 0;
mailbox_t cmbox = NULL;
- if (! (command->states & state))
- return util_finish (command, RESP_BAD, "Wrong state");
-
msgset = util_getword (arg, &sp);
name = util_getword (NULL, &sp);
util_unquote (&name);
if (!msgset || !name || *name == '\0')
- return util_finish (command, RESP_BAD, "Too few args");
+ {
+ snprintf (resp, resplen, "Too few args");
+ return RESP_BAD;
+ }
/* Get the message numbers in set[]. */
- status = util_msgset (msgset, &set, &n, 0);
+ status = util_msgset (msgset, &set, &n, isuid);
if (status != 0)
- return util_finish (command, RESP_BAD, "Bogus number set");
+ {
+ snprintf (resp, resplen, "Bogus number set");
+ return RESP_BAD;
+ }
if (strcasecmp (name, "INBOX") == 0)
{
@@ -71,7 +94,8 @@ imap4d_copy (struct imap4d_command *command, char *arg)
for (i = 0; i < n; i++)
{
message_t msg = NULL;
- mailbox_get_message (mbox, set[i], &msg);
+ size_t msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
+ mailbox_get_message (mbox, msgno, &msg);
mailbox_append_message (cmbox, msg);
}
mailbox_close (cmbox);
@@ -82,16 +106,16 @@ imap4d_copy (struct imap4d_command *command, char *arg)
free (mailbox_name);
if (status == 0)
- return util_finish (command, RESP_OK, "Completed");
-
- /* Since we do not call util_finish, reset the state ourself. */
- if (command->failure != STATE_NONE)
- state = command->failure;
+ {
+ snprintf (resp, resplen, "Completed");
+ return RESP_OK;
+ }
/* Unless it is certain that the destination mailbix can not be created,
the server MUST send the response code "[TRYCREATE]" as the prefix
of the text of the tagged NO response. This gives a hint to the
client that it can attempt a CREATE command and retry the copy if
the CREATE is successful. */
- return util_send ("%s NO [TRYCREATE] failed\r\n", command->tag);
+ snprintf (resp, resplen, "NO [TRYCREATE] failed");
+ return RESP_NONE;
}
diff --git a/imap4d/fetch.c b/imap4d/fetch.c
index bfca9aabd..c648369e0 100644
--- a/imap4d/fetch.c
+++ b/imap4d/fetch.c
@@ -32,176 +32,244 @@
["<" number "." nz_number ">"]
*/
-static int fetch_all __P ((struct imap4d_command *, char*));
-static int fetch_full __P ((struct imap4d_command *, char*));
-static int fetch_fast __P ((struct imap4d_command *, char*));
-static int fetch_envelope __P ((struct imap4d_command *, char*));
-static int fetch_flags __P ((struct imap4d_command *, char*));
-static int fetch_internaldate __P ((struct imap4d_command *, char*));
-static int fetch_rfc822_header __P ((struct imap4d_command *, char*));
-static int fetch_rfc822_size __P ((struct imap4d_command *, char*));
-static int fetch_rfc822_text __P ((struct imap4d_command *, char*));
-static int fetch_rfc822 __P ((struct imap4d_command *, char*));
-static int fetch_bodystructure __P ((struct imap4d_command *, char*));
-static int fetch_body_peek __P ((struct imap4d_command *, char*));
-static int fetch_body __P ((struct imap4d_command *, char*));
-static int fetch_uid __P ((struct imap4d_command *, char*));
-
-static int fetch_operation __P ((size_t, char *, int));
-static int fetch_message __P ((message_t, unsigned long, unsigned long));
-static int fetch_header __P ((message_t, unsigned long, unsigned long));
-static int fetch_content __P ((message_t, unsigned long, unsigned long));
-static int fetch_io __P ((stream_t, unsigned long, unsigned long));
-static int fetch_header_fields __P ((message_t, char *, unsigned long,
- unsigned long));
-static int fetch_header_fields_not __P ((message_t, char *, unsigned long,
- unsigned long));
-static int fetch_send_address __P ((char *));
-
-struct imap4d_command fetch_command_table [] =
+struct fetch_command;
+
+static int fetch_all __P ((struct fetch_command *, char*));
+static int fetch_full __P ((struct fetch_command *, char*));
+static int fetch_fast __P ((struct fetch_command *, char*));
+static int fetch_envelope __P ((struct fetch_command *, char*));
+static int fetch_envelope0 __P ((message_t));
+static int fetch_flags __P ((struct fetch_command *, char*));
+static int fetch_internaldate __P ((struct fetch_command *, char*));
+static int fetch_rfc822_header __P ((struct fetch_command *, char*));
+static int fetch_rfc822_size __P ((struct fetch_command *, char*));
+static int fetch_rfc822_text __P ((struct fetch_command *, char*));
+static int fetch_rfc822 __P ((struct fetch_command *, char*));
+static int fetch_bodystructure __P ((struct fetch_command *, char*));
+static int fetch_bodystructure0 __P ((message_t, int));
+static int bodystructure __P ((message_t, int));
+static int fetch_body_peek __P ((struct fetch_command *, char*));
+static int fetch_body __P ((struct fetch_command *, char*));
+static int fetch_uid __P ((struct fetch_command *, char*));
+
+static int fetch_operation __P ((size_t, char *, int));
+static int fetch_message __P ((message_t, unsigned long, unsigned long));
+static int fetch_header __P ((message_t, unsigned long, unsigned long));
+static int fetch_content __P ((message_t, unsigned long, unsigned long));
+static int fetch_io __P ((stream_t, unsigned long, unsigned long));
+static int fetch_header_fields __P ((message_t, char *, unsigned long, unsigned long));
+static int fetch_header_fields_not __P ((message_t, char *, unsigned long, unsigned long));
+static int fetch_send_address __P ((char *));
+
+static struct fetch_command* fetch_getcommand __P ((char *, struct fetch_command[]));
+
+struct fetch_command
+{
+ const char *name;
+ int (*func) __P ((struct fetch_command *, char *));
+ size_t msgno;
+} fetch_command_table [] =
{
#define F_ALL 0
- {"ALL", fetch_all, 0, 0, 0, NULL},
+ {"ALL", fetch_all, 0},
#define F_FULL 1
- {"FULL", fetch_full, 0, 0, 0, NULL},
+ {"FULL", fetch_full, 0},
#define F_FAST 2
- {"FAST", fetch_fast, 0, 0, 0, NULL},
+ {"FAST", fetch_fast, 0},
#define F_ENVELOPE 3
- {"ENVELOPE", fetch_envelope, 0, 0, 0, NULL},
+ {"ENVELOPE", fetch_envelope, 0},
#define F_FLAGS 4
- {"FLAGS", fetch_flags, 0, 0, 0, NULL},
+ {"FLAGS", fetch_flags, 0},
#define F_INTERNALDATE 5
- {"INTERNALDATE", fetch_internaldate, 0, 0, 0, NULL},
+ {"INTERNALDATE", fetch_internaldate, 0},
#define F_RFC822_HEADER 6
- {"RFC822.HEADER", fetch_rfc822_header, 0, 0, 0, NULL},
+ {"RFC822.HEADER", fetch_rfc822_header, 0},
#define F_RFC822_SIZE 7
- {"RFC822.SIZE", fetch_rfc822_size, 0, 0, 0, NULL},
+ {"RFC822.SIZE", fetch_rfc822_size, 0},
#define F_RFC822_TEXT 8
- {"RFC822.TEXT", fetch_rfc822_text, 0, 0, 0, NULL},
+ {"RFC822.TEXT", fetch_rfc822_text, 0},
#define F_RFC822 9
- {"RFC822", fetch_rfc822, 0, 0, 0, NULL},
+ {"RFC822", fetch_rfc822, 0},
#define F_BODYSTRUCTURE 10
- {"BODYSTRUCTURE", fetch_bodystructure, 0, 0, 0, NULL},
+ {"BODYSTRUCTURE", fetch_bodystructure, 0},
#define F_BODY_PEEK 11
- {"BODY.PEEK", fetch_body_peek, 0, 0, 0, NULL},
+ {"BODY.PEEK", fetch_body_peek, 0},
#define F_BODY 12
- {"BODY", fetch_body, 0, 0, 0, NULL},
+ {"BODY", fetch_body, 0},
#define F_UID 13
- {"UID", fetch_uid, 0, 0, 0, NULL},
- { NULL, 0, 0, 0, 0, NULL}
+ {"UID", fetch_uid, 0},
+ { NULL, 0, 0}
};
-/* NOTE: the state field in the command structure is use as a place
- holder for the message number. This save us from redifining another
- data structure. */
int
imap4d_fetch (struct imap4d_command *command, char *arg)
{
- char *sp = NULL;
- char *msgset;
- int *set = NULL;
- int i, n = 0;
- int rc = RESP_OK;
- int status;
- const char *errmsg = "Completed";
- struct imap4d_command *fcmd;
+ int rc;
+ char buffer[64];
if (! (command->states & state))
return util_finish (command, RESP_BAD, "Wrong state");
+ rc = imap4d_fetch0 (arg, 0, buffer, sizeof buffer);
+ return util_finish (command, rc, buffer);
+}
+
+static struct fetch_command *
+fetch_getcommand (char *cmd, struct fetch_command command_table[])
+{
+ size_t i, len = strlen (cmd);
+
+ for (i = 0; command_table[i].name != 0; i++)
+ {
+ if (strlen (command_table[i].name) == len &&
+ !strcasecmp (command_table[i].name, cmd))
+ return &command_table[i];
+ }
+ return NULL;
+}
+
+int
+imap4d_fetch0 (char *arg, int isuid, char *resp, size_t resplen)
+{
+ struct fetch_command *fcmd = NULL;
+ int rc = RESP_NO;
+ char *sp = NULL;
+ char *msgset;
+ size_t *set = NULL;
+ int n = 0;
+ int i;
+ int status;
+
msgset = util_getword (arg, &sp);
if (!msgset || !sp || *sp == '\0')
- return util_finish (command, RESP_BAD, "Too few args");
+ {
+ snprintf (resp, resplen, "Too few args");
+ return RESP_BAD;
+ }
/* Get the message numbers in set[]. */
- status = util_msgset (msgset, &set, &n, 0);
+ status = util_msgset (msgset, &set, &n, isuid);
if (status != 0)
- return util_finish (command, RESP_BAD, "Bogus number set");
+ {
+ snprintf (resp, resplen, "Bogus number set");
+ return RESP_BAD;
+ }
for (i = 0; i < n; i++)
{
char item[32];
char *items = strdup (sp);
char *p = items;
- util_send ("* FETCH %d (", set[i]);
+ int uid_sent = !isuid; /* Pretend we sent the uid if via fetch. */
+ util_send ("* %d FETCH (", set[i]);
item[0] = '\0';
/* Get the fetch command names. */
while (*items && *items != ')')
{
util_token (item, sizeof (item), &items);
+ if (fcmd)
+ util_send (" ");
/* Search in the table. */
- fcmd = util_getcommand (item, fetch_command_table);
+ fcmd = fetch_getcommand (item, fetch_command_table);
if (fcmd)
{
- /* We use the states field to hold the msgno/uid. */
- fcmd->states = set[i];
- fcmd->func (fcmd, items);
- util_send (" ");
+ fcmd->msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
+ if (fcmd->msgno != 0)
+ {
+ rc = fcmd->func (fcmd, items);
+ }
}
+ if (!uid_sent)
+ uid_sent = ((strstr (item, "UID") != NULL)
+ || (strstr (item, "uid") != NULL));
+ }
+ /* Always send the UID when fetch was done via the uid command. */
+ if (!uid_sent)
+ {
+ struct fetch_command c_uid = fetch_command_table[F_UID];
+ c_uid.msgno = set[i];
+ if (fcmd)
+ util_send (" ");
+ rc = fetch_uid (&c_uid, items);
}
free (p);
util_send (")\r\n");
}
free (set);
- return util_finish (command, rc, errmsg);
+ snprintf (resp, resplen, "Completed");
+ return rc;
}
-/* Combination of (FAST ENVELOPE). */
+/* The Fetch comand retireves data associated with a message in the
+ mailbox, The data items to be fetched can be either a single atom
+ or a parenthesized list. */
+
+/* Macro equivalent to: (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE)
+ or (FAST ENVELOPE) */
static int
-fetch_all (struct imap4d_command *command, char *arg)
+fetch_all (struct fetch_command *command, char *arg)
{
- struct imap4d_command c_env = fetch_command_table[F_ENVELOPE];
+ struct fetch_command c_env = fetch_command_table[F_ENVELOPE];
fetch_fast (command, arg);
util_send (" ");
- c_env.states = command->states;
+ c_env.msgno = command->msgno;
fetch_envelope (&c_env, arg);
- return 0;
+ return RESP_OK;
}
/* Combination of (ALL BODY). */
static int
-fetch_full (struct imap4d_command *command, char *arg)
+fetch_full (struct fetch_command *command, char *arg)
{
- struct imap4d_command c_body = fetch_command_table[F_BODY];
+ struct fetch_command c_body = fetch_command_table[F_BODY];
fetch_all (command, arg);
util_send (" ");
- c_body.states = command->states;
+ c_body.msgno = command->msgno;
fetch_body (&c_body, arg);
- return 0;
+ return RESP_OK;
}
/* Combination of (FLAGS INTERNALDATE RFC822.SIZE). */
static int
-fetch_fast (struct imap4d_command *command, char *arg)
+fetch_fast (struct fetch_command *command, char *arg)
{
- struct imap4d_command c_idate = fetch_command_table[F_INTERNALDATE];
- struct imap4d_command c_rfc = fetch_command_table[F_RFC822_SIZE];
- struct imap4d_command c_flags = fetch_command_table[F_FLAGS];
- c_flags.states = command->states;
+ struct fetch_command c_idate = fetch_command_table[F_INTERNALDATE];
+ struct fetch_command c_rfc = fetch_command_table[F_RFC822_SIZE];
+ struct fetch_command c_flags = fetch_command_table[F_FLAGS];
+ c_flags.msgno = command->msgno;
fetch_flags (&c_flags, arg);
util_send (" ");
- c_idate.states = command->states;
+ c_idate.msgno = command->msgno;
fetch_internaldate (&c_idate, arg);
util_send (" ");
- c_rfc.states = command->states;
+ c_rfc.msgno = command->msgno;
fetch_rfc822_size (&c_rfc, arg);
- return 0;
+ return RESP_OK;
}
/* Header: Date, Subject, From, Sender, Reply-To, To, Cc, Bcc, In-Reply-To,
and Message-Id. */
+static int
+fetch_envelope (struct fetch_command *command, char *arg)
+{
+ message_t msg = NULL;
+ int status;
+ mailbox_get_message (mbox, command->msgno, &msg);
+ util_send ("%s (", command->name);
+ status = fetch_envelope0 (msg);
+ util_send (")");
+ return status;
+}
+
/* FIXME: - strings change to literals when detecting '"' */
static int
-fetch_envelope (struct imap4d_command *command, char *arg)
+fetch_envelope0 (message_t msg)
{
- char *buffer;
- char *from;
+ char *buffer = NULL;
+ char *from = NULL;
header_t header = NULL;
- message_t msg = NULL;
- mailbox_get_message (mbox, command->states, &msg);
message_get_header (msg, &header);
- util_send ("%s(", command->name);
/* FIXME: Incorrect Date. */
header_aget_value (header, "Date", &buffer);
@@ -266,18 +334,18 @@ fetch_envelope (struct imap4d_command *command, char *arg)
free (buffer);
free (from);
- util_send (")");
- return 0;
+ return RESP_OK;
}
/* The flags that are set for this message. */
/* FIXME: User flags not done. */
static int
-fetch_flags (struct imap4d_command *command, char *arg)
+fetch_flags (struct fetch_command *command, char *arg)
{
attribute_t attr = NULL;
message_t msg = NULL;
- mailbox_get_message (mbox, command->states, &msg);
+ (void)arg;
+ mailbox_get_message (mbox, command->msgno, &msg);
message_get_attribute (msg, &attr);
util_send ("%s (", command->name);
if (attribute_is_deleted (attr))
@@ -286,23 +354,23 @@ fetch_flags (struct imap4d_command *command, char *arg)
util_send (" \\Answered");
if (attribute_is_flagged (attr))
util_send (" \\Flagged");
- if (attribute_is_seen (attr))
+ if (attribute_is_seen (attr) && attribute_is_read (attr))
util_send (" \\Seen");
if (attribute_is_draft (attr))
util_send (" \\Draft");
util_send (" )");
- return 0;
+ return RESP_OK;
}
/* The internal date of the message. */
/* FIXME: Wrong format? */
static int
-fetch_internaldate (struct imap4d_command *command, char *arg)
+fetch_internaldate (struct fetch_command *command, char *arg)
{
char date[512];
envelope_t env = NULL;
message_t msg = NULL;
- mailbox_get_message (mbox, command->states, &msg);
+ mailbox_get_message (mbox, command->msgno, &msg);
message_get_envelope (msg, &env);
date[0] = '\0';
envelope_date (env, date, sizeof (date), NULL);
@@ -310,76 +378,80 @@ fetch_internaldate (struct imap4d_command *command, char *arg)
if (date[strlen (date) - 1] == '\n')
date[strlen (date) - 1] = '\0';
util_send (" \"%s\"", date);
- return 0;
+ return RESP_OK;
}
/* Equivalent to BODY.PEEK[HEADER]. */
static int
-fetch_rfc822_header (struct imap4d_command *command, char *arg)
+fetch_rfc822_header (struct fetch_command *command, char *arg)
{
char buffer[16];
(void)arg;
util_send ("%s ", command->name);
strcpy (buffer, "[HEADER]");
- fetch_operation (command->states, buffer, 1);
- return 0;
+ fetch_operation (command->msgno, buffer, 1);
+ return RESP_OK;
}
/* 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)
+fetch_rfc822_text (struct fetch_command *command, char *arg)
{
char buffer[16];
attribute_t attr = NULL;
message_t msg = NULL;
- mailbox_get_message (mbox, command->states, &msg);
+ (void)arg;
+ mailbox_get_message (mbox, command->msgno, &msg);
message_get_attribute (msg, &attr);
- attribute_set_read (attr);
+ if (!attribute_is_seen (attr) && !attribute_is_read (attr))
+ {
+ util_send ("FLAGS (\\Seen) ");
+ attribute_set_seen (attr);
+ attribute_set_read (attr);
+ }
util_send ("%s ", command->name);
strcpy (buffer, "[TEXT]");
- fetch_operation (command->states, buffer, 1);
- return 0;
+ fetch_operation (command->msgno, buffer, 1);
+ return RESP_OK;
}
/* The [RFC-822] size of the message. */
static int
-fetch_rfc822_size (struct imap4d_command *command, char *arg)
+fetch_rfc822_size (struct fetch_command *command, char *arg)
{
size_t size = 0;
size_t lines = 0;
message_t msg = NULL;
(void)arg;
- mailbox_get_message (mbox, command->states, &msg);
+ mailbox_get_message (mbox, command->msgno, &msg);
message_size (msg, &size);
message_lines (msg, &lines);
util_send ("%s %u", command->name, size + lines);
- return 0;
+ return RESP_OK;
}
/* Equivalent to BODY[]. */
-/* FIXME: send a Fetch flag if the mail was not set seen ? */
static int
-fetch_rfc822 (struct imap4d_command *command, char *arg)
+fetch_rfc822 (struct fetch_command *command, char *arg)
{
if (*arg == '.')
{
if (strncasecmp (arg, ".SIZE", 5) == 0)
{
- struct imap4d_command c_rfc= fetch_command_table[F_RFC822_SIZE];
- c_rfc.states = command->states;
+ struct fetch_command c_rfc= fetch_command_table[F_RFC822_SIZE];
+ c_rfc.msgno = command->msgno;
fetch_rfc822_size (&c_rfc, arg);
}
else if (strncasecmp (arg, ".TEXT", 5) == 0)
{
- struct imap4d_command c_rfc = fetch_command_table[F_RFC822_TEXT];
- c_rfc.states = command->states;
+ struct fetch_command c_rfc = fetch_command_table[F_RFC822_TEXT];
+