dovecot-2.2: Created lib-imap-storage for IMAP-specific function...

dovecot at dovecot.org dovecot at dovecot.org
Sat Jun 2 19:02:27 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/07e6ca397a72
changeset: 14591:07e6ca397a72
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sat Jun 02 17:56:27 2012 +0300
description:
Created lib-imap-storage for IMAP-specific functionality that uses lib-storage.
This is done to prevent introducing dependencies on lib-storage in
lib-imap. It contains IMAP message part access functionality, including
URL-based access.

diffstat:

 configure.in                            |    5 +-
 src/Makefile.am                         |    1 +
 src/imap/Makefile.am                    |    2 +-
 src/imap/imap-fetch-body.c              |   53 +----
 src/lib-imap-storage/Makefile.am        |   21 +
 src/lib-imap-storage/imap-msgpart-url.c |  230 +++++++++++++++++++
 src/lib-imap-storage/imap-msgpart-url.h |   29 ++
 src/lib-imap-storage/imap-msgpart.c     |  371 ++++++++++++++++++++++++++++++++
 src/lib-imap-storage/imap-msgpart.h     |   24 ++
 src/lib-storage/Makefile.am             |    1 +
 10 files changed, 683 insertions(+), 54 deletions(-)

diffs (truncated from 839 to 300 lines):

diff -r 9eef4f7b0187 -r 07e6ca397a72 configure.in
--- a/configure.in	Sat Jun 02 17:53:31 2012 +0300
+++ b/configure.in	Sat Jun 02 17:56:27 2012 +0300
@@ -2512,13 +2512,13 @@
 if test "$want_shared_libs" = "yes"; then
   LIBDOVECOT_DEPS='$(top_builddir)/src/lib-dovecot/libdovecot.la'
   LIBDOVECOT="$LIBDOVECOT_DEPS"
-  LIBDOVECOT_STORAGE_DEPS='$(top_builddir)/src/lib-storage/libdovecot-storage.la'
+  LIBDOVECOT_STORAGE_DEPS='$(top_builddir)/src/lib-storage/libdovecot-storage.la $(top_builddir)/src/lib-imap-storage/libimap-storage.la'
   LIBDOVECOT_LOGIN='$(top_builddir)/src/login-common/libdovecot-login.la'
   LIBDOVECOT_LDA='$(top_builddir)/src/lib-lda/libdovecot-lda.la'
 else
   LIBDOVECOT_DEPS='$(top_builddir)/src/lib-master/libmaster.la $(top_builddir)/src/lib-settings/libsettings.la $(top_builddir)/src/lib-dict/libdict.la $(top_builddir)/src/lib-dns/libdns.la $(top_builddir)/src/lib-fs/libfs.la $(top_builddir)/src/lib-imap/libimap.la $(top_builddir)/src/lib-mail/libmail.la $(top_builddir)/src/lib-auth/libauth.la $(top_builddir)/src/lib-charset/libcharset.la $(top_builddir)/src/lib/liblib.la'
   LIBDOVECOT="$LIBDOVECOT_DEPS \$(LIBICONV)"
-  LIBDOVECOT_STORAGE_LAST='$(top_builddir)/src/lib-storage/list/libstorage_list.la $(top_builddir)/src/lib-storage/index/libstorage_index.la $(top_builddir)/src/lib-storage/libstorage.la $(top_builddir)/src/lib-index/libindex.la'
+  LIBDOVECOT_STORAGE_LAST='$(top_builddir)/src/lib-storage/list/libstorage_list.la $(top_builddir)/src/lib-storage/index/libstorage_index.la $(top_builddir)/src/lib-storage/libstorage.la $(top_builddir)/src/lib-index/libindex.la $(top_builddir)/src/lib-imap-storage/libimap-storage.la'
   LIBDOVECOT_STORAGE_FIRST='$(top_builddir)/src/lib-storage/libstorage_service.la $(top_builddir)/src/lib-storage/register/libstorage_register.la'
   LIBDOVECOT_STORAGE_DEPS="$LIBDOVECOT_STORAGE_FIRST $LINKED_STORAGE_LIBS $LIBDOVECOT_STORAGE_LAST"
   LIBDOVECOT_LOGIN='$(top_builddir)/src/login-common/liblogin.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la'
@@ -2748,6 +2748,7 @@
 src/lib-dns/Makefile
 src/lib-fs/Makefile
 src/lib-imap/Makefile
+src/lib-imap-storage/Makefile
 src/lib-imap-client/Makefile
 src/lib-index/Makefile
 src/lib-lda/Makefile
diff -r 9eef4f7b0187 -r 07e6ca397a72 src/Makefile.am
--- a/src/Makefile.am	Sat Jun 02 17:53:31 2012 +0300
+++ b/src/Makefile.am	Sat Jun 02 17:56:27 2012 +0300
@@ -6,6 +6,7 @@
 	lib-fs \
 	lib-mail \
 	lib-imap \
