1 /* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "array.h"
5 #include "http-client.h"
6 #include "mail-user.h"
7 #include "mail-storage-hooks.h"
8 #include "solr-connection.h"
9 #include "fts-user.h"
10 #include "fts-solr-plugin.h"
11 
12 #define DEFAULT_SOLR_BATCH_SIZE 1000
13 
14 const char *fts_solr_plugin_version = DOVECOT_ABI_VERSION;
15 struct http_client *solr_http_client = NULL;
16 
17 struct fts_solr_user_module fts_solr_user_module =
18 	MODULE_CONTEXT_INIT(&mail_user_module_register);
19 
20 static int
fts_solr_plugin_init_settings(struct mail_user * user,struct fts_solr_settings * set,const char * str)21 fts_solr_plugin_init_settings(struct mail_user *user,
22 			      struct fts_solr_settings *set, const char *str)
23 {
24 	const char *const *tmp;
25 
26 	if (str == NULL)
27 		str = "";
28 
29 	set->batch_size = DEFAULT_SOLR_BATCH_SIZE;
30 	set->soft_commit = TRUE;
31 
32 	for (tmp = t_strsplit_spaces(str, " "); *tmp != NULL; tmp++) {
33 		if (str_begins(*tmp, "url=")) {
34 			set->url = p_strdup(user->pool, *tmp + 4);
35 		} else if (strcmp(*tmp, "debug") == 0) {
36 			set->debug = TRUE;
37 		} else if (strcmp(*tmp, "use_libfts") == 0) {
38 			set->use_libfts = TRUE;
39 		} else if (str_begins(*tmp, "default_ns=")) {
40 			set->default_ns_prefix =
41 				p_strdup(user->pool, *tmp + 11);
42 		} else if (str_begins(*tmp, "rawlog_dir=")) {
43 			set->rawlog_dir = p_strdup(user->pool, *tmp + 11);
44 		} else if (str_begins(*tmp, "batch_size=")) {
45 			if (str_to_uint(*tmp+11, &set->batch_size) < 0 ||
46 			    set->batch_size == 0) {
47 				i_error("fts_solr: batch_size must be a positive integer");
48 					return -1;
49 			}
50 		} else if (str_begins(*tmp, "soft_commit=")) {
51 			if (strcmp(*tmp + 12, "yes") == 0) {
52 				set->soft_commit = TRUE;
53 			} else if (strcmp(*tmp + 12, "no") == 0) {
54 				set->soft_commit = FALSE;
55 			} else {
56 				i_error("fts_solr: Invalid setting for soft_commit: %s", *tmp+12);
57 				return -1;
58 			}
59 		} else {
60 			i_error("fts_solr: Invalid setting: %s", *tmp);
61 			return -1;
62 		}
63 	}
64 	if (set->url == NULL) {
65 		i_error("fts_solr: url setting missing");
66 		return -1;
67 	}
68 	return 0;
69 }
70 
fts_solr_mail_user_deinit(struct mail_user * user)71 static void fts_solr_mail_user_deinit(struct mail_user *user)
72 {
73 	struct fts_solr_user *fuser = FTS_SOLR_USER_CONTEXT_REQUIRE(user);
74 
75 	fts_mail_user_deinit(user);
76 	fuser->module_ctx.super.deinit(user);
77 }
78 
fts_solr_mail_user_create(struct mail_user * user,const char * env)79 static void fts_solr_mail_user_create(struct mail_user *user, const char *env)
80 {
81 	struct mail_user_vfuncs *v = user->vlast;
82 	struct fts_solr_user *fuser;
83 	const char *error;
84 
85 	fuser = p_new(user->pool, struct fts_solr_user, 1);
86 	if (fts_solr_plugin_init_settings(user, &fuser->set, env) < 0) {
87 		/* invalid settings, disabling */
88 		return;
89 	}
90 	if (fts_mail_user_init(user, fuser->set.use_libfts, &error) < 0) {
91 		i_error("fts-solr: %s", error);
92 		return;
93 	}
94 
95 	fuser->module_ctx.super = *v;
96 	user->vlast = &fuser->module_ctx.super;
97 	v->deinit = fts_solr_mail_user_deinit;
98 	MODULE_CONTEXT_SET(user, fts_solr_user_module, fuser);
99 }
100 
fts_solr_mail_user_created(struct mail_user * user)101 static void fts_solr_mail_user_created(struct mail_user *user)
102 {
103 	const char *env;
104 
105 	env = mail_user_plugin_getenv(user, "fts_solr");
106 	if (env != NULL)
107 		fts_solr_mail_user_create(user, env);
108 }
109 
110 static struct mail_storage_hooks fts_solr_mail_storage_hooks = {
111 	.mail_user_created = fts_solr_mail_user_created
112 };
113 
fts_solr_plugin_init(struct module * module)114 void fts_solr_plugin_init(struct module *module)
115 {
116 	fts_backend_register(&fts_backend_solr);
117 	fts_backend_register(&fts_backend_solr_old);
118 	mail_storage_hooks_add(module, &fts_solr_mail_storage_hooks);
119 }
120 
fts_solr_plugin_deinit(void)121 void fts_solr_plugin_deinit(void)
122 {
123 	fts_backend_unregister(fts_backend_solr.name);
124 	fts_backend_unregister(fts_backend_solr_old.name);
125 	mail_storage_hooks_remove(&fts_solr_mail_storage_hooks);
126 	if (solr_http_client != NULL)
127 		http_client_deinit(&solr_http_client);
128 
129 }
130 
131 const char *fts_solr_plugin_dependencies[] = { "fts", NULL };
132