No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | evolution-mbox-importer.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | evolution-mbox-importer.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 *
16 * Authors:
17 * Iain Holmes <iain@ximian.com>
18 * Michael Zucchi <notzed@ximian.com>
19 *
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32
33 #include <stdio.h>
34 #include <ctype.h>
35 #include <string.h>
36 #include <errno.h>
37
38 #include <gtk/gtk.h>
39 #include <glib/gi18n.h>
40 #include <glib/gstdio.h>
41
42 #include "shell/e-shell.h"
43 #include "shell/e-shell-window.h"
44 #include "shell/e-shell-view.h"
45 #include "shell/e-shell-sidebar.h"
46
47 #include "mail/e-mail-backend.h"
48 #include "mail/em-folder-selection-button.h"
49 #include "mail/em-folder-tree-model.h"
50 #include "mail/em-folder-tree.h"
51 #include "libemail-utils/mail-mt.h"
52
53 #include "mail-importer.h"
54
55 #include "e-util/e-import.h"
56 #include "misc/e-web-view-preview.h"
57
58 typedef struct {
59 EImport *import;
60 EImportTarget *target;
61
62 GMutex *status_lock;
63 gchar *status_what;
64 gint status_pc;
65 gint status_timeout_id;
66 GCancellable *cancellable; /* cancel/status port */
67
68 gchar *uri;
69 } MboxImporter;
70
71 static void
72 folder_selected (EMFolderSelectionButton *button,
73 EImportTargetURI *target)
74 {
75 g_free (target->uri_dest);
76 target->uri_dest = g_strdup (em_folder_selection_button_get_folder_uri (button));
77 }
78
79 static GtkWidget *
80 mbox_getwidget (EImport *ei,
81 EImportTarget *target,
82 EImportImporter *im)
83 {
84 EShell *shell;
85 EShellBackend *shell_backend;
86 EMailBackend *backend;
87 EMailSession *session;
88 GtkWindow *window;
89 GtkWidget *hbox, *w;
90 GtkLabel *label;
91 gchar *select_uri = NULL;
92
93 /* XXX Dig up the mail backend from the default EShell.
94 * Since the EImport framework doesn't allow for user
95 * data, I don't see how else to get to it. */
96 shell = e_shell_get_default ();
97 shell_backend = e_shell_get_backend_by_name (shell, "mail");
98
99 backend = E_MAIL_BACKEND (shell_backend);
100 session = e_mail_backend_get_session (backend);
101
102 /* preselect the folder selected in a mail view */
103 window = e_shell_get_active_window (shell);
104 if (E_IS_SHELL_WINDOW (window)) {
105 EShellWindow *shell_window;
106 const gchar *view;
107
108 shell_window = E_SHELL_WINDOW (window);
109 view = e_shell_window_get_active_view (shell_window);
110
111 if (view && g_str_equal (view, "mail")) {
112 EShellView *shell_view;
113 EShellSidebar *shell_sidebar;
114 EMFolderTree *folder_tree = NULL;
115
116 shell_view = e_shell_window_get_shell_view (
117 shell_window, view);
118
119 shell_sidebar =
120 e_shell_view_get_shell_sidebar (shell_view);
121
122 g_object_get (
123 shell_sidebar, "folder-tree",
124 &folder_tree, NULL);
125
126 select_uri =
127 em_folder_tree_get_selected_uri (folder_tree);
128
129 g_object_unref (folder_tree);
130 }
131 }
132
133 if (!select_uri) {
134 const gchar *uri;
135 uri = e_mail_session_get_local_folder_uri (
136 session, E_MAIL_LOCAL_FOLDER_INBOX);
137 select_uri = g_strdup (uri);
138 }
139
140 hbox = gtk_hbox_new (FALSE, 0);
141
142 w = gtk_label_new_with_mnemonic (_("_Destination folder:"));
143 gtk_box_pack_start ((GtkBox *) hbox, w, FALSE, TRUE, 6);
144
145 label = GTK_LABEL (w);
146
147 w = em_folder_selection_button_new (
148 session, _("Select folder"),
149 _("Select folder to import into"));
150 gtk_label_set_mnemonic_widget (label, w);
151 em_folder_selection_button_set_folder_uri (
152 EM_FOLDER_SELECTION_BUTTON (w), select_uri);
153 folder_selected (
154 EM_FOLDER_SELECTION_BUTTON (w), (EImportTargetURI *) target);
155 g_signal_connect (
156 w, "selected",
157 G_CALLBACK (folder_selected), target);
158 gtk_box_pack_start ((GtkBox *) hbox, w, FALSE, TRUE, 6);
159
160 w = gtk_vbox_new (FALSE, 0);
161 gtk_box_pack_start ((GtkBox *) w, hbox, FALSE, FALSE, 0);
162 gtk_widget_show_all (w);
163
164 g_free (select_uri);
165
166 return w;
167 }
168
169 static gboolean
170 mbox_supported (EImport *ei,
171 EImportTarget *target,
172 EImportImporter *im)
173 {
174 gchar signature[6];
175 gboolean ret = FALSE;
176 gint fd, n;
177 EImportTargetURI *s;
178 gchar *filename;
179
180 if (target->type != E_IMPORT_TARGET_URI)
181 return FALSE;
182
183 s = (EImportTargetURI *) target;
184 if (s->uri_src == NULL)
185 return TRUE;
186
187 if (strncmp (s->uri_src, "file:///", strlen ("file:///")) != 0)
188 return FALSE;
189
190 filename = g_filename_from_uri (s->uri_src, NULL, NULL);
191 fd = g_open (filename, O_RDONLY, 0);
192 g_free (filename);
193 if (fd != -1) {
194 n = read (fd, signature, 5);
195 ret = n == 5 && memcmp (signature, "From ", 5) == 0;
196 close (fd);
197 }
198
199 return ret;
200 }
201
202 static void
203 mbox_status (CamelOperation *op,
204 const gchar *what,
205 gint pc,
206 gpointer data)
207 {
208 MboxImporter *importer = data;
209
210 g_mutex_lock (importer->status_lock);
211 g_free (importer->status_what);
212 importer->status_what = g_strdup (what);
213 importer->status_pc = pc;
214 g_mutex_unlock (importer->status_lock);
215 }
216
217 static gboolean
218 mbox_status_timeout (gpointer data)
219 {
220 MboxImporter *importer = data;
221 gint pc;
222 gchar *what;
223
224 if (importer->status_what) {
225 g_mutex_lock (importer->status_lock);
226 what = importer->status_what;
227 importer->status_what = NULL;
228 pc = importer->status_pc;
229 g_mutex_unlock (importer->status_lock);
230
231 e_import_status (
232 importer->import, (EImportTarget *)
233 importer->target, what, pc);
234 }
235
236 return TRUE;
237 }
238
239 static void
240 mbox_import_done (gpointer data,
241 GError **error)
242 {
243 MboxImporter *importer = data;
244
245 g_source_remove (importer->status_timeout_id);
246 g_free (importer->status_what);
247 g_mutex_free (importer->status_lock);
248 g_object_unref (importer->cancellable);
249
250 e_import_complete (importer->import, importer->target);
251 g_free (importer);
252 }
253
254 static void
255 mbox_import (EImport *ei,
256 EImportTarget *target,
257 EImportImporter *im)
258 {
259 EShell *shell;
260 EShellBackend *shell_backend;
261 EMailSession *session;
262 MboxImporter *importer;
263 gchar *filename;
264
265 /* XXX Dig up the EMailSession from the default EShell.
266 * Since the EImport framework doesn't allow for user
267 * data, I don't see how else to get to it. */
268 shell = e_shell_get_default ();
269 shell_backend = e_shell_get_backend_by_name (shell, "mail");
270 session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend));
271
272 /* TODO: do we validate target? */
273
274 importer = g_malloc0 (sizeof (*importer));
275 g_datalist_set_data (&target->data, "mbox-data", importer);
276 importer->import = ei;
277 importer->target = target;
278 importer->status_lock = g_mutex_new ();
279 importer->status_timeout_id = g_timeout_add (100, mbox_status_timeout, importer);
280 importer->cancellable = camel_operation_new ();
281
282 g_signal_connect (
283 importer->cancellable, "status",
284 G_CALLBACK (mbox_status), importer);
285
286 filename = g_filename_from_uri (
287 ((EImportTargetURI *) target)->uri_src, NULL, NULL);
288 mail_importer_import_mbox (
289 session, filename, ((EImportTargetURI *) target)->uri_dest,
290 importer->cancellable, mbox_import_done, importer);
291 g_free (filename);
292 }
293
294 static void
295 mbox_cancel (EImport *ei,
296 EImportTarget *target,
297 EImportImporter *im)
298 {
299 MboxImporter *importer = g_datalist_get_data (&target->data, "mbox-data");
300
301 if (importer)
302 g_cancellable_cancel (importer->cancellable);
303 }
304
305 static MboxImporterCreatePreviewFunc create_preview_func = NULL;
306 static MboxImporterFillPreviewFunc fill_preview_func = NULL;
307
308 void
309 mbox_importer_set_preview_funcs (MboxImporterCreatePreviewFunc create_func,
310 MboxImporterFillPreviewFunc fill_func)
311 {
312 create_preview_func = create_func;
313 fill_preview_func = fill_func;
314 }
315
316 static void
317 preview_selection_changed_cb (GtkTreeSelection *selection,
318 EWebViewPreview *preview)
319 {
320 GtkTreeIter iter;
321 GtkTreeModel *model = NULL;
322 gboolean found = FALSE;
323
324 g_return_if_fail (selection != NULL);
325 g_return_if_fail (preview != NULL);
326 g_return_if_fail (fill_preview_func != NULL);
327
328 if (gtk_tree_selection_get_selected (selection, &model, &iter) && model) {
329 CamelMimeMessage *msg = NULL;
330
331 gtk_tree_model_get (model, &iter, 2, &msg, -1);
332
333 if (msg) {
334 found = TRUE;
335 fill_preview_func (G_OBJECT (preview), msg);
336 g_object_unref (msg);
337 }
338 }
339
340 if (!found) {
341 e_web_view_preview_begin_update (preview);
342 e_web_view_preview_end_update (preview);
343 }
344 }
345
346 static GtkWidget *
347 mbox_get_preview (EImport *ei,
348 EImportTarget *target,
349 EImportImporter *im)
350 {
351 GtkWidget *preview = NULL;
352 EImportTargetURI *s = (EImportTargetURI *) target;
353 gchar *filename;
354 gint fd;
355 CamelMimeParser *mp;
356 GtkListStore *store = NULL;
357 GtkTreeIter iter;
358 GtkWidget *preview_widget = NULL;
359
360 if (!create_preview_func || !fill_preview_func)
361 return NULL;
362
363 filename = g_filename_from_uri (s->uri_src, NULL, NULL);
364 if (!filename) {
365 g_message (G_STRLOC ": Couldn't get filename from URI '%s'", s->uri_src);
366 return NULL;
367 }
368
369 fd = g_open (filename, O_RDONLY | O_BINARY, 0);
370 if (fd == -1) {
371 g_warning (
372 "Cannot find source file to import '%s': %s",
373 filename, g_strerror (errno));
374 g_free (filename);
375 return NULL;
376 }
377
378 g_free (filename);
379
380 mp = camel_mime_parser_new ();
381 camel_mime_parser_scan_from (mp, TRUE);
382 if (camel_mime_parser_init_with_fd (mp, fd) == -1) {
383 g_object_unref (mp);
384 return NULL;
385 }
386
387 while (camel_mime_parser_step (mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM) {
388 CamelMimeMessage *msg;
389 gchar *from;
390
391 msg = camel_mime_message_new ();
392 if (!camel_mime_part_construct_from_parser_sync (
393 (CamelMimePart *) msg, mp, NULL, NULL)) {
394 g_object_unref (msg);
395 break;
396 }
397
398 if (!store)
399 store = gtk_list_store_new (
400 3, G_TYPE_STRING, G_TYPE_STRING,
401 CAMEL_TYPE_MIME_MESSAGE);
402
403 from = NULL;
404 if (camel_mime_message_get_from (msg))
405 from = camel_address_encode (
406 CAMEL_ADDRESS (
407 camel_mime_message_get_from (msg)));
408
409 gtk_list_store_append (store, &iter);
410 gtk_list_store_set (
411 store, &iter,
412 0, camel_mime_message_get_subject (msg) ?
413 camel_mime_message_get_subject (msg) : "",
414 1, from ? from : "", 2, msg, -1);
415
416 g_object_unref (msg);
417 g_free (from);
418
419 camel_mime_parser_step (mp, NULL, NULL);
420 }
421
422 if (store) {
423 GtkTreeView *tree_view;
424 GtkTreeSelection *selection;
425 gboolean valid;
426
427 preview = e_web_view_preview_new ();
428 gtk_widget_show (preview);
429
430 tree_view = e_web_view_preview_get_tree_view (
431 E_WEB_VIEW_PREVIEW (preview));
432 g_return_val_if_fail (tree_view != NULL, NULL);
433
434 gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (store));
435 g_object_unref (store);
436
437 /* Translators: Column header for a message subject */
438 gtk_tree_view_insert_column_with_attributes (
439 tree_view, -1, C_("mboxImp", "Subject"),
440 gtk_cell_renderer_text_new (), "text", 0, NULL);
441
442 /* Translators: Column header for a message From address */
443 gtk_tree_view_insert_column_with_attributes (
444 tree_view, -1, C_("mboxImp", "From"),
445 gtk_cell_renderer_text_new (), "text", 1, NULL);
446
447 if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) > 1)
448 e_web_view_preview_show_tree_view (
449 E_WEB_VIEW_PREVIEW (preview));
450
451 create_preview_func (G_OBJECT (preview), &preview_widget);
452 g_return_val_if_fail (preview_widget != NULL, NULL);
453
454 e_web_view_preview_set_preview (
455 E_WEB_VIEW_PREVIEW (preview), preview_widget);
456 gtk_widget_show (preview_widget);
457
458 selection = gtk_tree_view_get_selection (tree_view);
459 valid = gtk_tree_model_get_iter_first (
460 GTK_TREE_MODEL (store), &iter);
461 g_return_val_if_fail (valid, NULL);
462 gtk_tree_selection_select_iter (selection, &iter);
463
464 g_signal_connect (
465 selection, "changed",
466 G_CALLBACK (preview_selection_changed_cb), preview);
467
468 preview_selection_changed_cb (
469 selection, E_WEB_VIEW_PREVIEW (preview));
470 }
471
472 return preview;
473 }
474
475 static EImportImporter mbox_importer = {
476 E_IMPORT_TARGET_URI,
477 0,
478 mbox_supported,
479 mbox_getwidget,
480 mbox_import,
481 mbox_cancel,
482 mbox_get_preview,
483 };
484
485 EImportImporter *
486 mbox_importer_peek (void)
487 {
488 mbox_importer.name = _("Berkeley Mailbox (mbox)");
489 mbox_importer.description = _("Importer Berkeley Mailbox format folders");
490
491 return &mbox_importer;
492 }