+	lib-imap-storage \
 	lib-master \
 	lib-dict \
 	lib-settings
diff -r 9eef4f7b0187 -r 07e6ca397a72 src/imap/Makefile.am
--- a/src/imap/Makefile.am	Sat Jun 02 17:53:31 2012 +0300
+++ b/src/imap/Makefile.am	Sat Jun 02 17:56:27 2012 +0300
@@ -9,6 +9,7 @@
 	-I$(top_srcdir)/src/lib-master \
 	-I$(top_srcdir)/src/lib-mail \
 	-I$(top_srcdir)/src/lib-imap \
+	-I$(top_srcdir)/src/lib-imap-storage \
 	-I$(top_srcdir)/src/lib-index \
 	-I$(top_srcdir)/src/lib-storage
 
@@ -78,7 +79,6 @@
 	mail-storage-callbacks.c \
 	main.c
 
-
 headers = \
 	imap-client.h \
 	imap-commands.h \
diff -r 9eef4f7b0187 -r 07e6ca397a72 src/imap/imap-fetch-body.c
--- a/src/imap/imap-fetch-body.c	Sat Jun 02 17:53:31 2012 +0300
+++ b/src/imap/imap-fetch-body.c	Sat Jun 02 17:56:27 2012 +0300
@@ -11,6 +11,7 @@
 #include "message-send.h"
 #include "mail-storage-private.h"
 #include "imap-parser.h"
+#include "imap-msgpart.h"
 #include "imap-fetch.h"
 
 #include <stdlib.h>
@@ -464,63 +465,13 @@
 	return fetch_data(ctx, body, &size);
 }
 
