evolution-3.6.4/mail/importers/evolution-mbox-importer.c

No issues found

Incomplete coverage

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
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  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 }