Fancy: Escape the custom stylesheet path for use in URI.
[claws.git] / src / plugins / fancy / fancy_prefs.c
1 /*
2  * Claws Mail -- A GTK+ based, lightweight, and fast e-mail client
3  * Copyright(C) 1999-2015 the Claws Mail Team
4  * == Fancy Plugin ==
5  * This file Copyright (C) 2009-2015 Salvatore De Paolis
6  * <iwkse@claws-mail.org> and the Claws Mail Team
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write tothe Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #include "claws-features.h"
23 #endif
24
25 #include <glib.h>
26 #include <glib/gi18n.h>
27
28 #include "defs.h"
29 #include "version.h"
30 #include "claws.h"
31 #include "plugin.h"
32 #include "gtkutils.h"
33 #include "utils.h"
34 #include "prefs.h"
35 #include "prefs_common.h"
36 #include "prefs_gtk.h"
37 #include "prefswindow.h"
38 #include "combobox.h"
39 #include "addressbook.h"
40 #include "filesel.h"
41
42 #include "fancy_prefs.h"
43
44 #define PREFS_BLOCK_NAME "fancy"
45
46 FancyPrefs fancy_prefs;
47
48 static void prefs_set_proxy_entry_sens(GtkWidget *button, GtkEntry *entry_str);
49
50 #ifdef HAVE_LIBSOUP_GNOME
51 static void prefs_disable_fancy_proxy(GtkWidget *checkbox, GtkWidget *block);
52 #endif
53 typedef struct _FancyPrefsPage FancyPrefsPage;
54
55 struct _FancyPrefsPage {
56         PrefsPage page;
57         GtkWidget *enable_images;
58         GtkWidget *enable_remote_content;
59         GtkWidget *enable_scripts;
60         GtkWidget *enable_plugins;
61         GtkWidget *enable_java;
62         GtkWidget *open_external;
63 #ifdef HAVE_LIBSOUP_GNOME
64         GtkWidget *gnome_proxy_checkbox;
65 #endif
66         GtkWidget *proxy_checkbox;
67         GtkWidget *proxy_str;
68         GtkWidget *stylesheet;
69 };
70
71 static PrefParam param[] = {
72                 {"enable_images", "TRUE", &fancy_prefs.enable_images, P_BOOL,
73                 NULL, NULL, NULL},
74                 {"enable_remote_content", "FALSE", &fancy_prefs.enable_remote_content, P_BOOL,
75                 NULL, NULL, NULL},
76                 {"enable_scripts", "FALSE", &fancy_prefs.enable_scripts, P_BOOL,
77                 NULL, NULL, NULL},
78                 {"enable_plugins", "FALSE", &fancy_prefs.enable_plugins, P_BOOL,
79                 NULL, NULL, NULL},
80                 {"open_external", "TRUE", &fancy_prefs.open_external, P_BOOL,
81                 NULL, NULL, NULL},
82                 {"zoom_level", "100", &fancy_prefs.zoom_level, P_INT,
83                 NULL, NULL, NULL},
84                 {"enable_java", "FALSE", &fancy_prefs.enable_java, P_BOOL,
85                 NULL, NULL, NULL},
86 #ifdef HAVE_LIBSOUP_GNOME
87                 {"enable_gnome_proxy","FALSE", &fancy_prefs.enable_gnome_proxy, P_BOOL,
88                 NULL, NULL, NULL},
89 #endif
90                 {"enable_proxy", "FALSE", &fancy_prefs.enable_proxy, P_BOOL,
91                 NULL, NULL, NULL},
92                 {"proxy_server", "http://SERVERNAME:PORT", &fancy_prefs.proxy_str, P_STRING,
93                 NULL, NULL, NULL},
94                 {"stylesheet", "", &fancy_prefs.stylesheet, P_STRING, NULL, NULL, NULL},
95                 {0,0,0,0}
96 };
97
98 static FancyPrefsPage fancy_prefs_page;
99
100 static void fancy_prefs_stylesheet_browse_cb    (GtkWidget *widget, gpointer data);
101 static void fancy_prefs_stylesheet_edit_cb      (GtkWidget *widget, gpointer data);
102 static void fancy_prefs_stylesheet_changed_cb   (GtkWidget *widget, gpointer data);
103
104 static void create_fancy_prefs_page     (PrefsPage *page, GtkWindow *window, gpointer   data);
105 static void destroy_fancy_prefs_page    (PrefsPage *page);
106 static void save_fancy_prefs_page       (PrefsPage *page);
107 static void save_fancy_prefs            (PrefsPage *page);
108
109 void fancy_prefs_init(void)
110 {
111         static gchar *path[3];
112         gchar *rcpath;
113
114         path[0] = _("Plugins");
115         path[1] = "Fancy";
116         path[2] = NULL;
117
118         prefs_set_default(param);
119         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
120         prefs_read_config(param, PREFS_BLOCK_NAME, rcpath, NULL);
121         g_free(rcpath);
122         
123         fancy_prefs_page.page.path = path;
124         fancy_prefs_page.page.create_widget = create_fancy_prefs_page;
125         fancy_prefs_page.page.destroy_widget = destroy_fancy_prefs_page;
126         fancy_prefs_page.page.save_page = save_fancy_prefs_page;
127         fancy_prefs_page.page.weight = 30.0;
128         prefs_gtk_register_page((PrefsPage *) &fancy_prefs_page);
129 }
130
131 void fancy_prefs_done(void)
132 {
133         save_fancy_prefs((PrefsPage *) &fancy_prefs_page);
134         prefs_gtk_unregister_page((PrefsPage *) &fancy_prefs_page);
135 }
136
137 static void remote_content_set_labels_cb(GtkWidget *button, FancyPrefsPage *prefs_page)
138 {
139         GtkTreeModel *model;
140         GtkTreeIter iter;
141         gboolean remote_enabled = gtk_toggle_button_get_active(
142                                         GTK_TOGGLE_BUTTON(prefs_page->enable_remote_content));
143
144         /* Enable images */
145         gtk_button_set_label(GTK_BUTTON(prefs_page->enable_images),
146                              remote_enabled ? _("Display images")
147                                             : _("Display embedded images"));
148
149         /* Enable Javascript */
150         gtk_button_set_label(GTK_BUTTON(prefs_page->enable_scripts),
151                              remote_enabled ? _("Execute javascript")
152                                             : _("Execute embedded javascript"));
153
154         /* Enable java */
155         gtk_button_set_label(GTK_BUTTON(prefs_page->enable_java),
156                              remote_enabled ? _("Execute Java applets")
157                                             : _("Execute embedded Java applets"));
158
159         /* Enable plugins */
160         gtk_button_set_label(GTK_BUTTON(prefs_page->enable_plugins),
161                              remote_enabled ? _("Render objects using plugins")
162                                             : _("Render embedded objects using plugins"));
163
164         /* Open links */
165         model = gtk_combo_box_get_model(GTK_COMBO_BOX(prefs_page->open_external));
166         if (gtk_tree_model_get_iter_first (model, &iter)) {
167                 if (remote_enabled)
168                         gtk_list_store_set(GTK_LIST_STORE(model), &iter, COMBOBOX_TEXT,
169                                            _("Open in viewer (remote content is enabled)"), -1);
170                 else
171                         gtk_list_store_set(GTK_LIST_STORE(model), &iter, COMBOBOX_TEXT,
172                                            _("Do nothing (remote content is disabled)"), -1);
173         }
174
175 }
176 static void create_fancy_prefs_page(PrefsPage *page, GtkWindow *window,
177                                                                         gpointer data)
178 {
179         FancyPrefsPage *prefs_page = (FancyPrefsPage *) page;
180
181         GtkWidget *vbox;
182 #ifdef HAVE_LIBSOUP_GNOME
183         GtkWidget *gnome_proxy_checkbox;
184 #endif
185         GtkWidget *proxy_checkbox;
186         GtkWidget *proxy_str;
187         GtkWidget *vbox_proxy;
188         GtkWidget *frame_proxy;
189
190         GtkWidget *frame_remote;
191         GtkWidget *vbox_remote;
192         GtkWidget *remote_label;
193         GtkWidget *enable_remote_content;
194         GtkWidget *enable_images;
195         GtkWidget *enable_scripts;
196         GtkWidget *enable_plugins;
197         GtkWidget *enable_java;
198         GtkWidget *stylesheet_label;
199         GtkWidget *stylesheet;
200         GtkWidget *stylesheet_browse_button;
201         GtkWidget *stylesheet_edit_button;
202
203         vbox = gtk_vbox_new(FALSE, 3);
204         gtk_container_set_border_width(GTK_CONTAINER(vbox), VBOX_BORDER);
205         gtk_widget_show(vbox);
206
207         GtkWidget *block = gtk_hbox_new(FALSE, 5);
208
209         vbox_proxy = gtkut_get_options_frame(vbox, &frame_proxy, _("Proxy"));
210 #ifdef HAVE_LIBSOUP_GNOME
211         gnome_proxy_checkbox = gtk_check_button_new_with_label(_("Use GNOME's proxy settings"));        
212         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gnome_proxy_checkbox),
213                                      fancy_prefs.enable_gnome_proxy);
214         gtk_box_pack_start(GTK_BOX(vbox_proxy), gnome_proxy_checkbox, FALSE, FALSE, 0);
215         gtk_widget_show(gnome_proxy_checkbox);
216         g_signal_connect(G_OBJECT(gnome_proxy_checkbox), "toggled",
217                          G_CALLBACK(prefs_disable_fancy_proxy), block);
218 #endif
219         proxy_checkbox = gtk_check_button_new_with_label(_("Use proxy"));
220         proxy_str = gtk_entry_new();
221 #ifdef HAVE_LIBSOUP_GNOME
222         if (fancy_prefs.enable_gnome_proxy)
223                 gtk_widget_set_sensitive(proxy_checkbox, FALSE);
224 #endif
225         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(proxy_checkbox),
226                                      fancy_prefs.enable_proxy);
227         prefs_set_proxy_entry_sens(proxy_checkbox, GTK_ENTRY(proxy_str));
228         g_signal_connect(G_OBJECT(proxy_checkbox), "toggled",
229                          G_CALLBACK(prefs_set_proxy_entry_sens), proxy_str);
230         pref_set_entry_from_pref(GTK_ENTRY(proxy_str), fancy_prefs.proxy_str);
231
232         gtk_box_pack_start(GTK_BOX(block), proxy_checkbox, FALSE, FALSE, 0);
233         gtk_box_pack_start(GTK_BOX(block), proxy_str, TRUE, TRUE, 0);
234         gtk_box_pack_start(GTK_BOX(vbox_proxy), block, FALSE, FALSE, 0);
235         gtk_widget_show_all(vbox_proxy);
236
237         vbox_remote = gtkut_get_options_frame(vbox, &frame_remote, _("Remote resources"));
238         remote_label = gtk_label_new(_("Loading remote resources can lead to some privacy issues.\n"
239                                         "When remote content loading is disabled, nothing will be requested\n"
240                                         "from the network. Rendering of images, scripts, plugin objects or\n"
241                                         "Java applets can still be enabled for content that is attached\n"
242                                         "in the email."));
243         gtk_misc_set_alignment(GTK_MISC(remote_label), 0, 0);
244         enable_remote_content = gtk_check_button_new_with_label(_("Enable loading of remote content"));
245         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_remote_content),
246                                      fancy_prefs.enable_remote_content);
247         gtk_box_pack_start (GTK_BOX (vbox_remote), remote_label, FALSE, FALSE, 0);
248         gtk_box_pack_start (GTK_BOX (vbox_remote), enable_remote_content, FALSE, FALSE, 0);
249         gtk_widget_show_all(vbox_remote);
250         
251         enable_images = gtk_check_button_new_with_label(("IMAGES"));
252         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_images),
253                                      fancy_prefs.enable_images);
254         gtk_box_pack_start(GTK_BOX(vbox), enable_images, FALSE, FALSE, 0);
255         gtk_widget_show(enable_images);
256
257         enable_scripts = gtk_check_button_new_with_label("SCRIPTS");
258         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_scripts),
259                                      fancy_prefs.enable_scripts);
260         gtk_box_pack_start(GTK_BOX(vbox), enable_scripts, FALSE, FALSE, 0);
261         gtk_widget_show(enable_scripts);
262
263         enable_java = gtk_check_button_new_with_label("JAVA");
264         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_java),
265                                      fancy_prefs.enable_java);
266         gtk_box_pack_start(GTK_BOX(vbox), enable_java, FALSE, FALSE, 0);
267         gtk_widget_show(enable_java);
268
269         enable_plugins = gtk_check_button_new_with_label("PLUGINS");
270         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_plugins),
271                                      fancy_prefs.enable_plugins);
272         gtk_box_pack_start(GTK_BOX(vbox), enable_plugins, FALSE, FALSE, 0);
273         gtk_widget_show(enable_plugins);
274
275         GtkWidget *hbox_ext = gtk_hbox_new(FALSE, 8);
276         GtkWidget *open_external_label = gtk_label_new(_("When clicking on a link, by default"));
277         GtkWidget *optmenu_open_external = gtkut_sc_combobox_create(NULL, FALSE);
278         GtkListStore *menu = GTK_LIST_STORE(gtk_combo_box_get_model(
279                                 GTK_COMBO_BOX(optmenu_open_external)));
280         gtk_widget_show (optmenu_open_external);
281         GtkTreeIter iter;
282
283         COMBOBOX_ADD (menu, "DEFAULT_ACTION", FALSE);
284         COMBOBOX_ADD (menu, _("Open in external browser"), TRUE);
285
286         gtk_box_pack_start(GTK_BOX(hbox_ext), open_external_label, FALSE, FALSE, 0);
287         gtk_box_pack_start(GTK_BOX(hbox_ext), optmenu_open_external, FALSE, FALSE, 0);
288         gtk_widget_show_all(hbox_ext);
289         gtk_box_pack_start(GTK_BOX(vbox), hbox_ext, FALSE, FALSE, 0);
290
291         combobox_select_by_data(GTK_COMBO_BOX(optmenu_open_external),
292                         fancy_prefs.open_external);
293         
294         GtkWidget *hbox_css = gtk_hbox_new(FALSE, 8);
295         gtk_widget_show(hbox_css);
296         gtk_box_pack_start(GTK_BOX(vbox), hbox_css, FALSE, FALSE, 0);
297
298         CLAWS_SET_TIP(hbox_css, _("The CSS in this file will be applied to all HTML parts"));
299
300         stylesheet_label = gtk_label_new(_("Stylesheet"));
301         gtk_widget_show(stylesheet_label);
302         gtk_box_pack_start(GTK_BOX(hbox_css), stylesheet_label, FALSE, FALSE, 0);
303         
304         stylesheet = gtk_entry_new();
305         gtk_widget_show(stylesheet);
306         gtk_box_pack_start(GTK_BOX(hbox_css), stylesheet, TRUE, TRUE, 0);
307
308         stylesheet_browse_button = gtkut_get_browse_file_btn(_("Bro_wse"));
309         gtk_widget_show(stylesheet_browse_button);
310         gtk_box_pack_start(GTK_BOX(hbox_css), stylesheet_browse_button, FALSE, FALSE, 0);
311         g_signal_connect(G_OBJECT(stylesheet_browse_button), "clicked",
312                          G_CALLBACK(fancy_prefs_stylesheet_browse_cb), stylesheet);
313
314         stylesheet_edit_button = gtk_button_new_from_stock(GTK_STOCK_EDIT);
315         gtk_widget_show (stylesheet_edit_button);
316         gtk_box_pack_start(GTK_BOX(hbox_css), stylesheet_edit_button, FALSE, FALSE, 0);
317         g_signal_connect(G_OBJECT(stylesheet_edit_button), "clicked",
318                          G_CALLBACK(fancy_prefs_stylesheet_edit_cb), stylesheet);
319         g_signal_connect(G_OBJECT(stylesheet), "changed",
320                          G_CALLBACK(fancy_prefs_stylesheet_changed_cb), stylesheet_edit_button);
321         pref_set_entry_from_pref(GTK_ENTRY(stylesheet), fancy_prefs.stylesheet);
322         g_signal_emit_by_name(G_OBJECT(stylesheet), "changed", stylesheet_edit_button);
323
324
325 #ifdef HAVE_LIBSOUP_GNOME
326         prefs_page->gnome_proxy_checkbox = gnome_proxy_checkbox;
327 #endif
328         prefs_page->proxy_checkbox = proxy_checkbox;
329         prefs_page->proxy_str = proxy_str;
330         prefs_page->enable_remote_content = enable_remote_content;
331         prefs_page->enable_images = enable_images;
332         prefs_page->enable_scripts = enable_scripts;
333         prefs_page->enable_plugins = enable_plugins;
334         prefs_page->enable_java = enable_java;
335         prefs_page->open_external = optmenu_open_external;
336         prefs_page->stylesheet = stylesheet;
337         prefs_page->page.widget = vbox;
338
339         g_signal_connect(G_OBJECT(prefs_page->enable_remote_content), "toggled",
340                          G_CALLBACK(remote_content_set_labels_cb), prefs_page);
341         remote_content_set_labels_cb(NULL, prefs_page);
342 }
343
344 static void fancy_prefs_stylesheet_browse_cb(GtkWidget *widget, gpointer data)
345 {
346         gchar *filename;
347         gchar *utf8_filename;
348         GtkEntry *dest = GTK_ENTRY(data);
349
350         filename = filesel_select_file_open(_("Select stylesheet"), NULL);
351         if (!filename) return;
352
353         utf8_filename = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
354         if (!utf8_filename) {
355                 g_warning("fancy_prefs_stylesheet_browse_cb(): failed to convert character set.");
356                 utf8_filename = g_strdup(filename);
357         }
358         gtk_entry_set_text(GTK_ENTRY(dest), utf8_filename);
359         g_free(utf8_filename);
360 }
361
362 static void fancy_prefs_stylesheet_edit_cb(GtkWidget *widget, gpointer data)
363 {
364         const gchar *stylesheet = gtk_entry_get_text(GTK_ENTRY(data));
365         if (!is_file_exist(stylesheet))
366                 str_write_to_file(stylesheet, "");
367         open_txt_editor(stylesheet, prefs_common_get_ext_editor_cmd());
368 }
369
370 static void fancy_prefs_stylesheet_changed_cb(GtkWidget *widget, gpointer data)
371 {
372         const gchar *stylesheet = gtk_entry_get_text(GTK_ENTRY(widget));
373         gtk_widget_set_sensitive(GTK_WIDGET(data), (*stylesheet)? TRUE: FALSE);
374 }
375
376 static void prefs_set_proxy_entry_sens(GtkWidget *button, GtkEntry *entry_str) {
377         gtk_widget_set_sensitive(GTK_WIDGET(entry_str),
378                                  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
379 }
380
381 #ifdef HAVE_LIBSOUP_GNOME
382 static void prefs_disable_fancy_proxy(GtkWidget *checkbox, GtkWidget *block) {
383         gboolean toggle = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox));
384         gtk_widget_set_sensitive(block, !toggle);
385         GList *list = g_list_first(gtk_container_get_children(GTK_CONTAINER(block)));
386         if (toggle) {
387                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(list->data), FALSE);
388         }
389         else {
390                 gtk_widget_set_sensitive(GTK_WIDGET(list->data), TRUE);
391         }
392 }
393 #endif
394 static void destroy_fancy_prefs_page(PrefsPage *page)
395 {
396         /* Do nothing! */
397 }
398 static void save_fancy_prefs(PrefsPage *page)
399 {
400         PrefFile *pref_file;
401         gchar *rc_file_path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
402                                           COMMON_RC, NULL);
403         pref_file = prefs_write_open(rc_file_path);
404         g_free(rc_file_path);
405         if (!(pref_file) ||
406         (prefs_set_block_label(pref_file, PREFS_BLOCK_NAME) < 0))
407                 return;
408         
409         if (prefs_write_param(param, pref_file->fp) < 0) {
410                 g_warning("failed to write Fancy Plugin configuration");
411                 prefs_file_close_revert(pref_file);
412                 return;
413         }
414
415         if (fprintf(pref_file->fp, "\n") < 0) {
416         FILE_OP_ERROR(rc_file_path, "fprintf");
417         prefs_file_close_revert(pref_file);
418         } else
419                 prefs_file_close(pref_file);
420 }
421
422 static void save_fancy_prefs_page(PrefsPage *page)
423 {
424                 FancyPrefsPage *prefs_page = (FancyPrefsPage *) page;
425         
426 #ifdef HAVE_LIBSOUP_GNOME
427                 fancy_prefs.enable_gnome_proxy = gtk_toggle_button_get_active
428                                 (GTK_TOGGLE_BUTTON(prefs_page->gnome_proxy_checkbox));
429 #endif
430                 fancy_prefs.enable_images = gtk_toggle_button_get_active
431                                 (GTK_TOGGLE_BUTTON(prefs_page->enable_images));
432                 fancy_prefs.enable_remote_content = gtk_toggle_button_get_active
433                                 (GTK_TOGGLE_BUTTON(prefs_page->enable_remote_content));
434                 fancy_prefs.enable_scripts = gtk_toggle_button_get_active
435                                 (GTK_TOGGLE_BUTTON(prefs_page->enable_scripts));
436                 fancy_prefs.enable_plugins = gtk_toggle_button_get_active
437                                 (GTK_TOGGLE_BUTTON(prefs_page->enable_plugins));
438                 fancy_prefs.enable_java = gtk_toggle_button_get_active
439                                 (GTK_TOGGLE_BUTTON(prefs_page->enable_java));
440                 fancy_prefs.open_external = combobox_get_active_data
441                                 (GTK_COMBO_BOX(prefs_page->open_external));
442                 fancy_prefs.enable_proxy = gtk_toggle_button_get_active
443                                 (GTK_TOGGLE_BUTTON(prefs_page->proxy_checkbox));
444                 fancy_prefs.proxy_str = pref_get_pref_from_entry(GTK_ENTRY(prefs_page->proxy_str));
445                 fancy_prefs.stylesheet = pref_get_pref_from_entry(GTK_ENTRY(prefs_page->stylesheet));
446
447                 save_fancy_prefs(page);
448 }