1 /*
2 * preferences.c
3 * vim: expandtab:ts=4:sts=4:sw=4
4 *
5 * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
6 * Copyright (C) 2019 - 2021 Michael Vetter <jubalh@iodoru.org>
7 *
8 * This file is part of Profanity.
9 *
10 * Profanity is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Profanity is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Profanity. If not, see <https://www.gnu.org/licenses/>.
22 *
23 * In addition, as a special exception, the copyright holders give permission to
24 * link the code of portions of this program with the OpenSSL library under
25 * certain conditions as described in each individual source file, and
26 * distribute linked combinations including the two.
27 *
28 * You must obey the GNU General Public License in all respects for all of the
29 * code used other than OpenSSL. If you modify file(s) with this exception, you
30 * may extend this exception to your version of the file(s), but you are not
31 * obligated to do so. If you do not wish to do so, delete this exception
32 * statement from your version. If you delete this exception statement from all
33 * source files in the program, then also delete it here.
34 *
35 */
36
37 #include "config.h"
38
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42
43 #include <glib.h>
44 #include <glib/gstdio.h>
45
46 #include "common.h"
47 #include "log.h"
48 #include "preferences.h"
49 #include "tools/autocomplete.h"
50 #include "config/files.h"
51 #include "config/conflists.h"
52
53 // preference groups refer to the sections in .profrc or theme files
54 // for example [ui] but not [colours] which is handled in theme.c
55 #define PREF_GROUP_LOGGING "logging"
56 #define PREF_GROUP_CHATSTATES "chatstates"
57 #define PREF_GROUP_UI "ui"
58 #define PREF_GROUP_NOTIFICATIONS "notifications"
59 #define PREF_GROUP_PRESENCE "presence"
60 #define PREF_GROUP_CONNECTION "connection"
61 #define PREF_GROUP_ALIAS "alias"
62 #define PREF_GROUP_OTR "otr"
63 #define PREF_GROUP_PGP "pgp"
64 #define PREF_GROUP_OMEMO "omemo"
65 #define PREF_GROUP_OX "ox"
66 #define PREF_GROUP_MUC "muc"
67 #define PREF_GROUP_PLUGINS "plugins"
68 #define PREF_GROUP_EXECUTABLES "executables"
69
70 #define INPBLOCK_DEFAULT 1000
71
72 static gchar* prefs_loc;
73 static GKeyFile* prefs;
74 gint log_maxsize = 0;
75
76 static Autocomplete boolean_choice_ac;
77 static Autocomplete room_trigger_ac;
78
79 static void _save_prefs(void);
80 static const char* _get_group(preference_t pref);
81 static const char* _get_key(preference_t pref);
82 static gboolean _get_default_boolean(preference_t pref);
83 static char* _get_default_string(preference_t pref);
84
85 static void
_prefs_load(void)86 _prefs_load(void)
87 {
88 GError* err = NULL;
89 log_maxsize = g_key_file_get_integer(prefs, PREF_GROUP_LOGGING, "maxsize", &err);
90 if (err) {
91 log_maxsize = 0;
92 g_error_free(err);
93 }
94
95 // move pre 0.5.0 autoaway.time to autoaway.awaytime
96 if (g_key_file_has_key(prefs, PREF_GROUP_PRESENCE, "autoaway.time", NULL)) {
97 gint time = g_key_file_get_integer(prefs, PREF_GROUP_PRESENCE, "autoaway.time", NULL);
98 g_key_file_set_integer(prefs, PREF_GROUP_PRESENCE, "autoaway.awaytime", time);
99 g_key_file_remove_key(prefs, PREF_GROUP_PRESENCE, "autoaway.time", NULL);
100 }
101
102 // move pre 0.5.0 autoaway.message to autoaway.awaymessage
103 if (g_key_file_has_key(prefs, PREF_GROUP_PRESENCE, "autoaway.message", NULL)) {
104 char* message = g_key_file_get_string(prefs, PREF_GROUP_PRESENCE, "autoaway.message", NULL);
105 g_key_file_set_string(prefs, PREF_GROUP_PRESENCE, "autoaway.awaymessage", message);
106 g_key_file_remove_key(prefs, PREF_GROUP_PRESENCE, "autoaway.message", NULL);
107 g_free(message);
108 }
109
110 // migrate pre 0.5.0 time settings
111 if (g_key_file_has_key(prefs, PREF_GROUP_UI, "time", NULL)) {
112 char* time = g_key_file_get_string(prefs, PREF_GROUP_UI, "time", NULL);
113 char* val = NULL;
114 if (time) {
115 val = time;
116 } else {
117 val = "off";
118 }
119 g_key_file_set_string(prefs, PREF_GROUP_UI, "time.console", val);
120 g_key_file_set_string(prefs, PREF_GROUP_UI, "time.chat", val);
121 g_key_file_set_string(prefs, PREF_GROUP_UI, "time.muc", val);
122 g_key_file_set_string(prefs, PREF_GROUP_UI, "time.config", val);
123 g_key_file_set_string(prefs, PREF_GROUP_UI, "time.private", val);
124 g_key_file_set_string(prefs, PREF_GROUP_UI, "time.xmlconsole", val);
125 g_key_file_remove_key(prefs, PREF_GROUP_UI, "time", NULL);
126 g_free(time);
127 }
128
129 // move pre 0.5.0 notify settings
130 if (g_key_file_has_key(prefs, PREF_GROUP_NOTIFICATIONS, "room", NULL)) {
131 char* value = g_key_file_get_string(prefs, PREF_GROUP_NOTIFICATIONS, "room", NULL);
132 if (g_strcmp0(value, "on") == 0) {
133 g_key_file_set_boolean(prefs, PREF_GROUP_NOTIFICATIONS, "room", TRUE);
134 } else if (g_strcmp0(value, "off") == 0) {
135 g_key_file_set_boolean(prefs, PREF_GROUP_NOTIFICATIONS, "room", FALSE);
136 } else if (g_strcmp0(value, "mention") == 0) {
137 g_key_file_set_boolean(prefs, PREF_GROUP_NOTIFICATIONS, "room", FALSE);
138 g_key_file_set_boolean(prefs, PREF_GROUP_NOTIFICATIONS, "room.mention", TRUE);
139 }
140 g_free(value);
141 }
142
143 // move pre 0.6.0 titlebar settings to wintitle
144 if (g_key_file_has_key(prefs, PREF_GROUP_UI, "titlebar.show", NULL)) {
145 gboolean show = g_key_file_get_boolean(prefs, PREF_GROUP_UI, "titlebar.show", NULL);
146 g_key_file_set_boolean(prefs, PREF_GROUP_UI, "wintitle.show", show);
147 g_key_file_remove_key(prefs, PREF_GROUP_UI, "titlebar.show", NULL);
148 }
149 if (g_key_file_has_key(prefs, PREF_GROUP_UI, "titlebar.goodbye", NULL)) {
150 gboolean goodbye = g_key_file_get_boolean(prefs, PREF_GROUP_UI, "titlebar.goodbye", NULL);
151 g_key_file_set_boolean(prefs, PREF_GROUP_UI, "wintitle.goodbye", goodbye);
152 g_key_file_remove_key(prefs, PREF_GROUP_UI, "titlebar.goodbye", NULL);
153 }
154
155 // after 0.8.1: titlebar use jid|name -> titlebar show|hide jid|name
156 if (g_key_file_has_key(prefs, PREF_GROUP_UI, "titlebar.muc.title", NULL)) {
157 char* value = g_key_file_get_string(prefs, PREF_GROUP_UI, "titlebar.muc.title", NULL);
158 if (g_strcmp0(value, "name") == 0) {
159 g_key_file_set_boolean(prefs, PREF_GROUP_UI, "titlebar.muc.title.name", TRUE);
160 } else if (g_strcmp0(value, "jid") == 0) {
161 g_key_file_set_boolean(prefs, PREF_GROUP_UI, "titlebar.muc.title.jid", TRUE);
162 }
163 }
164
165 // 0.9.0 introduced /urlopen. It was saved under "logging" section. Now we have a new "executables" section.
166 if (g_key_file_has_key(prefs, PREF_GROUP_LOGGING, "urlopen.cmd", NULL)) {
167 char* val = g_key_file_get_string(prefs, PREF_GROUP_LOGGING, "urlopen.cmd", NULL);
168
169 GString* value = g_string_new("false;");
170 value = g_string_append(value, val);
171 value = g_string_append(value, " %u;");
172
173 g_key_file_set_locale_string(prefs, PREF_GROUP_EXECUTABLES, "url.open.cmd", "DEF", value->str);
174 g_key_file_remove_key(prefs, PREF_GROUP_LOGGING, "urlopen.cmd", NULL);
175
176 g_string_free(value, TRUE);
177 }
178
179 // 0.9.0 introduced configurable /avatar. It was saved under "logging" section. Now we have a new "executables" section.
180 if (g_key_file_has_key(prefs, PREF_GROUP_LOGGING, "avatar.cmd", NULL)) {
181 char* value = g_key_file_get_string(prefs, PREF_GROUP_LOGGING, "avatar.cmd", NULL);
182 g_key_file_set_string(prefs, PREF_GROUP_EXECUTABLES, "avatar.cmd", value);
183 g_key_file_remove_key(prefs, PREF_GROUP_LOGGING, "avatar.cmd", NULL);
184 }
185
186 // 0.10 will have omemo media sharing. So disabling of sendfile introduced in 0.9 is not needed (#1270)
187 if (g_key_file_has_key(prefs, PREF_GROUP_OMEMO, "sendfile", NULL)) {
188 g_key_file_remove_key(prefs, PREF_GROUP_OMEMO, "sendfile", NULL);
189 }
190
191 // 0.10 have changed the behavior of /url open and /url save to not use any
192 // file type or scheme matching. Move value saved under 'DEF' locale to a
193 // simple key-value string not under any locale.
194 {
195 char** values = g_key_file_get_locale_string_list(prefs, PREF_GROUP_EXECUTABLES, "url.open.cmd", "DEF", NULL, NULL);
196 if (values && !g_key_file_has_key(prefs, PREF_GROUP_EXECUTABLES, "url.open.cmd", NULL)) {
197 // First value in array is `require_save` option -- we ignore that
198 // one as there is no such option anymore.
199 char* executable = values[1];
200
201 g_key_file_set_string(prefs, PREF_GROUP_EXECUTABLES, "url.open.cmd", executable);
202 g_key_file_set_comment(prefs, PREF_GROUP_EXECUTABLES, "url.open.cmd", " Migrated from url.open.cmd[DEF]. `require_save` option has been removed in v0.10 and was discarded.", NULL);
203 g_key_file_remove_key(prefs, PREF_GROUP_EXECUTABLES, "url.open.cmd[DEF]", NULL);
204
205 g_strfreev(values);
206 }
207
208 char* value = g_key_file_get_locale_string(prefs, PREF_GROUP_EXECUTABLES, "url.save.cmd", "DEF", NULL);
209 if (value && !g_key_file_has_key(prefs, PREF_GROUP_EXECUTABLES, "url.save.cmd", NULL)) {
210 g_key_file_set_string(prefs, PREF_GROUP_EXECUTABLES, "url.save.cmd", value);
211 g_key_file_set_comment(prefs, PREF_GROUP_EXECUTABLES, "url.save.cmd", " Migrated from url.save.cmd[DEF].", NULL);
212 g_key_file_remove_key(prefs, PREF_GROUP_EXECUTABLES, "url.save.cmd[DEF]", NULL);
213 g_free(value);
214 }
215 }
216
217 _save_prefs();
218
219 boolean_choice_ac = autocomplete_new();
220 autocomplete_add(boolean_choice_ac, "on");
221 autocomplete_add(boolean_choice_ac, "off");
222
223 room_trigger_ac = autocomplete_new();
224 gsize len = 0;
225 gchar** triggers = g_key_file_get_string_list(prefs, PREF_GROUP_NOTIFICATIONS, "room.trigger.list", &len, NULL);
226
227 for (int i = 0; i < len; i++) {
228 autocomplete_add(room_trigger_ac, triggers[i]);
229 }
230 g_strfreev(triggers);
231 }
232
233 /* Clean up after _prefs_load() */
234 static void
_prefs_close(void)235 _prefs_close(void)
236 {
237 autocomplete_free(boolean_choice_ac);
238 autocomplete_free(room_trigger_ac);
239 }
240
241 void
prefs_reload(void)242 prefs_reload(void)
243 {
244 /*
245 * Current function contains copy-paste, but we wanted to avoid config_file
246 * manipulation from prefs_load/prefs_close
247 */
248
249 _prefs_close();
250
251 g_key_file_free(prefs);
252 prefs = NULL;
253
254 prefs = g_key_file_new();
255 g_key_file_load_from_file(prefs, prefs_loc, G_KEY_FILE_KEEP_COMMENTS, NULL);
256
257 _prefs_load();
258 }
259
260 void
prefs_load(char * config_file)261 prefs_load(char* config_file)
262 {
263
264 if (config_file == NULL) {
265 prefs_loc = files_get_config_path(FILE_PROFRC);
266 } else {
267 prefs_loc = g_strdup(config_file);
268 }
269
270 if (g_file_test(prefs_loc, G_FILE_TEST_EXISTS)) {
271 g_chmod(prefs_loc, S_IRUSR | S_IWUSR);
272 }
273
274 prefs = g_key_file_new();
275 g_key_file_load_from_file(prefs, prefs_loc, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, NULL);
276
277 _prefs_load();
278 }
279
280 void
prefs_save(void)281 prefs_save(void)
282 {
283 _save_prefs();
284 }
285
286 void
prefs_close(void)287 prefs_close(void)
288 {
289 _prefs_close();
290
291 g_key_file_free(prefs);
292 prefs = NULL;
293
294 g_free(prefs_loc);
295 prefs_loc = NULL;
296 }
297
298 char*
prefs_autocomplete_boolean_choice(const char * const prefix,gboolean previous,void * context)299 prefs_autocomplete_boolean_choice(const char* const prefix, gboolean previous, void* context)
300 {
301 return autocomplete_complete(boolean_choice_ac, prefix, TRUE, previous);
302 }
303
304 void
prefs_reset_boolean_choice(void)305 prefs_reset_boolean_choice(void)
306 {
307 autocomplete_reset(boolean_choice_ac);
308 }
309
310 char*
prefs_autocomplete_room_trigger(const char * const prefix,gboolean previous,void * context)311 prefs_autocomplete_room_trigger(const char* const prefix, gboolean previous, void* context)
312 {
313 return autocomplete_complete(room_trigger_ac, prefix, TRUE, previous);
314 }
315
316 void
prefs_reset_room_trigger_ac(void)317 prefs_reset_room_trigger_ac(void)
318 {
319 autocomplete_reset(room_trigger_ac);
320 }
321
322 gboolean
prefs_do_chat_notify(gboolean current_win)323 prefs_do_chat_notify(gboolean current_win)
324 {
325 if (prefs_get_boolean(PREF_NOTIFY_CHAT) == FALSE) {
326 return FALSE;
327 } else {
328 if ((current_win == FALSE) || ((current_win == TRUE) && prefs_get_boolean(PREF_NOTIFY_CHAT_CURRENT))) {
329 return TRUE;
330 } else {
331 return FALSE;
332 }
333 }
334 }
335
336 GList*
prefs_message_get_triggers(const char * const message)337 prefs_message_get_triggers(const char* const message)
338 {
339 GList* result = NULL;
340
341 char* message_lower = g_utf8_strdown(message, -1);
342 gsize len = 0;
343 gchar** triggers = g_key_file_get_string_list(prefs, PREF_GROUP_NOTIFICATIONS, "room.trigger.list", &len, NULL);
344
345 for (int i = 0; i < len; i++) {
346 char* trigger_lower = g_utf8_strdown(triggers[i], -1);
347 if (g_strrstr(message_lower, trigger_lower)) {
348 result = g_list_append(result, strdup(triggers[i]));
349 }
350 g_free(trigger_lower);
351 }
352
353 g_strfreev(triggers);
354 g_free(message_lower);
355
356 return result;
357 }
358
359 gboolean
prefs_do_room_notify(gboolean current_win,const char * const roomjid,const char * const mynick,const char * const theirnick,const char * const message,gboolean mention,gboolean trigger_found)360 prefs_do_room_notify(gboolean current_win, const char* const roomjid, const char* const mynick,
361 const char* const theirnick, const char* const message, gboolean mention, gboolean trigger_found)
362 {
363 if (g_strcmp0(mynick, theirnick) == 0) {
364 return FALSE;
365 }
366
367 gboolean notify_current = prefs_get_boolean(PREF_NOTIFY_ROOM_CURRENT);
368 gboolean notify_window = FALSE;
369 if (!current_win || (current_win && notify_current)) {
370 notify_window = TRUE;
371 }
372 if (!notify_window) {
373 return FALSE;
374 }
375
376 gboolean notify_room = FALSE;
377 if (g_key_file_has_key(prefs, roomjid, "notify", NULL)) {
378 notify_room = g_key_file_get_boolean(prefs, roomjid, "notify", NULL);
379 } else {
380 notify_room = prefs_get_boolean(PREF_NOTIFY_ROOM);
381 }
382 if (notify_room) {
383 return TRUE;
384 }
385
386 gboolean notify_mention = FALSE;
387 if (g_key_file_has_key(prefs, roomjid, "notify.mention", NULL)) {
388 notify_mention = g_key_file_get_boolean(prefs, roomjid, "notify.mention", NULL);
389 } else {
390 notify_mention = prefs_get_boolean(PREF_NOTIFY_ROOM_MENTION);
391 }
392 if (notify_mention && mention) {
393 return TRUE;
394 }
395
396 gboolean notify_trigger = FALSE;
397 if (g_key_file_has_key(prefs, roomjid, "notify.trigger", NULL)) {
398 notify_trigger = g_key_file_get_boolean(prefs, roomjid, "notify.trigger", NULL);
399 } else {
400 notify_trigger = prefs_get_boolean(PREF_NOTIFY_ROOM_TRIGGER);
401 }
402 if (notify_trigger && trigger_found) {
403 return TRUE;
404 }
405
406 return FALSE;
407 }
408
409 gboolean
prefs_do_room_notify_mention(const char * const roomjid,int unread,gboolean mention,gboolean trigger)410 prefs_do_room_notify_mention(const char* const roomjid, int unread, gboolean mention, gboolean trigger)
411 {
412 gboolean notify_room = FALSE;
413 if (g_key_file_has_key(prefs, roomjid, "notify", NULL)) {
414 notify_room = g_key_file_get_boolean(prefs, roomjid, "notify", NULL);
415 } else {
416 notify_room = prefs_get_boolean(PREF_NOTIFY_ROOM);
417 }
418 if (notify_room && unread > 0) {
419 return TRUE;
420 }
421
422 gboolean notify_mention = FALSE;
423 if (g_key_file_has_key(prefs, roomjid, "notify.mention", NULL)) {
424 notify_mention = g_key_file_get_boolean(prefs, roomjid, "notify.mention", NULL);
425 } else {
426 notify_mention = prefs_get_boolean(PREF_NOTIFY_ROOM_MENTION);
427 }
428 if (notify_mention && mention) {
429 return TRUE;
430 }
431
432 gboolean notify_trigger = FALSE;
433 if (g_key_file_has_key(prefs, roomjid, "notify.trigger", NULL)) {
434 notify_trigger = g_key_file_get_boolean(prefs, roomjid, "notify.trigger", NULL);
435 } else {
436 notify_trigger = prefs_get_boolean(PREF_NOTIFY_ROOM_TRIGGER);
437 }
438 if (notify_trigger && trigger) {
439 return TRUE;
440 }
441
442 return FALSE;
443 }
444
445 void
prefs_set_room_notify(const char * const roomjid,gboolean value)446 prefs_set_room_notify(const char* const roomjid, gboolean value)
447 {
448 g_key_file_set_boolean(prefs, roomjid, "notify", value);
449 }
450
451 void
prefs_set_room_notify_mention(const char * const roomjid,gboolean value)452 prefs_set_room_notify_mention(const char* const roomjid, gboolean value)
453 {
454 g_key_file_set_boolean(prefs, roomjid, "notify.mention", value);
455 }
456
457 void
prefs_set_room_notify_trigger(const char * const roomjid,gboolean value)458 prefs_set_room_notify_trigger(const char* const roomjid, gboolean value)
459 {
460 g_key_file_set_boolean(prefs, roomjid, "notify.trigger", value);
461 }
462
463 gboolean
prefs_has_room_notify(const char * const roomjid)464 prefs_has_room_notify(const char* const roomjid)
465 {
466 return g_key_file_has_key(prefs, roomjid, "notify", NULL);
467 }
468
469 gboolean
prefs_has_room_notify_mention(const char * const roomjid)470 prefs_has_room_notify_mention(const char* const roomjid)
471 {
472 return g_key_file_has_key(prefs, roomjid, "notify.mention", NULL);
473 }
474
475 gboolean
prefs_has_room_notify_trigger(const char * const roomjid)476 prefs_has_room_notify_trigger(const char* const roomjid)
477 {
478 return g_key_file_has_key(prefs, roomjid, "notify.trigger", NULL);
479 }
480
481 gboolean
prefs_get_room_notify(const char * const roomjid)482 prefs_get_room_notify(const char* const roomjid)
483 {
484 return g_key_file_get_boolean(prefs, roomjid, "notify", NULL);
485 }
486
487 gboolean
prefs_get_room_notify_mention(const char * const roomjid)488 prefs_get_room_notify_mention(const char* const roomjid)
489 {
490 return g_key_file_get_boolean(prefs, roomjid, "notify.mention", NULL);
491 }
492
493 gboolean
prefs_get_room_notify_trigger(const char * const roomjid)494 prefs_get_room_notify_trigger(const char* const roomjid)
495 {
496 return g_key_file_get_boolean(prefs, roomjid, "notify.trigger", NULL);
497 }
498
499 gboolean
prefs_reset_room_notify(const char * const roomjid)500 prefs_reset_room_notify(const char* const roomjid)
501 {
502 if (g_key_file_has_group(prefs, roomjid)) {
503 g_key_file_remove_group(prefs, roomjid, NULL);
504 return TRUE;
505 }
506
507 return FALSE;
508 }
509
510 gboolean
prefs_get_boolean(preference_t pref)511 prefs_get_boolean(preference_t pref)
512 {
513 const char* group = _get_group(pref);
514 const char* key = _get_key(pref);
515 gboolean def = _get_default_boolean(pref);
516
517 if (!g_key_file_has_key(prefs, group, key, NULL)) {
518 return def;
519 }
520
521 return g_key_file_get_boolean(prefs, group, key, NULL);
522 }
523
524 void
prefs_set_boolean(preference_t pref,gboolean value)525 prefs_set_boolean(preference_t pref, gboolean value)
526 {
527 const char* group = _get_group(pref);
528 const char* key = _get_key(pref);
529 g_key_file_set_boolean(prefs, group, key, value);
530 }
531
532 char*
prefs_get_string(preference_t pref)533 prefs_get_string(preference_t pref)
534 {
535 const char* group = _get_group(pref);
536 const char* key = _get_key(pref);
537 char* def = _get_default_string(pref);
538
539 char* result = g_key_file_get_string(prefs, group, key, NULL);
540
541 if (result == NULL) {
542 if (def) {
543 return g_strdup(def);
544 } else {
545 return NULL;
546 }
547 } else {
548 return result;
549 }
550 }
551
552 char*
prefs_get_string_with_option(preference_t pref,gchar * option)553 prefs_get_string_with_option(preference_t pref, gchar* option)
554 {
555 const char* group = _get_group(pref);
556 const char* key = _get_key(pref);
557 char* def = _get_default_string(pref);
558
559 char* result = g_key_file_get_locale_string(prefs, group, key, option, NULL);
560
561 if (result == NULL) {
562 // check for user set default
563 result = g_key_file_get_locale_string(prefs, group, key, "*", NULL);
564 if (result == NULL) {
565 if (def) {
566 // use hardcoded profanity default
567 return g_strdup(def);
568 } else {
569 return NULL;
570 }
571 }
572 }
573
574 return result;
575 }
576
577 void
prefs_set_string(preference_t pref,char * value)578 prefs_set_string(preference_t pref, char* value)
579 {
580 const char* group = _get_group(pref);
581 const char* key = _get_key(pref);
582 if (value == NULL) {
583 g_key_file_remove_key(prefs, group, key, NULL);
584 } else {
585 g_key_file_set_string(prefs, group, key, value);
586 }
587 }
588
589 void
prefs_set_string_with_option(preference_t pref,char * option,char * value)590 prefs_set_string_with_option(preference_t pref, char* option, char* value)
591 {
592 const char* group = _get_group(pref);
593 const char* key = _get_key(pref);
594 if (value == NULL) {
595 g_key_file_remove_key(prefs, group, key, NULL);
596 } else {
597 g_key_file_set_locale_string(prefs, group, key, option, value);
598 }
599 }
600
601 void
prefs_set_string_list_with_option(preference_t pref,char * option,const gchar * const * values)602 prefs_set_string_list_with_option(preference_t pref, char* option, const gchar* const* values)
603 {
604 const char* group = _get_group(pref);
605 const char* key = _get_key(pref);
606 if (values == NULL || *values == NULL) {
607 if (g_strcmp0(option, "*") == 0) {
608 g_key_file_set_string_list(prefs, group, key, NULL, 0);
609 } else {
610 g_key_file_set_locale_string_list(prefs, group, key, option, NULL, 0);
611 }
612 } else {
613 guint num_values = 0;
614 while (values[num_values]) {
615 num_values++;
616 }
617 if (g_strcmp0(option, "*") == 0) {
618 g_key_file_set_string_list(prefs, group, key, values, num_values);
619 } else {
620 g_key_file_set_locale_string_list(prefs, group, key, option, values, num_values);
621 }
622 }
623 }
624
625 char*
prefs_get_tls_certpath(void)626 prefs_get_tls_certpath(void)
627 {
628 const char* group = _get_group(PREF_TLS_CERTPATH);
629 const char* key = _get_key(PREF_TLS_CERTPATH);
630
631 char* setting = g_key_file_get_string(prefs, group, key, NULL);
632
633 if (g_strcmp0(setting, "none") == 0) {
634 g_free(setting);
635 return NULL;
636 }
637
638 if (setting == NULL) {
639 if (g_file_test("/etc/ssl/certs", G_FILE_TEST_IS_DIR)) {
640 return strdup("/etc/ssl/certs");
641 }
642 if (g_file_test("/etc/pki/tls/certs", G_FILE_TEST_IS_DIR)) {
643 return strdup("/etc/pki/tls/certs");
644 }
645 if (g_file_test("/etc/ssl", G_FILE_TEST_IS_DIR)) {
646 return strdup("/etc/ssl");
647 }
648 if (g_file_test("/etc/pki/tls", G_FILE_TEST_IS_DIR)) {
649 return strdup("/etc/pki/tls");
650 }
651 if (g_file_test("/system/etc/security/cacerts", G_FILE_TEST_IS_DIR)) {
652 return strdup("/system/etc/security/cacerts");
653 }
654
655 return NULL;
656 }
657
658 char* result = strdup(setting);
659 g_free(setting);
660
661 return result;
662 }
663
664 gint
prefs_get_gone(void)665 prefs_get_gone(void)
666 {
667 return g_key_file_get_integer(prefs, PREF_GROUP_CHATSTATES, "gone", NULL);
668 }
669
670 void
prefs_set_gone(gint value)671 prefs_set_gone(gint value)
672 {
673 g_key_file_set_integer(prefs, PREF_GROUP_CHATSTATES, "gone", value);
674 }
675
676 gint
prefs_get_notify_remind(void)677 prefs_get_notify_remind(void)
678 {
679 return g_key_file_get_integer(prefs, PREF_GROUP_NOTIFICATIONS, "remind", NULL);
680 }
681
682 void
prefs_set_notify_remind(gint value)683 prefs_set_notify_remind(gint value)
684 {
685 g_key_file_set_integer(prefs, PREF_GROUP_NOTIFICATIONS, "remind", value);
686 }
687
688 gint
prefs_get_max_log_size(void)689 prefs_get_max_log_size(void)
690 {
691 if (log_maxsize < PREFS_MIN_LOG_SIZE)
692 return PREFS_MAX_LOG_SIZE;
693 else
694 return log_maxsize;
695 }
696
697 void
prefs_set_max_log_size(gint value)698 prefs_set_max_log_size(gint value)
699 {
700 log_maxsize = value;
701 g_key_file_set_integer(prefs, PREF_GROUP_LOGGING, "maxsize", value);
702 }
703
704 gint
prefs_get_inpblock(void)705 prefs_get_inpblock(void)
706 {
707 int val = g_key_file_get_integer(prefs, PREF_GROUP_UI, "inpblock", NULL);
708 if (val == 0) {
709 return INPBLOCK_DEFAULT;
710 } else {
711 return val;
712 }
713 }
714
715 void
prefs_set_inpblock(gint value)716 prefs_set_inpblock(gint value)
717 {
718 g_key_file_set_integer(prefs, PREF_GROUP_UI, "inpblock", value);
719 }
720
721 gint
prefs_get_reconnect(void)722 prefs_get_reconnect(void)
723 {
724 if (!g_key_file_has_key(prefs, PREF_GROUP_CONNECTION, "reconnect", NULL)) {
725 return 30;
726 } else {
727 return g_key_file_get_integer(prefs, PREF_GROUP_CONNECTION, "reconnect", NULL);
728 }
729 }
730
731 void
prefs_set_reconnect(gint value)732 prefs_set_reconnect(gint value)
733 {
734 g_key_file_set_integer(prefs, PREF_GROUP_CONNECTION, "reconnect", value);
735 }
736
737 gint
prefs_get_autoping(void)738 prefs_get_autoping(void)
739 {
740 if (!g_key_file_has_key(prefs, PREF_GROUP_CONNECTION, "autoping", NULL)) {
741 return 60;
742 } else {
743 return g_key_file_get_integer(prefs, PREF_GROUP_CONNECTION, "autoping", NULL);
744 }
745 }
746
747 void
prefs_set_autoping(gint value)748 prefs_set_autoping(gint value)
749 {
750 g_key_file_set_integer(prefs, PREF_GROUP_CONNECTION, "autoping", value);
751 }
752
753 gint
prefs_get_autoping_timeout(void)754 prefs_get_autoping_timeout(void)
755 {
756 if (!g_key_file_has_key(prefs, PREF_GROUP_CONNECTION, "autoping.timeout", NULL)) {
757 return 20;
758 } else {
759 return g_key_file_get_integer(prefs, PREF_GROUP_CONNECTION, "autoping.timeout", NULL);
760 }
761 }
762
763 void
prefs_set_autoping_timeout(gint value)764 prefs_set_autoping_timeout(gint value)
765 {
766 g_key_file_set_integer(prefs, PREF_GROUP_CONNECTION, "autoping.timeout", value);
767 }
768
769 gint
prefs_get_autoaway_time(void)770 prefs_get_autoaway_time(void)
771 {
772 gint result = g_key_file_get_integer(prefs, PREF_GROUP_PRESENCE, "autoaway.awaytime", NULL);
773
774 if (result == 0) {
775 return 15;
776 } else {
777 return result;
778 }
779 }
780
781 gint
prefs_get_autoxa_time(void)782 prefs_get_autoxa_time(void)
783 {
784 return g_key_file_get_integer(prefs, PREF_GROUP_PRESENCE, "autoaway.xatime", NULL);
785 }
786
787 void
prefs_set_autoaway_time(gint value)788 prefs_set_autoaway_time(gint value)
789 {
790 g_key_file_set_integer(prefs, PREF_GROUP_PRESENCE, "autoaway.awaytime", value);
791 }
792
793 void
prefs_set_autoxa_time(gint value)794 prefs_set_autoxa_time(gint value)
795 {
796 g_key_file_set_integer(prefs, PREF_GROUP_PRESENCE, "autoaway.xatime", value);
797 }
798
799 void
prefs_set_tray_timer(gint value)800 prefs_set_tray_timer(gint value)
801 {
802 g_key_file_set_integer(prefs, PREF_GROUP_NOTIFICATIONS, "tray.timer", value);
803 }
804
805 gint
prefs_get_tray_timer(void)806 prefs_get_tray_timer(void)
807 {
808 gint result = g_key_file_get_integer(prefs, PREF_GROUP_NOTIFICATIONS, "tray.timer", NULL);
809
810 if (result == 0) {
811 return 5;
812 } else {
813 return result;
814 }
815 }
816
817 gint
prefs_get_statusbartabs(void)818 prefs_get_statusbartabs(void)
819 {
820 if (!g_key_file_has_key(prefs, PREF_GROUP_UI, "statusbar.tabs", NULL)) {
821 return 10;
822 } else {
823 return g_key_file_get_integer(prefs, PREF_GROUP_UI, "statusbar.tabs", NULL);
824 }
825 }
826
827 void
prefs_set_statusbartabs(gint value)828 prefs_set_statusbartabs(gint value)
829 {
830 g_key_file_set_integer(prefs, PREF_GROUP_UI, "statusbar.tabs", value);
831 }
832
833 gint
prefs_get_statusbartablen(void)834 prefs_get_statusbartablen(void)
835 {
836 if (!g_key_file_has_key(prefs, PREF_GROUP_UI, "statusbar.tablen", NULL)) {
837 return 0;
838 } else {
839 return g_key_file_get_integer(prefs, PREF_GROUP_UI, "statusbar.tablen", NULL);
840 }
841 }
842
843 void
prefs_set_statusbartablen(gint value)844 prefs_set_statusbartablen(gint value)
845 {
846 g_key_file_set_integer(prefs, PREF_GROUP_UI, "statusbar.tablen", value);
847 }
848
849 gchar**
prefs_get_plugins(void)850 prefs_get_plugins(void)
851 {
852 if (!g_key_file_has_group(prefs, PREF_GROUP_PLUGINS)) {
853 return NULL;
854 }
855 if (!g_key_file_has_key(prefs, PREF_GROUP_PLUGINS, "load", NULL)) {
856 return NULL;
857 }
858
859 return g_key_file_get_string_list(prefs, PREF_GROUP_PLUGINS, "load", NULL, NULL);
860 }
861
862 void
prefs_add_plugin(const char * const name)863 prefs_add_plugin(const char* const name)
864 {
865 conf_string_list_add(prefs, PREF_GROUP_PLUGINS, "load", name);
866 _save_prefs();
867 }
868
869 void
prefs_remove_plugin(const char * const name)870 prefs_remove_plugin(const char* const name)
871 {
872 conf_string_list_remove(prefs, PREF_GROUP_PLUGINS, "load", name);
873 _save_prefs();
874 }
875
876 void
prefs_free_plugins(gchar ** plugins)877 prefs_free_plugins(gchar** plugins)
878 {
879 g_strfreev(plugins);
880 }
881
882 void
prefs_set_occupants_size(gint value)883 prefs_set_occupants_size(gint value)
884 {
885 g_key_file_set_integer(prefs, PREF_GROUP_UI, "occupants.size", value);
886 }
887
888 gint
prefs_get_occupants_size(void)889 prefs_get_occupants_size(void)
890 {
891 gint result = g_key_file_get_integer(prefs, PREF_GROUP_UI, "occupants.size", NULL);
892
893 if (result > 99 || result < 1) {
894 return 15;
895 } else {
896 return result;
897 }
898 }
899
900 char
prefs_get_occupants_char(void)901 prefs_get_occupants_char(void)
902 {
903 char result = 0;
904
905 char* resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "occupants.char", NULL);
906 if (!resultstr) {
907 result = 0;
908 } else {
909 result = resultstr[0];
910 }
911 free(resultstr);
912
913 return result;
914 }
915
916 void
prefs_set_occupants_char(char ch)917 prefs_set_occupants_char(char ch)
918 {
919 char str[2];
920 str[0] = ch;
921 str[1] = '\0';
922
923 g_key_file_set_string(prefs, PREF_GROUP_UI, "occupants.char", str);
924 }
925
926 void
prefs_clear_occupants_char(void)927 prefs_clear_occupants_char(void)
928 {
929 g_key_file_remove_key(prefs, PREF_GROUP_UI, "occupants.char", NULL);
930 }
931
932 gint
prefs_get_occupants_indent(void)933 prefs_get_occupants_indent(void)
934 {
935 if (!g_key_file_has_key(prefs, PREF_GROUP_UI, "occupants.indent", NULL)) {
936 return 2;
937 }
938
939 gint result = g_key_file_get_integer(prefs, PREF_GROUP_UI, "occupants.indent", NULL);
940 if (result < 0) {
941 result = 0;
942 }
943
944 return result;
945 }
946
947 void
prefs_set_occupants_indent(gint value)948 prefs_set_occupants_indent(gint value)
949 {
950 g_key_file_set_integer(prefs, PREF_GROUP_UI, "occupants.indent", value);
951 }
952
953 char
prefs_get_occupants_header_char(void)954 prefs_get_occupants_header_char(void)
955 {
956 char result = 0;
957
958 char* resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "occupants.header.char", NULL);
959 if (!resultstr) {
960 result = 0;
961 } else {
962 result = resultstr[0];
963 }
964 free(resultstr);
965
966 return result;
967 }
968
969 void
prefs_set_occupants_header_char(char ch)970 prefs_set_occupants_header_char(char ch)
971 {
972 char str[2];
973 str[0] = ch;
974 str[1] = '\0';
975
976 g_key_file_set_string(prefs, PREF_GROUP_UI, "occupants.header.char", str);
977 }
978
979 void
prefs_clear_occupants_header_char(void)980 prefs_clear_occupants_header_char(void)
981 {
982 g_key_file_remove_key(prefs, PREF_GROUP_UI, "occupants.header.char", NULL);
983 }
984
985 void
prefs_set_roster_size(gint value)986 prefs_set_roster_size(gint value)
987 {
988 g_key_file_set_integer(prefs, PREF_GROUP_UI, "roster.size", value);
989 }
990
991 gint
prefs_get_roster_size(void)992 prefs_get_roster_size(void)
993 {
994 gint result = g_key_file_get_integer(prefs, PREF_GROUP_UI, "roster.size", NULL);
995
996 if (result > 99 || result < 1) {
997 return 25;
998 } else {
999 return result;
1000 }
1001 }
1002
1003 static char*
_prefs_get_encryption_char(const char * const ch,const char * const pref_group,const char * const key)1004 _prefs_get_encryption_char(const char* const ch, const char* const pref_group, const char* const key)
1005 {
1006 char* result = NULL;
1007
1008 char* resultstr = g_key_file_get_string(prefs, pref_group, key, NULL);
1009 if (!resultstr) {
1010 result = strdup(ch);
1011 } else {
1012 result = resultstr;
1013 }
1014
1015 return result;
1016 }
1017
1018 static gboolean
_prefs_set_encryption_char(const char * const ch,const char * const pref_group,const char * const key)1019 _prefs_set_encryption_char(const char* const ch, const char* const pref_group, const char* const key)
1020 {
1021 if (g_utf8_strlen(ch, 4) == 1) {
1022 g_key_file_set_string(prefs, pref_group, key, ch);
1023 return TRUE;
1024 } else {
1025 log_error("Could not set %s encryption char to: %s", key, ch);
1026 }
1027 return FALSE;
1028 }
1029
1030 char*
prefs_get_otr_char(void)1031 prefs_get_otr_char(void)
1032 {
1033 return _prefs_get_encryption_char("~", PREF_GROUP_OTR, "otr.char");
1034 }
1035
1036 gboolean
prefs_set_otr_char(char * ch)1037 prefs_set_otr_char(char* ch)
1038 {
1039 return _prefs_set_encryption_char(ch, PREF_GROUP_OTR, "otr.char");
1040 }
1041
1042 char*
prefs_get_pgp_char(void)1043 prefs_get_pgp_char(void)
1044 {
1045 return _prefs_get_encryption_char("~", PREF_GROUP_PGP, "pgp.char");
1046 }
1047
1048 gboolean
prefs_set_pgp_char(char * ch)1049 prefs_set_pgp_char(char* ch)
1050 {
1051 return _prefs_set_encryption_char(ch, PREF_GROUP_PGP, "pgp.char");
1052 }
1053
1054 char*
prefs_get_ox_char(void)1055 prefs_get_ox_char(void)
1056 {
1057 return _prefs_get_encryption_char("%", PREF_GROUP_OX, "ox.char");
1058 }
1059
1060 gboolean
prefs_set_ox_char(char * ch)1061 prefs_set_ox_char(char* ch)
1062 {
1063 return _prefs_set_encryption_char(ch, PREF_GROUP_OX, "ox.char");
1064 }
1065
1066 char*
prefs_get_omemo_char(void)1067 prefs_get_omemo_char(void)
1068 {
1069 return _prefs_get_encryption_char("~", PREF_GROUP_OMEMO, "omemo.char");
1070 }
1071
1072 gboolean
prefs_set_omemo_char(char * ch)1073 prefs_set_omemo_char(char* ch)
1074 {
1075 return _prefs_set_encryption_char(ch, PREF_GROUP_OMEMO, "omemo.char");
1076 }
1077
1078 char
prefs_get_roster_header_char(void)1079 prefs_get_roster_header_char(void)
1080 {
1081 char result = 0;
1082
1083 char* resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "roster.header.char", NULL);
1084 if (!resultstr) {
1085 result = 0;
1086 } else {
1087 result = resultstr[0];
1088 }
1089 free(resultstr);
1090
1091 return result;
1092 }
1093
1094 void
prefs_set_roster_header_char(char ch)1095 prefs_set_roster_header_char(char ch)
1096 {
1097 char str[2];
1098 str[0] = ch;
1099 str[1] = '\0';
1100
1101 g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.header.char", str);
1102 }
1103
1104 void
prefs_clear_roster_header_char(void)1105 prefs_clear_roster_header_char(void)
1106 {
1107 g_key_file_remove_key(prefs, PREF_GROUP_UI, "roster.header.char", NULL);
1108 }
1109
1110 char
prefs_get_roster_contact_char(void)1111 prefs_get_roster_contact_char(void)
1112 {
1113 char result = 0;
1114
1115 char* resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "roster.contact.char", NULL);
1116 if (!resultstr) {
1117 result = 0;
1118 } else {
1119 result = resultstr[0];
1120 }
1121 free(resultstr);
1122
1123 return result;
1124 }
1125
1126 void
prefs_set_roster_contact_char(char ch)1127 prefs_set_roster_contact_char(char ch)
1128 {
1129 char str[2];
1130 str[0] = ch;
1131 str[1] = '\0';
1132
1133 g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.contact.char", str);
1134 }
1135
1136 void
prefs_clear_roster_contact_char(void)1137 prefs_clear_roster_contact_char(void)
1138 {
1139 g_key_file_remove_key(prefs, PREF_GROUP_UI, "roster.contact.char", NULL);
1140 }
1141
1142 char
prefs_get_roster_resource_char(void)1143 prefs_get_roster_resource_char(void)
1144 {
1145 char result = 0;
1146
1147 char* resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "roster.resource.char", NULL);
1148 if (!resultstr) {
1149 result = 0;
1150 } else {
1151 result = resultstr[0];
1152 }
1153 free(resultstr);
1154
1155 return result;
1156 }
1157
1158 void
prefs_set_roster_resource_char(char ch)1159 prefs_set_roster_resource_char(char ch)
1160 {
1161 char str[2];
1162 str[0] = ch;
1163 str[1] = '\0';
1164
1165 g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.resource.char", str);
1166 }
1167
1168 void
prefs_clear_roster_resource_char(void)1169 prefs_clear_roster_resource_char(void)
1170 {
1171 g_key_file_remove_key(prefs, PREF_GROUP_UI, "roster.resource.char", NULL);
1172 }
1173
1174 char
prefs_get_roster_private_char(void)1175 prefs_get_roster_private_char(void)
1176 {
1177 char result = 0;
1178
1179 char* resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "roster.private.char", NULL);
1180 if (!resultstr) {
1181 result = 0;
1182 } else {
1183 result = resultstr[0];
1184 }
1185 free(resultstr);
1186
1187 return result;
1188 }
1189
1190 void
prefs_set_roster_private_char(char ch)1191 prefs_set_roster_private_char(char ch)
1192 {
1193 char str[2];
1194 str[0] = ch;
1195 str[1] = '\0';
1196
1197 g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.private.char", str);
1198 }
1199
1200 void
prefs_clear_roster_private_char(void)1201 prefs_clear_roster_private_char(void)
1202 {
1203 g_key_file_remove_key(prefs, PREF_GROUP_UI, "roster.private.char", NULL);
1204 }
1205
1206 char
prefs_get_roster_room_char(void)1207 prefs_get_roster_room_char(void)
1208 {
1209 char result = 0;
1210
1211 char* resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "roster.rooms.char", NULL);
1212 if (!resultstr) {
1213 result = 0;
1214 } else {
1215 result = resultstr[0];
1216 }
1217 free(resultstr);
1218
1219 return result;
1220 }
1221
1222 void
prefs_set_roster_room_char(char ch)1223 prefs_set_roster_room_char(char ch)
1224 {
1225 char str[2];
1226 str[0] = ch;
1227 str[1] = '\0';
1228
1229 g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.rooms.char", str);
1230 }
1231
1232 void
prefs_clear_roster_room_char(void)1233 prefs_clear_roster_room_char(void)
1234 {
1235 g_key_file_remove_key(prefs, PREF_GROUP_UI, "roster.rooms.char", NULL);
1236 }
1237
1238 char
prefs_get_roster_room_private_char(void)1239 prefs_get_roster_room_private_char(void)
1240 {
1241 char result = 0;
1242
1243 char* resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "roster.rooms.private.char", NULL);
1244 if (!resultstr) {
1245 result = 0;
1246 } else {
1247 result = resultstr[0];
1248 }
1249 free(resultstr);
1250
1251 return result;
1252 }
1253
1254 void
prefs_set_roster_room_private_char(char ch)1255 prefs_set_roster_room_private_char(char ch)
1256 {
1257 char str[2];
1258 str[0] = ch;
1259 str[1] = '\0';
1260
1261 g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.rooms.private.char", str);
1262 }
1263
1264 void
prefs_clear_roster_room_private_char(void)1265 prefs_clear_roster_room_private_char(void)
1266 {
1267 g_key_file_remove_key(prefs, PREF_GROUP_UI, "roster.rooms.pruvate.char", NULL);
1268 }
1269
1270 gint
prefs_get_roster_contact_indent(void)1271 prefs_get_roster_contact_indent(void)
1272 {
1273 if (!g_key_file_has_key(prefs, PREF_GROUP_UI, "roster.contact.indent", NULL)) {
1274 return 2;
1275 }
1276
1277 gint result = g_key_file_get_integer(prefs, PREF_GROUP_UI, "roster.contact.indent", NULL);
1278 if (result < 0) {
1279 result = 0;
1280 }
1281
1282 return result;
1283 }
1284
1285 void
prefs_set_roster_contact_indent(gint value)1286 prefs_set_roster_contact_indent(gint value)
1287 {
1288 g_key_file_set_integer(prefs, PREF_GROUP_UI, "roster.contact.indent", value);
1289 }
1290
1291 gint
prefs_get_roster_resource_indent(void)1292 prefs_get_roster_resource_indent(void)
1293 {
1294 if (!g_key_file_has_key(prefs, PREF_GROUP_UI, "roster.resource.indent", NULL)) {
1295 return 2;
1296 }
1297
1298 gint result = g_key_file_get_integer(prefs, PREF_GROUP_UI, "roster.resource.indent", NULL);
1299 if (result < 0) {
1300 result = 0;
1301 }
1302
1303 return result;
1304 }
1305
1306 void
prefs_set_roster_resource_indent(gint value)1307 prefs_set_roster_resource_indent(gint value)
1308 {
1309 g_key_file_set_integer(prefs, PREF_GROUP_UI, "roster.resource.indent", value);
1310 }
1311
1312 gint
prefs_get_roster_presence_indent(void)1313 prefs_get_roster_presence_indent(void)
1314 {
1315 if (!g_key_file_has_key(prefs, PREF_GROUP_UI, "roster.presence.indent", NULL)) {
1316 return 2;
1317 }
1318
1319 gint result = g_key_file_get_integer(prefs, PREF_GROUP_UI, "roster.presence.indent", NULL);
1320 if (result < -1) {
1321 result = 0;
1322 }
1323
1324 return result;
1325 }
1326
1327 void
prefs_set_roster_presence_indent(gint value)1328 prefs_set_roster_presence_indent(gint value)
1329 {
1330 g_key_file_set_integer(prefs, PREF_GROUP_UI, "roster.presence.indent", value);
1331 }
1332
1333 char*
prefs_get_correction_char(void)1334 prefs_get_correction_char(void)
1335 {
1336 char* result = "+";
1337
1338 char* resultstr = g_key_file_get_string(prefs, PREF_GROUP_UI, "correction.char", NULL);
1339 if (!resultstr) {
1340 result = strdup("+");
1341 } else {
1342 result = resultstr;
1343 }
1344
1345 return result;
1346 }
1347
1348 void
prefs_set_correction_char(char ch)1349 prefs_set_correction_char(char ch)
1350 {
1351 char str[2];
1352 str[0] = ch;
1353 str[1] = '\0';
1354
1355 g_key_file_set_string(prefs, PREF_GROUP_UI, "correction.char", str);
1356 }
1357
1358 gboolean
prefs_add_room_notify_trigger(const char * const text)1359 prefs_add_room_notify_trigger(const char* const text)
1360 {
1361 gboolean res = conf_string_list_add(prefs, PREF_GROUP_NOTIFICATIONS, "room.trigger.list", text);
1362
1363 if (res) {
1364 autocomplete_add(room_trigger_ac, text);
1365 }
1366
1367 return res;
1368 }
1369
1370 gboolean
prefs_remove_room_notify_trigger(const char * const text)1371 prefs_remove_room_notify_trigger(const char* const text)
1372 {
1373 gboolean res = conf_string_list_remove(prefs, PREF_GROUP_NOTIFICATIONS, "room.trigger.list", text);
1374 _save_prefs();
1375
1376 if (res) {
1377 autocomplete_remove(room_trigger_ac, text);
1378 }
1379
1380 return res;
1381 }
1382
1383 GList*
prefs_get_room_notify_triggers(void)1384 prefs_get_room_notify_triggers(void)
1385 {
1386 GList* result = NULL;
1387 gsize len = 0;
1388 gchar** triggers = g_key_file_get_string_list(prefs, PREF_GROUP_NOTIFICATIONS, "room.trigger.list", &len, NULL);
1389
1390 for (int i = 0; i < len; i++) {
1391 result = g_list_append(result, strdup(triggers[i]));
1392 }
1393
1394 g_strfreev(triggers);
1395
1396 return result;
1397 }
1398
1399 ProfWinPlacement*
prefs_create_profwin_placement(int titlebar,int mainwin,int statusbar,int inputwin)1400 prefs_create_profwin_placement(int titlebar, int mainwin, int statusbar, int inputwin)
1401 {
1402 ProfWinPlacement* placement = malloc(sizeof(ProfWinPlacement));
1403 placement->titlebar_pos = titlebar;
1404 placement->mainwin_pos = mainwin;
1405 placement->statusbar_pos = statusbar;
1406 placement->inputwin_pos = inputwin;
1407
1408 return placement;
1409 }
1410
1411 void
prefs_free_win_placement(ProfWinPlacement * placement)1412 prefs_free_win_placement(ProfWinPlacement* placement)
1413 {
1414 free(placement);
1415 }
1416
1417 ProfWinPlacement*
prefs_get_win_placement(void)1418 prefs_get_win_placement(void)
1419 {
1420 // read from settings file
1421 int titlebar_pos = g_key_file_get_integer(prefs, PREF_GROUP_UI, "titlebar.position", NULL);
1422 int mainwin_pos = g_key_file_get_integer(prefs, PREF_GROUP_UI, "mainwin.position", NULL);
1423 int statusbar_pos = g_key_file_get_integer(prefs, PREF_GROUP_UI, "statusbar.position", NULL);
1424 int inputwin_pos = g_key_file_get_integer(prefs, PREF_GROUP_UI, "inputwin.position", NULL);
1425
1426 // default if setting invalid, or not present
1427 if (titlebar_pos < 1 || titlebar_pos > 4) {
1428 titlebar_pos = 1;
1429 }
1430 if (mainwin_pos < 1 || mainwin_pos > 4) {
1431 mainwin_pos = 2;
1432 }
1433 if (statusbar_pos < 1 || statusbar_pos > 4) {
1434 statusbar_pos = 3;
1435 }
1436 if (inputwin_pos < 1 || inputwin_pos > 4) {
1437 inputwin_pos = 4;
1438 }
1439
1440 // return default if duplicates found
1441 if (titlebar_pos == mainwin_pos) {
1442 return prefs_create_profwin_placement(1, 2, 3, 4);
1443 }
1444 if (titlebar_pos == statusbar_pos) {
1445 return prefs_create_profwin_placement(1, 2, 3, 4);
1446 }
1447 if (titlebar_pos == inputwin_pos) {
1448 return prefs_create_profwin_placement(1, 2, 3, 4);
1449 }
1450
1451 if (mainwin_pos == statusbar_pos) {
1452 return prefs_create_profwin_placement(1, 2, 3, 4);
1453 }
1454 if (mainwin_pos == inputwin_pos) {
1455 return prefs_create_profwin_placement(1, 2, 3, 4);
1456 }
1457
1458 if (statusbar_pos == inputwin_pos) {
1459 return prefs_create_profwin_placement(1, 2, 3, 4);
1460 }
1461
1462 // return settings
1463 return prefs_create_profwin_placement(titlebar_pos, mainwin_pos, statusbar_pos, inputwin_pos);
1464 }
1465
1466 void
prefs_save_win_placement(ProfWinPlacement * placement)1467 prefs_save_win_placement(ProfWinPlacement* placement)
1468 {
1469 g_key_file_set_integer(prefs, PREF_GROUP_UI, "titlebar.position", placement->titlebar_pos);
1470 g_key_file_set_integer(prefs, PREF_GROUP_UI, "mainwin.position", placement->mainwin_pos);
1471 g_key_file_set_integer(prefs, PREF_GROUP_UI, "statusbar.position", placement->statusbar_pos);
1472 g_key_file_set_integer(prefs, PREF_GROUP_UI, "inputwin.position", placement->inputwin_pos);
1473 _save_prefs();
1474 }
1475
1476 gboolean
prefs_titlebar_pos_up(void)1477 prefs_titlebar_pos_up(void)
1478 {
1479 ProfWinPlacement* placement = prefs_get_win_placement();
1480
1481 for (int pos = 2; pos < 5; pos++) {
1482 if (placement->titlebar_pos == pos) {
1483 placement->titlebar_pos = pos - 1;
1484
1485 if (placement->mainwin_pos == pos - 1) {
1486 placement->mainwin_pos = pos;
1487 } else if (placement->statusbar_pos == pos - 1) {
1488 placement->statusbar_pos = pos;
1489 } else if (placement->inputwin_pos == pos - 1) {
1490 placement->inputwin_pos = pos;
1491 }
1492
1493 prefs_save_win_placement(placement);
1494 prefs_free_win_placement(placement);
1495 return TRUE;
1496 }
1497 }
1498
1499 prefs_free_win_placement(placement);
1500 return FALSE;
1501 }
1502
1503 gboolean
prefs_mainwin_pos_up(void)1504 prefs_mainwin_pos_up(void)
1505 {
1506 ProfWinPlacement* placement = prefs_get_win_placement();
1507
1508 for (int pos = 2; pos < 5; pos++) {
1509 if (placement->mainwin_pos == pos) {
1510 placement->mainwin_pos = pos - 1;
1511
1512 if (placement->titlebar_pos == pos - 1) {
1513 placement->titlebar_pos = pos;
1514 } else if (placement->statusbar_pos == pos - 1) {
1515 placement->statusbar_pos = pos;
1516 } else if (placement->inputwin_pos == pos - 1) {
1517 placement->inputwin_pos = pos;
1518 }
1519
1520 prefs_save_win_placement(placement);
1521 prefs_free_win_placement(placement);
1522 return TRUE;
1523 }
1524 }
1525
1526 prefs_free_win_placement(placement);
1527 return FALSE;
1528 }
1529
1530 gboolean
prefs_statusbar_pos_up(void)1531 prefs_statusbar_pos_up(void)
1532 {
1533 ProfWinPlacement* placement = prefs_get_win_placement();
1534
1535 for (int pos = 2; pos < 5; pos++) {
1536 if (placement->statusbar_pos == pos) {
1537 placement->statusbar_pos = pos - 1;
1538
1539 if (placement->titlebar_pos == pos - 1) {
1540 placement->titlebar_pos = pos;
1541 } else if (placement->mainwin_pos == pos - 1) {
1542 placement->mainwin_pos = pos;
1543 } else if (placement->inputwin_pos == pos - 1) {
1544 placement->inputwin_pos = pos;
1545 }
1546
1547 prefs_save_win_placement(placement);
1548 prefs_free_win_placement(placement);
1549 return TRUE;
1550 }
1551 }
1552
1553 prefs_free_win_placement(placement);
1554 return FALSE;
1555 }
1556
1557 gboolean
prefs_inputwin_pos_up(void)1558 prefs_inputwin_pos_up(void)
1559 {
1560 ProfWinPlacement* placement = prefs_get_win_placement();
1561
1562 for (int pos = 2; pos < 5; pos++) {
1563 if (placement->inputwin_pos == pos) {
1564 placement->inputwin_pos = pos - 1;
1565
1566 if (placement->titlebar_pos == pos - 1) {
1567 placement->titlebar_pos = pos;
1568 } else if (placement->mainwin_pos == pos - 1) {
1569 placement->mainwin_pos = pos;
1570 } else if (placement->statusbar_pos == pos - 1) {
1571 placement->statusbar_pos = pos;
1572 }
1573
1574 prefs_save_win_placement(placement);
1575 prefs_free_win_placement(placement);
1576 return TRUE;
1577 }
1578 }
1579
1580 prefs_free_win_placement(placement);
1581 return FALSE;
1582 }
1583
1584 gboolean
prefs_titlebar_pos_down(void)1585 prefs_titlebar_pos_down(void)
1586 {
1587 ProfWinPlacement* placement = prefs_get_win_placement();
1588
1589 for (int pos = 1; pos < 4; pos++) {
1590 if (placement->titlebar_pos == pos) {
1591 placement->titlebar_pos = pos + 1;
1592
1593 if (placement->mainwin_pos == pos + 1) {
1594 placement->mainwin_pos = pos;
1595 } else if (placement->statusbar_pos == pos + 1) {
1596 placement->statusbar_pos = pos;
1597 } else if (placement->inputwin_pos == pos + 1) {
1598 placement->inputwin_pos = pos;
1599 }
1600
1601 prefs_save_win_placement(placement);
1602 prefs_free_win_placement(placement);
1603 return TRUE;
1604 }
1605 }
1606
1607 prefs_free_win_placement(placement);
1608 return FALSE;
1609 }
1610
1611 gboolean
prefs_mainwin_pos_down(void)1612 prefs_mainwin_pos_down(void)
1613 {
1614 ProfWinPlacement* placement = prefs_get_win_placement();
1615
1616 for (int pos = 1; pos < 4; pos++) {
1617 if (placement->mainwin_pos == pos) {
1618 placement->mainwin_pos = pos + 1;
1619
1620 if (placement->titlebar_pos == pos + 1) {
1621 placement->titlebar_pos = pos;
1622 } else if (placement->statusbar_pos == pos + 1) {
1623 placement->statusbar_pos = pos;
1624 } else if (placement->inputwin_pos == pos + 1) {
1625 placement->inputwin_pos = pos;
1626 }
1627
1628 prefs_save_win_placement(placement);
1629 prefs_free_win_placement(placement);
1630 return TRUE;
1631 }
1632 }
1633
1634 prefs_free_win_placement(placement);
1635 return FALSE;
1636 }
1637
1638 gboolean
prefs_statusbar_pos_down(void)1639 prefs_statusbar_pos_down(void)
1640 {
1641 ProfWinPlacement* placement = prefs_get_win_placement();
1642
1643 for (int pos = 1; pos < 4; pos++) {
1644 if (placement->statusbar_pos == pos) {
1645 placement->statusbar_pos = pos + 1;
1646
1647 if (placement->titlebar_pos == pos + 1) {
1648 placement->titlebar_pos = pos;
1649 } else if (placement->mainwin_pos == pos + 1) {
1650 placement->mainwin_pos = pos;
1651 } else if (placement->inputwin_pos == pos + 1) {
1652 placement->inputwin_pos = pos;
1653 }
1654
1655 prefs_save_win_placement(placement);
1656 prefs_free_win_placement(placement);
1657 return TRUE;
1658 }
1659 }
1660
1661 prefs_free_win_placement(placement);
1662 return FALSE;
1663 }
1664
1665 gboolean
prefs_inputwin_pos_down(void)1666 prefs_inputwin_pos_down(void)
1667 {
1668 ProfWinPlacement* placement = prefs_get_win_placement();
1669
1670 for (int pos = 1; pos < 4; pos++) {
1671 if (placement->inputwin_pos == pos) {
1672 placement->inputwin_pos = pos + 1;
1673
1674 if (placement->titlebar_pos == pos + 1) {
1675 placement->titlebar_pos = pos;
1676 } else if (placement->mainwin_pos == pos + 1) {
1677 placement->mainwin_pos = pos;
1678 } else if (placement->statusbar_pos == pos + 1) {
1679 placement->statusbar_pos = pos;
1680 }
1681
1682 prefs_save_win_placement(placement);
1683 prefs_free_win_placement(placement);
1684 return TRUE;
1685 }
1686 }
1687
1688 prefs_free_win_placement(placement);
1689 return FALSE;
1690 }
1691
1692 gboolean
prefs_add_alias(const char * const name,const char * const value)1693 prefs_add_alias(const char* const name, const char* const value)
1694 {
1695 if (g_key_file_has_key(prefs, PREF_GROUP_ALIAS, name, NULL)) {
1696 return FALSE;
1697 } else {
1698 g_key_file_set_string(prefs, PREF_GROUP_ALIAS, name, value);
1699 return TRUE;
1700 }
1701 }
1702
1703 char*
prefs_get_alias(const char * const name)1704 prefs_get_alias(const char* const name)
1705 {
1706 return g_key_file_get_string(prefs, PREF_GROUP_ALIAS, name, NULL);
1707 }
1708
1709 gboolean
prefs_remove_alias(const char * const name)1710 prefs_remove_alias(const char* const name)
1711 {
1712 if (!g_key_file_has_key(prefs, PREF_GROUP_ALIAS, name, NULL)) {
1713 return FALSE;
1714 } else {
1715 g_key_file_remove_key(prefs, PREF_GROUP_ALIAS, name, NULL);
1716 return TRUE;
1717 }
1718 }
1719
1720 static gint
_alias_cmp(gconstpointer * p1,gconstpointer * p2)1721 _alias_cmp(gconstpointer* p1, gconstpointer* p2)
1722 {
1723 ProfAlias* alias1 = (ProfAlias*)p1;
1724 ProfAlias* alias2 = (ProfAlias*)p2;
1725
1726 return strcmp(alias1->name, alias2->name);
1727 }
1728
1729 GList*
prefs_get_aliases(void)1730 prefs_get_aliases(void)
1731 {
1732 if (!g_key_file_has_group(prefs, PREF_GROUP_ALIAS)) {
1733 return NULL;
1734 } else {
1735 GList* result = NULL;
1736 gsize len;
1737 gchar** keys = g_key_file_get_keys(prefs, PREF_GROUP_ALIAS, &len, NULL);
1738
1739 for (int i = 0; i < len; i++) {
1740 char* name = keys[i];
1741 char* value = g_key_file_get_string(prefs, PREF_GROUP_ALIAS, name, NULL);
1742
1743 if (value) {
1744 ProfAlias* alias = malloc(sizeof(struct prof_alias_t));
1745 alias->name = strdup(name);
1746 alias->value = strdup(value);
1747
1748 free(value);
1749
1750 result = g_list_insert_sorted(result, alias, (GCompareFunc)_alias_cmp);
1751 }
1752 }
1753
1754 g_strfreev(keys);
1755
1756 return result;
1757 }
1758 }
1759
1760 void
_free_alias(ProfAlias * alias)1761 _free_alias(ProfAlias* alias)
1762 {
1763 FREE_SET_NULL(alias->name);
1764 FREE_SET_NULL(alias->value);
1765 FREE_SET_NULL(alias);
1766 }
1767
1768 void
prefs_free_aliases(GList * aliases)1769 prefs_free_aliases(GList* aliases)
1770 {
1771 g_list_free_full(aliases, (GDestroyNotify)_free_alias);
1772 }
1773
1774 static void
_save_prefs(void)1775 _save_prefs(void)
1776 {
1777 gsize g_data_size;
1778 gchar* g_prefs_data = g_key_file_to_data(prefs, &g_data_size, NULL);
1779 gchar* base = g_path_get_dirname(prefs_loc);
1780 gchar* true_loc = get_file_or_linked(prefs_loc, base);
1781
1782 g_file_set_contents(true_loc, g_prefs_data, g_data_size, NULL);
1783 g_chmod(prefs_loc, S_IRUSR | S_IWUSR);
1784
1785 g_free(base);
1786 free(true_loc);
1787 g_free(g_prefs_data);
1788 }
1789
1790 // get the preference group for a specific preference
1791 // for example the PREF_BEEP setting ("beep" in .profrc, see _get_key) belongs
1792 // to the [ui] section.
1793 static const char*
_get_group(preference_t pref)1794 _get_group(preference_t pref)
1795 {
1796 switch (pref) {
1797 case PREF_CLEAR_PERSIST_HISTORY:
1798 case PREF_SPLASH:
1799 case PREF_BEEP:
1800 case PREF_THEME:
1801 case PREF_VERCHECK:
1802 case PREF_WINTITLE_SHOW:
1803 case PREF_WINTITLE_GOODBYE:
1804 case PREF_FLASH:
1805 case PREF_INTYPE:
1806 case PREF_INTYPE_CONSOLE:
1807 case PREF_HISTORY:
1808 case PREF_OCCUPANTS:
1809 case PREF_OCCUPANTS_JID:
1810 case PREF_OCCUPANTS_OFFLINE:
1811 case PREF_OCCUPANTS_WRAP:
1812 case PREF_STATUSES:
1813 case PREF_STATUSES_CONSOLE:
1814 case PREF_STATUSES_CHAT:
1815 case PREF_STATUSES_MUC:
1816 case PREF_MUC_PRIVILEGES:
1817 case PREF_PRESENCE:
1818 case PREF_WRAP:
1819 case PREF_TIME_CONSOLE:
1820 case PREF_TIME_CHAT:
1821 case PREF_TIME_MUC:
1822 case PREF_TIME_CONFIG:
1823 case PREF_TIME_PRIVATE:
1824 case PREF_TIME_XMLCONSOLE:
1825 case PREF_TIME_STATUSBAR:
1826 case PREF_TIME_LASTACTIVITY:
1827 case PREF_ROSTER:
1828 case PREF_ROSTER_OFFLINE:
1829 case PREF_ROSTER_RESOURCE:
1830 case PREF_ROSTER_PRESENCE:
1831 case PREF_ROSTER_STATUS:
1832 case PREF_ROSTER_EMPTY:
1833 case PREF_ROSTER_BY:
1834 case PREF_ROSTER_ORDER:
1835 case PREF_ROSTER_UNREAD:
1836 case PREF_ROSTER_COUNT:
1837 case PREF_ROSTER_COUNT_ZERO:
1838 case PREF_ROSTER_PRIORITY:
1839 case PREF_ROSTER_WRAP:
1840 case PREF_ROSTER_RESOURCE_JOIN:
1841 case PREF_ROSTER_CONTACTS:
1842 case PREF_ROSTER_UNSUBSCRIBED:
1843 case PREF_ROSTER_ROOMS:
1844 case PREF_ROSTER_ROOMS_POS:
1845 case PREF_ROSTER_ROOMS_BY:
1846 case PREF_ROSTER_ROOMS_ORDER:
1847 case PREF_ROSTER_ROOMS_UNREAD:
1848 case PREF_ROSTER_ROOMS_SERVER:
1849 case PREF_ROSTER_ROOMS_USE_AS_NAME:
1850 case PREF_ROSTER_PRIVATE:
1851 case PREF_RESOURCE_TITLE:
1852 case PREF_RESOURCE_MESSAGE:
1853 case PREF_ENC_WARN:
1854 case PREF_INPBLOCK_DYNAMIC:
1855 case PREF_TLS_SHOW:
1856 case PREF_CONSOLE_MUC:
1857 case PREF_CONSOLE_PRIVATE:
1858 case PREF_CONSOLE_CHAT:
1859 case PREF_COLOR_NICK:
1860 case PREF_COLOR_NICK_OWN:
1861 case PREF_ROSTER_COLOR_NICK:
1862 case PREF_OCCUPANTS_COLOR_NICK:
1863 case PREF_STATUSBAR_SHOW_NAME:
1864 case PREF_STATUSBAR_SHOW_NUMBER:
1865 case PREF_STATUSBAR_SHOW_READ:
1866 case PREF_STATUSBAR_SELF:
1867 case PREF_STATUSBAR_CHAT:
1868 case PREF_STATUSBAR_ROOM:
1869 case PREF_TITLEBAR_MUC_TITLE_JID:
1870 case PREF_TITLEBAR_MUC_TITLE_NAME:
1871 case PREF_SLASH_GUARD:
1872 case PREF_COMPOSE_EDITOR:
1873 return PREF_GROUP_UI;
1874 case PREF_STATES:
1875 case PREF_OUTTYPE:
1876 return PREF_GROUP_CHATSTATES;
1877 case PREF_NOTIFY_TYPING:
1878 case PREF_NOTIFY_TYPING_CURRENT:
1879 case PREF_NOTIFY_CHAT:
1880 case PREF_NOTIFY_CHAT_CURRENT:
1881 case PREF_NOTIFY_CHAT_TEXT:
1882 case PREF_NOTIFY_ROOM:
1883 case PREF_NOTIFY_ROOM_MENTION:
1884 case PREF_NOTIFY_ROOM_TRIGGER:
1885 case PREF_NOTIFY_ROOM_CURRENT:
1886 case PREF_NOTIFY_ROOM_TEXT:
1887 case PREF_NOTIFY_INVITE:
1888 case PREF_NOTIFY_SUB:
1889 case PREF_NOTIFY_MENTION_CASE_SENSITIVE:
1890 case PREF_NOTIFY_MENTION_WHOLE_WORD:
1891 case PREF_TRAY:
1892 case PREF_TRAY_READ:
1893 case PREF_ADV_NOTIFY_DISCO_OR_VERSION:
1894 return PREF_GROUP_NOTIFICATIONS;
1895 case PREF_CHLOG:
1896 case PREF_GRLOG:
1897 case PREF_LOG_ROTATE:
1898 case PREF_LOG_SHARED:
1899 return PREF_GROUP_LOGGING;
1900 case PREF_AVATAR_CMD:
1901 case PREF_URL_OPEN_CMD:
1902 case PREF_URL_SAVE_CMD:
1903 return PREF_GROUP_EXECUTABLES;
1904 case PREF_AUTOAWAY_CHECK:
1905 case PREF_AUTOAWAY_MODE:
1906 case PREF_AUTOAWAY_MESSAGE:
1907 case PREF_AUTOXA_MESSAGE:
1908 case PREF_LASTACTIVITY:
1909 return PREF_GROUP_PRESENCE;
1910 case PREF_CONNECT_ACCOUNT:
1911 case PREF_DEFAULT_ACCOUNT:
1912 case PREF_CARBONS:
1913 case PREF_RECEIPTS_SEND:
1914 case PREF_RECEIPTS_REQUEST:
1915 case PREF_REVEAL_OS:
1916 case PREF_TLS_CERTPATH:
1917 case PREF_CORRECTION_ALLOW:
1918 case PREF_MAM:
1919 case PREF_SILENCE_NON_ROSTER:
1920 return PREF_GROUP_CONNECTION;
1921 case PREF_OTR_LOG:
1922 case PREF_OTR_POLICY:
1923 case PREF_OTR_SENDFILE:
1924 return PREF_GROUP_OTR;
1925 case PREF_PGP_LOG:
1926 case PREF_PGP_SENDFILE:
1927 return PREF_GROUP_PGP;
1928 case PREF_BOOKMARK_INVITE:
1929 case PREF_ROOM_LIST_CACHE:
1930 return PREF_GROUP_MUC;
1931 case PREF_PLUGINS_SOURCEPATH:
1932 return PREF_GROUP_PLUGINS;
1933 case PREF_OMEMO_LOG:
1934 case PREF_OMEMO_POLICY:
1935 case PREF_OMEMO_TRUST_MODE:
1936 return PREF_GROUP_OMEMO;
1937 default:
1938 return NULL;
1939 }
1940 }
1941
1942 // get the key used in .profrc for the preference
1943 // for example the PREF_AUTOAWAY_MODE maps to "autoaway.mode" in .profrc
1944 static const char*
_get_key(preference_t pref)1945 _get_key(preference_t pref)
1946 {
1947 switch (pref) {
1948 case PREF_CLEAR_PERSIST_HISTORY:
1949 return "clear.persist_history";
1950 case PREF_SPLASH:
1951 return "splash";
1952 case PREF_BEEP:
1953 return "beep";
1954 case PREF_THEME:
1955 return "theme";
1956 case PREF_VERCHECK:
1957 return "vercheck";
1958 case PREF_WINTITLE_SHOW:
1959 return "wintitle.show";
1960 case PREF_WINTITLE_GOODBYE:
1961 return "wintitle.goodbye";
1962 case PREF_FLASH:
1963 return "flash";
1964 case PREF_TRAY:
1965 return "tray";
1966 case PREF_TRAY_READ:
1967 return "tray.read";
1968 case PREF_ADV_NOTIFY_DISCO_OR_VERSION:
1969 return "adv.notify.discoversion";
1970 case PREF_INTYPE:
1971 return "intype";
1972 case PREF_INTYPE_CONSOLE:
1973 return "intype.console";
1974 case PREF_HISTORY:
1975 return "history";
1976 case PREF_CARBONS:
1977 return "carbons";
1978 case PREF_RECEIPTS_SEND:
1979 return "receipts.send";
1980 case PREF_RECEIPTS_REQUEST:
1981 return "receipts.request";
1982 case PREF_REVEAL_OS:
1983 return "reveal.os";
1984 case PREF_OCCUPANTS:
1985 return "occupants";
1986 case PREF_OCCUPANTS_JID:
1987 return "occupants.jid";
1988 case PREF_OCCUPANTS_OFFLINE:
1989 return "occupants.offline";
1990 case PREF_OCCUPANTS_WRAP:
1991 return "occupants.wrap";
1992 case PREF_MUC_PRIVILEGES:
1993 return "privileges";
1994 case PREF_STATUSES:
1995 return "statuses";
1996 case PREF_STATUSES_CONSOLE:
1997 return "statuses.console";
1998 case PREF_STATUSES_CHAT:
1999 return "statuses.chat";
2000 case PREF_STATUSES_MUC:
2001 return "statuses.muc";
2002 case PREF_STATES:
2003 return "enabled";
2004 case PREF_OUTTYPE:
2005 return "outtype";
2006 case PREF_NOTIFY_TYPING:
2007 return "typing";
2008 case PREF_NOTIFY_TYPING_CURRENT:
2009 return "typing.current";
2010 case PREF_NOTIFY_CHAT:
2011 return "message";
2012 case PREF_NOTIFY_CHAT_CURRENT:
2013 return "message.current";
2014 case PREF_NOTIFY_CHAT_TEXT:
2015 return "message.text";
2016 case PREF_NOTIFY_ROOM:
2017 return "room";
2018 case PREF_NOTIFY_ROOM_TRIGGER:
2019 return "room.trigger";
2020 case PREF_NOTIFY_ROOM_MENTION:
2021 return "room.mention";
2022 case PREF_NOTIFY_ROOM_CURRENT:
2023 return "room.current";
2024 case PREF_NOTIFY_ROOM_TEXT:
2025 return "room.text";
2026 case PREF_NOTIFY_INVITE:
2027 return "invite";
2028 case PREF_NOTIFY_SUB:
2029 return "sub";
2030 case PREF_NOTIFY_MENTION_CASE_SENSITIVE:
2031 return "room.mention.casesensitive";
2032 case PREF_NOTIFY_MENTION_WHOLE_WORD:
2033 return "room.mention.wholeword";
2034 case PREF_CHLOG:
2035 return "chlog";
2036 case PREF_GRLOG:
2037 return "grlog";
2038 case PREF_AUTOAWAY_CHECK:
2039 return "autoaway.check";
2040 case PREF_AUTOAWAY_MODE:
2041 return "autoaway.mode";
2042 case PREF_AUTOAWAY_MESSAGE:
2043 return "autoaway.awaymessage";
2044 case PREF_AUTOXA_MESSAGE:
2045 return "autoaway.xamessage";
2046 case PREF_CONNECT_ACCOUNT:
2047 return "account";
2048 case PREF_DEFAULT_ACCOUNT:
2049 return "defaccount";
2050 case PREF_OTR_LOG:
2051 return "log";
2052 case PREF_OTR_POLICY:
2053 return "policy";
2054 case PREF_OTR_SENDFILE:
2055 return "sendfile";
2056 case PREF_LOG_ROTATE:
2057 return "rotate";
2058 case PREF_LOG_SHARED:
2059 return "shared";
2060 case PREF_PRESENCE:
2061 return "presence";
2062 case PREF_WRAP:
2063 return "wrap";
2064 case PREF_TIME_CONSOLE:
2065 return "time.console";
2066 case PREF_TIME_CHAT:
2067 return "time.chat";
2068 case PREF_TIME_MUC:
2069 return "time.muc";
2070 case PREF_TIME_CONFIG:
2071 return "time.config";
2072 case PREF_TIME_PRIVATE:
2073 return "time.private";
2074 case PREF_TIME_XMLCONSOLE:
2075 return "time.xmlconsole";
2076 case PREF_TIME_STATUSBAR:
2077 return "time.statusbar";
2078 case PREF_TIME_LASTACTIVITY:
2079 return "time.lastactivity";
2080 case PREF_ROSTER:
2081 return "roster";
2082 case PREF_ROSTER_OFFLINE:
2083 return "roster.offline";
2084 case PREF_ROSTER_RESOURCE:
2085 return "roster.resource";
2086 case PREF_ROSTER_PRESENCE:
2087 return "roster.presence";
2088 case PREF_ROSTER_STATUS:
2089 return "roster.status";
2090 case PREF_ROSTER_EMPTY:
2091 return "roster.empty";
2092 case PREF_ROSTER_BY:
2093 return "roster.by";
2094 case PREF_ROSTER_ORDER:
2095 return "roster.order";
2096 case PREF_ROSTER_UNREAD:
2097 return "roster.unread";
2098 case PREF_ROSTER_COUNT:
2099 return "roster.count";
2100 case PREF_ROSTER_COUNT_ZERO:
2101 return "roster.count.zero";
2102 case PREF_ROSTER_PRIORITY:
2103 return "roster.priority";
2104 case PREF_ROSTER_WRAP:
2105 return "roster.wrap";
2106 case PREF_ROSTER_RESOURCE_JOIN:
2107 return "roster.resource.join";
2108 case PREF_ROSTER_CONTACTS:
2109 return "roster.contacts";
2110 case PREF_ROSTER_UNSUBSCRIBED:
2111 return "roster.unsubscribed";
2112 case PREF_ROSTER_ROOMS:
2113 return "roster.rooms";
2114 case PREF_ROSTER_ROOMS_POS:
2115 return "roster.rooms.pos";
2116 case PREF_ROSTER_ROOMS_BY:
2117 return "roster.rooms.by";
2118 case PREF_ROSTER_ROOMS_ORDER:
2119 return "roster.rooms.order";
2120 case PREF_ROSTER_ROOMS_UNREAD:
2121 return "roster.rooms.unread";
2122 case PREF_ROSTER_ROOMS_SERVER:
2123 return "roster.rooms.server";
2124 case PREF_ROSTER_ROOMS_USE_AS_NAME:
2125 return "roster.rooms.use.name";
2126 case PREF_ROSTER_PRIVATE:
2127 return "roster.private";
2128 case PREF_RESOURCE_TITLE:
2129 return "resource.title";
2130 case PREF_RESOURCE_MESSAGE:
2131 return "resource.message";
2132 case PREF_INPBLOCK_DYNAMIC:
2133 return "inpblock.dynamic";
2134 case PREF_ENC_WARN:
2135 return "enc.warn";
2136 case PREF_TITLEBAR_MUC_TITLE_JID:
2137 return "titlebar.muc.title.jid";
2138 case PREF_TITLEBAR_MUC_TITLE_NAME:
2139 return "titlebar.muc.title.name";
2140 case PREF_PGP_LOG:
2141 return "log";
2142 case PREF_PGP_SENDFILE:
2143 return "sendfile";
2144 case PREF_TLS_CERTPATH:
2145 return "tls.certpath";
2146 case PREF_TLS_SHOW:
2147 return "tls.show";
2148 case PREF_LASTACTIVITY:
2149 return "lastactivity";
2150 case PREF_CONSOLE_MUC:
2151 return "console.muc";
2152 case PREF_CONSOLE_PRIVATE:
2153 return "console.private";
2154 case PREF_CONSOLE_CHAT:
2155 return "console.chat";
2156 case PREF_COLOR_NICK:
2157 return "color.nick";
2158 case PREF_COLOR_NICK_OWN:
2159 return "color.nick.own";
2160 case PREF_ROSTER_COLOR_NICK:
2161 return "color.roster.nick";
2162 case PREF_OCCUPANTS_COLOR_NICK:
2163 return "color.occupants.nick";
2164 case PREF_BOOKMARK_INVITE:
2165 return "bookmark.invite";
2166 case PREF_PLUGINS_SOURCEPATH:
2167 return "sourcepath";
2168 case PREF_ROOM_LIST_CACHE:
2169 return "rooms.cache";
2170 case PREF_STATUSBAR_SHOW_NAME:
2171 return "statusbar.show.name";
2172 case PREF_STATUSBAR_SHOW_NUMBER:
2173 return "statusbar.show.number";
2174 case PREF_STATUSBAR_SHOW_READ:
2175 return "statusbar.show.read";
2176 case PREF_STATUSBAR_SELF:
2177 return "statusbar.self";
2178 case PREF_STATUSBAR_CHAT:
2179 return "statusbar.chat";
2180 case PREF_STATUSBAR_ROOM:
2181 return "statusbar.room";
2182 case PREF_OMEMO_LOG:
2183 return "log";
2184 case PREF_OMEMO_POLICY:
2185 return "policy";
2186 case PREF_OMEMO_TRUST_MODE:
2187 return "trustmode";
2188 case PREF_CORRECTION_ALLOW:
2189 return "correction.allow";
2190 case PREF_AVATAR_CMD:
2191 return "avatar.cmd";
2192 case PREF_SLASH_GUARD:
2193 return "slashguard";
2194 case PREF_MAM:
2195 return "mam";
2196 case PREF_URL_OPEN_CMD:
2197 return "url.open.cmd";
2198 case PREF_URL_SAVE_CMD:
2199 return "url.save.cmd";
2200 case PREF_COMPOSE_EDITOR:
2201 return "compose.editor";
2202 case PREF_SILENCE_NON_ROSTER:
2203 return "silence.incoming.nonroster";
2204 default:
2205 return NULL;
2206 }
2207 }
2208
2209 // the default setting for a boolean type preference
2210 // if it is not specified in .profrc
2211 static gboolean
_get_default_boolean(preference_t pref)2212 _get_default_boolean(preference_t pref)
2213 {
2214 switch (pref) {
2215 case PREF_ENC_WARN:
2216 case PREF_AUTOAWAY_CHECK:
2217 case PREF_LOG_ROTATE:
2218 case PREF_LOG_SHARED:
2219 case PREF_SPLASH:
2220 case PREF_OCCUPANTS:
2221 case PREF_MUC_PRIVILEGES:
2222 case PREF_PRESENCE:
2223 case PREF_WRAP:
2224 case PREF_INPBLOCK_DYNAMIC:
2225 case PREF_RESOURCE_TITLE:
2226 case PREF_RESOURCE_MESSAGE:
2227 case PREF_ROSTER:
2228 case PREF_ROSTER_OFFLINE:
2229 case PREF_ROSTER_EMPTY:
2230 case PREF_ROSTER_COUNT_ZERO:
2231 case PREF_ROSTER_PRIORITY:
2232 case PREF_ROSTER_RESOURCE_JOIN:
2233 case PREF_ROSTER_CONTACTS:
2234 case PREF_ROSTER_UNSUBSCRIBED:
2235 case PREF_ROSTER_ROOMS:
2236 case PREF_ROSTER_ROOMS_SERVER:
2237 case PREF_TLS_SHOW:
2238 case PREF_LASTACTIVITY:
2239 case PREF_TRAY_READ:
2240 case PREF_BOOKMARK_INVITE:
2241 case PREF_ROOM_LIST_CACHE:
2242 case PREF_STATUSBAR_SHOW_NUMBER:
2243 case PREF_STATUSBAR_SHOW_READ:
2244 case PREF_REVEAL_OS:
2245 case PREF_CORRECTION_ALLOW:
2246 case PREF_RECEIPTS_SEND:
2247 case PREF_CARBONS:
2248 case PREF_STATES:
2249 case PREF_OUTTYPE:
2250 case PREF_TITLEBAR_MUC_TITLE_NAME:
2251 case PREF_COLOR_NICK_OWN:
2252 case PREF_INTYPE:
2253 case PREF_INTYPE_CONSOLE:
2254 case PREF_NOTIFY_MENTION_WHOLE_WORD:
2255 return TRUE;
2256 default:
2257 return FALSE;
2258 }
2259 }
2260
2261 // the default setting for a string type preference
2262 // if it is not specified in .profrc
2263 static char*
_get_default_string(preference_t pref)2264 _get_default_string(preference_t pref)
2265 {
2266 switch (pref) {
2267 case PREF_AUTOAWAY_MODE:
2268 return "off";
2269 case PREF_OTR_LOG:
2270 return "redact";
2271 case PREF_OTR_POLICY:
2272 return "manual";
2273 case PREF_STATUSES_CONSOLE:
2274 case PREF_STATUSES_CHAT:
2275 case PREF_STATUSES_MUC:
2276 return "all";
2277 case PREF_ROSTER_BY:
2278 return "presence";
2279 case PREF_ROSTER_COUNT:
2280 return "unread";
2281 case PREF_ROSTER_ORDER:
2282 return "presence";
2283 case PREF_ROSTER_UNREAD:
2284 return "after";
2285 case PREF_ROSTER_ROOMS_POS:
2286 return "last";
2287 case PREF_ROSTER_ROOMS_BY:
2288 return "none";
2289 case PREF_ROSTER_ROOMS_USE_AS_NAME:
2290 return "name";
2291 case PREF_ROSTER_ROOMS_ORDER:
2292 return "name";
2293 case PREF_ROSTER_ROOMS_UNREAD:
2294 return "after";
2295 case PREF_ROSTER_PRIVATE:
2296 return "room";
2297 case PREF_TIME_CONSOLE:
2298 return "%H:%M:%S";
2299 case PREF_TIME_CHAT:
2300 return "%H:%M:%S";
2301 case PREF_TIME_MUC:
2302 return "%H:%M:%S";
2303 case PREF_TIME_CONFIG:
2304 return "%H:%M:%S";
2305 case PREF_TIME_PRIVATE:
2306 return "%H:%M:%S";
2307 case PREF_TIME_XMLCONSOLE:
2308 return "%H:%M:%S";
2309 case PREF_TIME_STATUSBAR:
2310 return "%H:%M";
2311 case PREF_TIME_LASTACTIVITY:
2312 return "%d/%m/%y %H:%M:%S";
2313 case PREF_PGP_LOG:
2314 return "redact";
2315 case PREF_CONSOLE_MUC:
2316 case PREF_CONSOLE_PRIVATE:
2317 case PREF_CONSOLE_CHAT:
2318 return "all";
2319 case PREF_STATUSBAR_SELF:
2320 return "fulljid";
2321 case PREF_STATUSBAR_CHAT:
2322 return "user";
2323 case PREF_STATUSBAR_ROOM:
2324 return "room";
2325 case PREF_OMEMO_LOG:
2326 return "redact";
2327 case PREF_OMEMO_POLICY:
2328 return "automatic";
2329 case PREF_OMEMO_TRUST_MODE:
2330 return "manual";
2331 case PREF_COLOR_NICK:
2332 return "false";
2333 case PREF_AVATAR_CMD:
2334 return "xdg-open";
2335 case PREF_URL_OPEN_CMD:
2336 return "xdg-open %u";
2337 case PREF_COMPOSE_EDITOR:
2338 return "vim";
2339 case PREF_URL_SAVE_CMD:
2340 return NULL; // Default to built-in method.
2341 default:
2342 return NULL;
2343 }
2344 }
2345