solr-connection.c revision f817e98f79893a17b09214081f51834c3d733919
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2006-2017 Dovecot authors, see the included COPYING file */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "lib.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include "array.h"
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen#include "hash.h"
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "str.h"
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "strescape.h"
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang#include "ioloop.h"
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "istream.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include "http-url.h"
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "http-client.h"
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang#include "fts-solr-plugin.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include "solr-connection.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include <expat.h>
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
998395f6743fbecc07ee65ae08c416fa6cea9e09Teemu Huovilaenum solr_xml_response_state {
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang SOLR_XML_RESPONSE_STATE_ROOT,
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang SOLR_XML_RESPONSE_STATE_RESPONSE,
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang SOLR_XML_RESPONSE_STATE_RESULT,
eb568e46e82bc814ca3384236a483691a12f9c54Baofeng Wang SOLR_XML_RESPONSE_STATE_DOC,
eb568e46e82bc814ca3384236a483691a12f9c54Baofeng Wang SOLR_XML_RESPONSE_STATE_CONTENT
eb568e46e82bc814ca3384236a483691a12f9c54Baofeng Wang};
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenenum solr_xml_content_state {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen SOLR_XML_CONTENT_STATE_NONE = 0,
3448096d5b1cd324ed5132045de0345cd7120a25Timo Sirainen SOLR_XML_CONTENT_STATE_UID,
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen SOLR_XML_CONTENT_STATE_SCORE,
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen SOLR_XML_CONTENT_STATE_MAILBOX,
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen SOLR_XML_CONTENT_STATE_NAMESPACE,
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody SOLR_XML_CONTENT_STATE_UIDVALIDITY,
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody SOLR_XML_CONTENT_STATE_ERROR
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody};
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstruct solr_lookup_xml_context {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen enum solr_xml_response_state state;
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen enum solr_xml_content_state content_state;
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen int depth;
72c4ef3b44c50c662b37bba93b463b0caeb63a4fTimo Sirainen
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila uint32_t uid, uidvalidity;
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody float score;
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody char *mailbox, *ns;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen pool_t result_pool;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen /* box_id -> solr_result */
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen HASH_TABLE(char *, struct solr_result *) mailboxes;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen ARRAY(struct solr_result *) results;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen};
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
202468f94e6c6c8b5d3d98ee74e01bb0d0bb04aaTimo Sirainenstruct solr_connection_post {
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen struct solr_connection *conn;
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen struct http_client_request *http_req;
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen bool failed:1;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen};
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstruct solr_connection {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen XML_Parser xml_parser;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen char *http_host;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila in_port_t http_port;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen char *http_base_url;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila char *http_failure;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila char *http_user;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen char *http_password;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen int request_status;
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen struct istream *payload;
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen struct io *io;
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen bool debug:1;
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen bool posting:1;
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen bool xml_failed:1;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen bool http_ssl:1;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen};
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic int solr_xml_parse(struct solr_connection *conn,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen const void *data, size_t size, bool done)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen enum XML_Error err;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen int line, col;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (conn->xml_failed)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return -1;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen if (XML_Parse(conn->xml_parser, data, size, done ? 1 : 0) != 0)
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang return 0;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen err = XML_GetErrorCode(conn->xml_parser);
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen if (err != XML_ERROR_FINISHED) {
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang line = XML_GetCurrentLineNumber(conn->xml_parser);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen col = XML_GetCurrentColumnNumber(conn->xml_parser);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen i_error("fts_solr: Invalid XML input at %d:%d: %s "
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen "(near: %.*s)", line, col, XML_ErrorString(err),
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen (int)I_MIN(size, 128), (const char *)data);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen conn->xml_failed = TRUE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return -1;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return 0;
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen}
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenint solr_connection_init(const char *url, bool debug,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen struct solr_connection **conn_r, const char **error_r)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen struct http_client_settings http_set;
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang struct solr_connection *conn;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen struct http_url *http_url;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen const char *error;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (http_url_parse(url, NULL, HTTP_URL_ALLOW_USERINFO_PART, pool_datastack_create(),
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen &http_url, &error) < 0) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen *error_r = t_strdup_printf(
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen "fts_solr: Failed to parse HTTP url: %s", error);
62461eb609e1d852e027cf4e07d30d51288678a2Aki Tuomi return -1;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen conn = i_new(struct solr_connection, 1);
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang conn->http_host = i_strdup(http_url->host.name);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen conn->http_port = http_url->port;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen conn->http_base_url = i_strconcat(http_url->path, http_url->enc_query, NULL);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen conn->http_ssl = http_url->have_ssl;
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen if (http_url->user != NULL) {
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang conn->http_user = i_strdup(http_url->user);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* allow empty password */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen conn->http_password = i_strdup(http_url->password != NULL ? http_url->password : "");
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen }
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen conn->debug = debug;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (solr_http_client == NULL) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen i_zero(&http_set);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen http_set.max_idle_time_msecs = 5*1000;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen http_set.max_parallel_connections = 1;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen http_set.max_pipelined_requests = 1;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen http_set.max_redirects = 1;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen http_set.max_attempts = 3;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen http_set.debug = debug;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen http_set.connect_timeout_msecs = 5*1000;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen http_set.request_timeout_msecs = 60*1000;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen solr_http_client = http_client_init(&http_set);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen conn->xml_parser = XML_ParserCreate("UTF-8");
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (conn->xml_parser == NULL) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen i_fatal_status(FATAL_OUTOFMEM,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen "fts_solr: Failed to allocate XML parser");
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
3448096d5b1cd324ed5132045de0345cd7120a25Timo Sirainen *conn_r = conn;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return 0;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen}
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenvoid solr_connection_deinit(struct solr_connection **_conn)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
78f87ea1d30f3f54bdf8560ea947ab7ee094283aTeemu Huovila struct solr_connection *conn = *_conn;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen *_conn = NULL;
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen XML_ParserFree(conn->xml_parser);
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen i_free(conn->http_host);
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila i_free(conn->http_base_url);
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila i_free(conn->http_user);
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila i_free(conn->http_password);
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody i_free(conn);
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen}
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainenstatic const char *attrs_get_name(const char **attrs)
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen{
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen for (; *attrs != NULL; attrs += 2) {
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen if (strcmp(attrs[0], "name") == 0)
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen return attrs[1];
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen }
202468f94e6c6c8b5d3d98ee74e01bb0d0bb04aaTimo Sirainen return "";
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen}
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainenstatic void
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainensolr_lookup_xml_start(void *context, const char *name, const char **attrs)
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen{
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct solr_lookup_xml_context *ctx = context;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen const char *name_attr;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen i_assert(ctx->depth >= (int)ctx->state);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen ctx->depth++;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila if (ctx->depth - 1 > (int)ctx->state) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* skipping over unwanted elements */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* response -> result -> doc */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen switch (ctx->state) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen case SOLR_XML_RESPONSE_STATE_ROOT:
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen if (strcmp(name, "response") == 0)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen ctx->state++;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen break;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen case SOLR_XML_RESPONSE_STATE_RESPONSE:
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (strcmp(name, "result") == 0)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen ctx->state++;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen break;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen case SOLR_XML_RESPONSE_STATE_RESULT:
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (strcmp(name, "doc") == 0) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen ctx->state++;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen ctx->uid = 0;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen ctx->score = 0;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen i_free_and_null(ctx->mailbox);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen i_free_and_null(ctx->ns);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen ctx->uidvalidity = 0;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
3448096d5b1cd324ed5132045de0345cd7120a25Timo Sirainen break;
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila case SOLR_XML_RESPONSE_STATE_DOC:
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila name_attr = attrs_get_name(attrs);
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody if (strcmp(name_attr, "uid") == 0)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_UID;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen else if (strcmp(name_attr, "score") == 0)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_SCORE;
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila else if (strcmp(name_attr, "box") == 0)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_MAILBOX;
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen else if (strcmp(name_attr, "ns") == 0)
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_NAMESPACE;
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila else if (strcmp(name_attr, "uidv") == 0)
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila ctx->content_state = SOLR_XML_CONTENT_STATE_UIDVALIDITY;
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila else
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody break;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen ctx->state++;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen break;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen case SOLR_XML_RESPONSE_STATE_CONTENT:
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen break;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen }
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen}
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainenstatic struct solr_result *
202468f94e6c6c8b5d3d98ee74e01bb0d0bb04aaTimo Sirainensolr_result_get(struct solr_lookup_xml_context *ctx, const char *box_id)
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen{
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen struct solr_result *result;
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen char *box_id_dup;
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen result = hash_table_lookup(ctx->mailboxes, box_id);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (result != NULL)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return result;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen box_id_dup = p_strdup(ctx->result_pool, box_id);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen result = p_new(ctx->result_pool, struct solr_result, 1);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen result->box_id = box_id_dup;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila p_array_init(&result->uids, ctx->result_pool, 32);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen p_array_init(&result->scores, ctx->result_pool, 32);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen hash_table_insert(ctx->mailboxes, box_id_dup, result);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen array_append(&ctx->results, &result, 1);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return result;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen}
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainenstatic int solr_lookup_add_doc(struct solr_lookup_xml_context *ctx)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen{
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct fts_score_map *score;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct solr_result *result;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen const char *box_id;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila if (ctx->uid == 0) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila i_error("fts_solr: uid missing from inside doc");
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila return -1;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila }
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila if (ctx->mailbox == NULL) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* looking up from a single mailbox only */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila box_id = "";
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila } else if (ctx->uidvalidity != 0) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* old style lookup */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila string_t *str = t_str_new(64);
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody str_printfa(str, "%u\001", ctx->uidvalidity);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila str_append(str, ctx->mailbox);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila if (ctx->ns != NULL)
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila str_printfa(str, "\001%s", ctx->ns);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila box_id = str_c(str);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila } else {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* new style lookup */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila box_id = ctx->mailbox;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila }
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila result = solr_result_get(ctx, box_id);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody if (seq_range_array_add(&result->uids, ctx->uid)) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* duplicate result */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila } else if (ctx->score != 0) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila score = array_append_space(&result->scores);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila score->uid = ctx->uid;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila score->score = ctx->score;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila }
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila return 0;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila}
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovilastatic void solr_lookup_xml_end(void *context, const char *name ATTR_UNUSED)
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila{
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila struct solr_lookup_xml_context *ctx = context;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila int ret;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila if (ctx->content_state == SOLR_XML_CONTENT_STATE_ERROR)
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila return;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila i_assert(ctx->depth >= (int)ctx->state);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila if (ctx->state == SOLR_XML_RESPONSE_STATE_CONTENT &&
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila ctx->content_state == SOLR_XML_CONTENT_STATE_MAILBOX &&
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila ctx->mailbox == NULL) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* mailbox is namespace prefix */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila ctx->mailbox = i_strdup("");
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila }
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila if (ctx->depth == (int)ctx->state) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila ret = 0;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila if (ctx->state == SOLR_XML_RESPONSE_STATE_DOC) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila T_BEGIN {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila ret = solr_lookup_add_doc(ctx);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila } T_END;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila }
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila ctx->state--;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (ret < 0)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_ERROR;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen else
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_NONE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen }
af177be2664018e8074d69449b9c6a2d9741ec25Teemu Huovila ctx->depth--;
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang}
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wangstatic int uint32_parse(const char *str, int len, uint32_t *value_r)
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang{
eb568e46e82bc814ca3384236a483691a12f9c54Baofeng Wang uint32_t value = 0;
eb568e46e82bc814ca3384236a483691a12f9c54Baofeng Wang int i;
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen for (i = 0; i < len; i++) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (str[i] < '0' || str[i] > '9')
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen break;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen value = value*10 + str[i]-'0';
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen }
908c417cc19ec4a2a01db542498c13ade3943601Timo Sirainen if (i != len)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return -1;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen *value_r = value;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return 0;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen}
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic void solr_lookup_xml_data(void *context, const char *str, int len)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct solr_lookup_xml_context *ctx = context;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen char *new_name;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen switch (ctx->content_state) {
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang case SOLR_XML_CONTENT_STATE_NONE:
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang break;
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang case SOLR_XML_CONTENT_STATE_UID:
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang if (uint32_parse(str, len, &ctx->uid) < 0 || ctx->uid == 0) {
eb568e46e82bc814ca3384236a483691a12f9c54Baofeng Wang i_error("fts_solr: received invalid uid '%s'",
eb568e46e82bc814ca3384236a483691a12f9c54Baofeng Wang t_strndup(str, len));
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang ctx->content_state = SOLR_XML_CONTENT_STATE_ERROR;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen break;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen case SOLR_XML_CONTENT_STATE_SCORE:
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen T_BEGIN {
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila ctx->score = strtod(t_strndup(str, len), NULL);
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila } T_END;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen break;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen case SOLR_XML_CONTENT_STATE_MAILBOX:
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* this may be called multiple times, for example if input
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen contains '&' characters */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen new_name = ctx->mailbox == NULL ? i_strndup(str, len) :
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen i_strconcat(ctx->mailbox, t_strndup(str, len), NULL);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen i_free(ctx->mailbox);
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila ctx->mailbox = new_name;
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila break;
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila case SOLR_XML_CONTENT_STATE_NAMESPACE:
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila new_name = ctx->ns == NULL ? i_strndup(str, len) :
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila i_strconcat(ctx->ns, t_strndup(str, len), NULL);
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila i_free(ctx->ns);
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila ctx->ns = new_name;
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila break;
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila case SOLR_XML_CONTENT_STATE_UIDVALIDITY:
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila if (uint32_parse(str, len, &ctx->uidvalidity) < 0)
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila i_error("fts_solr: received invalid uidvalidity");
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen break;
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen case SOLR_XML_CONTENT_STATE_ERROR:
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen break;
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen}
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenstatic void solr_connection_payload_input(struct solr_connection *conn)
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang{
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang const unsigned char *data;
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang size_t size;
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang int ret;
eb568e46e82bc814ca3384236a483691a12f9c54Baofeng Wang
eb568e46e82bc814ca3384236a483691a12f9c54Baofeng Wang /* read payload */
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang while ((ret = i_stream_read_more(conn->payload, &data, &size)) > 0) {
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen (void)solr_xml_parse(conn, data, size, FALSE);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen i_stream_skip(conn->payload, size);
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen }
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen if (ret == 0) {
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* we will be called again for more data */
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen } else {
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen if (conn->payload->stream_errno != 0) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen i_error("fts_solr: failed to read payload from HTTP server: %m");
c4b772bfbdafe68ac1a0076eab26cd681f8e5046Timo Sirainen conn->request_status = -1;
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen }
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen io_remove(&conn->io);
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen i_stream_unref(&conn->payload);
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen }
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen}
c4b772bfbdafe68ac1a0076eab26cd681f8e5046Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainenstatic void
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainensolr_connection_select_response(const struct http_response *response,
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen struct solr_connection *conn)
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen{
c4b772bfbdafe68ac1a0076eab26cd681f8e5046Timo Sirainen if (response->status / 100 != 2) {
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen i_error("fts_solr: Lookup failed: %u %s",
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen response->status, response->reason);
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen conn->request_status = -1;
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen return;
c4b772bfbdafe68ac1a0076eab26cd681f8e5046Timo Sirainen }
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen if (response->payload == NULL) {
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen i_error("fts_solr: Lookup failed: Empty response payload");
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen conn->request_status = -1;
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen return;
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen }
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen i_stream_ref(response->payload);
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen conn->payload = response->payload;
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen conn->io = io_add_istream(response->payload,
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen solr_connection_payload_input, conn);
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen solr_connection_payload_input(conn);
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen}
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen
0d6f8e7e231ac3fc8647d8fc3072d7d1e477a7cfBaofeng Wangint solr_connection_select(struct solr_connection *conn, const char *query,
b7324e421e2132cbbf753e6fdbe675bbaecdf929Timo Sirainen pool_t pool, struct solr_result ***box_results_r)
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen{
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen struct solr_lookup_xml_context solr_lookup_context;
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen struct http_client_request *http_req;
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen const char *url;
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen int parse_ret;
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen i_zero(&solr_lookup_context);
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen solr_lookup_context.result_pool = pool;
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen hash_table_create(&solr_lookup_context.mailboxes, default_pool, 0,
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen str_hash, strcmp);
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen p_array_init(&solr_lookup_context.results, pool, 32);
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen i_free_and_null(conn->http_failure);
0d6f8e7e231ac3fc8647d8fc3072d7d1e477a7cfBaofeng Wang conn->xml_failed = FALSE;
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen XML_ParserReset(conn->xml_parser, "UTF-8");
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen XML_SetElementHandler(conn->xml_parser,
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen solr_lookup_xml_start, solr_lookup_xml_end);
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen XML_SetCharacterDataHandler(conn->xml_parser, solr_lookup_xml_data);
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen XML_SetUserData(conn->xml_parser, &solr_lookup_context);
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen url = t_strconcat(conn->http_base_url, "select?", query, NULL);
0d6f8e7e231ac3fc8647d8fc3072d7d1e477a7cfBaofeng Wang
edc654a35c3368dfb529ba784aee41dff6f45149Timo Sirainen http_req = http_client_request(solr_http_client, "GET",
0d6f8e7e231ac3fc8647d8fc3072d7d1e477a7cfBaofeng Wang conn->http_host, url,
0d6f8e7e231ac3fc8647d8fc3072d7d1e477a7cfBaofeng Wang solr_connection_select_response, conn);
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen if (conn->http_user != NULL) {
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen http_client_request_set_auth_simple(http_req, conn->http_user, conn->http_password);
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen }
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen http_client_request_set_port(http_req, conn->http_port);
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen http_client_request_set_ssl(http_req, conn->http_ssl);
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen http_client_request_submit(http_req);
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen conn->request_status = 0;
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen http_client_wait(solr_http_client);
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen if (conn->request_status < 0 ||
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen solr_lookup_context.content_state == SOLR_XML_CONTENT_STATE_ERROR)
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen return -1;
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen parse_ret = solr_xml_parse(conn, "", 0, TRUE);
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen hash_table_destroy(&solr_lookup_context.mailboxes);
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen array_append_zero(&solr_lookup_context.results);
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen *box_results_r = array_idx_modifiable(&solr_lookup_context.results, 0);
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen return parse_ret;
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen}
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainenstatic void
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainensolr_connection_update_response(const struct http_response *response,
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen struct solr_connection *conn)
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen{
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen if (response->status / 100 != 2) {
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen i_error("fts_solr: Indexing failed: %u %s",
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen response->status, response->reason);
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen conn->request_status = -1;
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen }
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen}
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainenstatic struct http_client_request *
62461eb609e1d852e027cf4e07d30d51288678a2Aki Tuomisolr_connection_post_request(struct solr_connection *conn)
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen{
5c97732871842800816aea0215c56bf701f623a6Aki Tuomi struct http_client_request *http_req;
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen const char *url;
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen url = t_strconcat(conn->http_base_url, "update", NULL);
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen http_req = http_client_request(solr_http_client, "POST",
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen conn->http_host, url,
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen solr_connection_update_response, conn);
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen if (conn->http_user != NULL) {
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen http_client_request_set_auth_simple(http_req, conn->http_user, conn->http_password);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen http_client_request_set_port(http_req, conn->http_port);
baf3e87e186453fda13bd21f7cbcb2efc8492e8bTimo Sirainen http_client_request_set_ssl(http_req, conn->http_ssl);
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen http_client_request_add_header(http_req, "Content-Type", "text/xml");
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return http_req;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen}
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenstruct solr_connection_post *
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovilasolr_connection_post_begin(struct solr_connection *conn)
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila{
b1b0b2b543dc1a10015272fc970ad7534f84e0c5Timo Sirainen struct solr_connection_post *post;
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen
0d6f8e7e231ac3fc8647d8fc3072d7d1e477a7cfBaofeng Wang i_assert(!conn->posting);
9d92ea347e1c098fa33ea517514dfdc0bb8995e2Timo Sirainen conn->posting = TRUE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen post = i_new(struct solr_connection_post, 1);
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen post->conn = conn;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen post->http_req = solr_connection_post_request(conn);
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen XML_ParserReset(conn->xml_parser, "UTF-8");
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen return post;
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen}
507ea0bc5b25efb4c96033a19dec66689a50ebd0Baofeng Wang
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainenvoid solr_connection_post_more(struct solr_connection_post *post,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen const unsigned char *data, size_t size)
{
struct solr_connection *conn = post->conn;
i_assert(post->conn->posting);
if (post->failed)
return;
if (conn->request_status == 0)
(void)http_client_request_send_payload(&post->http_req, data, size);
if (conn->request_status < 0)
post->failed = TRUE;
}
int solr_connection_post_end(struct solr_connection_post **_post)
{
struct solr_connection_post *post = *_post;
struct solr_connection *conn = post->conn;
int ret = post->failed ? -1 : 0;
i_assert(conn->posting);
*_post = NULL;
if (!post->failed) {
if (http_client_request_finish_payload(&post->http_req) < 0 ||
conn->request_status < 0) {
ret = -1;
}
} else {
if (post->http_req != NULL)
http_client_request_abort(&post->http_req);
}
i_free(post);
conn->posting = FALSE;
return ret;
}
int solr_connection_post(struct solr_connection *conn, const char *cmd)
{
struct http_client_request *http_req;
struct istream *post_payload;
i_assert(!conn->posting);
http_req = solr_connection_post_request(conn);
post_payload = i_stream_create_from_data(cmd, strlen(cmd));
http_client_request_set_payload(http_req, post_payload, TRUE);
i_stream_unref(&post_payload);
http_client_request_submit(http_req);
XML_ParserReset(conn->xml_parser, "UTF-8");
conn->request_status = 0;
http_client_wait(solr_http_client);
return conn->request_status;
}