1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2001-2016 the Claws Mail team
4  * This file (C) 2005-2015 Andrej Kacian <andrej@kacian.sk>
5  *
6  * - Plugin preferences
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif
26 
27 /* Global includes */
28 #include <glib.h>
29 #include <glib/gi18n.h>
30 
31 /* Claws Mail includes */
32 #include <common/defs.h>
33 #include <prefs_gtk.h>
34 #include <mainwindow.h>
35 #include <gtk/filesel.h>
36 
37 /* Local includes */
38 #include "rssyl.h"
39 #include "rssyl_prefs.h"
40 #include "rssyl_feed.h"
41 
42 static RPrefsPage rssyl_gtk_prefs_page;
43 RPrefs rssyl_prefs;
44 
45 static void destroy_rssyl_prefs_page(PrefsPage *page);
46 static void create_rssyl_prefs_page(PrefsPage *page,
47 		GtkWindow *window, gpointer data);
48 static void save_rssyl_prefs(PrefsPage *page);
49 static void rssyl_apply_prefs(void);
50 
51 static PrefParam param[] = {
52 	{ "refresh_interval", PREF_DEFAULT_REFRESH, &rssyl_prefs.refresh,
53 		P_INT, NULL, NULL, NULL },
54 	{ "refresh_on_startup", "FALSE", &rssyl_prefs.refresh_on_startup,
55 		P_BOOL,	NULL, NULL, NULL },
56 	{ "refresh_enabled", "TRUE", &rssyl_prefs.refresh_enabled,
57 		P_BOOL,	NULL, NULL, NULL },
58 	{ "cookies_path", "", &rssyl_prefs.cookies_path,
59 		P_STRING, NULL, NULL, NULL },
60 	{ "ssl_verify_peer", "TRUE", &rssyl_prefs.ssl_verify_peer,
61 		P_BOOL,	NULL, NULL, NULL },
62 	{ 0, 0, 0, 0, 0, 0, 0 }
63 };
64 
rssyl_prefs_init(void)65 void rssyl_prefs_init(void)
66 {
67 	static gchar *path[3];
68 	gchar *rcpath;
69 
70 	path[0] = _("Plugins");
71 	path[1] = PLUGIN_NAME;		/* We don't need this translated */
72 	path[2] = NULL;
73 
74 	prefs_set_default(param);
75 	rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
76 	prefs_read_config(param, PREFS_BLOCK_NAME, rcpath, NULL);
77 	g_free(rcpath);
78 
79 	rssyl_gtk_prefs_page.page.path = path;
80 	rssyl_gtk_prefs_page.page.create_widget = create_rssyl_prefs_page;
81 	rssyl_gtk_prefs_page.page.destroy_widget = destroy_rssyl_prefs_page;
82 	rssyl_gtk_prefs_page.page.save_page = save_rssyl_prefs;
83 	rssyl_gtk_prefs_page.page.weight = 30.0;
84 
85 	prefs_gtk_register_page((PrefsPage *) &rssyl_gtk_prefs_page);
86 }
87 
rssyl_prefs_done(void)88 void rssyl_prefs_done(void)
89 {
90 	prefs_gtk_unregister_page((PrefsPage *) &rssyl_gtk_prefs_page);
91 }
92 
93 /* Toggle the refresh timeout spinbutton sensitivity after the
94  * checkbutton was toggled. */
95 static gboolean
rssyl_refresh_enabled_toggled_cb(GtkToggleButton * tb,gpointer data)96 rssyl_refresh_enabled_toggled_cb(GtkToggleButton *tb, gpointer data)
97 {
98 	gtk_widget_set_sensitive(GTK_WIDGET(data),
99 			gtk_toggle_button_get_active(tb));
100 	return FALSE;
101 }
102 
103 /* Open a file select dialog and set file path to cookies entry */
104 static void
rssyl_prefs_cookies_browse_cb(GtkWidget * widget,gpointer data)105 rssyl_prefs_cookies_browse_cb(GtkWidget* widget, gpointer data)
106 {
107 	gchar *filename;
108 	gchar *utf8_filename;
109 	GtkEntry *dest = GTK_ENTRY(data);
110 
111 	filename = filesel_select_file_open(_("Select cookies file"), NULL);
112 	if (!filename) return;
113 
114 	utf8_filename = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
115 	if (!utf8_filename) {
116 		g_warning("rssyl_prefs_cookies_browse_cb(): failed to convert character set.");
117 		utf8_filename = g_strdup(filename);
118 	}
119 	gtk_entry_set_text(GTK_ENTRY(dest), utf8_filename);
120 	g_free(utf8_filename);
121 }
122 
create_rssyl_prefs_page(PrefsPage * page,GtkWindow * window,gpointer data)123 static void create_rssyl_prefs_page(PrefsPage *page,
124 		GtkWindow *window, gpointer data)
125 {
126 	RPrefsPage *prefs_page = (RPrefsPage *) page;
127 	GtkWidget *vbox, *vbox1, *vbox2;
128 	GtkWidget *frame;
129 	GtkWidget *refresh, *refresh_enabled, *refresh_hbox;
130 	GtkWidget *label;
131 	GtkWidget *refresh_on_startup;
132 	GtkObject *refresh_adj;
133 	GtkWidget *cookies_path, *cookies_btn, *cookies_hbox;
134 	GtkWidget *ssl_verify_peer;
135 
136 	vbox1 = gtk_vbox_new(FALSE, 6);
137 
138 	/* Refresh interval */
139 	refresh_hbox = gtk_hbox_new(FALSE, 6);
140 	refresh_enabled = gtk_check_button_new_with_label(
141 			_("Default refresh interval"));
142 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(refresh_enabled),
143 			rssyl_prefs.refresh_enabled);
144 	gtk_box_pack_start(GTK_BOX(refresh_hbox), refresh_enabled, FALSE, FALSE, 0);
145 
146 	refresh_adj = gtk_adjustment_new(rssyl_prefs.refresh,
147 			1, 100000, 1, 10, 0);
148 	refresh = gtk_spin_button_new(GTK_ADJUSTMENT(refresh_adj), 1, 0);
149 	gtk_widget_set_sensitive(GTK_WIDGET(refresh), rssyl_prefs.refresh_enabled);
150 	g_signal_connect(G_OBJECT(refresh_enabled), "toggled",
151 			G_CALLBACK(rssyl_refresh_enabled_toggled_cb), refresh);
152 	gtk_box_pack_start(GTK_BOX(refresh_hbox), refresh, FALSE, FALSE, 0);
153 
154 	label = gtk_label_new(_("minutes"));
155 	gtk_box_pack_start(GTK_BOX(refresh_hbox), label, FALSE, FALSE, 0);
156 
157 	gtk_box_pack_start(GTK_BOX(vbox1), refresh_hbox, FALSE, FALSE, 0);
158 
159 	/* Whether to refresh all feeds on CM startup */
160 	refresh_on_startup = gtk_check_button_new_with_label(
161 			_("Refresh all feeds on application start"));
162 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(refresh_on_startup),
163 			rssyl_prefs.refresh_on_startup);
164 	gtk_box_pack_start(GTK_BOX(vbox1), refresh_on_startup, FALSE, FALSE, 0);
165 
166 	vbox2 = gtk_vbox_new(FALSE, 6);
167 
168 	/* Whether to verify SSL peer certificate */
169 	ssl_verify_peer = gtk_check_button_new_with_label(
170 			_("Verify SSL/TLS certificates validity for new feeds"));
171 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ssl_verify_peer),
172 			rssyl_prefs.ssl_verify_peer);
173 	gtk_box_pack_start(GTK_BOX(vbox2), ssl_verify_peer, FALSE, FALSE, 0);
174 
175 	/* Path to cookies file for libcurl to use */
176 	cookies_hbox = gtk_hbox_new(FALSE, 6);
177 	label = gtk_label_new(_("Path to cookies file"));
178 	gtk_box_pack_start(GTK_BOX(cookies_hbox), label, FALSE, FALSE, 0);
179 
180 	cookies_path = gtk_entry_new();
181 	gtk_entry_set_text(GTK_ENTRY(cookies_path), rssyl_prefs.cookies_path);
182 	gtk_box_pack_start(GTK_BOX(cookies_hbox), cookies_path, TRUE, TRUE, 0);
183 	gtk_widget_set_tooltip_text(cookies_path,
184 			_("Path to Netscape-style cookies.txt file containing your cookies"));
185 
186 	cookies_btn = gtkut_get_browse_file_btn(_("Bro_wse"));
187 	gtk_box_pack_start(GTK_BOX(cookies_hbox), cookies_btn, FALSE, FALSE, 0);
188 	g_signal_connect(G_OBJECT(cookies_btn), "clicked",
189 		G_CALLBACK(rssyl_prefs_cookies_browse_cb), cookies_path);
190 	gtk_box_pack_start(GTK_BOX(vbox2), cookies_hbox, FALSE, FALSE, 0);
191 
192 	vbox = gtk_vbox_new(FALSE, 6);
193 	gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
194 
195 	PACK_FRAME (vbox, frame, _("Refreshing"));
196 	gtk_container_set_border_width(GTK_CONTAINER(vbox1), 6);
197 	gtk_container_add(GTK_CONTAINER(frame), vbox1);
198 
199 	PACK_FRAME (vbox, frame, _("Security and privacy"));
200 	gtk_container_set_border_width(GTK_CONTAINER(vbox2), 6);
201 	gtk_container_add(GTK_CONTAINER(frame), vbox2);
202 
203 	gtk_widget_show_all(vbox);
204 
205 	/* Store pointers to relevant widgets */
206 	prefs_page->page.widget = vbox;
207 	prefs_page->refresh_enabled = refresh_enabled;
208 	prefs_page->refresh = refresh;
209 	prefs_page->refresh_on_startup = refresh_on_startup;
210 	prefs_page->cookies_path = cookies_path;
211 	prefs_page->ssl_verify_peer = ssl_verify_peer;
212 }
213 
destroy_rssyl_prefs_page(PrefsPage * page)214 static void destroy_rssyl_prefs_page(PrefsPage *page)
215 {
216 	/* Do nothing! */
217 }
218 
save_rssyl_prefs(PrefsPage * page)219 static void save_rssyl_prefs(PrefsPage *page)
220 {
221 	RPrefsPage *prefs_page = (RPrefsPage *)page;
222 	PrefFile *pref_file;
223 	gchar *rc_file_path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
224 			COMMON_RC, NULL);
225 
226 	/* Grab values from GTK widgets */
227 	rssyl_prefs.refresh_enabled = gtk_toggle_button_get_active(
228 			GTK_TOGGLE_BUTTON(prefs_page->refresh_enabled));
229 	rssyl_prefs.refresh = gtk_spin_button_get_value_as_int(
230 			GTK_SPIN_BUTTON(prefs_page->refresh));
231 	rssyl_prefs.refresh_on_startup = gtk_toggle_button_get_active(
232 			GTK_TOGGLE_BUTTON(prefs_page->refresh_on_startup));
233 	g_free(rssyl_prefs.cookies_path);
234 	rssyl_prefs.cookies_path = g_strdup(gtk_entry_get_text(
235 				GTK_ENTRY(prefs_page->cookies_path)));
236 	rssyl_prefs.ssl_verify_peer = gtk_toggle_button_get_active(
237 			GTK_TOGGLE_BUTTON(prefs_page->ssl_verify_peer));
238 
239 	/* Store prefs in rc file */
240 	pref_file = prefs_write_open(rc_file_path);
241 	g_free(rc_file_path);
242 
243 	if( !pref_file || prefs_set_block_label(pref_file, PREFS_BLOCK_NAME) < 0 )
244 				return;
245 
246 	if( prefs_write_param(param, pref_file->fp) < 0 ) {
247 		g_warning("Failed to write RSSyl plugin configuration");
248 		prefs_file_close_revert(pref_file);
249 		return;
250 	}
251 
252 	fprintf(pref_file->fp, "\n");
253 	prefs_file_close(pref_file);
254 
255 	rssyl_apply_prefs();
256 }
257 
rssyl_prefs_get(void)258 RPrefs *rssyl_prefs_get(void)
259 {
260 	return &rssyl_prefs;
261 }
262 
rssyl_start_default_refresh_timeouts_func(FolderItem * item,gpointer data)263 static void rssyl_start_default_refresh_timeouts_func(FolderItem *item,
264 		gpointer data)
265 {
266 	RFolderItem *ritem = (RFolderItem *)item;
267 	guint prefs_interval = GPOINTER_TO_UINT(data);
268 
269 	if( !IS_RSSYL_FOLDER_ITEM(item) )
270 		return;
271 
272 	if( folder_item_parent(item) == NULL || ritem->url == NULL )
273 		return;
274 
275 	/* Feeds which use default refresh interval */
276 	if( ritem->default_refresh_interval ) {
277 		/* Start a new timer if the default value has changed
278 		 * (ritem->refresh_interval should contain previous default
279 		 * value in this case). */
280 		if( ritem->refresh_interval != prefs_interval ) {
281 			ritem->refresh_interval = prefs_interval;
282 			rssyl_feed_start_refresh_timeout(ritem);
283 		}
284 	}
285 }
286 
rssyl_start_default_refresh_timeouts(void)287 static void rssyl_start_default_refresh_timeouts(void)
288 {
289 	RPrefs *rsprefs = rssyl_prefs_get();
290 
291 	folder_func_to_all_folders(
292 			(FolderItemFunc)rssyl_start_default_refresh_timeouts_func,
293 			GUINT_TO_POINTER(rsprefs->refresh));
294 }
295 
296 /* rssyl_apply_prefs():
297  * Do what's needed to start using newly set preferences */
rssyl_apply_prefs(void)298 static void rssyl_apply_prefs(void)
299 {
300 	/* Update refresh timeouts for feeds which use default interval. */
301 	rssyl_start_default_refresh_timeouts();
302 
303 	/* Nothing else here, so far... */
304 }
305