Mercurial > dovecot > original-hg > dovecot-1.2
changeset 8499:252b29ac5f43 HEAD
fts: Added support for handling multiple namespaces.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 30 Nov 2008 01:27:19 +0200 |
parents | fb5fedcf4deb |
children | 3efcdc45d111 |
files | doc/solr-schema.xml src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h src/plugins/fts-solr/fts-backend-solr.c src/plugins/fts-solr/fts-solr-plugin.c src/plugins/fts-solr/fts-solr-plugin.h src/plugins/fts-solr/solr-connection.c src/plugins/fts-solr/solr-connection.h src/plugins/fts/fts-storage.c src/plugins/virtual/virtual-config.c src/plugins/virtual/virtual-storage.c src/plugins/virtual/virtual-storage.h |
diffstat | 13 files changed, 273 insertions(+), 110 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/solr-schema.xml Sun Nov 30 01:26:36 2008 +0200 +++ b/doc/solr-schema.xml Sun Nov 30 01:27:19 2008 +0200 @@ -43,6 +43,7 @@ <field name="uidv" type="long" indexed="true" stored="true" required="true" /> <field name="box" type="string" indexed="true" stored="true" required="true" /> <field name="user" type="string" indexed="true" stored="true" required="true" /> + <field name="ns" type="string" indexed="true" stored="true" required="false" /> <field name="last_uid" type="boolean" indexed="true" stored="false" /> <field name="hdr" type="text" indexed="true" stored="false" /> <field name="body" type="text" indexed="true" stored="false" />
--- a/src/lib-storage/mail-storage-private.h Sun Nov 30 01:26:36 2008 +0200 +++ b/src/lib-storage/mail-storage-private.h Sun Nov 30 01:27:19 2008 +0200 @@ -146,8 +146,8 @@ ARRAY_TYPE(mailboxes) *mailboxes, bool only_with_msgs); void (*get_virtual_box_patterns)(struct mailbox *box, - ARRAY_TYPE(const_string) *includes, - ARRAY_TYPE(const_string) *excludes); + ARRAY_TYPE(mailbox_virtual_patterns) *includes, + ARRAY_TYPE(mailbox_virtual_patterns) *excludes); struct mail * (*mail_alloc)(struct mailbox_transaction_context *t,
--- a/src/lib-storage/mail-storage.c Sun Nov 30 01:26:36 2008 +0200 +++ b/src/lib-storage/mail-storage.c Sun Nov 30 01:27:19 2008 +0200 @@ -651,13 +651,16 @@ } void mailbox_get_virtual_box_patterns(struct mailbox *box, - ARRAY_TYPE(const_string) *includes, - ARRAY_TYPE(const_string) *excludes) + ARRAY_TYPE(mailbox_virtual_patterns) *includes, + ARRAY_TYPE(mailbox_virtual_patterns) *excludes) { if (box->v.get_virtual_box_patterns == NULL) { - const char *name = box->name; + struct mailbox_virtual_pattern pat; - array_append(includes, &name, 1); + memset(&pat, 0, sizeof(pat)); + pat.ns = box->storage->ns; + pat.pattern = box->name; + array_append(includes, &pat, 1); } else { box->v.get_virtual_box_patterns(box, includes, excludes); }
--- a/src/lib-storage/mail-storage.h Sun Nov 30 01:26:36 2008 +0200 +++ b/src/lib-storage/mail-storage.h Sun Nov 30 01:27:19 2008 +0200 @@ -234,6 +234,12 @@ }; +struct mailbox_virtual_pattern { + struct mail_namespace *ns; + const char *pattern; +}; +ARRAY_DEFINE_TYPE(mailbox_virtual_patterns, struct mailbox_virtual_pattern); + ARRAY_DEFINE_TYPE(mailboxes, struct mailbox *); typedef void mailbox_notify_callback_t(struct mailbox *box, void *context); @@ -432,8 +438,8 @@ /* If mailbox is a virtual mailbox, return all mailbox list patterns that are used to figure out which mailboxes belong to the virtual mailbox. */ void mailbox_get_virtual_box_patterns(struct mailbox *box, - ARRAY_TYPE(const_string) *includes, - ARRAY_TYPE(const_string) *excludes); + ARRAY_TYPE(mailbox_virtual_patterns) *includes, + ARRAY_TYPE(mailbox_virtual_patterns) *excludes); /* Initialize header lookup for given headers. */ struct mailbox_header_lookup_ctx *
--- a/src/plugins/fts-solr/fts-backend-solr.c Sun Nov 30 01:26:36 2008 +0200 +++ b/src/plugins/fts-solr/fts-backend-solr.c Sun Nov 30 01:27:19 2008 +0200 @@ -13,10 +13,13 @@ #define SOLR_CMDBUF_SIZE (1024*64) #define SOLR_MAX_ROWS 100000 +#define FTS_SOLR_MAX_BOX_INC_PATTERNS 5 +#define FTS_SOLR_MAX_BOX_EXC_PATTERNS 5 struct solr_fts_backend { struct fts_backend backend; - char *id_username; + char *id_username, *id_namespace; + struct mail_namespace *default_ns; }; struct solr_fts_backend_build_context { @@ -28,18 +31,23 @@ bool headers; }; +struct solr_virtual_uid_map_context { + struct fts_backend *backend; + struct mailbox *box; + string_t *vname; +}; + struct fts_backend_solr_get_last_uids_context { + struct fts_backend *backend; pool_t pool; ARRAY_TYPE(fts_backend_uid_map) *last_uids; + + struct mailbox *box; + string_t *vname; }; static struct solr_connection *solr_conn = NULL; -static void solr_quote_str(string_t *dest, const char *str) -{ - solr_connection_quote_str(solr_conn, dest, str); -} - static void xml_encode_data(string_t *dest, const unsigned char *data, unsigned int len) { @@ -97,18 +105,50 @@ return str_c(tmp); } +static void solr_quote(string_t *dest, const char *str) +{ + str_append_c(dest, '"'); + str_append(dest, str_escape(str)); + str_append_c(dest, '"'); +} + +static void solr_quote_http(string_t *dest, const char *str) +{ + str_append(dest, "%22"); + solr_connection_http_escape(solr_conn, dest, str); + str_append(dest, "%22"); +} + static struct fts_backend * fts_backend_solr_init(struct mailbox *box) { const struct fts_solr_settings *set = &fts_solr_settings; struct solr_fts_backend *backend; - const char *username = box->storage->ns->user->username; + struct mail_namespace *ns = box->storage->ns; + const char *str; if (solr_conn == NULL) solr_conn = solr_connection_init(set->url, set->debug); backend = i_new(struct solr_fts_backend, 1); - backend->id_username = i_strdup(solr_escape_id_str(username)); + str = fts_solr_settings.default_ns_prefix; + if (str != NULL) { + backend->default_ns = + mail_namespace_find_prefix(ns->user->namespaces, str); + if (backend->default_ns == NULL) { + i_fatal("fts_solr: default_ns setting points to " + "nonexisting namespace"); + } + } else { + backend->default_ns = + mail_namespace_find_inbox(ns->user->namespaces); + } + str = solr_escape_id_str(ns->user->username); + backend->id_username = i_strdup(str); + if (box->storage->ns != backend->default_ns) { + str = solr_escape_id_str(ns->prefix); + backend->id_namespace = i_strdup(str); + } backend->backend = fts_backend_solr; if (set->substring_search) @@ -120,20 +160,40 @@ { struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend; + i_free(backend->id_namespace); i_free(backend->id_username); i_free(backend); } -static const char *fts_backend_solr_username(struct fts_backend *_backend) +static void +solr_add_ns_query(string_t *str, struct fts_backend *_backend, + struct mail_namespace *ns) { struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend; - return backend->id_username; + if (ns == backend->default_ns || *ns->prefix == '\0') + str_append(str, " -ns:[* TO *]"); + else { + str_append(str, " ns:"); + solr_quote(str, ns->prefix); + } +} + +static void +solr_add_ns_query_http(string_t *str, struct fts_backend *backend, + struct mail_namespace *ns) +{ + string_t *tmp; + + tmp = t_str_new(64); + solr_add_ns_query(tmp, backend, ns); + solr_connection_http_escape(solr_conn, str, str_c(tmp)); } static int fts_backend_solr_get_last_uid_fallback(struct fts_backend *backend, uint32_t *last_uid_r) { + struct mailbox *box = backend->box; struct mailbox_status status; ARRAY_TYPE(seq_range) uids; const struct seq_range *uidvals; @@ -141,13 +201,14 @@ string_t *str; str = t_str_new(256); - str_append(str, "fl=uid&rows=1&sort=uid%20desc&q="); + str_append(str, "fl=uid&rows=1&sort=uid+desc&q="); - mailbox_get_status(backend->box, STATUS_UIDVALIDITY, &status); - str_printfa(str, "uidv:%u%%20box:", status.uidvalidity); - solr_quote_str(str, backend->box->name); - str_append(str, "%20user:"); - solr_quote_str(str, backend->box->storage->ns->user->username); + mailbox_get_status(box, STATUS_UIDVALIDITY, &status); + str_printfa(str, "uidv:%u+box:", status.uidvalidity); + solr_quote_http(str, box->name); + solr_add_ns_query_http(str, backend, box->storage->ns); + str_append(str, "+user:"); + solr_quote_http(str, box->storage->ns->user->username); t_array_init(&uids, 1); if (solr_connection_select(solr_conn, str_c(str), @@ -170,6 +231,7 @@ static int fts_backend_solr_get_last_uid(struct fts_backend *backend, uint32_t *last_uid_r) { + struct mailbox *box = backend->box; struct mailbox_status status; ARRAY_TYPE(seq_range) uids; const struct seq_range *uidvals; @@ -177,13 +239,14 @@ string_t *str; str = t_str_new(256); - str_append(str, "fl=uid&rows=1&q=last_uid:TRUE%20"); + str_append(str, "fl=uid&rows=1&q=last_uid:TRUE+"); - mailbox_get_status(backend->box, STATUS_UIDVALIDITY, &status); - str_printfa(str, "uidv:%u%%20box:", status.uidvalidity); - solr_quote_str(str, backend->box->name); - str_append(str, "%20user:"); - solr_quote_str(str, backend->box->storage->ns->user->username); + mailbox_get_status(box, STATUS_UIDVALIDITY, &status); + str_printfa(str, "uidv:%u+box:", status.uidvalidity); + solr_quote_http(str, box->name); + solr_add_ns_query_http(str, backend, box->storage->ns); + str_append(str, "+user:"); + solr_quote_http(str, box->storage->ns->user->username); t_array_init(&uids, 1); if (solr_connection_select(solr_conn, str_c(str), @@ -205,41 +268,67 @@ return 0; } +static const char * +solr_get_vmailbox(struct fts_backend *_backend, + struct mailbox *box, const char *ns_prefix, + const char *mailbox, string_t *dest) +{ + struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend; + struct mail_namespace *namespaces = box->storage->ns->user->namespaces; + struct mail_namespace *ns; + + if (ns_prefix == NULL) + ns = backend->default_ns; + else { + ns = mail_namespace_find_prefix(namespaces, ns_prefix); + if (ns == NULL) + return FALSE; + } + return mail_namespace_get_vname(ns, dest, mailbox); +} + static bool -solr_virtual_get_last_uids(const char *mailbox, uint32_t uidvalidity, - uint32_t *uid, void *context) +solr_virtual_get_last_uids(const char *ns_prefix, const char *mailbox, + uint32_t uidvalidity, uint32_t *uid, void *context) { struct fts_backend_solr_get_last_uids_context *ctx = context; struct fts_backend_uid_map *map; + const char *vname; + + vname = solr_get_vmailbox(ctx->backend, ctx->box, ns_prefix, + mailbox, ctx->vname); map = array_append_space(ctx->last_uids); - map->mailbox = p_strdup(ctx->pool, mailbox); + map->mailbox = p_strdup(ctx->pool, vname); map->uidvalidity = uidvalidity; map->uid = *uid; return FALSE; } -static void add_pattern_as_solr(string_t *str, const char *pattern) +static void +solr_add_pattern(string_t *str, const struct mailbox_virtual_pattern *pattern) { - const char *p; + const char *name, *p; + + name = pattern->pattern; + if (!mail_namespace_update_name(pattern->ns, &name)) + name = mail_namespace_fix_sep(pattern->ns, name); /* first check if there are any wildcards in the pattern */ - for (p = pattern; *p != '\0'; p++) { + for (p = name; *p != '\0'; p++) { if (*p == '%' || *p == '*') break; } if (*p == '\0') { /* full mailbox name */ - str_append_c(str, '"'); - str_append(str, str_escape(pattern)); - str_append_c(str, '"'); + solr_quote(str, name); return; } /* there are at least some wildcards. */ - for (p = pattern; *p != '\0'; p++) { + for (p = name; *p != '\0'; p++) { if (*p == '%' || *p == '*') { - if (p == pattern || (p[-1] != '%' && p[-1] != '*')) + if (p == name || (p[-1] != '%' && p[-1] != '*')) str_append_c(str, '*'); } else { if (!i_isalnum(*p)) @@ -250,12 +339,13 @@ } static void -fts_backend_solr_filter_mailboxes(struct solr_connection *solr_conn, +fts_backend_solr_filter_mailboxes(struct fts_backend *_backend, string_t *str, struct mailbox *box) { - ARRAY_TYPE(const_string) includes_arr, excludes_arr; - const char *const *includes, *const *excludes; - unsigned int i, inc_count, exc_count; + struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend; + ARRAY_TYPE(mailbox_virtual_patterns) includes_arr, excludes_arr; + const struct mailbox_virtual_pattern *includes, *excludes; + unsigned int i, inc_count, exc_count, len; string_t *fq; t_array_init(&includes_arr, 16); @@ -269,27 +359,41 @@ Solr doesn't allow them, so in that case we'll need to return all mailboxes. */ for (i = 0; i < inc_count; i++) { - if (*includes[i] == '*' || *includes[i] == '%') + if (*includes[i].pattern == '*' || + *includes[i].pattern == '%') break; } fq = t_str_new(128); - if (i == inc_count) { + if (i == inc_count && inc_count <= FTS_SOLR_MAX_BOX_INC_PATTERNS) { /* we can filter what mailboxes we want returned */ str_append_c(fq, '('); for (i = 0; i < inc_count; i++) { if (i != 0) str_append(fq, " OR "); + str_append_c(fq, '('); str_append(fq, "box:"); - add_pattern_as_solr(fq, includes[i]); + solr_add_pattern(fq, &includes[i]); + solr_add_ns_query(fq, _backend, includes[i].ns); + str_append_c(fq, ')'); } str_append_c(fq, ')'); } + exc_count = I_MIN(FTS_SOLR_MAX_BOX_EXC_PATTERNS, exc_count); for (i = 0; i < exc_count; i++) { - if (str_len(fq) > 0) + if (str_len(fq) > len) str_append_c(fq, ' '); + str_append_c(fq, '('); str_append(fq, "-box:"); - add_pattern_as_solr(fq, excludes[i]); + solr_add_pattern(fq, &excludes[i]); + if (excludes[i].ns == backend->default_ns) { + str_append(fq, " OR NOT"); + solr_add_ns_query(fq, _backend, excludes[i].ns); + } else if (*excludes[i].ns->prefix != '\0') { + str_append(fq, " OR -ns:"); + solr_quote(fq, excludes[i].ns->prefix); + } + str_append_c(fq, ')'); } if (str_len(fq) > 0) { str_append(str, "&fq="); @@ -305,14 +409,17 @@ string_t *str; memset(&ctx, 0, sizeof(ctx)); + ctx.backend = backend; ctx.pool = pool; ctx.last_uids = last_uids; + ctx.box = backend->box; + ctx.vname = t_str_new(256); str = t_str_new(256); - str_printfa(str, "fl=uid,box,uidv&rows=%u&q=last_uid:TRUE%%20user:", + str_printfa(str, "fl=uid,box,uidv,ns&rows=%u&q=last_uid:TRUE+user:", SOLR_MAX_ROWS); - solr_quote_str(str, backend->box->storage->ns->user->username); - fts_backend_solr_filter_mailboxes(solr_conn, str, backend->box); + solr_quote_http(str, backend->box->storage->ns->user->username); + fts_backend_solr_filter_mailboxes(backend, str, backend->box); return solr_connection_select(solr_conn, str_c(str), solr_virtual_get_last_uids, &ctx, @@ -343,6 +450,8 @@ fts_backend_solr_add_doc_prefix(struct solr_fts_backend_build_context *ctx, uint32_t uid) { + struct solr_fts_backend *backend = + (struct solr_fts_backend *)ctx->ctx.backend; struct mailbox *box = ctx->ctx.backend->box; str_printfa(ctx->cmd, "<doc>" @@ -350,6 +459,11 @@ "<field name=\"uidv\">%u</field>", uid, ctx->uid_validity); + if (box->storage->ns != backend->default_ns) { + str_append(ctx->cmd, "<field name=\"ns\">"); + xml_encode(ctx->cmd, box->storage->ns->prefix); + str_append(ctx->cmd, "</field>"); + } str_append(ctx->cmd, "<field name=\"box\">"); xml_encode(ctx->cmd, box->name); str_append(ctx->cmd, "</field><field name=\"user\">"); @@ -357,6 +471,26 @@ str_append(ctx->cmd, "</field>"); } +static void xml_encode_id(string_t *str, struct fts_backend *_backend, + uint32_t uid, uint32_t uid_validity, + const char *mailbox) +{ + struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend; + + if (uid != 0) + str_printfa(str, "%u/", uid); + else + str_append(str, "L/"); + if (backend->id_namespace != NULL) { + xml_encode(str, backend->id_namespace); + str_append_c(str, '/'); + } + str_printfa(str, "%u/", uid_validity); + xml_encode(str, backend->id_username); + str_append_c(str, '/'); + xml_encode(str, mailbox); +} + static int fts_backend_solr_build_more(struct fts_backend_build_context *_ctx, uint32_t uid, const unsigned char *data, @@ -379,11 +513,9 @@ ctx->prev_uid = uid; fts_backend_solr_add_doc_prefix(ctx, uid); - str_printfa(cmd, "<field name=\"id\">%u/%u/", - uid, ctx->uid_validity); - xml_encode(cmd, fts_backend_solr_username(ctx->ctx.backend)); - str_append_c(cmd, '/'); - xml_encode(cmd, box->name); + str_printfa(cmd, "<field name=\"id\">"); + xml_encode_id(cmd, _ctx->backend, uid, ctx->uid_validity, + box->name); str_append(cmd, "</field>"); ctx->headers = headers; @@ -425,10 +557,9 @@ in future by reindexing some messages. */ fts_backend_solr_add_doc_prefix(ctx, ctx->prev_uid); str_printfa(ctx->cmd, "<field name=\"last_uid\">TRUE</field>" - "<field name=\"id\">L/%u/", ctx->uid_validity); - xml_encode(ctx->cmd, fts_backend_solr_username(ctx->ctx.backend)); - str_append_c(ctx->cmd, '/'); - xml_encode(ctx->cmd, box->name); + "<field name=\"id\">"); + xml_encode_id(ctx->cmd, ctx->ctx.backend, 0, ctx->uid_validity, + box->name); str_append(ctx->cmd, "</field></doc></add>"); solr_connection_post_more(ctx->post, str_data(ctx->cmd), @@ -466,11 +597,9 @@ string_t *cmd; cmd = t_str_new(256); - str_printfa(cmd, "<delete><id>%u/%u/", - mail->uid, status.uidvalidity); - xml_encode(cmd, fts_backend_solr_username(backend)); - str_append_c(cmd, '/'); - xml_encode(cmd, mail->box->name); + str_append(cmd, "<delete><id>"); + xml_encode_id(cmd, backend, mail->uid, status.uidvalidity, + mail->box->name); str_append(cmd, "</id></delete>"); (void)solr_connection_post(solr_conn, str_c(cmd)); @@ -495,13 +624,16 @@ { } -static bool solr_virtual_uid_map(const char *mailbox, uint32_t uidvalidity, - uint32_t *uid, void *context) +static bool solr_virtual_uid_map(const char *ns_prefix, const char *mailbox, + uint32_t uidvalidity, uint32_t *uid, + void *context) { - struct mailbox *box = context; + struct solr_virtual_uid_map_context *ctx = context; + const char *vname; - return mailbox_get_virtual_uid(box, mailbox, uidvalidity, - *uid, uid); + vname = solr_get_vmailbox(ctx->backend, ctx->box, ns_prefix, + mailbox, ctx->vname); + return mailbox_get_virtual_uid(ctx->box, vname, uidvalidity, *uid, uid); } static int fts_backend_solr_lookup(struct fts_backend_lookup_context *ctx, @@ -510,6 +642,7 @@ ARRAY_TYPE(fts_score_map) *scores) { struct mailbox *box = ctx->backend->box; + struct solr_virtual_uid_map_context uid_map_ctx; const struct fts_backend_lookup_field *fields; unsigned int i, count; struct mailbox_status status; @@ -521,11 +654,11 @@ str = t_str_new(256); if (!virtual) { - str_printfa(str, "fl=uid,score&rows=%u&sort=uid%%20asc&q=", + str_printfa(str, "fl=uid,score&rows=%u&sort=uid+asc&q=", status.uidnext); } else { - str_printfa(str, "fl=uid,score,box,uidv&rows=%u" - "&sort=box%%20asc,uid%%20asc&q=", + str_printfa(str, "fl=uid,score,box,uidv,ns&rows=%u" + "&sort=box+asc,uid+asc&q=", SOLR_MAX_ROWS); } @@ -533,7 +666,7 @@ fields = array_get(&ctx->fields, &count); for (i = 0; i < count; i++) { if (i > 0) - str_append(str, "%20"); + str_append_c(str, '+'); if ((fields[i].flags & FTS_LOOKUP_FLAG_INVERT) != 0) str_append_c(str, '-'); @@ -549,18 +682,19 @@ /* both */ str_append(str, "any:"); } - solr_quote_str(str, fields[i].key); + solr_quote_http(str, fields[i].key); } /* use a separate filter query for selecting the mailbox. it shouldn't affect the score and there could be some caching benefits too. */ str_append(str, "&fq=user:"); - solr_quote_str(str, box->storage->ns->user->username); + solr_quote_http(str, box->storage->ns->user->username); if (virtual) - fts_backend_solr_filter_mailboxes(solr_conn, str, box); + fts_backend_solr_filter_mailboxes(ctx->backend, str, box); else { - str_printfa(str, "%%20uidv:%u%%20box:", status.uidvalidity); - solr_quote_str(str, box->name); + str_printfa(str, "+uidv:%u+box:", status.uidvalidity); + solr_quote_http(str, box->name); + solr_add_ns_query_http(str, ctx->backend, box->storage->ns); } array_clear(maybe_uids); @@ -568,8 +702,13 @@ return solr_connection_select(solr_conn, str_c(str), NULL, NULL, definite_uids, scores); } else { + memset(&uid_map_ctx, 0, sizeof(uid_map_ctx)); + uid_map_ctx.backend = ctx->backend; + uid_map_ctx.box = box; + uid_map_ctx.vname = t_str_new(256); return solr_connection_select(solr_conn, str_c(str), - solr_virtual_uid_map, box, + solr_virtual_uid_map, + &uid_map_ctx, definite_uids, scores); } }
--- a/src/plugins/fts-solr/fts-solr-plugin.c Sun Nov 30 01:26:36 2008 +0200 +++ b/src/plugins/fts-solr/fts-solr-plugin.c Sun Nov 30 01:27:19 2008 +0200 @@ -24,6 +24,9 @@ set->debug = TRUE; } else if (strcmp(*tmp, "break-imap-search") == 0) { set->substring_search = TRUE; + } else if (strcmp(*tmp, "default_ns=") == 0) { + i_free(set->default_ns_prefix); + set->default_ns_prefix = i_strdup(*tmp + 11); } else { i_fatal("fts_solr: Invalid setting: %s", *tmp); }
--- a/src/plugins/fts-solr/fts-solr-plugin.h Sun Nov 30 01:26:36 2008 +0200 +++ b/src/plugins/fts-solr/fts-solr-plugin.h Sun Nov 30 01:27:19 2008 +0200 @@ -4,7 +4,7 @@ #include "fts-api-private.h" struct fts_solr_settings { - char *url; + char *url, *default_ns_prefix; bool debug; bool substring_search; };
--- a/src/plugins/fts-solr/solr-connection.c Sun Nov 30 01:26:36 2008 +0200 +++ b/src/plugins/fts-solr/solr-connection.c Sun Nov 30 01:27:19 2008 +0200 @@ -24,6 +24,7 @@ SOLR_XML_CONTENT_STATE_UID, SOLR_XML_CONTENT_STATE_SCORE, SOLR_XML_CONTENT_STATE_MAILBOX, + SOLR_XML_CONTENT_STATE_NAMESPACE, SOLR_XML_CONTENT_STATE_UIDVALIDITY }; @@ -34,7 +35,7 @@ uint32_t uid, uidvalidity; float score; - char *mailbox; + char *mailbox, *ns; solr_uid_map_callback_t *callback; void *context; @@ -192,16 +193,6 @@ i_free(conn); } -void solr_connection_quote_str(struct solr_connection *conn, string_t *dest, - const char *str) -{ - char *encoded; - - encoded = curl_easy_escape(conn->curl, str_escape(str), 0); - str_printfa(dest, "%%22%s%%22", encoded); - curl_free(encoded); -} - void solr_connection_http_escape(struct solr_connection *conn, string_t *dest, const char *str) { @@ -251,6 +242,7 @@ ctx->uid = 0; ctx->score = 0; i_free_and_null(ctx->mailbox); + i_free_and_null(ctx->ns); ctx->uidvalidity = 0; } break; @@ -262,6 +254,8 @@ ctx->content_state = SOLR_XML_CONTENT_STATE_SCORE; else if (strcmp(name_attr, "box") == 0) ctx->content_state = SOLR_XML_CONTENT_STATE_MAILBOX; + else if (strcmp(name_attr, "ns") == 0) + ctx->content_state = SOLR_XML_CONTENT_STATE_NAMESPACE; else if (strcmp(name_attr, "uidv") == 0) ctx->content_state = SOLR_XML_CONTENT_STATE_UIDVALIDITY; else @@ -287,7 +281,7 @@ i_error("fts_solr: Query didn't return mailbox"); return; } - if (!ctx->callback(ctx->mailbox, ctx->uidvalidity, + if (!ctx->callback(ctx->ns, ctx->mailbox, ctx->uidvalidity, &ctx->uid, ctx->context)) return; } @@ -357,6 +351,12 @@ i_free(ctx->mailbox); ctx->mailbox = new_name; break; + case SOLR_XML_CONTENT_STATE_NAMESPACE: + new_name = ctx->ns == NULL ? i_strndup(str, len) : + i_strconcat(ctx->ns, t_strndup(str, len), NULL); + i_free(ctx->ns); + ctx->ns = new_name; + break; case SOLR_XML_CONTENT_STATE_UIDVALIDITY: if (uint32_parse(str, len, &ctx->uidvalidity) < 0) i_error("fts_solr: received invalid uidvalidity");
--- a/src/plugins/fts-solr/solr-connection.h Sun Nov 30 01:26:36 2008 +0200 +++ b/src/plugins/fts-solr/solr-connection.h Sun Nov 30 01:27:19 2008 +0200 @@ -5,14 +5,13 @@ #include "fts-api.h" /* Returns TRUE if UID conversion was done, FALSE if uid should be skipped. */ -typedef bool solr_uid_map_callback_t(const char *mailbox, uint32_t uidvalidity, - uint32_t *uid, void *context); +typedef bool solr_uid_map_callback_t(const char *ns_prefix, const char *mailbox, + uint32_t uidvalidity, uint32_t *uid, + void *context); struct solr_connection *solr_connection_init(const char *url, bool debug); void solr_connection_deinit(struct solr_connection *conn); -void solr_connection_quote_str(struct solr_connection *conn, string_t *dest, - const char *str); void solr_connection_http_escape(struct solr_connection *conn, string_t *dest, const char *str);
--- a/src/plugins/fts/fts-storage.c Sun Nov 30 01:26:36 2008 +0200 +++ b/src/plugins/fts/fts-storage.c Sun Nov 30 01:27:19 2008 +0200 @@ -7,6 +7,7 @@ #include "istream.h" #include "message-parser.h" #include "message-decoder.h" +#include "mail-namespace.h" #include "mail-search-build.h" #include "mail-storage-private.h" #include "fts-api-private.h" @@ -289,6 +290,8 @@ struct mailbox *const *boxes; const struct fts_backend_uid_map *last_uids; unsigned int boxi, uidi, box_count, last_uid_count; + const char *vname; + string_t *tmp; int ret, vret = 0; if (vctx->pool == NULL) @@ -300,10 +303,13 @@ boxes = array_get(&vctx->mailboxes, &box_count); last_uids = array_get(&vctx->last_uids, &last_uid_count); + tmp = t_str_new(256); boxi = vctx->boxi; uidi = vctx->uidi; while (vret == 0 && boxi < box_count && uidi < last_uid_count) { - ret = strcmp(boxes[boxi]->name, last_uids[uidi].mailbox); + vname = mail_namespace_get_vname(boxes[boxi]->storage->ns, tmp, + boxes[boxi]->name); + ret = strcmp(vname, last_uids[uidi].mailbox); if (ret == 0) { /* match. check also that uidvalidity matches. */ mailbox_get_status(boxes[boxi], STATUS_UIDVALIDITY,
--- a/src/plugins/virtual/virtual-config.c Sun Nov 30 01:26:36 2008 +0200 +++ b/src/plugins/virtual/virtual-config.c Sun Nov 30 01:27:19 2008 +0200 @@ -119,11 +119,11 @@ if (strcasecmp(line, "INBOX") == 0) line = "INBOX"; bbox->name = p_strdup(ctx->pool, line); + bbox->ns = mail_namespace_find(user->namespaces, &line); if (strchr(bbox->name, '*') != NULL || strchr(bbox->name, '%') != NULL) { name = bbox->name[0] == '-' ? bbox->name + 1 : bbox->name; bbox->glob = imap_match_init(ctx->pool, name, TRUE, ctx->sep); - bbox->ns = mail_namespace_find(user->namespaces, &line); ctx->have_wildcards = TRUE; } array_append(&ctx->mbox->backend_boxes, &bbox, 1); @@ -134,19 +134,25 @@ virtual_mailbox_get_list_patterns(struct virtual_parse_context *ctx) { struct virtual_mailbox *mbox = ctx->mbox; - ARRAY_TYPE(const_string) *dest; + ARRAY_TYPE(mailbox_virtual_patterns) *dest; + struct mailbox_virtual_pattern pattern; struct virtual_backend_box *const *bboxes; unsigned int i, count; + memset(&pattern, 0, sizeof(pattern)); bboxes = array_get_modifiable(&mbox->backend_boxes, &count); p_array_init(&mbox->list_include_patterns, ctx->pool, count); p_array_init(&mbox->list_exclude_patterns, ctx->pool, count); for (i = 0; i < count; i++) { - if (*bboxes[i]->name == '-') + pattern.ns = bboxes[i]->ns; + pattern.pattern = bboxes[i]->name; + if (*pattern.pattern != '-') + dest = &mbox->list_include_patterns; + else { dest = &mbox->list_exclude_patterns; - else - dest = &mbox->list_include_patterns; - array_append(dest, &bboxes[i]->name, 1); + pattern.pattern++; + } + array_append(dest, &pattern, 1); } }
--- a/src/plugins/virtual/virtual-storage.c Sun Nov 30 01:26:36 2008 +0200 +++ b/src/plugins/virtual/virtual-storage.c Sun Nov 30 01:27:19 2008 +0200 @@ -595,8 +595,8 @@ static void virtual_get_virtual_box_patterns(struct mailbox *box, - ARRAY_TYPE(const_string) *includes, - ARRAY_TYPE(const_string) *excludes) + ARRAY_TYPE(mailbox_virtual_patterns) *includes, + ARRAY_TYPE(mailbox_virtual_patterns) *excludes) { struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
--- a/src/plugins/virtual/virtual-storage.h Sun Nov 30 01:26:36 2008 +0200 +++ b/src/plugins/virtual/virtual-storage.h Sun Nov 30 01:27:19 2008 +0200 @@ -109,8 +109,8 @@ /* Mailboxes this virtual mailbox consists of, sorted by mailbox_id */ ARRAY_TYPE(virtual_backend_box) backend_boxes; - ARRAY_TYPE(const_string) list_include_patterns; - ARRAY_TYPE(const_string) list_exclude_patterns; + ARRAY_TYPE(mailbox_virtual_patterns) list_include_patterns; + ARRAY_TYPE(mailbox_virtual_patterns) list_exclude_patterns; unsigned int uids_mapped:1; unsigned int sync_initialized:1;