dovecot-2.0: lib-storage: Added search query building from human...

dovecot at dovecot.org dovecot at dovecot.org
Tue Apr 13 20:25:38 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/3649ad8c9f9a
changeset: 11146:3649ad8c9f9a
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Apr 13 20:25:00 2010 +0300
description:
lib-storage: Added search query building from human-friendly input.

diffstat:

 src/imap/imap-search-args.c                  |    3 +-
 src/lib-storage/Makefile.am                  |    1 +
 src/lib-storage/mail-search-build.c          |  125 ++++++++++++++---
 src/lib-storage/mail-search-build.h          |   21 ++-
 src/lib-storage/mail-search-register-human.c |  202 ++++++++++++++++++++++++++++
 src/lib-storage/mail-search-register-imap.c  |  103 ++++----------
 src/lib-storage/mail-search-register.c       |   26 ++-
 src/lib-storage/mail-search-register.h       |   10 +
 src/lib-storage/mail-storage-private.h       |    2 -
 src/lib-storage/mail-storage.c               |    4 +-
 src/plugins/virtual/virtual-config.c         |    3 +-
 11 files changed, 393 insertions(+), 107 deletions(-)

diffs (truncated from 849 to 300 lines):

diff -r 8d1d1eb2c2a0 -r 3649ad8c9f9a src/imap/imap-search-args.c
--- a/src/imap/imap-search-args.c	Tue Apr 13 19:01:58 2010 +0300
+++ b/src/imap/imap-search-args.c	Tue Apr 13 20:25:00 2010 +0300
@@ -47,7 +47,8 @@
 		return -1;
 	}
 
