diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-09-07 13:57:30 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-09-07 13:57:30 +0300 |
commit | 817286698ccc3f262cd0003401becef6c11050ae (patch) | |
tree | 5e90dce6beec2618a4894b8708f28d877fb99ad6 | |
parent | bfb29ced5d88dbe449347d5b8b86e6ee887c450b (diff) | |
download | mailutils-817286698ccc3f262cd0003401becef6c11050ae.tar.gz mailutils-817286698ccc3f262cd0003401becef6c11050ae.tar.bz2 |
Finish pop3 mailbox implementation.
* mailbox/msgscan.c: New file.
* mailbox/Makefile.am (libmailutils_la_SOURCES): Add it.
* include/mailutils/body.h (mu_body_set_get_stream): New prototype.
* include/mailutils/message.h (MU_SCAN_SEEK, MU_SCAN_SIZE): New
defines.
(mu_message_scan): New structure.
(mu_stream_scan_message): New prototype.
(mu_message_set_get_stream): New prototype.
* include/mailutils/stream.h (mu_stream_copy): Change signature: takes
4 arguments now.
* include/mailutils/sys/body.h (_mu_body) <_get_stream>: New method.
* include/mailutils/sys/message.h (_mu_message) <_get_stream>: New method.
* mailbox/body.c (_body_get_stream): Call _get_stream, if provided.
* mailbox/message.c (_message_get_stream): Call _get_stream, if provided.
* mailbox/stream.c (_stream_flush_buffer): Avoid infinite recursion:
call stream->seek directly.
* mailbox/streamcpy.c (mu_stream_copy): Return the number of bytes
actually copied in the fourth argument. All uses updated.
* mailbox/streamref.c (streamref_return): Do not propagate internal
flags.
(_streamref_readdelim): Ensure there is enough buffer space for the
mu_stream_readdelim call.
* libproto/pop/mbox.c: Finish client implementation.
* mail/print.c (mail_print_msg): Close pager before returning on
error.
-rw-r--r-- | examples/base64.c | 2 | ||||
-rw-r--r-- | examples/mucat.c | 4 | ||||
-rw-r--r-- | imap4d/io.c | 2 | ||||
-rw-r--r-- | include/mailutils/body.h | 5 | ||||
-rw-r--r-- | include/mailutils/message.h | 24 | ||||
-rw-r--r-- | include/mailutils/stream.h | 3 | ||||
-rw-r--r-- | include/mailutils/sys/body.h | 1 | ||||
-rw-r--r-- | include/mailutils/sys/message.h | 1 | ||||
-rw-r--r-- | libmu_scm/mu_message.c | 2 | ||||
-rw-r--r-- | libmu_sieve/actions.c | 2 | ||||
-rw-r--r-- | libmu_sieve/extensions/pipe.c | 2 | ||||
-rw-r--r-- | libmu_sieve/extensions/spamd.c | 2 | ||||
-rw-r--r-- | libmu_sieve/extensions/vacation.c | 2 | ||||
-rw-r--r-- | libproto/mbox/mbox.c | 8 | ||||
-rw-r--r-- | libproto/pop/mbox.c | 385 | ||||
-rw-r--r-- | mail/decode.c | 2 | ||||
-rw-r--r-- | mail/print.c | 2 | ||||
-rw-r--r-- | mailbox/Makefile.am | 1 | ||||
-rw-r--r-- | mailbox/body.c | 84 | ||||
-rw-r--r-- | mailbox/message.c | 59 | ||||
-rw-r--r-- | mailbox/msgscan.c | 106 | ||||
-rw-r--r-- | mailbox/rdcache_stream.c | 2 | ||||
-rw-r--r-- | mailbox/stream.c | 10 | ||||
-rw-r--r-- | mailbox/streamcpy.c | 18 | ||||
-rw-r--r-- | mailbox/streamref.c | 18 | ||||
-rw-r--r-- | mh/burst.c | 2 | ||||
-rw-r--r-- | mh/comp.c | 2 | ||||
-rw-r--r-- | mh/mhn.c | 10 | ||||
-rw-r--r-- | pop3d/retr.c | 2 | ||||
-rw-r--r-- | pop3d/top.c | 2 |
30 files changed, 611 insertions, 154 deletions
diff --git a/examples/base64.c b/examples/base64.c index 226cde96b..aa6bdebd5 100644 --- a/examples/base64.c +++ b/examples/base64.c @@ -55,7 +55,7 @@ c_copy (mu_stream_t out, mu_stream_t in) } } else - MU_ASSERT (mu_stream_copy (out, in, 0)); + MU_ASSERT (mu_stream_copy (out, in, 0, NULL)); mu_stream_write (out, "\n", 1, NULL); mu_stream_close (out); mu_stream_close (in); diff --git a/examples/mucat.c b/examples/mucat.c index b8cb314f7..92f55eb24 100644 --- a/examples/mucat.c +++ b/examples/mucat.c @@ -69,14 +69,14 @@ main (int argc, char * argv []) MU_ASSERT (mu_stream_seek (in, skip_off, MU_SEEK_SET, NULL)); } - MU_ASSERT (mu_stream_copy (out, in, 0)); + MU_ASSERT (mu_stream_copy (out, in, 0, NULL)); if (reread_option) { mu_stream_printf (out, "rereading from %lu:\n", (unsigned long) reread_off); MU_ASSERT (mu_stream_seek (in, reread_off, MU_SEEK_SET, NULL)); - MU_ASSERT (mu_stream_copy (out, in, 0)); + MU_ASSERT (mu_stream_copy (out, in, 0, NULL)); } mu_stream_close (in); diff --git a/imap4d/io.c b/imap4d/io.c index 05645ae62..a8b6cb0be 100644 --- a/imap4d/io.c +++ b/imap4d/io.c @@ -152,7 +152,7 @@ sc2string (int rc) int io_copy_out (mu_stream_t str, size_t size) { - return mu_stream_copy (iostream, str, size); + return mu_stream_copy (iostream, str, size, NULL); } int diff --git a/include/mailutils/body.h b/include/mailutils/body.h index 5fc25b72c..d935d00e2 100644 --- a/include/mailutils/body.h +++ b/include/mailutils/body.h @@ -36,7 +36,10 @@ extern int mu_body_get_stream (mu_body_t, mu_stream_t *) __attribute__ ((deprecated)); extern int mu_body_get_streamref (mu_body_t body, mu_stream_t *pstream); extern int mu_body_set_stream (mu_body_t, mu_stream_t, void *owner); - +extern int mu_body_set_get_stream (mu_body_t, + int (*) (mu_body_t, mu_stream_t *), + void *owner); + extern int mu_body_get_filename (mu_body_t, char *, size_t, size_t *); extern int mu_body_size (mu_body_t, size_t *); diff --git a/include/mailutils/message.h b/include/mailutils/message.h index 8a2416ff5..14df6f69a 100644 --- a/include/mailutils/message.h +++ b/include/mailutils/message.h @@ -26,6 +26,25 @@ extern "C" { #endif +#define MU_SCAN_SEEK 0x01 +#define MU_SCAN_SIZE 0x02 + +struct mu_message_scan +{ + int flags; + mu_off_t message_start; + mu_off_t message_size; + + mu_off_t body_start; + mu_off_t body_end; + size_t header_lines; + size_t body_lines; + int attr_flags; + unsigned long uidvalidity; +}; + +int mu_stream_scan_message (mu_stream_t stream, struct mu_message_scan *sp); + /* A message is considered to be a container for: mu_header_t, mu_body_t, and its mu_attribute_t. */ @@ -34,7 +53,7 @@ extern void mu_message_destroy (mu_message_t *, void *owner); extern int mu_message_create_copy (mu_message_t *to, mu_message_t from); -extern void * mu_message_get_owner (mu_message_t); +extern void *mu_message_get_owner (mu_message_t); extern int mu_message_is_modified (mu_message_t); extern int mu_message_clear_modified (mu_message_t); extern int mu_message_get_mailbox (mu_message_t, mu_mailbox_t *); @@ -64,6 +83,9 @@ extern int mu_message_set_attribute (mu_message_t, mu_attribute_t, void *); extern int mu_message_get_observable (mu_message_t, mu_observable_t *); +extern int mu_message_set_get_stream (mu_message_t, + int (*) (mu_message_t, mu_stream_t *), + void *); extern int mu_message_is_multipart (mu_message_t, int *); extern int mu_message_set_is_multipart (mu_message_t, int (*_is_multipart) (mu_message_t, diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h index f2af9b399..e7d04ea4d 100644 --- a/include/mailutils/stream.h +++ b/include/mailutils/stream.h @@ -115,7 +115,8 @@ int mu_stream_clr_flags (mu_stream_t stream, int fl); int mu_stream_vprintf (mu_stream_t str, const char *fmt, va_list ap); int mu_stream_printf (mu_stream_t stream, const char *fmt, ...); -int mu_stream_copy (mu_stream_t dst, mu_stream_t src, size_t size); +int mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size, + mu_off_t *pcsz); int mu_file_stream_create (mu_stream_t *pstream, const char *filename, int flags); diff --git a/include/mailutils/sys/body.h b/include/mailutils/sys/body.h index 9c82a2a50..7ec58e382 100644 --- a/include/mailutils/sys/body.h +++ b/include/mailutils/sys/body.h @@ -40,6 +40,7 @@ struct _mu_body int (*_size) (mu_body_t, size_t*); int (*_lines) (mu_body_t, size_t*); + int (*_get_stream) (mu_body_t, mu_stream_t *); }; #ifdef __cplusplus diff --git a/include/mailutils/sys/message.h b/include/mailutils/sys/message.h index ec913723b..5e96d85a0 100644 --- a/include/mailutils/sys/message.h +++ b/include/mailutils/sys/message.h @@ -52,6 +52,7 @@ struct _mu_message /* Reference count. */ int ref; + int (*_get_stream) (mu_message_t, mu_stream_t *); int (*_get_uidl) (mu_message_t, char *, size_t, size_t *); int (*_get_uid) (mu_message_t, size_t *); int (*_get_qid) (mu_message_t, mu_message_qid_t *); diff --git a/libmu_scm/mu_message.c b/libmu_scm/mu_message.c index ffcf9e34e..1cb06c068 100644 --- a/libmu_scm/mu_message.c +++ b/libmu_scm/mu_message.c @@ -219,7 +219,7 @@ SCM_DEFINE_PUBLIC (scm_mu_message_copy, "mu-message-copy", 1, 0, 0, "Cannot get output stream", SCM_BOOL_F); } - status = mu_stream_copy (out, in, 0); + status = mu_stream_copy (out, in, 0, NULL); mu_stream_destroy (&in); mu_stream_destroy (&out); if (status) diff --git a/libmu_sieve/actions.c b/libmu_sieve/actions.c index 940b6913b..952626a3c 100644 --- a/libmu_sieve/actions.c +++ b/libmu_sieve/actions.c @@ -252,7 +252,7 @@ mime_create_quote (mu_mime_t mime, mu_message_t msg) mu_body_get_streamref (body, &ostream); mu_message_get_streamref (msg, &istream); - rc = mu_stream_copy (ostream, istream, 0); + rc = mu_stream_copy (ostream, istream, 0, NULL); mu_stream_destroy (&istream); mu_stream_close (ostream); diff --git a/libmu_sieve/extensions/pipe.c b/libmu_sieve/extensions/pipe.c index 717706ad2..1378461d2 100644 --- a/libmu_sieve/extensions/pipe.c +++ b/libmu_sieve/extensions/pipe.c @@ -118,7 +118,7 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) ONERR (rc, _("stream write failed"), NULL); } - rc = mu_stream_copy (pstr, mstr, 0); + rc = mu_stream_copy (pstr, mstr, 0, NULL); ONERR (rc, _("command failed"), cmd); } while (0); diff --git a/libmu_sieve/extensions/spamd.c b/libmu_sieve/extensions/spamd.c index 26640d4d7..e620e5866 100644 --- a/libmu_sieve/extensions/spamd.c +++ b/libmu_sieve/extensions/spamd.c @@ -117,7 +117,7 @@ spamd_send_message (mu_stream_t stream, mu_message_t msg) return rc; } - rc = mu_stream_copy (stream, flt, 0); + rc = mu_stream_copy (stream, flt, 0, NULL); mu_stream_destroy (&mstr); mu_stream_destroy (&flt); diff --git a/libmu_sieve/extensions/vacation.c b/libmu_sieve/extensions/vacation.c index f22e0e653..6b220df58 100644 --- a/libmu_sieve/extensions/vacation.c +++ b/libmu_sieve/extensions/vacation.c @@ -111,7 +111,7 @@ build_mime (mu_sieve_machine_t mach, mu_list_t tags, mu_mime_t *pmime, } mu_stream_seek (input, 0, MU_SEEK_SET, NULL); - rc = mu_stream_copy (stream, input, 0); + rc = mu_stream_copy (stream, input, 0, NULL); if (rc) { mu_sieve_error (mach, diff --git a/libproto/mbox/mbox.c b/libproto/mbox/mbox.c index 51da14e5a..7b14817f9 100644 --- a/libproto/mbox/mbox.c +++ b/libproto/mbox/mbox.c @@ -1086,7 +1086,7 @@ append_message_to_stream (mu_stream_t ostr, mu_message_t msg, if (status) return status; } - status = mu_stream_copy (ostr, istr, 0); + status = mu_stream_copy (ostr, istr, 0, NULL); mu_stream_destroy (&istr); if (status == 0) status = mu_stream_write (ostr, "\n", 1, NULL); @@ -1264,7 +1264,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, return status; } status = mu_stream_copy (tempstr, mailbox->stream, - mum->body_end - mum->envel_from); + mum->body_end - mum->envel_from, NULL); if (status) { mu_error (_("%s:%d: error copying: %s"), @@ -1295,7 +1295,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, return status; } - status = mu_stream_copy (tempstr, mailbox->stream, len); + status = mu_stream_copy (tempstr, mailbox->stream, len, NULL); if (status) { mu_error (_("%s:%d: error writing to temporary stream: %s"), @@ -1342,7 +1342,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, return status; } - status = mu_stream_copy (mailbox->stream, tempstr, size); + status = mu_stream_copy (mailbox->stream, tempstr, size, NULL); if (status) { mu_error (_("%s:%d: copying from the temporary stream: %s"), diff --git a/libproto/pop/mbox.c b/libproto/pop/mbox.c index 3b538a0ef..ced5126f2 100644 --- a/libproto/pop/mbox.c +++ b/libproto/pop/mbox.c @@ -41,6 +41,7 @@ #include <mailutils/observer.h> #include <mailutils/property.h> #include <mailutils/stream.h> +#include <mailutils/filter.h> #include <mailutils/url.h> #include <mailutils/secret.h> #include <mailutils/tls.h> @@ -56,22 +57,24 @@ #include <mailutils/sys/registrar.h> #include <mailutils/sys/url.h> -#define _POP3_MSG_INBODY 0x01 -#define _POP3_MSG_SKIPHDR 0x02 -#define _POP3_MSG_SKIPBDY 0x04 +#define _POP3_MSG_CACHED 0x01 /* Message is already cached */ +#define _POP3_MSG_SIZE 0x02 /* Message size obtained */ +#define _POP3_MSG_SCANNED 0x04 /* Message has been scanned */ +#define _POP3_MSG_ATTRSET 0x08 /* Attributes has been set */ struct _pop3_message { int flags; - size_t body_size; - size_t header_size; - size_t body_lines; - size_t header_lines; - size_t message_size; - size_t num; - char *uidl; /* Cache the uidl string. */ - int attr_flags; - mu_message_t message; + mu_off_t offset; /* Offset in the message cache stream */ + mu_off_t body_start; /* Start of message, relative to offset */ + mu_off_t body_end; /* End of message, relative to offset */ + size_t header_lines; /* Number of lines in the header */ + size_t body_lines; /* Number of lines in the body */ + int attr_flags; /* Message attributes */ + size_t message_size; /* Message size */ + size_t num; /* Message number */ + char *uidl; /* Cached uidl string. */ + mu_message_t message; /* Pointer to the message structure */ struct _pop3_mailbox *mpd; /* Back pointer. */ }; @@ -87,10 +90,16 @@ struct _pop3_mailbox size_t msg_max; /* Actual size of the array */ mu_mailbox_t mbox; /* MU mailbox corresponding to this one. */ - char *user; /* Temporary holders for user and passwd. */ + mu_stream_t cache; /* Message cache stream */ + /* Temporary holders for user and passwd: */ + char *user; mu_secret_t secret; }; + +/* ------------------------------------------------------------------------- */ +/* Basic operations */ + static int pop_open (mu_mailbox_t mbox, int flags) { @@ -193,6 +202,7 @@ pop_close (mu_mailbox_t mbox) if (status) mu_error ("mu_pop3_disconnect failed: %s", mu_strerror (status)); mu_pop3_destroy (&mpd->pop3); + mu_stream_destroy (&mpd->cache); return 0; } @@ -220,6 +230,7 @@ pop_destroy (mu_mailbox_t mbox) free (mpd->user); if (mpd->secret) mu_secret_unref (mpd->secret); + mu_stream_destroy (&mpd->cache); } } @@ -319,6 +330,156 @@ pop_get_size (mu_mailbox_t mbox, mu_off_t *psize) } +/* ------------------------------------------------------------------------- */ +/* POP3 message streams */ + +static void +pop_stream_drain (mu_stream_t str) +{ + char buf[2048]; + size_t size; + + while (mu_stream_read (str, buf, sizeof buf, &size) == 0 && size) + ; +} + +static int +_pop_message_get_stream (struct _pop3_message *mpm, mu_stream_t *pstr) +{ + int status; + struct _pop3_mailbox *mpd = mpm->mpd; + + if (!(mpm->flags & _POP3_MSG_CACHED)) + { + mu_stream_t stream; + mu_off_t size; + + status = mu_pop3_retr (mpd->pop3, mpm->num, &stream); + if (status) + return status; + + do + { + mu_stream_t flt; + + if (!mpd->cache) + { + status = mu_temp_file_stream_create (&mpd->cache, NULL); + if (status) + /* FIXME: Try to recover first */ + break; + + status = mu_stream_open (mpd->cache); + if (status) + { + mu_stream_destroy (&mpd->cache); + break; + } + mu_stream_set_buffer (mpd->cache, mu_buffer_full, 8192); + } + + status = mu_stream_size (mpd->cache, &mpm->offset); + if (status) + break; + + status = mu_filter_create (&flt, stream, "CRLF", MU_FILTER_DECODE, + MU_STREAM_READ); + if (status) + break; + + status = mu_stream_copy (mpd->cache, flt, 0, &size); + + mu_stream_destroy (&flt); + } + while (0); + + if (status) + { + pop_stream_drain (stream); + mu_stream_unref (stream); + return status; + } + + mu_stream_unref (stream); + + mpm->message_size = size; /* FIXME: Possible overflow. */ + + mpm->flags |= _POP3_MSG_CACHED | _POP3_MSG_SIZE; + } + return mu_streamref_create_abridged (pstr, mpd->cache, + mpm->offset, + mpm->offset + mpm->message_size - 1); +} + +static int +pop_message_get_stream (mu_message_t msg, mu_stream_t *pstr) +{ + struct _pop3_message *mpm = mu_message_get_owner (msg); + return _pop_message_get_stream (mpm, pstr); +} + +static int +pop_scan_message (struct _pop3_message *mpm) +{ + int status; + mu_stream_t stream; + struct mu_message_scan scan; + + if (mpm->flags & _POP3_MSG_SCANNED) + return 0; + + status = _pop_message_get_stream (mpm, &stream); + if (status) + return status; + + scan.flags = MU_SCAN_SEEK | MU_SCAN_SIZE; + scan.message_start = 0; + scan.message_size = mpm->message_size; + status = mu_stream_scan_message (stream, &scan); + mu_stream_unref (stream); + + if (status == 0) + { + mpm->body_start = scan.body_start; + mpm->body_end = scan.body_end; + mpm->header_lines = scan.header_lines; + mpm->body_lines = scan.body_lines; + if (!(mpm->flags & _POP3_MSG_ATTRSET)) + { + mpm->attr_flags = scan.attr_flags; + mpm->flags |= _POP3_MSG_ATTRSET; + } + + mpm->flags |= _POP3_MSG_SCANNED; + } + + return status; +} + + +static int +pop_message_size (mu_message_t msg, size_t *psize) +{ + struct _pop3_message *mpm = mu_message_get_owner (msg); + struct _pop3_mailbox *mpd = mpm->mpd; + + if (mpm == NULL) + return EINVAL; + + if (!(mpm->flags & _POP3_MSG_SIZE)) + { + /* FIXME: The size obtained this way may differ from the actual one + by the number of lines in the message. */ + int status = mu_pop3_list (mpd->pop3, mpm->num, &mpm->message_size); + if (status) + return status; + mpm->flags |= _POP3_MSG_SIZE; + } + if (psize) + *psize = mpm->message_size; + return 0; +} + static int pop_create_message (struct _pop3_message *mpm, struct _pop3_mailbox *mpd) { @@ -328,7 +489,9 @@ pop_create_message (struct _pop3_message *mpm, struct _pop3_mailbox *mpd) status = mu_message_create (&msg, mpm); if (status) return status; - // FIXME... + + mu_message_set_get_stream (msg, pop_message_get_stream, mpm); + mu_message_set_size (msg, pop_message_size, mpm); mpm->message = msg; return 0; } @@ -337,46 +500,34 @@ pop_create_message (struct _pop3_message *mpm, struct _pop3_mailbox *mpd) /* ------------------------------------------------------------------------- */ /* Header */ -static int -pop_header_fill (void *data, char **pbuf, size_t *plen) +int +pop_header_blurb (mu_stream_t stream, size_t maxlines, + char **pbuf, size_t *plen) { - struct _pop3_message *mpm = data; - struct _pop3_mailbox *mpd = mpm->mpd; - mu_stream_t stream; - mu_opool_t opool; int status; + mu_opool_t opool; + size_t size = 0; + char *buf = NULL; + size_t n; + size_t nlines = 0; status = mu_opool_create (&opool, 0); if (status) return status; - - if (mu_pop3_capa_test (mpd->pop3, "TOP", NULL) == 0) - status = mu_pop3_top (mpd->pop3, mpm->num, 0, &stream); - else - status = mu_pop3_retr (mpd->pop3, mpm->num, &stream); - + + while ((status = mu_stream_getline (stream, &buf, &size, &n)) == 0 && n > 0) + { + size_t len = mu_rtrim_cset (buf, "\r\n"); + if (len == 0) + break; + mu_opool_append (opool, buf, len); + mu_opool_append_char (opool, '\n'); + if (maxlines && ++nlines >= maxlines) + break; + } + if (status == 0) { - size_t size = 0; - char *buf = NULL; - size_t n; - - while (mu_stream_getline (stream, &buf, &size, &n) == 0 - && n > 0) - { - size_t len = mu_rtrim_cset (buf, "\r\n"); - if (len == 0) - break; - mu_opool_append (opool, buf, len); - mu_opool_append_char (opool, '\n'); - } - - if (!mu_stream_eof (stream)) - /* Drain the stream. */ - while (mu_stream_getline (stream, &buf, &size, &n) == 0 - && n > 0); - mu_stream_destroy (&stream); - n = mu_opool_size (opool); if (n > size) { @@ -384,19 +535,53 @@ pop_header_fill (void *data, char **pbuf, size_t *plen) if (!p) { free (buf); - mu_opool_destroy (&opool); - return ENOMEM; + status = ENOMEM; } - buf = p; + else + buf = p; } + } + if (status == 0) + { mu_opool_copy (opool, buf, n); *pbuf = buf; *plen = n; - status = 0; } + else + free (buf); mu_opool_destroy (&opool); - + + return 0; +} + +static int +pop_header_fill (void *data, char **pbuf, size_t *plen) +{ + struct _pop3_message *mpm = data; + struct _pop3_mailbox *mpd = mpm->mpd; + mu_stream_t stream; + int status; + + if (mpm->flags & _POP3_MSG_SCANNED) + status = _pop_message_get_stream (mpm, &stream); + else + { + status = mu_pop3_top (mpd->pop3, mpm->num, 0, &stream); + if (status == 0) + { + status = pop_header_blurb (stream, 0, pbuf, plen); + if (!mu_stream_eof (stream)) + pop_stream_drain (stream); + mu_stream_destroy (&stream); + return status; + } + else + status = _pop_message_get_stream (mpm, &stream); + } + + status = pop_header_blurb (stream, mpm->header_lines, pbuf, plen); + mu_stream_destroy (&stream); return status; } @@ -437,7 +622,7 @@ pop_get_attribute (mu_attribute_t attr, int *pflags) if (mpm == NULL || pflags == NULL) return EINVAL; - if (mpm->attr_flags == 0) + if (!(mpm->flags & _POP3_MSG_ATTRSET)) { hdr_status[0] = '\0'; @@ -458,6 +643,7 @@ pop_set_attribute (mu_attribute_t attr, int flags) if (mpm == NULL) return EINVAL; mpm->attr_flags |= flags; + mpm->flags |= _POP3_MSG_ATTRSET; return 0; } @@ -469,6 +655,7 @@ pop_unset_attribute (mu_attribute_t attr, int flags) if (mpm == NULL) return EINVAL; mpm->attr_flags &= ~flags; + mpm->flags |= _POP3_MSG_ATTRSET; return 0; } @@ -492,11 +679,58 @@ pop_create_attribute (struct _pop3_message *mpm) /* ------------------------------------------------------------------------- */ /* Body */ +int +pop_body_get_stream (mu_body_t body, mu_stream_t *pstr) +{ + struct _pop3_message *mpm = mu_body_get_owner (body); + struct _pop3_mailbox *mpd = mpm->mpd; + int status = pop_scan_message (mpm); + if (status) + return status; + return mu_streamref_create_abridged (pstr, mpd->cache, + mpm->offset + mpm->body_start, + mpm->offset + mpm->body_end - 1); +} + +static int +pop_body_size (mu_body_t body, size_t *psize) +{ + struct _pop3_message *mpm = mu_body_get_owner (body); + int status = pop_scan_message (mpm); + if (status) + return status; + *psize = mpm->body_end - mpm->body_start; + return 0; +} + +static int +pop_body_lines (mu_body_t body, size_t *plines) +{ + struct _pop3_message *mpm = mu_body_get_owner (body); + int status = pop_scan_message (mpm); + if (status) + return status; + *plines = mpm->body_lines; + return 0; +} + static int pop_create_body (struct _pop3_message *mpm) { - /* FIXME */ - return ENOSYS; + int status; + mu_body_t body = NULL; + + status = mu_body_create (&body, mpm); + if (status) + return status; + + mu_body_set_get_stream (body, pop_body_get_stream, mpm); + mu_body_set_size (body, pop_body_size, mpm); + mu_body_set_lines (body, pop_body_lines, mpm); + + mu_message_set_body (mpm->message, body, mpm); + + return 0; } @@ -568,9 +802,9 @@ pop_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg) if (!mpd->msg) return ENOMEM; } - if (mpd->msg[msgno]) + if (mpd->msg[msgno - 1]) { - *pmsg = mpd->msg[msgno]->message; + *pmsg = mpd->msg[msgno - 1]->message; return 0; } @@ -613,13 +847,45 @@ pop_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg) mu_message_set_uid (mpm->message, pop_uid, mpm); - mpd->msg[msgno] = mpm; + mpd->msg[msgno - 1] = mpm; mu_message_set_mailbox (mpm->message, mbox, mpm); *pmsg = mpm->message; return 0; } static int +pop_expunge (mu_mailbox_t mbox) +{ + struct _pop3_mailbox *mpd = mbox->data; + int status = 0; + size_t i; + + if (mpd == NULL) + return EINVAL; + + if (!mpd->msg) + return 0; + + for (i = 0; i < mpd->msg_count; i++) + { + struct _pop3_message *mpm = mpd->msg[i]; + + if (mpm && + (mpm->flags & _POP3_MSG_ATTRSET) && + (mpm->attr_flags & MU_ATTRIBUTE_DELETED)) + { + status = mu_pop3_dele (mpd->pop3, mpm->num); + if (status) + break; + } + } + return 0; +} + +/* ------------------------------------------------------------------------- */ +/* Initialization */ + +static int _pop3_mailbox_init (mu_mailbox_t mbox, int pops) { struct _pop3_mailbox *mpd; @@ -649,13 +915,10 @@ _pop3_mailbox_init (mu_mailbox_t mbox, int pops) mbox->_message_unseen = pop_message_unseen; mbox->_get_size = pop_get_size; -#if 0 //FIXME /* Messages. */ mbox->_get_message = pop_get_message; mbox->_expunge = pop_expunge; - - /* Set our properties. */ { mu_property_t property = NULL; @@ -663,7 +926,6 @@ _pop3_mailbox_init (mu_mailbox_t mbox, int pops) mu_property_set_value (property, "TYPE", "POP3", 1); } -#endif /* Hack! POP does not really have a folder. */ mbox->folder->data = mbox; return status; @@ -682,6 +944,7 @@ _mailbox_pops_init (mu_mailbox_t mbox) } +/* ------------------------------------------------------------------------- */ /* Authentication */ /* Extract the User from the URL or the ticket. */ diff --git a/mail/decode.c b/mail/decode.c index 1a2f36936..cd1d159a5 100644 --- a/mail/decode.c +++ b/mail/decode.c @@ -424,7 +424,7 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg) mu_error ("mu_ |