1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2014-2016 Ricardo Mones and the Claws Mail Team
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program 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
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 #  include "config.h"
21 #include "claws-features.h"
22 #endif
23 
24 #include <glib.h>
25 #include <glib/gi18n.h>
26 
27 #include "libravatar.h"
28 
29 #include <gtk/gtk.h>
30 #include <gtk/filesel.h>
31 
32 #include "defs.h"
33 #include "libravatar_prefs.h"
34 #include "libravatar_cache.h"
35 #include "prefs_common.h"
36 #include "prefs_gtk.h"
37 #include "alertpanel.h"
38 
39 #define PREFS_BLOCK_NAME "Libravatar"
40 #define NUM_DEF_BUTTONS 9
41 #define CUSTOM_URL_BUTTON_INDEX 8
42 /* cache interval goes from 1 hour to 30 days */
43 #define INTERVAL_MIN_H 1.0
44 #define INTERVAL_MAX_H 720.0
45 /* timeout interval goes from 0 seconds (= use general timeout value)
46    to (general timeout value - 1) seconds */
47 #define TIMEOUT_MIN_S 0.0
48 
49 LibravatarPrefs libravatarprefs;
50 GHashTable *libravatarmisses;
51 
52 struct LibravatarPrefsPage
53 {
54 	PrefsPage page;
55 
56 	GtkWidget *cache_interval_spin;
57 	GtkWidget *cache_icons_check;
58 	GtkWidget *defm_radio[NUM_DEF_BUTTONS];
59 	GtkWidget *defm_url_text;
60 	GtkWidget *allow_redirects_check;
61 #if defined USE_GNUTLS
62 	GtkWidget *allow_federated_check;
63 #endif
64 	GtkWidget *timeout;
65 };
66 
67 struct LibravatarPrefsPage libravatarprefs_page;
68 
69 static PrefParam param[] = {
70 	{ "base_url", "http://cdn.libravatar.org/avatar",
71 	  &libravatarprefs.base_url,
72           P_STRING, NULL, NULL, NULL },
73 	{ "cache_interval", "24",
74 	  &libravatarprefs.cache_interval,
75           P_INT, NULL, NULL, NULL },
76 	{ "cache_icons", "TRUE",
77 	  &libravatarprefs.cache_icons,
78           P_BOOL, NULL, NULL, NULL },
79 	{ "default_mode", "0",
80 	  &libravatarprefs.default_mode,
81           P_INT, NULL, NULL, NULL },
82 	{ "default_mode_url", "",
83 	  &libravatarprefs.default_mode_url,
84           P_STRING, NULL, NULL, NULL },
85 	{ "allow_redirects", "TRUE",
86 	  &libravatarprefs.allow_redirects,
87           P_BOOL, NULL, NULL, NULL },
88 #if defined USE_GNUTLS
89 	{ "allow_federated", "TRUE",
90 	  &libravatarprefs.allow_federated,
91           P_BOOL, NULL, NULL, NULL },
92 #endif
93 	{ "timeout", "0",
94 	  &libravatarprefs.timeout,
95           P_INT, NULL, NULL, NULL },
96 	{ "max_redirects_url", "7",
97 	  &libravatarprefs.max_redirects_url,
98           P_INT, NULL, NULL, NULL },
99 	{ "max_redirects_mm", "5",
100 	  &libravatarprefs.max_redirects_mm,
101           P_INT, NULL, NULL, NULL },
102 	{ "max_redirects", "3",
103 	  &libravatarprefs.max_redirects,
104           P_INT, NULL, NULL, NULL },
105 	{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
106 };
107 
create_checkbox(gchar * label,gchar * hint)108 static GtkWidget *create_checkbox(gchar *label, gchar *hint)
109 {
110 	GtkWidget *cb = gtk_check_button_new_with_mnemonic(label);
111 	CLAWS_SET_TIP(cb, hint);
112 	gtk_widget_show(cb);
113 
114 	return cb;
115 }
116 
cache_icons_check_toggled_cb(GtkToggleButton * button,gpointer data)117 static void cache_icons_check_toggled_cb(GtkToggleButton *button, gpointer data)
118 {
119 	gtk_widget_set_sensitive(libravatarprefs_page.cache_interval_spin,
120 				 gtk_toggle_button_get_active(button));
121 }
122 
labeled_spinner_box(gchar * label,GtkWidget * spinner,gchar * units,gchar * hint)123 static GtkWidget *labeled_spinner_box(gchar *label, GtkWidget *spinner, gchar *units, gchar *hint)
124 {
125 	GtkWidget *lbl, *lbla, *hbox;
126 
127 	lbl = gtk_label_new(label);
128 	gtk_widget_show(lbl);
129 	lbla = gtk_label_new(units);
130 	gtk_widget_show(lbla);
131 	hbox = gtk_hbox_new(FALSE, 6);
132 	if (hint != NULL) {
133 		CLAWS_SET_TIP(spinner, hint);
134 	}
135 	gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 0);
136 	gtk_box_pack_start(GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
137 	gtk_box_pack_start(GTK_BOX(hbox), lbla, FALSE, FALSE, 0);
138 
139 	return hbox;
140 }
141 
avatar_stats_label_markup(AvatarCacheStats * stats)142 static gchar *avatar_stats_label_markup(AvatarCacheStats *stats)
143 {
144 	if (stats == NULL)
145 		return g_strdup(g_strconcat("<span color=\"red\">",
146 			_("Error reading cache stats"), "</span>", NULL));
147 
148 	if (stats->errors > 0)
149 		return g_markup_printf_escaped(g_strconcat("<span color=\"red\">",
150 			_("Using %s in %d files, %d "
151 			"directories, %d others and %d errors"), "</span>", NULL),
152 			to_human_readable((goffset) stats->bytes),
153 			stats->files,
154 			stats->dirs,
155 			stats->others,
156 			stats->errors);
157 
158 	return g_strdup_printf(
159 		_("Using %s in %d files, %d directories and %d others"),
160 		to_human_readable((goffset) stats->bytes),
161 		stats->files,
162 		stats->dirs,
163 		stats->others);
164 }
165 
cache_clean_button_clicked_cb(GtkButton * button,gpointer data)166 static void cache_clean_button_clicked_cb(GtkButton *button, gpointer data)
167 {
168 	GtkLabel *label = (GtkLabel *) data;
169 	gint val = 0;
170 	AvatarCleanupResult *acr;
171 	guint misses;
172 
173 	val = alertpanel_full(_("Clear icon cache"),
174 			_("Are you sure you want to remove all cached avatar icons?"),
175 			GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_FIRST, FALSE,
176 			NULL, ALERT_WARNING);
177 	if (val != G_ALERTALTERNATE)
178 		return;
179 
180 	debug_print("cleaning missing cache\n");
181 	misses = g_hash_table_size(libravatarmisses);
182 	g_hash_table_remove_all(libravatarmisses);
183 
184 	debug_print("cleaning disk cache\n");
185 	acr = libravatar_cache_clean();
186 	if (acr == NULL) {
187 		alertpanel_error(_("Not enough memory for operation"));
188 		return;
189 	}
190 
191 	if (acr->e_stat == 0 && acr->e_unlink == 0) {
192 		alertpanel_notice(_("Icon cache successfully cleared:\n"
193 			"• %u missing entries removed.\n"
194 			"• %u files removed."),
195 			misses, acr->removed);
196 		gtk_label_set_markup(label, g_strconcat("<span color=\"#006400\">",
197 			_("Icon cache successfully cleared!"), "</span>", NULL));
198 	}
199 	else {
200 		alertpanel_warning(_("Errors clearing icon cache:\n"
201 			"• %u missing entries removed.\n"
202 			"• %u files removed.\n"
203 			"• %u files failed to be read.\n"
204 			"• %u files couldn't be removed."),
205 			misses, acr->removed, acr->e_stat, acr->e_unlink);
206 		gtk_label_set_markup(label, g_strconcat("<span color=\"red\">",
207 			_("Error clearing icon cache."), "</span>", NULL));
208 	}
209 	gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
210 	g_free(acr);
211 }
212 
p_create_frame_cache(struct LibravatarPrefsPage * page)213 static GtkWidget *p_create_frame_cache(struct LibravatarPrefsPage *page)
214 {
215 	GtkWidget *vbox, *checkbox, *spinner, *hbox, *label, *button;
216 	GtkAdjustment *adj;
217 	AvatarCacheStats *stats;
218 	gchar *markup;
219 
220 	vbox =  gtk_vbox_new(FALSE, 6);
221 
222 	checkbox = create_checkbox(_("_Use cached icons"),
223 				   _("Keep icons on disk for reusing instead "
224 				     "of making another network request"));
225 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox),
226 				     libravatarprefs.cache_icons);
227 	g_signal_connect(checkbox, "toggled",
228 			 G_CALLBACK(cache_icons_check_toggled_cb), NULL);
229 	page->cache_icons_check = checkbox;
230 
231 	adj = (GtkAdjustment *) gtk_adjustment_new(
232 					libravatarprefs.cache_interval,
233 					INTERVAL_MIN_H, INTERVAL_MAX_H, 1.0,
234 					0.0, 0.0);
235 	spinner = gtk_spin_button_new(adj, 1.0, 0);
236 	gtk_widget_show(spinner);
237 	gtk_widget_set_sensitive(spinner, libravatarprefs.cache_icons);
238 	hbox = labeled_spinner_box(_("Cache refresh interval"), spinner, _("hours"), NULL);
239 	page->cache_interval_spin = spinner;
240 
241 	gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 0);
242 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
243 
244 	label = gtk_label_new(NULL);
245 	gtk_widget_show(label);
246 	stats = libravatar_cache_stats();
247 	markup = avatar_stats_label_markup(stats);
248 	gtk_label_set_markup(GTK_LABEL(label), markup);
249 	g_free(markup);
250 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
251 
252 	button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
253 	gtk_widget_show(button);
254 	g_signal_connect(button, "clicked",
255 		G_CALLBACK(cache_clean_button_clicked_cb), label);
256 	gtk_widget_set_sensitive(button, (stats != NULL && stats->bytes > 0));
257 
258 	hbox = gtk_hbox_new(FALSE, 6);
259 	gtk_widget_show(hbox);
260 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
261 	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
262 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
263 
264 	if (stats != NULL)
265 		g_free(stats);
266 
267 	return vbox;
268 }
269 
default_mode_radio_button_cb(GtkToggleButton * button,gpointer data)270 static void default_mode_radio_button_cb(GtkToggleButton *button, gpointer data)
271 {
272 	guint mode;
273 	gboolean is_url;
274 
275 	if (gtk_toggle_button_get_active(button) != TRUE)
276 		return;
277 
278 	mode = *((guint *)data);
279 	is_url = (mode == DEF_MODE_URL)? TRUE: FALSE;
280 
281 	gtk_widget_set_sensitive(libravatarprefs_page.defm_url_text, is_url);
282 	if (is_url) /* custom URL requires following redirects */
283 		gtk_toggle_button_set_active(
284 			GTK_TOGGLE_BUTTON(libravatarprefs_page.allow_redirects_check),
285 			TRUE);
286 
287 	if (mode == DEF_MODE_NONE) {
288 		prefs_common_get_prefs()->enable_avatars = AVATARS_ENABLE_BOTH;
289 	} else {
290 		/* don't waste time with headers that won't be displayed */
291 		prefs_common_get_prefs()->enable_avatars = AVATARS_DISABLE;
292 		/* empty missing cache when switching to generated */
293 		g_hash_table_remove_all(libravatarmisses);
294 	}
295 }
296 
297 static const guint radio_value[] = {
298 	DEF_MODE_NONE,
299 	DEF_MODE_MM,
300 	DEF_MODE_IDENTICON,
301 	DEF_MODE_MONSTERID,
302 	DEF_MODE_WAVATAR,
303 	DEF_MODE_RETRO,
304 	DEF_MODE_ROBOHASH,
305 	DEF_MODE_PAGAN,
306 	DEF_MODE_URL
307 };
308 
p_create_frame_missing(struct LibravatarPrefsPage * page)309 static GtkWidget *p_create_frame_missing(struct LibravatarPrefsPage *page)
310 {
311 	GtkWidget *vbox, *radio[NUM_DEF_BUTTONS], *hbox, *entry;
312 	gboolean enable = FALSE;
313 	int i, e = 0;
314 	gchar *radio_label[] = {
315 		_("None"),
316 		_("Mystery man"),
317 		_("Identicon"),
318 		_("MonsterID"),
319 		_("Wavatar"),
320 		_("Retro"),
321 		_("Robohash"),
322 		_("Pagan"),
323 		_("Custom URL")
324 	};
325 	gchar *radio_hint[] = {
326 		_("A blank image"),
327 		_("The unobtrusive low-contrast greyish silhouette"),
328 		_("A generated geometric pattern"),
329 		_("A generated full-body monster"),
330 		_("A generated almost unique face"),
331 		_("A generated 8-bit arcade-style pixelated image"),
332 		_("A generated robotic character"),
333 		_("A generated retro adventure game character"),
334 		_("Redirect to a user provided URL")
335 	};
336 
337 	vbox =  gtk_vbox_new(FALSE, 6);
338 
339 	for (i = 0; i < NUM_DEF_BUTTONS; ++i) {
340 		enable = (libravatarprefs.default_mode == radio_value[i])? TRUE: FALSE;
341 		e += enable? 1: 0;
342 		radio[i] = gtk_radio_button_new_with_label_from_widget(
343 				(i > 0)? GTK_RADIO_BUTTON(radio[i - 1]): NULL, radio_label[i]);
344 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[i]), enable);
345 		if (i == CUSTOM_URL_BUTTON_INDEX) {
346 			/* set related entry next to radio button */
347 			entry = gtk_entry_new();
348 			CLAWS_SET_TIP(entry, _("Enter the URL you want to be "
349 				"redirected when no user icon is available. "
350 				"Leave an empty URL to use the default "
351 				"libravatar orange icon."));
352 			gtk_entry_set_text(GTK_ENTRY(entry),
353 				libravatarprefs.default_mode_url);
354 			gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_URL_LENGTH);
355 			hbox = gtk_hbox_new(FALSE, 6);
356 			gtk_box_pack_start(GTK_BOX(hbox), radio[i], FALSE, FALSE, 0);
357 			gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
358 			gtk_widget_set_sensitive(entry,
359 				(libravatarprefs.default_mode == DEF_MODE_URL)
360 				? TRUE: FALSE);
361 			gtk_widget_show(entry);
362 			page->defm_url_text = entry;
363 			gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
364 		} else {
365 			gtk_box_pack_start(GTK_BOX(vbox), radio[i], FALSE, FALSE, 0);
366 		}
367 		g_signal_connect(radio[i], "toggled",
368 				 G_CALLBACK(default_mode_radio_button_cb),
369 				 (gpointer) &(radio_value[i]));
370 		CLAWS_SET_TIP(radio[i], radio_hint[i]);
371 		gtk_widget_show(radio[i]);
372 		page->defm_radio[i] = radio[i];
373 	}
374 	if (e == 0) { /* unknown value, go default */
375 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[0]), TRUE);
376 		libravatarprefs.default_mode = DEF_MODE_NONE;
377 	}
378 	/* don't waste time with headers that won't be displayed */
379 	prefs_common_get_prefs()->enable_avatars =
380 		(libravatarprefs.default_mode == DEF_MODE_NONE)
381 		? AVATARS_ENABLE_BOTH: AVATARS_DISABLE;
382 
383 
384 
385 	return vbox;
386 }
387 
p_create_frame_network(struct LibravatarPrefsPage * page)388 static GtkWidget *p_create_frame_network(struct LibravatarPrefsPage *page)
389 {
390 	GtkWidget *vbox, *chk_redirects, *spinner, *hbox;
391 	GtkAdjustment *adj;
392 #if defined USE_GNUTLS
393 	GtkWidget *chk_federated;
394 #endif
395 
396 	vbox =  gtk_vbox_new(FALSE, 6);
397 
398 	chk_redirects = create_checkbox(_("_Allow redirects to other sites"),
399 				   _("Follow redirect responses received from "
400 				     "libravatar server to other avatar "
401 				     "services like gravatar.com"));
402 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_redirects),
403 				     libravatarprefs.allow_redirects);
404 	page->allow_redirects_check = chk_redirects;
405 	gtk_box_pack_start(GTK_BOX(vbox), chk_redirects, FALSE, FALSE, 0);
406 
407 #if defined USE_GNUTLS
408 	chk_federated = create_checkbox(_("_Enable federated servers"),
409 				_("Try to get avatar from sender's domain "
410 				  "libravatar server"));
411 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_federated),
412 				     libravatarprefs.allow_federated);
413 	page->allow_federated_check = chk_federated;
414 	gtk_box_pack_start(GTK_BOX(vbox), chk_federated, FALSE, FALSE, 0);
415 #endif
416 
417 	adj = (GtkAdjustment *) gtk_adjustment_new(
418 					libravatarprefs.timeout,
419 					TIMEOUT_MIN_S,
420 					(prefs_common_get_prefs()->io_timeout_secs > 0)
421 					? (prefs_common_get_prefs()->io_timeout_secs - 1)
422 					: 0,
423 					1.0, 0.0, 0.0);
424 	spinner = gtk_spin_button_new(adj, 1.0, 0);
425 	gtk_widget_show(spinner);
426 	hbox = labeled_spinner_box(_("Request timeout"), spinner, _("second(s)"),
427 		_("Set to 0 to use global socket I/O timeout. "
428                   "Maximum value must be also less than global socket "
429                   "I/O timeout."));
430 	page->timeout = spinner;
431 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
432 
433 	return vbox;
434 }
435 
436 /*
437   ┌─Icon cache───────────────────────────────────────────┐
438   │ [✔] Use cached icons                                 │
439   │ Cache refresh interval [ 24 |⬘] hours                │
440   │ Using X KB in Y files and Z directories [Clear]      │
441   └──────────────────────────────────────────────────────┘
442   ┌─Default missing icon mode────────────────────────────┐
443   │ (•) None                                             │
444   │ ( ) Mystery man                                      │
445   │ ( ) Identicon                                        │
446   │ ( ) MonsterID                                        │
447   │ ( ) Wavatar                                          │
448   │ ( ) Retro                                            │
449   │ ( ) Robohash                                         │
450   │ ( ) Pagan                                            │
451   │ ( ) Custom URL [___________________________________] │
452   └──────────────────────────────────────────────────────┘
453   ┌─Network──────────────────────────────────────────────┐
454   │ [✔] Allow redirects                                  │
455   │ [✔] Federated servers                                │
456   │ Timeout [ 10 |⬘] seconds                             │
457   └──────────────────────────────────────────────────────┘
458  */
libravatar_prefs_create_widget_func(PrefsPage * _page,GtkWindow * window,gpointer data)459 static void libravatar_prefs_create_widget_func(PrefsPage * _page,
460 					        GtkWindow * window,
461 					        gpointer data)
462 {
463 	struct LibravatarPrefsPage *page = (struct LibravatarPrefsPage *) _page;
464 	GtkWidget *vbox, *vbox1, *vbox2, *vbox3, *frame;
465 
466 	vbox1 = p_create_frame_cache(page);
467 	vbox2 = p_create_frame_missing(page);
468 	vbox3 = p_create_frame_network(page);
469 
470 	vbox = gtk_vbox_new(FALSE, 6);
471 	gtk_container_set_border_width(GTK_CONTAINER(vbox), VBOX_BORDER);
472 
473 	PACK_FRAME (vbox, frame, _("Icon cache"));
474 	gtk_container_set_border_width(GTK_CONTAINER(vbox1), 6);
475 	gtk_container_add(GTK_CONTAINER(frame), vbox1);
476 
477 	PACK_FRAME (vbox, frame, _("Default missing icon mode"));
478 	gtk_container_set_border_width(GTK_CONTAINER(vbox2), 6);
479 	gtk_container_add(GTK_CONTAINER(frame), vbox2);
480 
481 	PACK_FRAME (vbox, frame, _("Network"));
482 	gtk_container_set_border_width(GTK_CONTAINER(vbox3), 6);
483 	gtk_container_add(GTK_CONTAINER(frame), vbox3);
484 
485 	gtk_widget_show_all(vbox);
486 	page->page.widget = vbox;
487 }
488 
libravatar_prefs_destroy_widget_func(PrefsPage * _page)489 static void libravatar_prefs_destroy_widget_func(PrefsPage *_page)
490 {
491 	/* nothing */
492 }
493 
libravatar_save_config(void)494 static void libravatar_save_config(void)
495 {
496 	PrefFile *pfile;
497 	gchar *rcpath;
498 
499 	debug_print("Saving Libravatar Page\n");
500 
501 	rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
502 	pfile = prefs_write_open(rcpath);
503 	g_free(rcpath);
504 	if (!pfile || (prefs_set_block_label(pfile, PREFS_BLOCK_NAME) < 0))
505 		return;
506 
507 	if (prefs_write_param(param, pfile->fp) < 0) {
508 		g_warning("failed to write Libravatar configuration to file");
509 		prefs_file_close_revert(pfile);
510 		return;
511 	}
512         if (fprintf(pfile->fp, "\n") < 0) {
513 		FILE_OP_ERROR(rcpath, "fprintf");
514 		prefs_file_close_revert(pfile);
515 	} else
516 	        prefs_file_close(pfile);
517 }
518 
libravatar_prefs_save_func(PrefsPage * _page)519 static void libravatar_prefs_save_func(PrefsPage * _page)
520 {
521 	struct LibravatarPrefsPage *page = (struct LibravatarPrefsPage *) _page;
522 	int i;
523 
524 	/* cache */
525 	libravatarprefs.cache_icons = gtk_toggle_button_get_active(
526 		GTK_TOGGLE_BUTTON(page->cache_icons_check));
527 	/* cache interval */
528 	libravatarprefs.cache_interval = gtk_spin_button_get_value_as_int(
529 		GTK_SPIN_BUTTON(page->cache_interval_spin));
530 	/* default mode */
531 	for (i = 0; i < NUM_DEF_BUTTONS; ++i) {
532 		if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->defm_radio[i]))) {
533 			libravatarprefs.default_mode = radio_value[i];
534 			break;
535 		}
536 	}
537 	/* custom url */
538 	if (libravatarprefs.default_mode_url != NULL) {
539 		g_free(libravatarprefs.default_mode_url);
540 	}
541 	libravatarprefs.default_mode_url = gtk_editable_get_chars(
542 		GTK_EDITABLE(page->defm_url_text), 0, -1);
543 	/* redirects */
544 	libravatarprefs.allow_redirects = gtk_toggle_button_get_active(
545 		GTK_TOGGLE_BUTTON(page->allow_redirects_check));
546 	/* federation */
547 #if defined USE_GNUTLS
548 	libravatarprefs.allow_federated = gtk_toggle_button_get_active(
549 		GTK_TOGGLE_BUTTON(page->allow_federated_check));
550 #endif
551 	/* timeout */
552 	libravatarprefs.timeout = gtk_spin_button_get_value_as_int(
553 		GTK_SPIN_BUTTON(page->timeout));
554 
555 	libravatar_save_config();
556 }
557 
libravatar_prefs_init(void)558 void libravatar_prefs_init(void)
559 {
560 	static gchar *path[3];
561 	gchar *rcpath;
562 
563 	path[0] = _("Plugins");
564 	path[1] = _("Libravatar");
565 	path[2] = NULL;
566 
567 	prefs_set_default(param);
568 	rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
569 	prefs_read_config(param, PREFS_BLOCK_NAME, rcpath, NULL);
570 	g_free(rcpath);
571 
572 	libravatarprefs_page.page.path = path;
573 	libravatarprefs_page.page.create_widget = libravatar_prefs_create_widget_func;
574 	libravatarprefs_page.page.destroy_widget = libravatar_prefs_destroy_widget_func;
575 	libravatarprefs_page.page.save_page = libravatar_prefs_save_func;
576 	libravatarprefs_page.page.weight = 40.0;
577 
578 	prefs_gtk_register_page((PrefsPage *) &libravatarprefs_page);
579 }
580 
libravatar_prefs_done(void)581 void libravatar_prefs_done(void)
582 {
583 	prefs_gtk_unregister_page((PrefsPage *) &libravatarprefs_page);
584 }
585 
586