-	if (mail_search_build_from_imap_args(args, charset,
+	if (mail_search_build_from_imap_args(mail_search_register_imap,
+					     args, charset,
 					     &sargs, &error) < 0) {
 		client_send_command_error(cmd, error);
 		return -1;
diff -r 8d1d1eb2c2a0 -r 3649ad8c9f9a src/lib-storage/Makefile.am
--- a/src/lib-storage/Makefile.am	Tue Apr 13 19:01:58 2010 +0300
+++ b/src/lib-storage/Makefile.am	Tue Apr 13 20:25:00 2010 +0300
@@ -23,6 +23,7 @@
 	mail-search.c \
 	mail-search-build.c \
 	mail-search-register.c \
+	mail-search-register-human.c \
 	mail-search-register-imap.c \
 	mail-storage.c \
 	mail-storage-hooks.c \
diff -r 8d1d1eb2c2a0 -r 3649ad8c9f9a src/lib-storage/mail-search-build.c
--- a/src/lib-storage/mail-search-build.c	Tue Apr 13 19:01:58 2010 +0300
+++ b/src/lib-storage/mail-search-build.c	Tue Apr 13 20:25:00 2010 +0300
@@ -8,16 +8,63 @@
 
 #include <stdlib.h>
 
+int mail_search_build_next_astring(struct mail_search_build_context *ctx,
+				   const struct imap_arg **imap_args,
+				   const char **value_r)
+{
+	if (IMAP_ARG_IS_EOL(*imap_args)) {
+		ctx->error = "Missing parameter for argument";
+		return -1;
+	}
+	if (!imap_arg_get_astring(*imap_args, value_r)) {
+		ctx->error = "Invalid parameter for argument";
+		return -1;
+	}
+
+	*imap_args += 1;
+	return 0;
+}
+
+struct mail_search_arg *
+mail_search_build_new(struct mail_search_build_context *ctx,
+		      enum mail_search_arg_type type)
+{
+	struct mail_search_arg *arg;
+
+	arg = p_new(ctx->pool, struct mail_search_arg, 1);
+	arg->type = type;
+	return arg;
+}
+
+struct mail_search_arg *
+mail_search_build_str(struct mail_search_build_context *ctx,
+		      const struct imap_arg **imap_args,
+		      enum mail_search_arg_type type)
+{
+	struct mail_search_arg *sarg;
+	const char *value;
+
+	sarg = mail_search_build_new(ctx, type);
+	if (mail_search_build_next_astring(ctx, imap_args, &value) < 0)
+		return NULL;
+	sarg->value.str = p_strdup(ctx->pool, value);
+	return sarg;
+}
+
 struct mail_search_arg *
 mail_search_build_next(struct mail_search_build_context *ctx,
+		       struct mail_search_arg *parent,
 		       const struct imap_arg **imap_args)
 {
-	struct mail_search_arg **subargs, *sarg;
+	struct mail_search_arg *sarg;
+	struct mail_search_arg *old_parent = ctx->parent;
 	const struct imap_arg *listargs;
 	const char *key;
 	const struct mail_search_register_arg *reg_arg;
 	mail_search_register_fallback_t *fallback;
 
+	ctx->parent = parent;
+
 	if (IMAP_ARG_IS_EOL(*imap_args)) {
 		ctx->error = "Missing argument";
 		return NULL;
@@ -35,17 +82,9 @@
 			return NULL;
 		}
 
-		sarg = p_new(ctx->pool, struct mail_search_arg, 1);
-		sarg->type = SEARCH_SUB;
-		subargs = &sarg->value.subargs;
-		while (!IMAP_ARG_IS_EOL(listargs)) {
-			*subargs = mail_search_build_next(ctx, &listargs);
-			if (*subargs == NULL)
-				return NULL;
-			subargs = &(*subargs)->next;
-		}
-
+		sarg = mail_search_build_list(ctx, listargs);
 		*imap_args += 1;
+		ctx->parent = old_parent;
 		return sarg;
 	}
 
@@ -64,17 +103,54 @@
 		ctx->error = p_strconcat(ctx->pool, "Unknown argument ",
 					 key, NULL);
 	}
+
+	ctx->parent = old_parent;
 	return sarg;
 }
 
-int mail_search_build_from_imap_args(const struct imap_arg *imap_args,
+struct mail_search_arg *
+mail_search_build_list(struct mail_search_build_context *ctx,
+		       const struct imap_arg *imap_args)
+{
+	struct mail_search_arg *sarg, **subargs;
+	enum mail_search_arg_type cur_type = SEARCH_SUB;
+
+	sarg = p_new(ctx->pool, struct mail_search_arg, 1);
+	sarg->type = cur_type;
+
+	subargs = &sarg->value.subargs;
+	while (!IMAP_ARG_IS_EOL(imap_args)) {
+		sarg->type = SEARCH_SUB;
+		*subargs = mail_search_build_next(ctx, sarg, &imap_args);
+		if (*subargs == NULL)
+			return NULL;
+
+		if (cur_type == sarg->type) {
+			/* expected type */
+		} else if (cur_type == SEARCH_SUB) {
+			/* type changed. everything in this list must now
+			   belong to this type. */
+			cur_type = sarg->type;
+		} else {
+			ctx->error = cur_type == SEARCH_OR ?
+				"Use parenthesis when using ORs" :
+				"Use parenthesis when mixing subtypes";
+			return NULL;
+		}
+		subargs = &(*subargs)->next;
+	}
+	return sarg;
+}
+
+int mail_search_build_from_imap_args(struct mail_search_register *reg,
+				     const struct imap_arg *imap_args,
 				     const char *charset,
 				     struct mail_search_args **args_r,
 				     const char **error_r)
 {
         struct mail_search_build_context ctx;
 	struct mail_search_args *args;
-	struct mail_search_arg **sargs;
+	struct mail_search_arg *root;
 
 	*args_r = NULL;
 	*error_r = NULL;
@@ -84,17 +160,20 @@
 
 	memset(&ctx, 0, sizeof(ctx));
 	ctx.pool = args->pool;
-	ctx.reg = mail_search_register_imap;
+	ctx.reg = reg;
 
-	sargs = &args->args;
-	while (!IMAP_ARG_IS_EOL(imap_args)) {
-		*sargs = mail_search_build_next(&ctx, &imap_args);
-		if (*sargs == NULL) {
-			*error_r = t_strdup(ctx.error);
-			pool_unref(&args->pool);
-			return -1;
-		}
-		sargs = &(*sargs)->next;
+	root = mail_search_build_list(&ctx, imap_args);
+	if (root == NULL) {
+		*error_r = t_strdup(ctx.error);
+		pool_unref(&args->pool);
+		return -1;
+	}
+
+	if (root->type == SEARCH_SUB && !root->not) {
+		/* simple SUB root */
+		args->args = root->value.subargs;
+	} else {
+		args->args = root;
 	}
 
 	*args_r = args;
diff -r 8d1d1eb2c2a0 -r 3649ad8c9f9a src/lib-storage/mail-search-build.h
--- a/src/lib-storage/mail-search-build.h	Tue Apr 13 19:01:58 2010 +0300
+++ b/src/lib-storage/mail-search-build.h	Tue Apr 13 20:25:00 2010 +0300
@@ -2,6 +2,7 @@
 #define MAIL_SEARCH_BUILD_H
 
 #include "mail-search.h"
+#include "mail-search-register.h"
 
 struct imap_arg;
 struct mailbox;
@@ -9,6 +10,8 @@
 struct mail_search_build_context {
 	pool_t pool;
 	struct mail_search_register *reg;
+
+	struct mail_search_arg *parent;
 	const char *error;
 };
 
@@ -17,7 +20,8 @@
 struct mail_search_args *mail_search_build_init(void);
 
 /* Convert IMAP SEARCH command compatible parameters to mail_search_args. */
-int mail_search_build_from_imap_args(const struct imap_arg *imap_args,
+int mail_search_build_from_imap_args(struct mail_search_register *reg,
+				     const struct imap_arg *imap_args,
 				     const char *charset,
 				     struct mail_search_args **args_r,
 				     const char **error_r);
@@ -28,8 +32,23 @@
 void mail_search_build_add_seqset(struct mail_search_args *args,
 				  uint32_t seq1, uint32_t seq2);
 
+int mail_search_build_next_astring(struct mail_search_build_context *ctx,
+				   const struct imap_arg **imap_args,
+				   const char **value_r);
+
+struct mail_search_arg *
+mail_search_build_new(struct mail_search_build_context *ctx,
+		      enum mail_search_arg_type type);
+struct mail_search_arg *
+mail_search_build_str(struct mail_search_build_context *ctx,
+		      const struct imap_arg **imap_args,
+		      enum mail_search_arg_type type);
 struct mail_search_arg *
 mail_search_build_next(struct mail_search_build_context *ctx,
+		       struct mail_search_arg *parent,
 		       const struct imap_arg **imap_args);
+struct mail_search_arg *
+mail_search_build_list(struct mail_search_build_context *ctx,
+		       const struct imap_arg *imap_args);
 
 #endif
diff -r 8d1d1eb2c2a0 -r 3649ad8c9f9a src/lib-storage/mail-search-register-human.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/mail-search-register-human.c	Tue Apr 13 20:25:00 2010 +0300
@@ -0,0 +1,202 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "array.h"
+#include "settings-parser.h"
+#include "imap-date.h"
+#include "mail-search-register.h"
+#include "mail-search-build.h"
+
+#include <time.h>
+#include <ctype.h>
+
+struct mail_search_register *mail_search_register_human;
+
+static struct mail_search_arg *
+human_search_or(struct mail_search_build_context *ctx,
+		const struct imap_arg **imap_args)
+{
+	/* this changes the parent arg to be an OR block instead of AND block */
+	ctx->parent->type = SEARCH_OR;
+	return mail_search_build_next(ctx, ctx->parent, imap_args);
+}
+
+static struct mail_search_arg *
+arg_new_human_date(struct mail_search_build_context *ctx,
+		   const struct imap_arg **imap_args,
+		   enum mail_search_arg_type type,
+		   enum mail_search_date_type date_type)
+{
+	struct mail_search_arg *sarg;
+	const char *value, *error;
+	struct tm tm;
+	unsigned int secs;
+	int tz;
+
+	sarg = mail_search_build_new(ctx, type);
+	if (mail_search_build_next_astring(ctx, imap_args, &value) < 0)
+		return NULL;
+
+	/* a) yyyy-mm-dd
+	   b) imap date-time


More information about the dovecot-cvs mailing list