2007-10-28 [colin] 3.0.2cvs105
[claws.git] / src / plugins / dillo_viewer / dillo_viewer.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2007 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
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include <unistd.h>
25
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <gtk/gtk.h>
29 #include <gdk/gdkx.h>
30
31 #include "common/claws.h"
32 #include "common/version.h"
33 #include "plugin.h"
34 #include "utils.h"
35 #include "mimeview.h"
36 #include "addr_compl.h"
37
38 #include "dillo_prefs.h"
39
40 #define PLUGIN_NAME (_("Dillo HTML Viewer"))
41
42 typedef struct _DilloViewer DilloViewer;
43
44 struct _DilloViewer
45 {
46         MimeViewer       mimeviewer;
47         GtkWidget       *widget;        
48         GtkWidget       *socket;
49         gchar           *filename;
50 };
51
52 static MimeViewerFactory dillo_viewer_factory;
53
54 static GtkWidget *dillo_get_widget(MimeViewer *_viewer)
55 {
56         DilloViewer *viewer = (DilloViewer *) _viewer;
57
58         debug_print("dillo_get_widget\n");
59
60         return GTK_WIDGET(viewer->widget);
61 }
62
63 static gboolean socket_destroy_cb(GtkObject *object, gpointer data)
64 {
65         DilloViewer *viewer = (DilloViewer *) data;
66         debug_print("Destroyed dillo socket %p\n", viewer->socket);
67         viewer->socket = NULL;
68         return FALSE;
69 }
70
71 static gboolean found_in_addressbook(const gchar *address)
72 {
73         gchar *addr = NULL;
74         gboolean found = FALSE;
75         gint num_addr = 0;
76         
77         if (!address)
78                 return FALSE;
79         
80         addr = g_strdup(address);
81         extract_address(addr);
82         num_addr = complete_address(addr);
83         if (num_addr > 1) {
84                 /* skip first item (this is the search string itself) */
85                 int i = 1;
86                 for (; i < num_addr && !found; i++) {
87                         gchar *caddr = get_complete_address(i);
88                         extract_address(caddr);
89                         if (strcasecmp(caddr, addr) == 0)
90                                 found = TRUE;
91                         g_free(caddr);
92                 }
93         }
94         g_free(addr);
95         return found;
96 }
97
98 static gboolean load_images(DilloViewer *viewer)
99 {
100         MessageView *messageview = ((MimeViewer *)viewer)->mimeview 
101                                         ? ((MimeViewer *)viewer)->mimeview->messageview 
102                                         : NULL;
103         MsgInfo *msginfo = NULL;
104         gchar *ab_folderpath = NULL;
105
106         if (messageview == NULL)
107                 return FALSE;
108         
109         msginfo = messageview->msginfo;
110         
111         if (msginfo == NULL)
112                 return FALSE;
113
114         /* don't load remote images, period. */
115         if (dillo_prefs.local)
116                 return FALSE;
117         
118         /* don't do whitelisting -> load images */
119         if (!dillo_prefs.whitelist_ab)
120                 return TRUE;
121
122         if (*dillo_prefs.whitelist_ab_folder != '\0' &&
123             strcasecmp(dillo_prefs.whitelist_ab_folder, _("Any")) != 0)
124                 ab_folderpath = dillo_prefs.whitelist_ab_folder;
125
126         start_address_completion(ab_folderpath);
127
128         /* do whitelisting -> check sender */
129         if (found_in_addressbook(msginfo->from)) {
130                 end_address_completion();
131                 return TRUE;
132         }
133         
134         end_address_completion();
135         return FALSE;
136 }
137
138 static void dillo_show_mimepart(MimeViewer *_viewer,
139                                 const gchar *infile,
140                                 MimeInfo *partinfo)
141 {
142         DilloViewer *viewer = (DilloViewer *) _viewer;
143
144         debug_print("dillo_show_mimepart\n");
145
146         if (viewer->filename != NULL) {
147                 g_unlink(viewer->filename);
148                 g_free(viewer->filename);
149         }
150
151         viewer->filename = procmime_get_tmp_file_name(partinfo);
152         
153         if (!(procmime_get_part(viewer->filename, partinfo) < 0)) {
154                 gchar *cmd;
155
156                 if (viewer->socket)
157                         gtk_widget_destroy(viewer->socket);
158                 viewer->socket = gtk_socket_new();
159                 debug_print("Adding dillo socket %p", viewer->socket);
160                 gtk_container_add(GTK_CONTAINER(viewer->widget),
161                                   viewer->socket);
162                 gtk_widget_realize(viewer->socket);
163                 gtk_widget_show(viewer->socket);
164                 g_signal_connect(G_OBJECT(viewer->socket), "destroy", 
165                                  G_CALLBACK(socket_destroy_cb), viewer);
166
167                 cmd = g_strdup_printf("dillo %s%s-x %d \"%s\"",
168                                       (!load_images(viewer) ? "-l " : ""),
169                                       (dillo_prefs.full ? "-f " : ""),
170                                       (gint) GDK_WINDOW_XWINDOW(viewer->socket->window),
171                                       viewer->filename);
172
173                 execute_command_line(cmd, TRUE);
174                 g_free(cmd);
175         }
176 }
177
178 static void dillo_clear_viewer(MimeViewer *_viewer)
179 {
180         DilloViewer *viewer = (DilloViewer *) _viewer;
181
182         debug_print("dillo_clear_viewer\n");
183         debug_print("Removing dillo socket %p\n", viewer->socket);
184
185         if (viewer->socket) {
186                 gtk_widget_destroy(viewer->socket);
187         }
188 }
189
190 static void dillo_destroy_viewer(MimeViewer *_viewer)
191 {
192         DilloViewer *viewer = (DilloViewer *) _viewer;
193
194         debug_print("dillo_destroy_viewer\n");
195
196         if (viewer->socket) {
197                 gtk_widget_destroy(viewer->socket);
198         }
199
200         gtk_widget_unref(GTK_WIDGET(viewer->widget));
201         g_unlink(viewer->filename);
202         g_free(viewer->filename);
203         g_free(viewer);
204 }
205
206 static MimeViewer *dillo_viewer_create(void)
207 {
208         DilloViewer *viewer;
209
210         debug_print("dillo_viewer_create\n");
211         
212         viewer = g_new0(DilloViewer, 1);
213         viewer->mimeviewer.factory = &dillo_viewer_factory;
214         viewer->mimeviewer.get_widget = dillo_get_widget;
215         viewer->mimeviewer.show_mimepart = dillo_show_mimepart;
216         viewer->mimeviewer.clear_viewer = dillo_clear_viewer;
217         viewer->mimeviewer.destroy_viewer = dillo_destroy_viewer;       
218         viewer->mimeviewer.get_selection = NULL;
219         viewer->widget = gtk_event_box_new();
220
221         gtk_widget_show(viewer->widget);
222         gtk_widget_ref(viewer->widget);
223
224         viewer->filename = NULL;
225
226         return (MimeViewer *) viewer;
227 }
228
229 static gchar *content_types[] = 
230         {"text/html", NULL};
231
232 static MimeViewerFactory dillo_viewer_factory =
233 {
234         content_types,  
235         0,
236
237         dillo_viewer_create,
238 };
239
240 gint plugin_init(gchar **error)
241 {
242         gchar *dillo_path = NULL;
243         if (!check_plugin_version(MAKE_NUMERIC_VERSION(2,9,2,72),
244                                 VERSION_NUMERIC, PLUGIN_NAME, error))
245                 return -1;
246
247         if ((dillo_path = g_find_program_in_path("dillo")) == NULL) {
248                 *error = g_strdup(_("Can't find the dillo executable in PATH. Is it installed?"));
249                 return -1;
250         }
251         g_free(dillo_path);
252
253         dillo_prefs_init();
254
255         mimeview_register_viewer_factory(&dillo_viewer_factory);
256
257         return 0;       
258 }
259
260 gboolean plugin_done(void)
261 {
262         mimeview_unregister_viewer_factory(&dillo_viewer_factory);
263
264         dillo_prefs_done();
265         return TRUE;
266 }
267
268 const gchar *plugin_name(void)
269 {
270         return PLUGIN_NAME;
271 }
272
273 const gchar *plugin_desc(void)
274 {
275         return _("This plugin renders HTML mail using the Dillo "
276                 "web browser.\n"
277                 "\n"
278                 "Options can be found in /Configuration/Preferences/Plugins/Dillo Browser");
279 }
280
281 const gchar *plugin_type(void)
282 {
283         return "GTK2";
284 }
285
286 const gchar *plugin_licence(void)
287 {
288         return "GPL3+";
289 }
290
291 const gchar *plugin_version(void)
292 {
293         return VERSION;
294 }
295
296 struct PluginFeature *plugin_provides(void)
297 {
298         static struct PluginFeature features[] = 
299                 { {PLUGIN_MIMEVIEWER, N_("text/html")},
300                   {PLUGIN_NOTHING, NULL}};
301         return features;
302 }