fts-backend-solr-old.c revision c32d111cf4d8be4ffdc582b440b5348d87461066
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2017 Dovecot authors, see the included COPYING file */
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenstatic const char *solr_escape_chars = "+-&|!(){}[]^\"~*?:\\/ ";
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen /* Valid characters in XML:
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] |
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen [#x10000-#x10FFFF]
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen This function gets called only for #x80 and higher */
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenxml_encode_data(string_t *dest, const unsigned char *data, size_t len)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen for (i = 0; i < len; i++) {
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen switch (data[i]) {
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen /* exceptions to the following control char check */
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen /* SOLR doesn't like control characters.
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen replace them with spaces. */
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen /* make sure the character is valid for XML
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen so we don't get XML parser errors */
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen unsigned int char_len =
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenstatic void xml_encode(string_t *dest, const char *str)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen xml_encode_data(dest, (const unsigned char *)str, strlen(str));
5441373137620aa8094ceafd9e698d430f5ed0d0Aki Tuomistatic const char *solr_escape_id_str(const char *str)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen const char *p;
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen if (*p == '\0')
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen switch (*p) {
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenstatic const char *solr_escape(const char *str)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen unsigned int i;
2f779122ee7263be9c8fc7ffd6fa7405e888d755Timo Sirainen return "\"\"";
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen if (strchr(solr_escape_chars, str[i]) != NULL)
132bfe8fcb7a1be790dc8b5bf9d155c9f060808dTimo Sirainenstatic void solr_quote(string_t *dest, const char *str)
132bfe8fcb7a1be790dc8b5bf9d155c9f060808dTimo Sirainenstatic void solr_quote_http(string_t *dest, const char *str)
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainen http_url_escape_param(dest, solr_escape(str));
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainenstatic void fts_solr_set_default_ns(struct solr_fts_backend *backend)
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainen struct mail_namespace *ns = backend->backend.ns;
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainen struct fts_solr_user *fuser = FTS_SOLR_USER_CONTEXT(ns->user);
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainen const struct fts_solr_settings *set = &fuser->set;
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainen const char *str;
2f779122ee7263be9c8fc7ffd6fa7405e888d755Timo Sirainen mail_namespace_find_prefix(ns->user->namespaces,
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen i_error("fts_solr: default_ns setting points to "
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen "nonexistent namespace");
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen mail_namespace_find_inbox(ns->user->namespaces);
2f779122ee7263be9c8fc7ffd6fa7405e888d755Timo Sirainen while (backend->default_ns->alias_for != NULL)
2f779122ee7263be9c8fc7ffd6fa7405e888d755Timo Sirainen backend->default_ns = backend->default_ns->alias_for;
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenstatic void fts_box_name_get_root(struct mail_namespace **ns, const char **name)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen ((*ns)->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
71e88fae3be360e9a93b3398e743f99a6f05d2edTimo Sirainen /* ugly workaround to allow selecting INBOX from a Maildir/
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen when it's not in the inbox=yes namespace. */
71e88fae3be360e9a93b3398e743f99a6f05d2edTimo Sirainenstatic const char *
87346782e83fdb1f316d6cf1d8fa51466c3f0e3aTimo Sirainenfts_box_get_root(struct mailbox *box, struct mail_namespace **ns_r)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen struct mail_namespace *ns = mailbox_get_namespace(box);
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainen if (t_imap_utf8_to_utf7(box->name, &name) < 0)
95c4f06cba717df14358ec883b1bd1aec6cbf0a1Timo Sirainenstatic struct fts_backend *fts_backend_solr_alloc(void)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainenfts_backend_solr_init(struct fts_backend *_backend, const char **error_r)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen struct fts_solr_user *fuser = FTS_SOLR_USER_CONTEXT(_backend->ns->user);
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen const char *str;
2f779122ee7263be9c8fc7ffd6fa7405e888d755Timo Sirainen if (solr_connection_init(fuser->set.url, fuser->set.debug,
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen str = solr_escape_id_str(_backend->ns->user->username);
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainenstatic void fts_backend_solr_deinit(struct fts_backend *_backend)
56c35c844320b0a157d1aaa6b3e62b7f3851b235Timo Sirainen struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
if (!neg)
if (!neg)
const char *box_name;
unsigned int count;
int ret = 0;
*last_uid_r = 0;
return ret;
static struct fts_backend_update_context *
if (uid != 0)
const char *box_name;
const char *str;
int ret;
return ret;
T_BEGIN {
} T_END;
i_unreached();
return TRUE;
return FALSE;
case SEARCH_TEXT: {
case SEARCH_BODY:
return FALSE;
return TRUE;
bool and_args)
if (and_args)
return FALSE;
return TRUE;
const char *box_name;
int ret;
&status);
return ret;
const char *box_name;
char *box_id;
str_printfa(str, "fl=ns,box,uidv,uid,score&rows=%u&sort=box+asc,uid+asc&q=%%7b!lucene+q.op%%3dAND%%7d",
.flags = 0,
NULL,