1 /*
2  * Copyright (C) 2009, Nokia <ivan.frade@nokia.com>
3  * Copyright (C) 2014, Lanedo <martyn@lanedo.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301  USA
19  */
20 
21 #include "config.h"
22 
23 #include <string.h>
24 #include <stdlib.h>
25 
26 #include <glib.h>
27 #include <gio/gio.h>
28 
29 #define G_SETTINGS_ENABLE_BACKEND
30 #include <gio/gsettingsbackend.h>
31 
32 #include <libtracker-common/tracker-common.h>
33 
34 #include "tracker-fts-config.h"
35 
36 #define CONFIG_SCHEMA "org.freedesktop.Tracker.FTS"
37 #define CONFIG_PATH   "/org/freedesktop/tracker/fts/"
38 
39 /* Default values */
40 #define DEFAULT_MAX_WORD_LENGTH      30     /* 0->200 */
41 #define DEFAULT_MAX_WORDS_TO_INDEX   10000
42 #define DEFAULT_IGNORE_NUMBERS       TRUE
43 #define DEFAULT_IGNORE_STOP_WORDS    TRUE
44 #define DEFAULT_ENABLE_STEMMER       FALSE  /* As per GB#526346, disabled */
45 #define DEFAULT_ENABLE_UNACCENT      TRUE
46 
47 static void config_set_property         (GObject       *object,
48                                          guint          param_id,
49                                          const GValue  *value,
50                                          GParamSpec    *pspec);
51 static void config_get_property         (GObject       *object,
52                                          guint          param_id,
53                                          GValue        *value,
54                                          GParamSpec    *pspec);
55 static void config_finalize             (GObject       *object);
56 static void config_constructed          (GObject       *object);
57 
58 enum {
59 	PROP_0,
60 
61 	/* Indexing */
62 	PROP_MAX_WORD_LENGTH,
63 	PROP_ENABLE_STEMMER,
64 	PROP_ENABLE_UNACCENT,
65 	PROP_IGNORE_NUMBERS,
66 	PROP_IGNORE_STOP_WORDS,
67 
68 	/* Performance */
69 	PROP_MAX_WORDS_TO_INDEX,
70 };
71 
72 G_DEFINE_TYPE (TrackerFTSConfig, tracker_fts_config, G_TYPE_SETTINGS);
73 
74 static void
tracker_fts_config_class_init(TrackerFTSConfigClass * klass)75 tracker_fts_config_class_init (TrackerFTSConfigClass *klass)
76 {
77 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
78 
79 	object_class->set_property = config_set_property;
80 	object_class->get_property = config_get_property;
81 	object_class->finalize     = config_finalize;
82 	object_class->constructed  = config_constructed;
83 
84 	/* Indexing */
85 	g_object_class_install_property (object_class,
86 	                                 PROP_MAX_WORD_LENGTH,
87 	                                 g_param_spec_int ("max-word-length",
88 	                                                   "Maximum word length",
89 	                                                   " Set the maximum length of words to index (0->200, default=30)",
90 	                                                   0,
91 	                                                   200, /* Is this a reasonable limit? */
92 	                                                   DEFAULT_MAX_WORD_LENGTH,
93 	                                                   G_PARAM_READWRITE));
94 	g_object_class_install_property (object_class,
95 	                                 PROP_ENABLE_STEMMER,
96 	                                 g_param_spec_boolean ("enable-stemmer",
97 	                                                       "Enable Stemmer",
98 	                                                       " Flag to enable word stemming utility (default=FALSE)",
99 	                                                       DEFAULT_ENABLE_STEMMER,
100 	                                                       G_PARAM_READWRITE));
101 	g_object_class_install_property (object_class,
102 	                                 PROP_ENABLE_UNACCENT,
103 	                                 g_param_spec_boolean ("enable-unaccent",
104 	                                                       "Enable Unaccent",
105 	                                                       " Flag to enable word unaccenting (default=TRUE)",
106 	                                                       DEFAULT_ENABLE_UNACCENT,
107 	                                                       G_PARAM_READWRITE));
108 	g_object_class_install_property (object_class,
109 	                                 PROP_IGNORE_NUMBERS,
110 	                                 g_param_spec_boolean ("ignore-numbers",
111 	                                                       "Ignore numbers",
112 	                                                       " Flag to ignore numbers in FTS (default=TRUE)",
113 	                                                       DEFAULT_IGNORE_NUMBERS,
114 	                                                       G_PARAM_READWRITE));
115 	g_object_class_install_property (object_class,
116 	                                 PROP_IGNORE_STOP_WORDS,
117 	                                 g_param_spec_boolean ("ignore-stop-words",
118 	                                                       "Ignore stop words",
119 	                                                       " Flag to ignore stop words in FTS (default=TRUE)",
120 	                                                       DEFAULT_IGNORE_STOP_WORDS,
121 	                                                       G_PARAM_READWRITE));
122 	g_object_class_install_property (object_class,
123 	                                 PROP_MAX_WORDS_TO_INDEX,
124 	                                 g_param_spec_int ("max-words-to-index",
125 	                                                   "Maximum words to index",
126 	                                                   " Maximum unique words to index from a file's content (default=10000)",
127 	                                                   0,
128 	                                                   G_MAXINT,
129 	                                                   DEFAULT_MAX_WORDS_TO_INDEX,
130 	                                                   G_PARAM_READWRITE));
131 
132 }
133 
134 static void
tracker_fts_config_init(TrackerFTSConfig * object)135 tracker_fts_config_init (TrackerFTSConfig *object)
136 {
137 }
138 
139 static void
config_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)140 config_set_property (GObject      *object,
141                      guint         param_id,
142                      const GValue *value,
143                      GParamSpec   *pspec)
144 {
145 	switch (param_id) {
146 		/* Indexing */
147 	case PROP_MAX_WORD_LENGTH:
148 		tracker_fts_config_set_max_word_length (TRACKER_FTS_CONFIG (object),
149 		                                        g_value_get_int (value));
150 		break;
151 	case PROP_ENABLE_STEMMER:
152 		tracker_fts_config_set_enable_stemmer (TRACKER_FTS_CONFIG (object),
153 		                                       g_value_get_boolean (value));
154 		break;
155 	case PROP_ENABLE_UNACCENT:
156 		tracker_fts_config_set_enable_unaccent (TRACKER_FTS_CONFIG (object),
157 		                                        g_value_get_boolean (value));
158 		break;
159 	case PROP_IGNORE_NUMBERS:
160 		tracker_fts_config_set_ignore_numbers (TRACKER_FTS_CONFIG (object),
161 		                                       g_value_get_boolean (value));
162 		break;
163 	case PROP_IGNORE_STOP_WORDS:
164 		tracker_fts_config_set_ignore_stop_words (TRACKER_FTS_CONFIG (object),
165 		                                          g_value_get_boolean (value));
166 		break;
167 	case PROP_MAX_WORDS_TO_INDEX:
168 		tracker_fts_config_set_max_words_to_index (TRACKER_FTS_CONFIG (object),
169 		                                           g_value_get_int (value));
170 		break;
171 
172 	default:
173 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
174 		break;
175 	};
176 }
177 
178 static void
config_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)179 config_get_property (GObject    *object,
180                      guint       param_id,
181                      GValue     *value,
182                      GParamSpec *pspec)
183 {
184         TrackerFTSConfig *config = TRACKER_FTS_CONFIG (object);
185 
186 	switch (param_id) {
187 		/* Indexing */
188 	case PROP_MAX_WORD_LENGTH:
189 		g_value_set_int (value, tracker_fts_config_get_max_word_length (config));
190 		break;
191 	case PROP_ENABLE_STEMMER:
192 		g_value_set_boolean (value, tracker_fts_config_get_enable_stemmer (config));
193 		break;
194 	case PROP_ENABLE_UNACCENT:
195 		g_value_set_boolean (value, tracker_fts_config_get_enable_unaccent (config));
196 		break;
197 	case PROP_IGNORE_NUMBERS:
198 		g_value_set_boolean (value, tracker_fts_config_get_ignore_numbers (config));
199 		break;
200 	case PROP_IGNORE_STOP_WORDS:
201 		g_value_set_boolean (value, tracker_fts_config_get_ignore_stop_words (config));
202 		break;
203 	case PROP_MAX_WORDS_TO_INDEX:
204 		g_value_set_int (value, tracker_fts_config_get_max_words_to_index (config));
205 		break;
206 
207 	default:
208 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
209 		break;
210 	};
211 }
212 
213 static void
config_finalize(GObject * object)214 config_finalize (GObject *object)
215 {
216 	/* For now we do nothing here, we left this override in for
217 	 * future expansion.
218 	 */
219 
220 	(G_OBJECT_CLASS (tracker_fts_config_parent_class)->finalize) (object);
221 }
222 
223 static void
config_constructed(GObject * object)224 config_constructed (GObject *object)
225 {
226 	GSettings *settings;
227 
228 	(G_OBJECT_CLASS (tracker_fts_config_parent_class)->constructed) (object);
229 
230 	settings = G_SETTINGS (object);
231 
232 	if (G_LIKELY (!g_getenv ("TRACKER_USE_CONFIG_FILES"))) {
233 		g_settings_delay (settings);
234 	}
235 
236 	g_settings_bind (settings, "max-word-length", object, "max-word-length", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES);
237 	g_settings_bind (settings, "enable-stemmer", object, "enable-stemmer", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES);
238 	g_settings_bind (settings, "enable-unaccent", object, "enable-unaccent", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES);
239 	g_settings_bind (settings, "ignore-numbers", object, "ignore-numbers", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES);
240 	g_settings_bind (settings, "ignore-stop-words", object, "ignore-stop-words", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES);
241 	g_settings_bind (settings, "max-words-to-index", object, "max-words-to-index", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES);
242 }
243 
244 TrackerFTSConfig *
tracker_fts_config_new(void)245 tracker_fts_config_new (void)
246 {
247 	TrackerFTSConfig *config = NULL;
248 
249 	/* FIXME: should we unset GSETTINGS_BACKEND env var? */
250 
251 	if (G_UNLIKELY (g_getenv ("TRACKER_USE_CONFIG_FILES"))) {
252 		GSettingsBackend *backend;
253 		gchar *filename;
254 		gboolean need_to_save;
255 
256 		filename = g_build_filename (g_get_user_config_dir (), "tracker", "tracker-fts.cfg", NULL);
257 
258 		need_to_save = g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE;
259 
260 		backend = g_keyfile_settings_backend_new (filename, CONFIG_PATH, "General");
261 		g_info ("Using config file '%s'", filename);
262 		g_free (filename);
263 
264 		config = g_object_new (TRACKER_TYPE_FTS_CONFIG,
265 		                       "backend", backend,
266 		                       "schema-id", CONFIG_SCHEMA,
267 		                       "path", CONFIG_PATH,
268 		                       NULL);
269 		g_object_unref (backend);
270 
271 		if (need_to_save) {
272 			g_info ("  Config file does not exist, using default values...");
273 		}
274 	} else {
275 		config = g_object_new (TRACKER_TYPE_FTS_CONFIG,
276 		                       "schema-id", CONFIG_SCHEMA,
277 		                       "path", CONFIG_PATH,
278 		                       NULL);
279 	}
280 
281 	return config;
282 }
283 
284 gboolean
tracker_fts_config_save(TrackerFTSConfig * config)285 tracker_fts_config_save (TrackerFTSConfig *config)
286 {
287 	g_return_val_if_fail (TRACKER_IS_FTS_CONFIG (config), FALSE);
288 
289         g_settings_apply (G_SETTINGS (config));
290 
291 	return TRUE;
292 }
293 
294 gint
tracker_fts_config_get_max_word_length(TrackerFTSConfig * config)295 tracker_fts_config_get_max_word_length (TrackerFTSConfig *config)
296 {
297 	g_return_val_if_fail (TRACKER_IS_FTS_CONFIG (config), DEFAULT_MAX_WORD_LENGTH);
298 
299 	return g_settings_get_int (G_SETTINGS (config), "max-word-length");
300 }
301 
302 gboolean
tracker_fts_config_get_enable_stemmer(TrackerFTSConfig * config)303 tracker_fts_config_get_enable_stemmer (TrackerFTSConfig *config)
304 {
305 	g_return_val_if_fail (TRACKER_IS_FTS_CONFIG (config), DEFAULT_ENABLE_STEMMER);
306 
307 	return g_settings_get_boolean (G_SETTINGS (config), "enable-stemmer");
308 }
309 
310 gboolean
tracker_fts_config_get_enable_unaccent(TrackerFTSConfig * config)311 tracker_fts_config_get_enable_unaccent (TrackerFTSConfig *config)
312 {
313 	g_return_val_if_fail (TRACKER_IS_FTS_CONFIG (config), DEFAULT_ENABLE_UNACCENT);
314 
315 	return g_settings_get_boolean (G_SETTINGS (config), "enable-unaccent");
316 }
317 
318 gboolean
tracker_fts_config_get_ignore_numbers(TrackerFTSConfig * config)319 tracker_fts_config_get_ignore_numbers (TrackerFTSConfig *config)
320 {
321 	g_return_val_if_fail (TRACKER_IS_FTS_CONFIG (config), DEFAULT_IGNORE_NUMBERS);
322 
323 	return g_settings_get_boolean (G_SETTINGS (config), "ignore-numbers");
324 }
325 
326 gboolean
tracker_fts_config_get_ignore_stop_words(TrackerFTSConfig * config)327 tracker_fts_config_get_ignore_stop_words (TrackerFTSConfig *config)
328 {
329 	g_return_val_if_fail (TRACKER_IS_FTS_CONFIG (config), DEFAULT_IGNORE_STOP_WORDS);
330 
331 	return g_settings_get_boolean (G_SETTINGS (config),  "ignore-stop-words");
332 }
333 
334 gint
tracker_fts_config_get_max_words_to_index(TrackerFTSConfig * config)335 tracker_fts_config_get_max_words_to_index (TrackerFTSConfig *config)
336 {
337 	g_return_val_if_fail (TRACKER_IS_FTS_CONFIG (config), DEFAULT_MAX_WORDS_TO_INDEX);
338 
339 	return g_settings_get_int (G_SETTINGS (config), "max-words-to-index");
340 }
341 
342 void
tracker_fts_config_set_max_word_length(TrackerFTSConfig * config,gint value)343 tracker_fts_config_set_max_word_length (TrackerFTSConfig *config,
344                                         gint              value)
345 {
346 	g_return_if_fail (TRACKER_IS_FTS_CONFIG (config));
347 
348         g_settings_set_int (G_SETTINGS (config), "max-word-length", value);
349 	g_object_notify (G_OBJECT (config), "max-word-length");
350 }
351 
352 void
tracker_fts_config_set_enable_stemmer(TrackerFTSConfig * config,gboolean value)353 tracker_fts_config_set_enable_stemmer (TrackerFTSConfig *config,
354                                        gboolean          value)
355 {
356 	g_return_if_fail (TRACKER_IS_FTS_CONFIG (config));
357 
358         g_settings_set_boolean (G_SETTINGS (config), "enable-stemmer", value);
359 	g_object_notify (G_OBJECT (config), "enable-stemmer");
360 }
361 
362 void
tracker_fts_config_set_enable_unaccent(TrackerFTSConfig * config,gboolean value)363 tracker_fts_config_set_enable_unaccent (TrackerFTSConfig *config,
364 					gboolean          value)
365 {
366 	g_return_if_fail (TRACKER_IS_FTS_CONFIG (config));
367 
368         g_settings_set_boolean (G_SETTINGS (config), "enable-unaccent", value);
369 	g_object_notify (G_OBJECT (config), "enable-unaccent");
370 }
371 
372 void
tracker_fts_config_set_ignore_numbers(TrackerFTSConfig * config,gboolean value)373 tracker_fts_config_set_ignore_numbers (TrackerFTSConfig *config,
374                                        gboolean          value)
375 {
376 	g_return_if_fail (TRACKER_IS_FTS_CONFIG (config));
377 
378         g_settings_set_boolean (G_SETTINGS (config), "ignore-numbers", value);
379 	g_object_notify (G_OBJECT (config), "ignore-numbers");
380 }
381 
382 void
tracker_fts_config_set_ignore_stop_words(TrackerFTSConfig * config,gboolean value)383 tracker_fts_config_set_ignore_stop_words (TrackerFTSConfig *config,
384                                           gboolean          value)
385 {
386 	g_return_if_fail (TRACKER_IS_FTS_CONFIG (config));
387 
388         g_settings_set_boolean (G_SETTINGS (config), "ignore-stop-words", value);
389 	g_object_notify (G_OBJECT (config), "ignore-stop-words");
390 }
391 
392 void
tracker_fts_config_set_max_words_to_index(TrackerFTSConfig * config,gint value)393 tracker_fts_config_set_max_words_to_index (TrackerFTSConfig *config,
394                                            gint              value)
395 {
396 	g_return_if_fail (TRACKER_IS_FTS_CONFIG (config));
397 
398         g_settings_set_int (G_SETTINGS (config), "max-words-to-index", value);
399 	g_object_notify (G_OBJECT (config), "max-words-to-index");
400 }
401