summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-09-07 13:57:30 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-09-07 13:57:30 +0300
commit817286698ccc3f262cd0003401becef6c11050ae (patch)
tree5e90dce6beec2618a4894b8708f28d877fb99ad6
parentbfb29ced5d88dbe449347d5b8b86e6ee887c450b (diff)
downloadmailutils-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.c2
-rw-r--r--examples/mucat.c4
-rw-r--r--imap4d/io.c2
-rw-r--r--include/mailutils/body.h5
-rw-r--r--include/mailutils/message.h24
-rw-r--r--include/mailutils/stream.h3
-rw-r--r--include/mailutils/sys/body.h1
-rw-r--r--include/mailutils/sys/message.h1
-rw-r--r--libmu_scm/mu_message.c2
-rw-r--r--libmu_sieve/actions.c2
-rw-r--r--libmu_sieve/extensions/pipe.c2
-rw-r--r--libmu_sieve/extensions/spamd.c2
-rw-r--r--libmu_sieve/extensions/vacation.c2
-rw-r--r--libproto/mbox/mbox.c8
-rw-r--r--libproto/pop/mbox.c385
-rw-r--r--mail/decode.c2
-rw-r--r--mail/print.c2
-rw-r--r--mailbox/Makefile.am1
-rw-r--r--mailbox/body.c84
-rw-r--r--mailbox/message.c59
-rw-r--r--mailbox/msgscan.c106
-rw-r--r--mailbox/rdcache_stream.c2
-rw-r--r--mailbox/stream.c10
-rw-r--r--mailbox/streamcpy.c18
-rw-r--r--mailbox/streamref.c18
-rw-r--r--mh/burst.c2
-rw-r--r--mh/comp.c2
-rw-r--r--mh/mhn.c10
-rw-r--r--pop3d/retr.c2
-rw-r--r--pop3d/top.c2
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_