summaryrefslogtreecommitdiff
path: root/libproto/pop/mbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'libproto/pop/mbox.c')
-rw-r--r--libproto/pop/mbox.c1197
1 files changed, 0 insertions, 1197 deletions
diff --git a/libproto/pop/mbox.c b/libproto/pop/mbox.c
deleted file mode 100644
index b44667fe7..000000000
--- a/libproto/pop/mbox.c
+++ /dev/null
@@ -1,1197 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 1999-2019 Free Software Foundation, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General
- Public License along with this library. If not, see
- <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef ENABLE_POP
-
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <netinet/in.h>
-
-#include <mailutils/pop3.h>
-#include <mailutils/attribute.h>
-#include <mailutils/auth.h>
-#include <mailutils/body.h>
-#include <mailutils/debug.h>
-#include <mailutils/errno.h>
-#include <mailutils/error.h>
-#include <mailutils/header.h>
-#include <mailutils/message.h>
-#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>
-#include <mailutils/md5.h>
-#include <mailutils/io.h>
-#include <mailutils/util.h>
-#include <mailutils/cstr.h>
-#include <mailutils/cctype.h>
-#include <mailutils/opool.h>
-#include <mailutils/sockaddr.h>
-
-#include <mailutils/sys/folder.h>
-#include <mailutils/sys/mailbox.h>
-#include <mailutils/sys/registrar.h>
-#include <mailutils/sys/url.h>
-
-#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 */
-#define _POP3_MSG_LINES 0x10 /* Number of lines was obtained */
-
-struct _pop3_message
-{
- int flags;
- 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 message_lines; /* Number of lines in the message */
- 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. */
-};
-
-struct _pop3_mailbox
-{
- mu_pop3_t pop3; /* mu_pop3_t is the working horse */
- int pops; /* true if pop3 over SSL is being used */
- int is_updated; /* true if the mailbox info is up to date */
-
- size_t msg_count; /* Number of messages in the mailbox */
- mu_off_t total_size; /* Total mailbox size. */
- struct _pop3_message **msg; /* Array of messages */
- size_t msg_max; /* Actual size of the array */
- mu_mailbox_t mbox; /* MU mailbox corresponding to this one. */
-
- mu_stream_t cache; /* Message cache stream */
- /* Temporary holders for user and passwd: */
- char *user;
- mu_secret_t secret;
-};
-
-static int pop_create_pop3_message (struct _pop3_mailbox *mpd, size_t msgno,
- struct _pop3_message **mptr);
-
-
-/* ------------------------------------------------------------------------- */
-/* Basic operations */
-
-static int
-pop_open (mu_mailbox_t mbox, int flags)
-{
- struct _pop3_mailbox *mpd = mbox->data;
- int status;
- mu_stream_t stream;
- struct mu_sockaddr *sa;
- struct mu_sockaddr_hints hints;
-
- /* Sanity checks. */
- if (mpd == NULL)
- return EINVAL;
-
- mbox->flags = flags;
-
- memset (&hints, 0, sizeof (hints));
- hints.flags = MU_AH_DETECT_FAMILY;
- hints.port = mpd->pops ? MU_POPS_PORT : MU_POP_PORT;
- hints.protocol = IPPROTO_TCP;
- hints.socktype = SOCK_STREAM;
- status = mu_sockaddr_from_url (&sa, mbox->url, &hints);
- if (status)
- return status;
-
- status = mu_tcp_stream_create_from_sa (&stream, sa, NULL, mbox->flags);
- if (status)
- {
- mu_sockaddr_free (sa);
- return status;
- }
-#ifdef WITH_TLS
- if (mpd->pops)
- {
- mu_stream_t newstr;
-
- status = mu_tls_client_stream_create (&newstr, stream, stream, 0);
- mu_stream_unref (stream);
- if (status)
- {
- mu_error ("pop_open: mu_tls_client_stream_create: %s",
- mu_strerror (status));
- return status;
- }
- stream = newstr;
- }
-#endif /* WITH_TLS */
-
- /* FIXME: How to configure buffer size? */
- mu_stream_set_buffer (stream, mu_buffer_line, 0);
-
- status = mu_pop3_create (&mpd->pop3);
- if (status)
- {
- mu_stream_destroy (&stream);
- return status;
- }
- mu_pop3_set_carrier (mpd->pop3, stream);
-
- if (mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_PROT))
- mu_pop3_trace (mpd->pop3, MU_POP3_TRACE_SET);
- if (mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE6))
- mu_pop3_trace_mask (mpd->pop3, MU_POP3_TRACE_SET, MU_XSCRIPT_SECURE);
- if (mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE7))
- mu_pop3_trace_mask (mpd->pop3, MU_POP3_TRACE_SET, MU_XSCRIPT_PAYLOAD);
-
- do
- {
- status = mu_pop3_connect (mpd->pop3);
- if (status)
- break;
-
- status = mu_pop3_capa (mpd->pop3, 1, NULL);
- if (status == MU_ERR_REPLY)
- {
- mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
- ("server rejected the CAPA command: %s",
- mu_pop3_strresp (mpd->pop3)));
- /* try to continue anyway */
- }
- else if (status)
- return status;
-
-#ifdef WITH_TLS
- if (!mpd->pops &&
- mu_url_sget_param (mbox->url, "notls", NULL) == MU_ERR_NOENT &&
- mu_pop3_capa_test (mpd->pop3, "STLS", NULL) == 0)
- {
- status = mu_pop3_stls (mpd->pop3);
- if (status)
- break;
- }
-#endif
- status = mu_authority_authenticate (mbox->folder->authority);
- }
- while (0);
-
- if (status)
- mu_pop3_destroy (&mpd->pop3);
- return status;
-}
-
-static int
-pop_close (mu_mailbox_t mbox)
-{
- struct _pop3_mailbox *mpd = mbox->data;
- int status;
-
- status = mu_pop3_quit (mpd->pop3);
- if (status)
- mu_error ("mu_pop3_quit failed: %s", mu_strerror (status));
- status = mu_pop3_disconnect (mpd->pop3);
- if (status)
- mu_error ("mu_pop3_disconnect failed: %s", mu_strerror (status));
- if (mpd->msg)
- {
- size_t i;
-
- mu_monitor_wrlock (mbox->monitor);
- /* Destroy the pop messages and resources associated to them. */
- for (i = 0; i < mpd->msg_count; i++)
- {
- if (mpd->msg[i])
- {
- mu_message_destroy (&mpd->msg[i]->message, mpd->msg[i]);
- if (mpd->msg[i]->uidl)
- free (mpd->msg[i]->uidl);
- free (mpd->msg[i]);
- }
- }
- mu_monitor_unlock (mbox->monitor);
- }
- mu_stream_destroy (&mpd->cache);
- return 0;
-}
-
-static void
-pop_destroy (mu_mailbox_t mbox)
-{
- struct _pop3_mailbox *mpd = mbox->data;
- if (mpd)
- {
- mu_pop3_destroy (&mpd->pop3);
- if (mpd->user)
- free (mpd->user);
- if (mpd->secret)
- mu_secret_unref (mpd->secret);
- }
-}
-
-/* Update and scanning. */
-static int
-pop_is_updated (mu_mailbox_t mbox)
-{
- struct _pop3_mailbox *mpd = mbox->data;
- if (mpd == NULL)
- return 0;
- return mpd->is_updated;
-}
-
-/* Return the number of messages in the mailbox */
-static int
-pop_messages_count (mu_mailbox_t mbox, size_t *pcount)
-{
- struct _pop3_mailbox *mpd = mbox->data;
- int status;
-
- if (mpd == NULL)
- return EINVAL;
-
- if (pop_is_updated (mbox))
- {
- if (pcount)
- *pcount = mpd->msg_count;
- return 0;
- }
-
- status = mu_pop3_stat (mpd->pop3, &mpd->msg_count, &mpd->total_size);
- if (status == 0)
- {
- if (pcount)
- *pcount = mpd->msg_count;
- mpd->is_updated = 1;
- }
- return status;
-}
-
-static int
-pop_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount)
-{
- int status;
- size_t i;
- size_t count = 0;
- struct _pop3_mailbox *mpd = mbox->data;
- int flags;
- mu_iterator_t itr;
-
- status = pop_messages_count (mbox, &count);
- if (status != 0)
- return status;
- if (pcount)
- *pcount = count;
-
- flags = _POP3_MSG_SIZE;
- if (!mu_pop3_capa_test (mpd->pop3, "XLINES", NULL))
- flags |= _POP3_MSG_LINES;
-
- status = mu_pop3_list_all (mpd->pop3, &itr);
- if (status)
- return status;
-
- for (i = 0, mu_iterator_first (itr);
- i <= count && !mu_iterator_is_done (itr);
- i++, mu_iterator_next (itr))
- {
- const char *str;
- char *p;
- size_t num;
-
- mu_iterator_current (itr, (void**) &str);
- num = strtoul (str, &p, 10);
-
- if (*p != ' ')
- {
- mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
- ("invalid reply to LIST command: %s", str));
- status = MU_ERR_BADREPLY;
- break;
- }
- if (num >= msgno)
- {
- size_t size, lines;
- struct _pop3_message *mpm;
-
- size = strtoul (p + 1, &p, 10);
- if (flags & _POP3_MSG_LINES)
- {
- if (*p != ' ')
- {
- mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
- ("invalid reply to LIST command: %s", str));
- status = MU_ERR_BADREPLY;
- break;
- }
- lines = strtoul (p + 1, &p, 10);
- }
-
- status = pop_create_pop3_message (mpd, num, &mpm);
- if (status)
- break;
- mpm->message_size = size;
- if (flags & _POP3_MSG_LINES)
- mpm->message_lines = lines;
- mpm->flags |= flags;
-
- if (mbox->observable)
- {
- if (((i + 1) % 10) == 0)
- mu_observable_notify (mbox->observable,
- MU_EVT_MAILBOX_PROGRESS,
- NULL);
- }
- }
- }
-
- mu_iterator_destroy (&itr);
-
- if (mbox->observable)
- {
- /* MU_EVT_MESSAGE_ADD must be delivered only when it is already possible
- to retrieve the message in question. It could not be done in the
- main loop because no other pop3d function can be called while LIST
- is being handled. Hence the extra loop. */
- for (i = 0; i <= count; i++)
- {
- if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD,
- &i) != 0)
- break;
- }
- }
-
- return status;
-}
-
-/* There's no way to retrieve this info via POP3 */
-static int
-pop_message_unseen (mu_mailbox_t mbox, size_t *punseen)
-{
- size_t count = 0;
- int status = pop_messages_count (mbox, &count);
- if (status != 0)
- return status;
- if (punseen)
- *punseen = (count > 0) ? 1 : 0;
- return 0;
-}
-
-static int
-pop_get_size (mu_mailbox_t mbox, mu_off_t *psize)
-{
- struct _pop3_mailbox *mpd = mbox->data;
- int status = 0;
-
- if (mpd == NULL)
- return EINVAL;
-
- if (!pop_is_updated (mbox))
- status = pop_messages_count (mbox, NULL);
- if (psize)
- *psize = mpd->total_size;
- return status;
-}
-
-
-/* ------------------------------------------------------------------------- */
-/* 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, 0);
- if (status)
- /* FIXME: Try to recover first */
- 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_message_lines (mu_message_t msg, size_t *plines, int quick)
-{
- int rc;
- struct _pop3_message *mpm = mu_message_get_owner (msg);
-
- if (!(mpm->flags & _POP3_MSG_LINES))
- {
- if (quick && !(mpm->flags & _POP3_MSG_CACHED))
- return MU_ERR_INFO_UNAVAILABLE;
- if (!pop_is_updated (mpm->mpd->mbox))
- pop_scan (mpm->mpd->mbox, 1, NULL);
- rc = pop_scan_message (mpm);
- if (rc)
- return rc;
- mpm->message_lines = mpm->header_lines + mpm->body_lines + 1;
- mpm->flags |= _POP3_MSG_LINES;
- }
-
- *plines = mpm->message_lines;
- return 0;
-}
-
-static int
-pop_create_message (struct _pop3_message *mpm, struct _pop3_mailbox *mpd)
-{
- int status;
- mu_message_t msg;
-
- status = mu_message_create (&msg, mpm);
- if (status)
- return status;
-
- mu_message_set_get_stream (msg, pop_message_get_stream, mpm);
- mu_message_set_size (msg, pop_message_size, mpm);
- mu_message_set_lines (msg, pop_message_lines, mpm);
- mpm->message = msg;
- return 0;
-}
-
-static int
-pop_create_pop3_message (struct _pop3_mailbox *mpd, size_t msgno,
- struct _pop3_message **mptr)
-{
- struct _pop3_message *mpm;
-
- if (msgno > mpd->msg_count)
- return MU_ERR_NOENT;
-
- if (!mpd->msg)
- {
- mpd->msg = calloc (mpd->msg_count, sizeof (mpd->msg[0]));
- if (!mpd->msg)
- return ENOMEM;
- }
- if (mpd->msg[msgno - 1])
- {
- *mptr = mpd->msg[msgno - 1];
- return 0;
- }
-
- mpm = calloc (1, sizeof (*mpm));
- if (mpm == NULL)
- return ENOMEM;
-
- /* Back pointer. */
- mpm->mpd = mpd;
- mpm->num = msgno;
-
- mpd->msg[msgno - 1] = mpm;
- *mptr = mpm;
- return 0;
-}
-
-
-
-/* ------------------------------------------------------------------------- */
-/* Header */
-
-int
-pop_header_blurb (mu_stream_t stream, size_t maxlines,
- char **pbuf, size_t *plen)
-{
- 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, MU_OPOOL_DEFAULT);
- if (status)
- return status;
-
- while ((status = mu_stream_getline (stream, &buf, &size, &n)) == 0 && n > 0)
- {
- size_t len = mu_rtrim_class (buf, MU_CTYPE_ENDLN);
- if (len == 0)
- break;
- mu_opool_append (opool, buf, len);
- mu_opool_append_char (opool, '\n');
- if (maxlines && ++nlines >= maxlines)
- break;
- }
-
- if (status == 0)
- {
- n = mu_opool_size (opool);
- if (n > size)
- {
- char *p = realloc (buf, n);
- if (!p)
- {
- free (buf);
- status = ENOMEM;
- }
- else
- buf = p;
- }
- }
-
- if (status == 0)
- {
- mu_opool_copy (opool, buf, n);
- *pbuf = buf;
- *plen = n;
- }
- 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);
- if (status == 0)
- {
- status = pop_header_blurb (stream, mpm->header_lines, pbuf, plen);
- mu_stream_destroy (&stream);
- }
- }
- else
- {
- status = mu_pop3_top (mpd->pop3, mpm->num, 0, &stream);
- if (status)
- status = _pop_message_get_stream (mpm, &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;
- }
-
- return status;
-}
-
-static int
-pop_create_header (struct _pop3_message *mpm)
-{
- int status;
- mu_header_t header = NULL;
-
- status = mu_header_create (&header, NULL, 0);
- if (status)
- return status;
- mu_header_set_fill (header, pop_header_fill, mpm);
- mu_message_set_header (mpm->message, header, mpm);
- return 0;
-}
-
-
-/* ------------------------------------------------------------------------- */
-/* Attributes */
-
-/* There is no POP3 command to return message attributes, therefore we
- have to recurse to reading the "Status:" header. Unfortunately, some
- servers remove it when you dowload a message, and in this case a message
- will always look like new even if you already read it. There is also
- no way to set an attribute on remote mailbox via the POP server and
- many server once you do a RETR (and in some cases a TOP) will mark the
- message as read (Status: RO). Even worse, some servers may be configured
- to delete after the RETR, and some go as much as deleting after the TOP,
- since technicaly you can download a message via TOP without RETR'eiving
- it. */
-static int
-pop_get_attribute (mu_attribute_t attr, int *pflags)
-{
- struct _pop3_message *mpm = mu_attribute_get_owner (attr);
- char hdr_status[64];
- mu_header_t header = NULL;
-
- if (mpm == NULL || pflags == NULL)
- return EINVAL;
- if (!(mpm->flags & _POP3_MSG_ATTRSET))
- {
- hdr_status[0] = '\0';
-
- mu_message_get_header (mpm->message, &header);
- mu_header_get_value (header, MU_HEADER_STATUS,
- hdr_status, sizeof hdr_status, NULL);
- mu_string_to_flags (hdr_status, &mpm->attr_flags);
- }
- *pflags = mpm->attr_flags;
- return 0;
-}
-
-static int
-pop_set_attribute (mu_attribute_t attr, int flags)
-{
- struct _pop3_message *mpm = mu_attribute_get_owner (attr);
-
- if (mpm == NULL)
- return EINVAL;
- mpm->attr_flags |= flags;
- mpm->flags |= _POP3_MSG_ATTRSET;
- return 0;
-}
-
-static int
-pop_unset_attribute (mu_attribute_t attr, int flags)
-{
- struct _pop3_message *mpm = mu_attribute_get_owner (attr);
-
- if (mpm == NULL)
- return EINVAL;
- mpm->attr_flags &= ~flags;
- mpm->flags |= _POP3_MSG_ATTRSET;
- return 0;
-}
-
-static int
-pop_create_attribute (struct _pop3_message *mpm)
-{
- int status;
- mu_attribute_t attribute;
-
- status = mu_attribute_create (&attribute, mpm);
- if (status)
- return status;
-
- mu_attribute_set_get_flags (attribute, pop_get_attribute, mpm);
- mu_attribute_set_set_flags (attribute, pop_set_attribute, mpm);
- mu_attribute_set_unset_flags (attribute, pop_unset_attribute, mpm);
- mu_message_set_attribute (mpm->message, attribute, mpm);
- return 0;
-}
-
-/* ------------------------------------------------------------------------- */
-/* Body */
-
-int
-pop_body_get_stream (mu_body_t body, mu_stream_t *pstr)
-{
- mu_message_t msg = mu_body_get_owner (body);
- struct _pop3_message *mpm = mu_message_get_owner (msg);
- 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)
-{
- mu_message_t msg = mu_body_get_owner (body);
- struct _pop3_message *mpm = mu_message_get_owner (msg);
- 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)
-{
- mu_message_t msg = mu_body_get_owner (body);
- struct _pop3_message *mpm = mu_message_get_owner (msg);
- 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)
-{
- int status;
- mu_body_t body = NULL;
- mu_message_t msg = mpm->message;
-
- /* FIXME: The owner of the body *must* be the message it belongs to. */
- status = mu_body_create (&body, msg);
- if (status)
- return status;
-
- mu_body_set_get_stream (body, pop_body_get_stream, msg);
- mu_body_set_size (body, pop_body_size, msg);
- mu_body_set_lines (body, pop_body_lines, msg);
-
- mu_message_set_body (mpm->message, body, mpm);
-
- return 0;
-}
-
-
-/* FIXME: change prototype to avoid fixed size buffer */
-static int
-pop_uidl (mu_message_t msg, char *buffer, size_t buflen, size_t *pnwriten)
-{
- struct _pop3_message *mpm = mu_message_get_owner (msg);
- struct _pop3_mailbox *mpd = mpm->mpd;
- size_t len;
-
- if (!mpm->uidl)
- {
- if (mu_pop3_capa_test (mpd->pop3, "UIDL", NULL) == 0)
- {
- int status = mu_pop3_uidl (mpd->pop3, mpm->num, &mpm->uidl);
- if (status)
- return status;
- }
- else
- return ENOSYS;
- }
-
- len = strlen (mpm->uidl);
- if (buffer)
- {
- buflen--; /* Leave space for the null. */
- buflen = (len > buflen) ? buflen : len;
- memcpy (buffer, mpm->uidl, buflen);
- buffer[buflen] = 0;
- }
- else
- buflen = len;
- if (pnwriten)
- *pnwriten = buflen;
- return 0;
-}
-
-static int
-pop_uid (mu_message_t msg, size_t *puid)
-{
- struct _pop3_message *mpm = mu_message_get_owner (msg);
- if (puid)
- *puid = mpm->num;
- return 0;
-}
-
-static int
-pop_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg)
-{
- struct _pop3_mailbox *mpd = mbox->data;
- struct _pop3_message *mpm;
- int status;
-
- /* Sanity checks. */
- if (pmsg == NULL || mpd == NULL)
- return EINVAL;
-
- /* If we did not start a scanning yet do it now. */
- if (!pop_is_updated (mbox))
- pop_scan (mbox, 1, NULL);
-
- status = pop_create_pop3_message (mpd, msgno, &mpm);
- if (status)
- return status;
- if (mpm->message)
- {
- *pmsg = mpm->message;
- return 0;
- }
-
- status = pop_create_message (mpm, mpd);
- if (status)
- return status;
-
- do
- {
- status = pop_create_header (mpm);
- if (status)
- break;
- status = pop_create_attribute (mpm);
- if (status)
- break;
- status = pop_create_body (mpm);
- }
- while (0);
-
- if (status)
- {
- mu_message_destroy (&mpm->message, mpm);
- free (mpm);
- return status;
- }
-
- if (mu_pop3_capa_test (mpd->pop3, "UIDL", NULL) == 0)
- mu_message_set_uidl (mpm->message, pop_uidl, mpm);
-
- mu_message_set_uid (mpm->message, pop_uid, 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;
- size_t expcount = 0;
-
- 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))
- {
- size_t expevt[2] = { i + 1, expcount };
- status = mu_pop3_dele (mpd->pop3, mpm->num);
- if (status)
- break;
- mu_observable_notify (mbox->observable,
- MU_EVT_MAILBOX_MESSAGE_EXPUNGE,
- &expevt);
- ++expcount;
- }
- }
- return 0;
-}
-
-/* ------------------------------------------------------------------------- */
-/* Initialization */
-
-static int
-_pop3_mailbox_init (mu_mailbox_t mbox, int pops)
-{
- struct _pop3_mailbox *mpd;
- int status = 0;
-
- /* Allocate specifics for pop data. */
- mpd = mbox->data = calloc (1, sizeof (*mpd));
- if (mbox->data == NULL)
- return ENOMEM;
-
- mpd->pop3 = NULL;
-
- mpd->mbox = mbox; /* Back pointer. */
- mpd->pops = pops;
-
- /* Initialize the structure. */
- mbox->_destroy = pop_destroy;
-
- mbox->_open = pop_open;
- mbox->_close = pop_close;
- mbox->_messages_count = pop_messages_count;
- /* FIXME: There is no way to retrieve the number of recent messages via
- POP3 protocol, so we consider all messages recent. */
- mbox->_messages_recent = pop_messages_count;
- mbox->_is_updated = pop_is_updated;
- mbox->_scan = pop_scan;
- mbox->_message_unseen = pop_message_unseen;
- mbox->_get_size = pop_get_size;
-
- /* Messages. */
- mbox->_get_message = pop_get_message;
- mbox->_expunge = pop_expunge;
-
- /* Set our properties. */
- {
- mu_property_t property = NULL;
- mu_mailbox_get_property (mbox, &property);
- mu_property_set_value (property, "TYPE", "POP3", 1);
- }
-
- /* Hack! POP does not really have a folder. */
- mbox->folder->data = mbox;
- return status;
-}
-
-int
-_mailbox_pop_init (mu_mailbox_t mbox)
-{
- return _pop3_mailbox_init (mbox, 0);
-}
-
-int
-_mailbox_pops_init (mu_mailbox_t mbox)
-{
- return _pop3_mailbox_init (mbox, 1);
-}
-
-
-/* ------------------------------------------------------------------------- */
-/* Authentication */
-
-/* Extract the User from the URL or the ticket. */
-static int
-pop_get_user (mu_authority_t auth)
-{
- mu_folder_t folder = mu_authority_get_owner (auth);
- mu_mailbox_t mbox = folder->data;
- struct _pop3_mailbox *mpd = mbox->data;
- mu_ticket_t ticket = NULL;
- int status;
- /* Fetch the user from them. */
-
- mu_authority_get_ticket (auth, &ticket);
- if (mpd->user)
- {
- free (mpd->user);
- mpd->user = NULL;
- }
- /* Was it in the URL? */
- status = mu_url_aget_user (mbox->url, &mpd->user);
- if (status == MU_ERR_NOENT)
- status = mu_ticket_get_cred (ticket, mbox->url, "Pop User: ",
- &mpd->user, NULL);
- if (status == MU_ERR_NOENT || mpd->user == NULL)
- return MU_ERR_NOUSERNAME;
- return status;
-}
-
-/* Extract the User from the URL or the ticket. */
-static int
-pop_get_passwd (mu_authority_t auth)
-{
- mu_folder_t folder = mu_authority_get_owner (auth);
- mu_mailbox_t mbox = folder->data;
- struct _pop3_mailbox *mpd = mbox->data;
- mu_ticket_t ticket = NULL;
- int status;
-
- mu_authority_get_ticket (auth, &ticket);
- /* Was it in the URL? */
- status = mu_url_get_secret (mbox->url, &mpd->secret);
- if (status == MU_ERR_NOENT)
- status = mu_ticket_get_cred (ticket, mbox->url, "Pop Passwd: ",
- NULL, &mpd->secret);
- if (status == MU_ERR_NOENT || !mpd->secret)
- /* FIXME: Is this always right? The user might legitimately have
- no password */
- return MU_ERR_NOPASSWORD;
- return 0;
-}
-
-int
-_pop_apop (mu_authority_t auth)
-{
- mu_folder_t folder = mu_authority_get_owner (auth);
- mu_mailbox_t mbox = folder->data;
- struct _pop3_mailbox *mpd = mbox->data;
- int status;
-
- status = pop_get_user (auth);
- if (status)
- return status;
-
- /* Fetch the secret from them. */
- status = pop_get_passwd (auth);
- if (status)
- return status;
- status = mu_pop3_apop (mpd->pop3, mpd->user,
- mu_secret_password (mpd->secret));
- mu_secret_password_unref (mpd->secret);
- mu_secret_unref (mpd->secret);
- mpd->secret = NULL;
- free (mpd->user);
- mpd->user = NULL;
- return status;
-}
-
-int
-_pop_user (mu_authority_t auth)
-{
- mu_folder_t folder = mu_authority_get_owner (auth);
- mu_mailbox_t mbox = folder->data;
- struct _pop3_mailbox *mpd = mbox->data;
- int status;
-
- status = pop_get_user (auth);
- if (status)
- return status;
- status = mu_pop3_user (mpd->pop3, mpd->user);
- if (status == 0)
- {
- /* Fetch the secret from them. */
- status = pop_get_passwd (auth);
- if (status == 0)
- {
- status = mu_pop3_pass (mpd->pop3, mu_secret_password (mpd->secret));
- mu_secret_password_unref (mpd->secret);
- mu_secret_unref (mpd->secret);
- mpd->secret = NULL;
- }
- }
- free (mpd->user);
- mpd->user = NULL;
- return status;
-}
-
-
-#endif /* ENABLE_POP */

Return to:

Send suggestions and report system problems to the System administrator.