-/* Find message_part for section (eg. 1.3.4) */
-static int part_find(struct mail *mail, const struct imap_fetch_body_data *body,
-		     const struct message_part **part_r, const char **section_r)
-{
-	struct message_part *part;
-	const char *path;
-	unsigned int num;
-
-	if (mail_get_parts(mail, &part) < 0)
-		return -1;
-
-	path = body->section;
-	while (*path >= '0' && *path <= '9' && part != NULL) {
-		/* get part number, we have already verified its validity */
-		num = 0;
-		while (*path != '\0' && *path != '.') {
-			i_assert(*path >= '0' && *path <= '9');
-
-			num = num*10 + (*path - '0');
-			path++;
-		}
-
-		if (*path == '.')
-			path++;
-
-		if (part->flags & MESSAGE_PART_FLAG_MULTIPART) {
-			/* find the part */
-			part = part->children;
-			for (; num > 1 && part != NULL; num--)
-				part = part->next;
-		} else {
-			/* only 1 allowed with non-multipart messages */
-			if (num != 1)
-				part = NULL;
-		}
-
-		if (part != NULL &&
-		    (part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) &&
-		    (*path >= '0' && *path <= '9')) {
-			/* if we continue inside the message/rfc822, skip this
-			   body part */
-			part = part->children;
-		}
-	}
-
-	*part_r = part;
-	*section_r = path;
-	return 0;
-}
-
 static int fetch_body_mime(struct imap_fetch_context *ctx, struct mail *mail,
 			   const struct imap_fetch_body_data *body)
 {
 	const struct message_part *part;
 	const char *section;
 
-	if (part_find(mail, body, &part, &section) < 0)
+	if (imap_msgpart_find(mail, body->section, &part, &section) < 0)
 		return -1;
 
 	if (part == NULL) {
diff -r 9eef4f7b0187 -r 07e6ca397a72 src/lib-imap-storage/Makefile.am
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-imap-storage/Makefile.am	Sat Jun 02 17:56:27 2012 +0300
@@ -0,0 +1,21 @@
+noinst_LTLIBRARIES = libimap-storage.la
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/lib \
+	-I$(top_srcdir)/src/lib-test \
+	-I$(top_srcdir)/src/lib-charset \
+	-I$(top_srcdir)/src/lib-mail \
+	-I$(top_srcdir)/src/lib-storage \
+	-I$(top_srcdir)/src/lib-imap
+
+libimap_storage_la_SOURCES = \
+	imap-msgpart.c \
+	imap-msgpart-url.c
+
+headers = \
+	imap-msgpart.h \
+	imap-msgpart-url.h
+
+pkginc_libdir=$(pkgincludedir)
+pkginc_lib_HEADERS = $(headers)
+
diff -r 9eef4f7b0187 -r 07e6ca397a72 src/lib-imap-storage/imap-msgpart-url.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-imap-storage/imap-msgpart-url.c	Sat Jun 02 17:56:27 2012 +0300
@@ -0,0 +1,230 @@
+#include "lib.h"
+#include "network.h"
+#include "istream.h"
+#include "message-parser.h"
+#include "mail-storage.h"
+#include "mail-namespace.h"
+#include "imap-url.h"
+#include "imap-msgpart.h"
+#include "imap-msgpart-url.h"
+
+struct imap_msgpart_url {
+	char *mailbox;
+	uint32_t uidvalidity;
+	uint32_t uid;
+	char *section;
+	uoff_t partial_offset, partial_size;
+
+	struct mail_user *user;
+	struct mailbox *box;
+	struct mailbox_transaction_context *trans;
+	struct mail *mail;
+	
+	struct istream *input;
+	uoff_t part_size;
+};
+
+struct imap_msgpart_url *
+imap_msgpart_url_create(struct mail_user *user, const struct imap_url *url)
+{
+	struct imap_msgpart_url *mpurl;
+
+	i_assert(url->mailbox != NULL && url->uid != 0 &&
+		 url->search_program == NULL);
+
+	mpurl = i_new(struct imap_msgpart_url, 1);
+	mpurl->user = user;
+	mpurl->mailbox = i_strdup(url->mailbox);
+	mpurl->uidvalidity = url->uidvalidity;
+	mpurl->uid = url->uid;
+	if (url->section != NULL)
+		mpurl->section = i_strdup(url->section);
+	mpurl->partial_offset = url->partial_offset;
+	mpurl->partial_size = url->partial_size;
+	return mpurl;
+}
+
+struct imap_msgpart_url *
+imap_msgpart_url_parse(struct mail_user *user, struct mailbox *selected_box,
+		       const char *urlstr, const char **error_r)
+{
+	struct mailbox_status box_status;
+	struct imap_url base_url, *url;
+	const char  *error;
+
+	/* build base url */
+	memset(&base_url, 0, sizeof(base_url));
+	if (selected_box != NULL) {
+		mailbox_get_open_status(selected_box, STATUS_UIDVALIDITY,
+					&box_status);
+		base_url.mailbox = mailbox_get_vname(selected_box);
+		base_url.uidvalidity = box_status.uidvalidity;
+	}
+
+	/* parse url */
+	url = imap_url_parse(urlstr, NULL, &base_url,
+			     IMAP_URL_PARSE_REQUIRE_RELATIVE, &error);
+	if (url == NULL) {
+		*error_r = t_strconcat("Invalid IMAP URL: ", error, NULL);
+		return NULL;
+	}
+	if (url->mailbox == NULL) {
+		*error_r = "Mailbox-relative IMAP URL, but no mailbox selected";
+		return NULL;
+	}
+	if (url->uid == 0 || url->search_program != NULL) {
+		*error_r = "Invalid messagepart IMAP URL";
+		return NULL;
+	}
+	return imap_msgpart_url_create(user, url);
+}
+
+struct mailbox *imap_msgpart_url_get_mailbox(struct imap_msgpart_url *mpurl)
+{
+	return mpurl->box;
+}
+
+struct mailbox *
+imap_msgpart_url_open_mailbox(struct imap_msgpart_url *mpurl,
+			      const char **error_r)
+{
+	struct mailbox_status box_status;
+	enum mail_error error_code;
+	enum mailbox_flags flags = MAILBOX_FLAG_READONLY;
+	struct mail_namespace *ns;
+	struct mailbox *box;
+
+	if (mpurl->box != NULL)
+		return mpurl->box;
+
+	/* find mailbox namespace */
+	ns = mail_namespace_find(mpurl->user->namespaces, mpurl->mailbox);
+	if (ns == NULL) {
+		*error_r = "Nonexistent mailbox namespace";
+		return NULL;
+	}
+
+	/* open mailbox */
+	box = mailbox_alloc(ns->list, mpurl->mailbox, flags);
+	if (mailbox_open(box) < 0) {
+		*error_r = mail_storage_get_last_error(mailbox_get_storage(box),
+						       &error_code);
+		mailbox_free(&box);
+		return NULL;
+	}
+
+	/* verify UIDVALIDITY */
+	mailbox_get_open_status(box, STATUS_UIDVALIDITY, &box_status);
+	if (mpurl->uidvalidity > 0 &&
+	    box_status.uidvalidity != mpurl->uidvalidity) {
+		*error_r = "Invalid UIDVALIDITY";
+		mailbox_free(&box);
+		return NULL;
+	}
+	mpurl->box = box;
+	return box;
+}
+
+struct mail *
+imap_msgpart_url_open_mail(struct imap_msgpart_url *mpurl, const char **error_r)
+{
+	struct mailbox_transaction_context *t;
+	struct mail *mail;
+
+	if (mpurl->mail != NULL)
+		return mpurl->mail;
+
+	/* open mailbox if it is not yet open */
+	if (mpurl->box == NULL) {


More information about the dovecot-cvs mailing list