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